Kiến trúc
1. System Context (C4 L1)
2. Container View (C4 L2)
3. Component View (C4 L3) — Phân lớp nội bộ
| Lớp | Trách nhiệm |
|---|---|
| Routes | 13 base path trong RestPaths |
| Controllers | Auth gate, permission, mapping DTO |
| Services | Business logic, transaction, phát sự kiện |
| Repositories | Drizzle queries, soft-delete, FOR UPDATE locks |
| Components | Kafka producer, WebSocket emitter, Redis cache |
4. Chỉ mục máy trạng thái
| Thực thể | Trạng thái | Sơ đồ |
|---|---|---|
SaleOrder | DRAFT, PROCESSING, PARTIAL, COMPLETED, CANCELLED | → |
SaleCheck | PROCESSING, COMPLETED, CANCELLED | → |
KitchenTicket | PENDING, PROCESSING, READY, COMPLETED, VOIDED | → |
KitchenTicketItem | PENDING, COOKING, READY, SERVED, VOIDED | → |
AllocationUsage | ACTIVE, SUCCESS, CANCELLED, EXPIRED | → |
Reservation | PENDING, CONFIRMED, CANCELLED, CHECKED_IN | → |
PosSession | OPEN, CLOSED | → |
SaleOrder
| Từ | Sự kiện | Đến | Trigger |
|---|---|---|---|
DRAFT | checkout | PROCESSING | CheckoutService.checkout |
PROCESSING | revert | DRAFT | CheckoutService.revertCheckout |
PROCESSING | payment success (partial) | PARTIAL | webhook MQ-Pay → _handleOrderPaymentSuccess |
PROCESSING / PARTIAL | payment success (full) | COMPLETED | tương tự |
* | cancel / fail / expire | CANCELLED | webhook handler + hủy thủ công |
SaleCheck
KitchenTicket
Máy trạng thái cấp ticket khác với cấp item — xem Mô hình miền §4.3 để biết ánh xạ trạng thái.
KitchenTicketItem
Mỗi lần đổi trạng thái item phát Kafka
KITCHEN_TICKET_ITEM_STATUS_CHANGEDđược tiêu thụ bởi@nx/inventory.
AllocationUsage
Reservation
PosSession
5. Kịch bản runtime
5.1 Cart → Checkout → Thanh toán → Trừ kho
5.2 Thêm item — Pessimistic Lock
Ngăn race duplicate-merge khi hai thiết bị thêm cùng một item cùng lúc.
5.3 Gửi xuống Bếp → Nấu → Phục vụ
5.4 Tách hóa đơn (SaleCheck)
6. Mối quan tâm xuyên suốt
| Mối quan tâm | Service này xử lý ra sao |
|---|---|
| AuthN | JWT (ES256, JWKS từ identity); BASIC cho service-to-service. Endpoint webhook không có auth (tin cậy nội bộ). |
| AuthZ | Casbin qua PolicyDefinitionService (cache trong Redis) |
| i18n | jsonb { en, vi }; header Accept-Language |
| Logging | IGNIS có cấu trúc (key: %s); request-id được lan truyền |
| Idempotency | Per-saleOrderId cho Kafka emit; per-saleOrderId khi cộng điểm khách hàng; webhook handler kiểm tra transition đã có |
| Bảo vệ race | SELECT ... FOR UPDATE trên flow add-item và bulk update |
| Soft-delete | SoftDeletableRepository (deletedAt) |
| IDs | Snowflake qua IdGenerator, worker 3 |
| Dual mode | ApplicationRoles.API / WORKER trong constants — cho việc tách API/worker tương lai (hiện tại là single-process) |