Skip to content

Architecture

1. System Context (C4 L1)

2. Container View (C4 L2)

3. Component View (C4 L3) — Internal Layering

LayerResponsibility
Routes13 base paths in RestPaths
ControllersAuth gate, permission, DTO mapping
ServicesBusiness logic, transactions, event emission
RepositoriesDrizzle queries, soft-delete, FOR UPDATE locks
ComponentsKafka producer, WebSocket emitter, Redis cache

4. State Machines Index

EntityStatesDiagram
SaleOrderDRAFT, PROCESSING, PARTIAL, COMPLETED, CANCELLED
SaleCheckPROCESSING, COMPLETED, CANCELLED
KitchenTicketPENDING, PROCESSING, READY, COMPLETED, VOIDED
KitchenTicketItemPENDING, COOKING, READY, SERVED, VOIDED
AllocationUsageACTIVE, SUCCESS, CANCELLED, EXPIRED
ReservationPENDING, CONFIRMED, CANCELLED, CHECKED_IN
PosSessionOPEN, CLOSED

SaleOrder

FromEventToTrigger
DRAFTcheckoutPROCESSINGCheckoutService.checkout
PROCESSINGrevertDRAFTCheckoutService.revertCheckout
PROCESSINGpayment success (partial)PARTIALMQ-Pay webhook → _handleOrderPaymentSuccess
PROCESSING / PARTIALpayment success (full)COMPLETEDsame
*cancel / fail / expireCANCELLEDwebhook handlers + manual cancel

SaleCheck

KitchenTicket

The ticket-level state machine is different from the item-level one — see Domain Model §4.3 for status mapping.

KitchenTicketItem

Each item status change emits Kafka KITCHEN_TICKET_ITEM_STATUS_CHANGED consumed by @nx/inventory.

AllocationUsage

Reservation

PosSession

5. Runtime Scenarios

5.1 Cart → Checkout → Payment → Stock Deduct

5.2 Add Item — Pessimistic Lock

Prevents duplicate-merge race when two devices add the same item simultaneously.

5.3 Send to Kitchen → Cook → Serve

5.4 Bill Split (SaleCheck)

6. Crosscutting Concerns

ConcernHow this service handles it
AuthNJWT (ES256, JWKS from identity); BASIC for service-to-service. Webhook endpoint has no auth (trusted internal).
AuthZCasbin via PolicyDefinitionService (cached in Redis)
i18njsonb { en, vi }; Accept-Language header
LoggingIGNIS structured (key: %s); request-id propagated
IdempotencyPer-saleOrderId for Kafka emit; per-saleOrderId on customer-point award; webhook handlers check existing transitions
Race protectionSELECT ... FOR UPDATE on add-item and bulk update flows
Soft-deleteSoftDeletableRepository (deletedAt)
IDsSnowflake via IdGenerator, worker 3
Dual modeApplicationRoles.API / WORKER in constants — for future API/worker split (currently single-process)

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.