Sale Service
@nx/sale sở hữu vòng đời cart-and-order: một SaleOrder đảm nhận cả hai vai trò (DRAFT cart + đơn hàng đã commit). Nó nhận webhook MQ-Pay cho sự kiện thanh toán, điều phối luồng kitchen ticket, quản lý allocation và reservation cho dining, đồng thời phát Kafka topic + WebSocket event tới inventory, finance và các UI hạ nguồn.
1. Tham chiếu nhanh
| Thuộc tính | Giá trị |
|---|---|
| Package | @nx/sale |
| Code | SVC-00030-SALE |
| Loại | Microservice |
| Runtime | Bun |
| Base Class | VerifierApplication |
| Vị trí | packages/sale |
| Base Path | /v1/api/sale |
| Dev Port | 31030 |
| Container Port | 3000 (external 31030) |
| Snowflake ID | 3 |
| DB Schema | sale (đa bảng — xem Domain Model) |
| Binding Namespace | @nx/sale |
2. Mục đích & Phạm vi
| Bao gồm | Loại trừ |
|---|---|
Một entity SaleOrder cho cart + order (DRAFT → … → COMPLETED / CANCELLED) | Mutation tồn kho (ủy quyền cho @nx/inventory) |
Item modes: PRODUCT (auto-merge) và CUSTOM (luôn tạo dòng mới) | Tích hợp nhà cung cấp thanh toán (ủy quyền cho @nx/mq-pay) |
Định giá checkout qua HTTP call tới @nx/pricing | Engine tính thuế |
| Xử lý webhook thanh toán (MQ-Pay HTTP webhook) | In hóa đơn (mối quan tâm frontend) |
Tách bill: SaleCheck (nhóm thanh toán độc lập) | Engine loyalty rewards |
| Gộp / tách order (có thể đảo ngược) | Menu hướng khách hàng |
| Vòng đời kitchen ticket (FOH/BOH) — void, rush, ready, served | Dữ liệu recipe / BOM (thuộc @nx/inventory) |
| Sử dụng allocation (DINE_IN tables, zones, units) | |
| Reservation (đặt trước rồi đến) | |
| Quản lý ca / phiên POS | |
| Cộng điểm khách hàng (loyalty) khi thanh toán thành công | |
| Báo cáo bán hàng (tổng hợp ngày, theo product/category, purchase summary) | |
| Sự kiện WebSocket realtime (multi-room fanout) |
3. Tech Stack
External:
| Library | Mục đích |
|---|---|
@venizia/ignis | IoC container, DI, BaseService, BaseController, ControllerFactory |
@venizia/ignis-helpers | Logger, KafkaProducerHelper, Redis helper |
@platformatic/kafka | Kafka client (sale chỉ dùng producer với mặc định của helper — không cấu hình idempotent/lz4 tường minh) |
hono | HTTP server (qua IGNIS) |
@hono/zod-openapi | Sinh OpenAPI từ Zod schema |
@scalar/hono-api-reference | OpenAPI explorer tại /doc |
drizzle-orm | Truy cập DB qua PostgresCoreDataSource |
pg | PostgreSQL driver |
lodash | Tiện ích |
Internal:
| Package | Mục đích |
|---|---|
@nx/core | Schema, repository (re-export), VerifierApplication, KafkaTopics, SaleOrderStatuses, SaleOrderItemModes, SaleConstraints |
@nx/pricing | Chỉ HTTP — PricingNetworkService gọi pricing service để lấy giá động lúc checkout |
4. Cấu trúc Dự án
packages/sale/
├── src/
│ ├── application.ts # VerifierApplication subclass
│ ├── index.ts # bootstrapApplication()
│ ├── migrate.ts # bootstrapMigration()
│ ├── common/
│ │ ├── constants.ts # SaleConstraints, ApplicationRoles
│ │ ├── keys.ts # BindingKeys
│ │ ├── rest-paths.ts # 13 RestPaths
│ │ ├── webhook-types.ts # PaymentWebhookEventTypes + zod schemas
│ │ ├── websocket.ts # 7 WebSocket topics + room helpers
│ │ ├── sale-check.constants.ts # check splitting helpers
│ │ ├── shift.types.ts # shift session types
│ │ └── response.helper.ts # response shaping
│ ├── components/
│ │ ├── kafka/ # ApplicationKafkaComponent (chỉ producer)
│ │ └── websocket/ # ApplicationWebSocketComponent
│ ├── controllers/ # 13 thư mục controller → 16 lớp controller được đăng ký
│ ├── datasources/ # PostgresCoreDataSource
│ ├── migrations/processes/ # 2 migration (permissions, pos-session-report)
│ ├── models/ # zod request/response schemas
│ ├── repositories/ # re-exports từ @nx/core
│ └── services/ # 20 services
├── package.json
└── tsconfig.json5. Kiến trúc
Chi tiết: xem Architecture.
6. Tổng quan miền
ERD đầy đủ + bảng theo entity: xem Domain Model.
7. Tóm tắt Bề mặt
REST controllers — tham chiếu đầy đủ render trực tiếp từ /v1/api/sale/doc/openapi.json (live spec — Scalar viewer tại /doc, gateway portal):
| Controller | Base path | Ghi chú |
|---|---|---|
SaleOrderController | /sale-orders | + lifecycle (draft, items, checkout, revert, cancel, merge, split) |
SaleOrderItemController | /sale-order-items | CRUD + override để validate quantity |
SaleCheckController | /sale-checks | + split, split-equal, merge, rollback |
SaleOrderCheckController | /sale-orders/:id/checks | nested dưới order |
KitchenStationController | /kitchen-stations | CRUD |
KitchenTicketController | /kitchen-tickets | CRUD |
KitchenTicketSaleOrderController | /sale-orders/:id/kitchen-tickets/... | sendToKitchen |
KitchenTicketActionController | /kitchen-tickets/:id/... | void / rush / mark-ready / mark-served |
KitchenTicketItemActionController | /kitchen-ticket-items/:id/... | start-cooking / mark-ready / mark-served / void |
AllocationUsageController | /allocation-usages | CRUD + batch complete/cancel |
ReservationController | /reservations | + create with allocation |
ShiftController | /pos/sessions | + open / close |
CustomerController | /customers | CRUD |
PointTransactionController | /point-transactions | CRUD (đa số là đọc) |
SalesReportController | /reports/sales | Tổng hợp ngày, theo product, theo category, purchase-summary |
PaymentWebhookController | /webhooks/payment | Tiếp nhận sự kiện MQ-Pay (no auth) |
Async surface — tham chiếu đầy đủ tại API Events:
| Hướng | Channel | Số lượng |
|---|---|---|
| Inbound | HTTP webhook | 1 endpoint × 6 loại sự kiện |
| Outbound | Kafka | 2 (PAYMENT_SUCCESS, KITCHEN_TICKET_ITEM_STATUS_CHANGED) |
| Outbound | WebSocket | 7 topic × nhiều room helpers (merchant/order/check/kitchen/allocation/reservation) |
8. Components
| Component | File | Mục đích |
|---|---|---|
ApplicationKafkaComponent | src/components/kafka/component.ts | Idempotent producer; phát PAYMENT_SUCCESS + KITCHEN_TICKET_ITEM_STATUS_CHANGED (không có consumer) |
ApplicationWebSocketComponent | src/components/websocket/component.ts | WebSocket emitter qua signal service; room fanout |
| Redis cache (tùy chọn) | bind tại BindingKeys.APPLICATION_REDIS_CACHE | Cache permission cho authorization |
9. Services
| Service | File | Mô tả ngắn |
|---|---|---|
SaleOrderService | sale.service.ts | CRUD đơn DRAFT, add/clear item, cancel, archive |
SaleOrderItemService | sale-order-item.service.ts | Cập nhật item theo lô với row-level lock + recalc summary |
CheckoutService | checkout.service.ts | DRAFT → PROCESSING; pricing v1+v2; revert |
SaleCheckService | sale-check.service.ts | Tách bill: split, split-equal, merge, rollback |
OrderMergeService | order-merge.service.ts | Gộp nhiều draft order; có thể đảo ngược |
OrderSplitService | order-split.service.ts | Tách một order thành nhiều; phân phối lại item + allocation + pricing |
KitchenTicketService | kitchen-ticket.service.ts | Send-to-kitchen, void, rush, mark ready/served |
KitchenTicketItemService | kitchen-ticket-item.service.ts | Chuyển trạng thái theo dòng + emit Kafka |
AllocationUsageService | allocation-usage.service.ts | DINE_IN/TAKEAWAY/DELIVERY; reserved → completed/cancelled |
ReservationService | reservation.service.ts | Luồng booking với reserve allocation |
ShiftService | shift.service.ts | POS session: getCurrent, list, open, close, validate |
CustomerService | customer.service.ts | CRUD khách hàng |
CustomerPointService | customer-point.service.ts | Cộng điểm loyalty khi thanh toán thành công (idempotent) |
PaymentWebhookService | payment-webhook.service.ts | Dispatcher sự kiện webhook (route tới handler SaleOrder vs SaleCheck) |
SaleOrderPaymentWebhookService | sale-order-payment-webhook.service.ts | Xử lý sự kiện attempt + transaction cho SaleOrder; emit Kafka |
SaleCheckPaymentWebhookService | sale-check-payment-webhook.service.ts | Cùng luồng cho SaleCheck |
PricingNetworkService | pricing-network.service.ts | HTTP client gọi @nx/pricing cho calculate() + calculateV2() |
AllocationSnapshotService | allocation-snapshot.service.ts | Snapshot trạng thái allocation unit/zone trên sự kiện order để audit |
ProductVariantSnapshotService | product-variant-snapshot.service.ts | Snapshot metadata product variant lúc add order-item |
SalesReportService | sales-report.service.ts | Truy vấn tổng hợp daily / product / category / purchase |
10. Repositories
| Repository | Nguồn | Ghi chú |
|---|---|---|
SaleOrderRepository | @nx/core | + updateSummaryFromItems, getDailySummary, getProductSales, getCategorySales |
SaleOrderItemRepository | @nx/core | + updateAll, deleteAll |
SaleCheckRepository | @nx/core | + recalculateTotals |
SaleCheckItemRepository | @nx/core | + createAll |
KitchenTicketRepository | @nx/core | + findByIdempotencyKey, getNextSequence, evaluateTicketAutoProgression |
KitchenTicketItemRepository | @nx/core | + createAll |
KitchenStationRepository | @nx/core | — |
AllocationUsageRepository | @nx/core | + existsBySaleOrderId |
AllocationUnitRepository / AllocationZoneRepository | @nx/core | — |
ReservationRepository | @nx/core | — |
PosSessionRepository | @nx/core | + findOpenByDeviceId |
PosSessionReportRepository | @nx/core | — |
PointTransactionRepository | @nx/core | + existsBySaleOrderId |
CustomerRepository | @nx/core | — |
SaleChannelRepository | @nx/core | — |
ProductVariantRepository, ProductIdentifierRepository, ProductInfoRepository | @nx/core | Đọc liên package |
ConfigurationRepository | @nx/core | Đọc cấu hình thanh toán đã mã hóa |
FinanceTransactionRepository, FinanceWalletRepository | @nx/core | Đọc liên package cho metadata finance lúc checkout |
PurchaseOrderRepository | @nx/core | Đọc liên package cho báo cáo bán hàng |
MetaLinkRepository, SettingRepository, DeviceRepository | @nx/core | Liên package |
11. Điểm vào
| File | Mục đích |
|---|---|
src/index.ts | Service entry → bootstrapApplication() |
src/migrate.ts | Migration entry → bootstrapMigration() |
src/application.ts | Application extends VerifierApplication |
12. Cấu hình
Env vars + dữ liệu seed: xem Configuration.
13. Vận hành
Triển khai + observability + bảo mật + runbook: xem Operations.
14. Trang liên quan
Concepts — vì sao/cách thức:
- Architecture
- Domain Model
- Integration — webhook MQ-Pay + hợp đồng inventory/finance/commerce/identity
Reference — tra cứu:
- API Events
- Configuration
- Operations
- REST endpoints — live OpenAPI tại
/v1/api/sale/doc/openapi.json(live spec — Scalar viewer tại/doc, gateway portal)
Features — đào sâu:
- Sale Order
- Checkout
- Order Operations — merge / split
- Check Splitting
- Kitchen Orders
- Payment Webhooks
- Allocation Usage
- Reservation
- Shift / POS Session
- Sales Report
- Customer Points
Decisions: