Orders Domain
The Orders domain manages the order lifecycle, from creation through completion or cancellation. It includes order workflow state management, chat communication between buyers and sellers, comments/reviews, and payment tracking.
Overview
The Orders domain encompasses:
- Orders – Service purchase transactions with state machine workflow
- Chat – Real-time communication between customer and seller
- Comments – Reviews and ratings after order completion
- Payments – Payment tracking and status
Entities
Order Entity
Represents a service purchase with complex workflow.
// domain/orders/order.entity.ts
export class Order {
id: string;
sellerId: string;
customerId: string;
serviceId: string;
serviceTitle: string;
servicePrice: Decimal;
serviceDeliveryTime: number;
selectedOptions: Option[];
totalAmount: Decimal;
commissionAmount: Decimal;
paymentId: string;
state: State;
completionDate: Date | null;
createdAt: Date;
updatedAt: Date;
events: Event[];
notes: string;
static create(
id: string,
sellerId: string,
customerId: string,
serviceId: string,
serviceTitle: string,
servicePrice: Decimal,
serviceDeliveryTime: number,
selectedOptions: Option[],
paymentId: string,
commissionRate: Decimal
): Order
getTotalPrice(): Decimal
getDeliveryTime(): number
getAssumedDeliveryDate(): Date
isLate(): boolean
getCancelationRequestCount(): number
getNumber(): string
}
Order states:
type State =
| "paid" // Payment completed, awaiting seller acceptance
| "rejected" // Seller rejected the order
| "inprogress" // Seller accepted, working on it
| "cancel_requested" // Customer requested cancellation
| "disputing" // Dispute under admin review
| "delivered" // Seller delivered, awaiting customer approval
| "correction_requested" // Customer requested corrections
| "completed" // Customer approved, order complete
| "cancelled" // Order cancelled (refund issued)
Event types:
type EventType =
| "payment.completed"
| "order.accepted"
| "order.rejected"
| "order.delivered"
| "order.completed"
| "dispute.resolved"
| "order.cancel_accepted"
| "order.cancel_rejected"
| "order.requires_correction"
| "correction_request.accepted"
| "correction_request.declined"
| "order.cancel_requested"
Key properties:
- serviceTitle, servicePrice, serviceDeliveryTime – Captured at order time
- selectedOptions – Options selected by customer (immutable)
- totalAmount – Computed: servicePrice + sum of option prices
- commissionAmount – Platform commission: totalAmount × commissionRate
- events – Audit trail of state transitions
- notes – Admin notes or special instructions
Chat Entity
Communication channel for an order.
// domain/orders/chat.entity.ts
export class Chat {
id: string;
title: string;
serviceId: string | null;
orderId: string | null;
ownerId: string;
createdAt: Date;
lastMessageAt: Date;
}
export class Message {
id: string;
chatId: string;
senderId: string;
content: string;
timestamp: Date;
attachments: Attachment[];
}
export class ChatMember {
chatId: string;
userId: string;
isArchived: boolean;
}
type Attachment = {
path: string;
type: string;
size: number;
}
Key features:
- Chat can be order-specific or general
- Messages support file attachments
- Members can archive chats
- lastMessageAt used for sorting
Comment Entity
Reviews and ratings for completed orders.
// domain/orders/comment.entity.ts
export class Comment {
id: string;
userId: string;
authorName: string;
serviceId: string;
orderId: string;
content: string;
rating: number; // 1-5 stars
replies: Reply[];
createdAt: Date;
updatedAt: Date;
static create(
id: string,
userId: string,
authorName: string,
serviceId: string,
orderId: string,
content: string,
rating: number
): Comment
addReply(
id: string,
authorId: string,
authorName: string,
content: string,
createdAt: Date,
updatedAt: Date
): void
}
export class Reply {
id: string;
authorId: string;
authorName: string;
content: string;
createdAt: Date;
updatedAt: Date;
}
Key features:
- One comment per order
- Seller can reply to comments
- Rating affects Service.averageRating
- Comments visible on service page
Payment Entity
Payment transaction tracking.
// domain/orders/payment.entity.ts
export class Payment {
id: string;
amount: Decimal;
orderAmount: Decimal;
currency: string;
userId: string;
status: PaymentStatus; // 'received' | 'refunded' | 'released'
createdAt: Date;
static create(
id: string,
amount: Decimal,
orderAmount: Decimal,
currency: string,
userId: string,
status: PaymentStatus
): Payment
}
Payment statuses: - received – Payment collected from customer - refunded – Payment returned to customer (order rejected/cancelled) - released – Payment transferred to seller (order completed)
Repositories
OrderRepository
// domain/orders/order.repository.ts
export abstract class OrderRepository extends AbstractRepository<Order, string, OrderQueryPolicy> {
abstract updateState(
orderId: string,
state: State,
event: Event,
opts?: any
): Promise<void>;
abstract computeReceipt(orderId: string): Promise<Receipt>;
abstract computeInvoice(orderId: string, user: User): Promise<Invoice>;
abstract recordEvent(
orderId: string,
event: Event,
transaction?: any
): Promise<void>;
abstract monthlyCommission(filters: OrderOpQueryPolicy): Promise<MonthCommission[]>;
abstract getOrdersInState(state: State): Promise<Order[]>;
}
export class OrderQueryPolicy {
userId?: string;
state?: OrderState;
serviceId?: string;
serviceTitle?: string;
sellerId?: string;
customerId?: string;
createdFrom?: Date;
createdTo?: Date;
}
Key operations:
- updateState() – Transition to new state and record event
- recordEvent() – Add event to audit trail
- computeReceipt() – Generate receipt for order
- computeInvoice() – Generate invoice for seller
- monthlyCommission() – Calculate platform commission by month
- getOrdersInState() – Get all orders in specific state
ChatRepository
// domain/orders/chat.repository.ts
export abstract class ChatRepository extends AbstractRepository<Chat> {
abstract addMessage(message: Message): Promise<Message>;
abstract getMessages(chatId: string, pagination: Pagination): Promise<Paginated<Message>>;
abstract addMember(member: ChatMember): Promise<void>;
abstract getMembers(chatId: string): Promise<ChatMember[]>;
abstract isMember(userId: string, chatId: string): Promise<boolean>;
abstract archiveChat(userId: string, chatId: string): Promise<void>;
abstract updateLastMessageAt(chatId: string, timestamp: Date): Promise<void>;
}
CommentRepository
// domain/orders/comment.repository.ts
export abstract class CommentRepository extends AbstractRepository<Comment> {
abstract getByServiceId(serviceId: string): Promise<Comment[]>;
abstract getByOrderId(orderId: string): Promise<Comment | null>;
abstract addReply(commentId: string, reply: Reply): Promise<void>;
}
PaymentRepository
// domain/orders/payment.repository.ts
export abstract class PaymentRepository extends AbstractRepository<Payment> {
abstract updateStatus(id: string, status: PaymentStatus): Promise<void>;
}
Business Rules
Order Creation
- Payment must be completed first – Order created after successful payment
- Service data captured – Title, price, delivery time captured (immutable)
- Options captured – Selected options stored (immutable)
- Commission calculated – Based on current platform commission rate
- Initial state is "paid" – Awaiting seller acceptance
Order Workflow (State Machine)
The order follows a complex state machine (implemented with XState in adapters layer):
┌──────┐
│ paid │ (initial state)
└──┬───┘
│
┌───────┴────────┐
│ │
↓ ↓
┌──────────┐ ┌────────────┐
│ rejected │ │ inprogress │
└──────────┘ └─────┬──────┘
│
┌─────────────┼─────────────┐
│ │ │
↓ ↓ ↓
┌────────────────┐ ┌───────────┐ ┌──────────┐
│cancel_requested│ │ delivered │ │disputing │
└────────┬───────┘ └─────┬─────┘ └──────────┘
│ │
┌────┴────┐ ┌────┴────┐
│ │ │ │
↓ ↓ ↓ ↓
┌─────────┐┌───────────────────┐
│cancelled││correction_requested│
└─────────┘└─────────┬──────────┘
│
┌────┴────┐
│ │
↓ ↓
┌──────────┐┌──────────┐
│ delivered││ disputing│
└────┬─────┘└──────────┘
│
↓
┌───────────┐
│ completed │
└───────────┘
State transitions:
paid→rejected(seller declines, refund issued)paid→inprogress(seller accepts)inprogress→delivered(seller delivers work)inprogress→cancel_requested(customer requests cancel)cancel_requested→cancelled(seller accepts cancel, refund issued)cancel_requested→inprogress(seller rejects cancel)cancel_requested→disputing(after 3 cancel requests, admin review)delivered→completed(customer approves)delivered→correction_requested(customer requests changes)correction_requested→delivered(seller makes corrections)disputing→completed|cancelled(admin decision)
Refund Rules
Refunds are issued when:
- Seller rejects order (paid → rejected)
- Seller accepts cancellation (cancel_requested → cancelled)
- Admin resolves dispute in favor of customer
Payment Release Rules
Payment released to seller when:
- Order reaches completed state
- Platform commission deducted
- Seller receives: totalAmount - commissionAmount
Late Order Detection
order.isLate() // Returns true if current time > delivery date
order.getAssumedDeliveryDate() // createdAt + serviceDeliveryTime + sum(option.additionalTime)
Dispute Escalation
- After 3 cancellation requests, order moves to
disputing - Admin reviews and makes final decision
- Admin can resolve to
completed,cancelled, or keepinprogress
Use Cases
Order Management
- Create order – After payment completion
- Accept order – Seller accepts to work on it
- Reject order – Seller declines (within timeframe)
- Deliver order – Seller submits completed work
- Request corrections – Customer asks for changes
- Complete order – Customer approves delivery
- Request cancellation – Customer wants to cancel
- Process cancellation – Seller accepts/rejects cancel request
- Resolve dispute – Admin makes final decision
Chat Management
- Create chat – For an order or general inquiry
- Send message – Post message to chat
- Upload attachment – Attach files to message
- List messages – Get chat history
- Archive chat – Hide from chat list
- Join chat – Add participant (admin feature)
Comment Management
- Create comment – Review completed order
- Reply to comment – Seller responds to review
- List comments – Get reviews for a service
- Get order comment – Find comment for specific order
Integration Points
With Users Domain
Order.sellerIdandOrder.customerIdreferenceUser.id- Authorization checks: only customer/seller/admin can view order
- Notifications sent to users on state changes
With Services Domain
Order.serviceIdreferencesService.id- Service data captured at order creation
- Completed orders increment
Service.salesCount - Comments affect
Service.averageRating
With Payments Domain
Order.paymentIdreferencesPayment.id- Payment must be "received" before order creation
- Order completion triggers payment "released" status
With Accounts Domain
- Order completion triggers balance credit to seller
- Commission amount credited to platform account
- Refunds trigger balance debit
Key Workflows
Happy Path Order Flow
1. Customer initiates payment
↓
2. Payment completed
↓
3. Order created (state = "paid")
↓
4. Seller accepts (state = "inprogress")
↓
5. Chat created for communication
↓
6. Seller delivers (state = "delivered")
↓
7. Customer approves (state = "completed")
↓
8. Payment released to seller
↓
9. Customer leaves comment/rating
Cancellation Flow
1. Order in "inprogress"
↓
2. Customer requests cancellation (state = "cancel_requested")
↓
3. Seller receives notification
↓
4a. Seller accepts cancel (state = "cancelled")
↓
Refund issued
OR
4b. Seller rejects cancel (state = "inprogress")
↓
Work continues
OR
4c. After 3 cancel requests (state = "disputing")
↓
Admin resolves
Correction Request Flow
1. Order state = "delivered"
↓
2. Customer requests corrections (state = "correction_requested")
↓
3. Seller makes corrections
↓
4. Seller redelivers (state = "delivered")
↓
5. Customer reviews again
Data Model
┌──────────────┐
│ Order │
├──────────────┤
│ id │
│ sellerId │────► User
│ customerId │────► User
│ serviceId │────► Service
│ paymentId │────► Payment
│ state │
│ totalAmount │
│ commission │
│ events[] │
└──────────────┘
│ 1:1
↓
┌──────────────┐
│ Chat │
├──────────────┤
│ id │
│ orderId │
│ ownerId │
└──────────────┘
│ 1:N
↓
┌──────────────┐
│ Message │
├──────────────┤
│ id │
│ chatId │
│ senderId │
│ content │
│ attachments[]│
└──────────────┘
┌──────────────┐
│ Comment │
├──────────────┤
│ id │
│ orderId │────► Order
│ serviceId │────► Service
│ userId │────► User
│ rating │
│ content │
│ replies[] │
└──────────────┘
┌──────────────┐
│ Payment │
├──────────────┤
│ id │
│ amount │
│ status │
│ userId │
└──────────────┘
Analytics
Order Metrics
- Completion rate – completed / total orders
- Average delivery time – Actual vs promised
- Cancellation rate – cancelled / total orders
- Dispute rate – disputes / total orders
- Late orders – Count of isLate() orders
Seller Metrics
- Total orders – As seller
- Completion rate – completed / accepted
- Average rating – From comments
- Response time – Time to accept/reject orders
Customer Metrics
- Total orders – As customer
- Review count – Comments left
- Cancellation requests – Total cancel requests made
Best Practices
✅ Do
- Capture service data – Store title, price, delivery time at order creation
- Record all events – Maintain audit trail
- Use state machine – Enforce valid transitions
- Notify participants – Alert on state changes
- Check authorization – Verify user role before transitions
- Handle disputes fairly – Admin review for escalations
❌ Don't
- Don't modify service data – Order is snapshot at purchase time
- Don't allow invalid transitions – Use state machine guards
- Don't skip refunds – Always issue refunds for cancellations/rejections
- Don't allow late deliveries without consequences – Track and report
- Don't delete orders – Maintain history for accountability
- Don't bypass dispute resolution – Let admin handle escalations
Validation Rules
State Transitions
- Only seller can accept/reject orders
- Only seller can deliver work
- Only customer can approve/request corrections
- Only admin can resolve disputes
- Guards check user role before allowing transition
Comment Creation
- Can only comment on completed orders
- One comment per order
- Rating must be 1-5 stars
- Content: 10-1000 characters
Message Creation
- Must be chat member to send message
- Content required
- Attachments: max 5MB each
Summary
The Orders domain provides:
- Complex order workflow with state machine
- Real-time chat for customer-seller communication
- Review system for service quality feedback
- Payment tracking from capture to release
- Dispute resolution for problematic orders
- Audit trail of all order events
This domain orchestrates the entire service fulfillment process from purchase through completion or cancellation.