Order
Source: src/data/order/
Service
createOrderService / OrderService
Factory: createOrderService(orderRepository: OrderRepository, discountService: OrderDiscountService) — returns OrderService.
Creates order service with discount-aware deterministic pricing.
| Method | Parameters | Returns | Description |
|---|---|---|---|
| create | (ctx: RequestContext, input: OrderCreateInput) | Promise<OrderRecord> | Creates an order with deterministic pricing and idempotent replay behavior; evaluates and consumes discount if provided |
| getById | (ctx: RequestContext, id: string) | Promise<OrderRecord | null> | Returns an order by id for the current tenant |
| update | (ctx: RequestContext, id: string, patch: OrderPatchInput) | Promise<OrderRecord> | Patches an existing order |
| remove | (ctx: RequestContext, id: string) | Promise<void> | Deletes an order by id |
| listByTenant | (ctx: RequestContext) | Promise<OrderRecord[]> | Lists tenant orders |
| listOpenOrders | (ctx: RequestContext, filters: ListOpenOrdersInput) | Promise<OpenOrderListResult> | Returns paginated open orders for the dashboard. Fails closed if tenantId is empty. |
| getOpenOrderSummary | (ctx: RequestContext) | Promise<OpenOrderSummary> | Returns per-status open-order counts. Fails closed if tenantId is empty. |
createDiscordOrderFlowServiceWithDeps / DiscordOrderFlowService
Factory: createDiscordOrderFlowServiceWithDeps(deps) — returns DiscordOrderFlowService.
File: order-flow.service.ts
Creates tenant-aware Discord order flow orchestration across session, order, payment, inventory, discount, notification, and event-bus domains.
Dependencies:
orderSessionService: OrderSessionServiceorderService: OrderServicepaymentService: PaymentServiceinventoryService: InventoryServicebotConfigService: Pick<BotConfigService, 'resolvePaymentInstruction' | 'listShippingTypes'>adminNotificationService: AdminNotificationServicediscountService?: Pick<DiscountService, 'resolveBestForCustomer' | 'consumeAssignmentUsage'>customerService?: Pick<CustomerService, 'findByDiscordId' | 'addAddress'>eventBus?: Pick<EventBus, 'emit'>— when present, the flow emitsorder.createdso the notifications consumer can post the admin approval embed and DM the customer.
| Method | Parameters | Returns | Description |
|---|---|---|---|
| beginSession | (ctx, { discordUserId, guildId? }) | Promise<{ state: string }> | Creates or restores an active order capture session. |
| getActiveSession | (ctx, discordUserId) | Promise<OrderSessionRecord | null> | Returns the active session for a Discord user. |
| selectProduct | (ctx, { discordUserId, productId }) | Promise<{ state: string }> | Records the chosen product (pre-quantity). |
| addItem | (ctx, { discordUserId, item }) | Promise<{ state, itemCount }> | Adds an item (with quantity) and advances state. |
| setShipping | (ctx, { discordUserId, shippingAddress }) | Promise<{ state: string }> | Stores the shipping address and advances to shipping-type selection. |
| proposeCorrectedAddress | (ctx, { discordUserId, correctedAddress }) | Promise<{ state: string }> | Stores a validator-corrected suggestion awaiting customer choice. |
| acceptCorrectedAddress | (ctx, { discordUserId }) | Promise<{ state: string }> | Customer accepted the corrected address. |
| keepOriginalAddress | (ctx, { discordUserId }) | Promise<{ state: string }> | Customer kept their original address. |
| setShippingType | (ctx, { discordUserId, shippingType }) | Promise<{ state: string }> | Stores shipping carrier/type and cost; advances to payment selection. |
| setPaymentMethod | (ctx, { discordUserId, paymentMethod }) | Promise<{ state, paymentMethod }> | Stores payment method and advances to AWAITING_CONFIRMATION. |
| cancelSession | (ctx, { discordUserId }) | Promise<void> | Cancels the active session. |
| submit | (ctx, { discordUserId }) | Promise<OrderFlowSummary> | Resolves best discount, creates order + payment record, calls paymentService.submitForApproval, reserves inventory, emits order.created. Idempotent on replay. |
| confirmPayment | (ctx, { orderId, confirmedBy }) | Promise<void> | Confirms payment and finalizes the sale. |
| handlePaymentRejected | (ctx, { orderId, reason? }) | Promise<void> | Releases inventory reservations and transitions order to CANCELLED. Idempotent. |
OrderFlowSummary
Shape returned by submit:
| Field | Type | Description |
|---|---|---|
orderId | string | Created order id. |
orderNumber | string | Tenant-facing order number. |
paymentId | string | Pending payment id. |
paymentMethod | PaymentMethod | Payment method selected. |
paymentInstructions | string | Per-method instructions from bot config. |
subtotalCents | number | Pre-discount item total. |
shippingCostCents | number | Selected shipping-type cost. |
discountAmountCents | number | Amount discounted from subtotal. |
taxAmountCents | number | Sales tax in cents; 0 when TaxJar is not configured or no shipping address. |
totalCents | number | Final total: (subtotal − discount) + shipping + tax. |
currency | string | Order currency. |
referenceCode | string | Short reference shown to the customer. |
registerOrderPaymentConsumers
File: order.consumers.ts
Registers payment.rejected on the event bus. When an admin rejects a payment, the consumer calls orderFlow.handlePaymentRejected to release inventory and transition the order to CANCELLED. Wired by src/registries/events.registry.ts.
Repository
OrderRepository
| Method | Parameters | Returns |
|---|---|---|
| getById | (ctx: RequestContext, id: string) | Promise<OrderRecord | null> |
| findByOrderNumber | (ctx: RequestContext, orderNumber: string) | Promise<OrderRecord | null> |
| listByTenant | (ctx: RequestContext) | Promise<OrderRecord[]> |
| create | (ctx: RequestContext, input: Omit<OrderRecord, 'createdAt' | 'updatedAt'>) | Promise<OrderRecord> |
| update | (ctx: RequestContext, id: string, patch: OrderPatchInput) | Promise<OrderRecord> |
| delete | (ctx: RequestContext, id: string) | Promise<void> |
| listByCustomerId | (ctx: RequestContext, customerId: string) | Promise<OrderRecord[]> |
| reassignCustomer | (ctx: RequestContext, fromCustomerId: string, toCustomerId: string) | Promise<number> |
Validators
orderStatusSchema
Enum: PENDING_PAYMENT, PAID, FULFILLING, SHIPPED, COMPLETE, CANCELLED, REFUNDED, PARTIALLY_REFUNDED
PARTIALLY_REFUNDED is a closed status (excluded from the Open Orders dashboard). It is set when one or more partial refunds have been applied but the cumulative refunded amount has not yet reached the order total. When the cumulative total reaches the order amount, the status transitions to REFUNDED.
orderItemSchema
| Field | Type | Required | Default |
|---|---|---|---|
| productId | string | Yes | — |
| name | string | Yes | — |
| sku | string | Yes | — |
| quantity | number (int, positive) | Yes | — |
| unitPriceCents | number (int, ≥ 0) | Yes | — |
| currency | currencySchema | Yes | — |
orderCustomerSchema
| Field | Type | Required | Default |
|---|---|---|---|
| name | string | Yes | — |
string (email) | No | — | |
| discordId | string | No | — |
orderSchema
| Field | Type | Required | Default |
|---|---|---|---|
| tenantId | string | Yes | — |
| orderNumber | string | Yes | — |
| status | orderStatusSchema | Yes | — |
| items | orderItemSchema[] (min 1) | Yes | — |
| subtotalCents | number (int, ≥ 0) | Yes | — |
| totalCents | number (int, ≥ 0) | Yes | — |
| discountId | string | No | — |
| discountCode | string | No | — |
| discountAmountCents | number (int, ≥ 0) | No | 0 |
| currency | currencySchema | Yes | — |
| customer | orderCustomerSchema | Yes | — |
| customerId | string | No | — |
| customerRoleIds | string[] | No | [] |
| shippingAddress | addressSchema | No | — |
| shippingStatus | enum('PENDING', 'LABEL_CREATED', 'SHIPPED', 'DELIVERED', 'FAILED') | No | 'PENDING' |
| shipmentId | string | No | — |
| trackingNumber | string | No | — |
| notes | string | No | — |
| createdAt | Date (coerced) | Yes | — |
| updatedAt | Date (coerced) | Yes | — |
orderCreateInputSchema
Omits tenantId, subtotalCents, totalCents, discountId, discountAmountCents from base. status and shippingStatus are optional. Adds optional discountCode.
orderPatchInputSchema
All fields from base except tenantId and orderNumber, made partial.
Inferred Types
Order—z.infer<typeof orderSchema>OrderCreateInput—z.infer<typeof orderCreateInputSchema>OrderPatchInput—z.infer<typeof orderPatchInputSchema>OrderItem—z.infer<typeof orderItemSchema>OrderStatus—z.infer<typeof orderStatusSchema>