Skip to content

Mô hình miền

Bảng sale nằm trong schema PostgreSQL sale; bảng allocation trong schema allocation. Tất cả schema định nghĩa trong @nx/core/src/models/schemas/{sale,allocation}/. Cột số dùng decimal(15, 4).

1. ERD đầy đủ

2. Cột chung

CộtKiểuGhi chú
idtextPK, Snowflake
createdAt / modifiedAttimestamptz
createdBy / modifiedBytextAudit user
deletedAttimestamptzSoft-delete
metadatajsonbTúi mở rộng

3. Thực thể

3.1 SaleOrder

Thuộc tínhGiá trị
BảngSaleOrder
Nguồncore/src/models/schemas/sale/sale-order/schema.ts
Soft-delete
TrườngKiểuBắt buộcMô tả
orderNumbertextUnique partial per merchant
name / slugtextSlug unique partial
validityjsonb{ from, to } cho order giới hạn thời gian
statustextXem §4.1; mặc định DRAFT
draftAt / processingAt / partialAt / completedAt / cancelledAttimestamptzTimestamp theo trạng thái
cancellationReasontext
customerIdtextFK
merchantIdtextOwner
saleChannelIdtextFK
openedInSessionId / closedInSessionIdtextFK đến PosSession
currencytextMặc định VND
exchangeRatedecimal(12,6)Mặc định 1
subtotal / tax / discount / totaldecimal(15,4)Mặc định 0; duy trì bởi updateSummaryFromItems
originOrderIdtextTheo dõi parent của order-split
checkSplitAt / orderSplitAt / mergedAttimestamptzTimestamp thao tác
counterjsonb{ paid, paidItemIds[], total } — tiến trình thanh toán

3.2 SaleOrderItem

Thuộc tínhGiá trị
BảngSaleOrderItem
Polymorphic(itemType, itemId) qua generatePrincipalColumnDefs({ discriminator: 'item', defaultPolymorphic: 'ProductVariant' })
TrườngKiểuBắt buộcMô tả
saleOrderIdtextFK
itemTypetextPRODUCT_VARIANT (mặc định) / khác
itemIdtextFK target
modetextPRODUCT (mặc định — auto-merge duplicate) / CUSTOM (luôn dòng mới)
leadItemIdtextGroup lead cho combo items
currencytextMặc định VND
basePrice / unitPricedecimal(15,4)Trước/sau discount per đơn vị
discount / taxdecimal(15,4)Mặc định 0
quantitydecimal(15,4)Mặc định 1
totaldecimal(15,4)Tính toán
fareId / fareProvidertextTham chiếu nguồn pricing
priceMetadatajsonbSnapshot pricing (chi tiết v2)
transferHistoryjsonbArray<TTransferHistoryEntry> — theo dõi merge/split
recipeIdtextLiên kết MaterialRecipe.id đang active (snapshot)

3.3 SaleCheck / SaleCheckItem

SaleCheck:

TrườngKiểuBắt buộcMô tả
saleOrderIdtextOrder parent
statustextPROCESSING (mặc định) / COMPLETED / CANCELLED
subtotal / tax / discount / totaldecimal(15,4)Tính lại bởi recalculateTotals
customerIdtextKhách per-check (khác khách của order)

SaleCheckItem: saleCheckId, saleOrderItemId, quantity, subtotal/tax/discount/total.

3.4 KitchenStation / KitchenTicket / KitchenTicketItem

KitchenStation: merchantId, name (i18n), status (mặc định ACTIVATED).

KitchenTicket:

TrườngKiểuBắt buộcMô tả
ticketNumbertextUnique partial; tuần tự per station
saleOrderIdtextFK
merchantIdtextOwner
kitchenStationIdtextMục tiêu định tuyến (tùy chọn)
statustextXem §4.3; mặc định PENDING
priorityintMặc định 0 (cờ rush làm tăng priority)
sequenceintMặc định 1 (gợi ý thứ tự)
pendingAt / processingAt / readyAt / completedAt / voidedAttimestamptzTimestamp trạng thái

KitchenTicketItem:

TrườngKiểuBắt buộcMô tả
kitchenTicketIdtextFK
saleOrderItemIdtextFK
quantitydecimal(15,4)Mặc định 1
statustextXem §4.4; mặc định PENDING
startedAt / readyAt / servedAt / voidedAttimestamptzTimestamp trạng thái

Mỗi lần đổi trạng thái phát Kafka KITCHEN_TICKET_ITEM_STATUS_CHANGED và kích hoạt đánh giá auto-progression của ticket.

3.5 AllocationUsage / AllocationUnit / AllocationZone / AllocationLayout

Schema nằm trong schema allocation (tách khỏi sale).

AllocationUsage — sử dụng đa hình của một allocation unit:

TrườngKiểuBắt buộcMô tả
usageTypetextSALE_ORDER / RESERVATION (qua discriminator: 'usage')
usageIdtextId FK target
unitIdtextFK đến AllocationUnit
merchantIdtextOwner
assigneeIdtextNgười/staff được gán
statustextACTIVE (mặc định) / SUCCESS / CANCELLED / EXPIRED
typetextGENERAL (mặc định) / DINE_IN / TAKEAWAY / DELIVERY
reservedFrom / reservedTo / reservedAt / startedAt / completedAttimestamptzTimestamp vòng đời

AllocationUnit — đơn vị vật lý (bàn, ghế, tủ):

  • name (i18n), zoneId (notNull), placement (jsonb vị trí), style (jsonb), capacity (int), status.

AllocationZone — section / floor / area:

  • name (i18n), layoutId (notNull), style (jsonb), parentId (cấp bậc tự tham chiếu), status.

AllocationLayout — container floor plan cấp cao nhất.

3.6 Reservation

TrườngKiểuBắt buộcMô tả
merchantIdtextOwner
guestNametext
guestPhonetext
guestEmailtext
partySizeint
reservedFromtimestamptz
reservedTotimestamptz
notestext
sourcetextMặc định PHONE; WEB / WALK_IN / APP
occasiontextSinh nhật / kỷ niệm / v.v.
statustextPENDING (mặc định) / CONFIRMED / CHECKED_IN / CANCELLED
confirmedAt / checkedInAt / cancelledAttimestamptz
cancellationReasontext
saleOrderIdtextFK sau check-in

3.7 PosSession / PosSessionReport

PosSession:

TrườngKiểuBắt buộcMô tả
merchantIdtextOwner
saleChannelIdtextFK
deviceIdtextFK
openedByIdtextUser
closedByIdtext
statustextOPEN (mặc định) / CLOSED
openedAt / closedAttimestamptz
openingFloatdecimal(15,4)Mặc định 0
expectedCash / actualCash / cashDiscrepancydecimal(15,4)Đối chiếu
expectedNonCash / actualNonCashjsonbTPosSessionNonCashBreakdown
closeRecountCountintMặc định 0; theo dõi số lần đếm lại
notestext

PosSessionReport: snapshot metric của session khi đóng (sales, refunds, cash flow).

3.8 Customer

TrườngKiểuBắt buộcMô tả
nametext
phonetext
emailtext
userIdtextTài khoản user được liên kết (tùy chọn)
merchantIdtextOwner
pointBalancedecimal(15,4)Mặc định 0

3.9 PointTransaction

TrườngKiểuBắt buộcMô tả
customerIdtextFK
merchantIdtextOwner
saleOrderIdtextOrder nguồn
typetextAWARD / REDEEM / ADJUST (theo PointTransactionTypes)
pointsdecimal(15,4)Delta có dấu
conversionRatedecimal(15,4)Snapshot points-per-currency tại lúc award

Idempotency: PointTransactionRepository.existsBySaleOrderId chặn award duplicate.

4. Status Enums

4.1 SaleOrderStatuses

Giá trịGiai đoạn
DRAFTCart / item có thể đổi
PROCESSINGCheckout xong, chờ thanh toán
PARTIALĐã nhận một phần thanh toán
COMPLETEDĐã thanh toán đủ
CANCELLEDTerminal

4.2 SaleCheckStatuses

Giá trịGiai đoạn
PROCESSINGMặc định — chấp nhận thanh toán
PARTIALĐã nhận một phần thanh toán
COMPLETEDĐã thanh toán đủ
CANCELLEDTerminal

4.3 KitchenTicketStatuses

Nguồn: core/src/models/schemas/sale/kitchen-ticket/constants.ts. Ticket ở lớp khác với các item — chúng có bộ status khác nhau.

Giá trịCodeGiai đoạn
PENDING103_PENDINGVừa gửi xuống bếp, chưa item nào COOKING
PROCESSING203_PROCESSINGÍt nhất một item đang COOKING (auto-progress từ PENDING)
READY302_SUCCESSTất cả item READY-trở-đi (auto)
COMPLETED303_COMPLETEDTất cả item terminal, ≥1 SERVED (auto)
VOIDED505_CANCELLEDVoid thủ công

Helper guards: canVoid (bất kỳ active), canProgress (chỉ PENDING), canMarkReady (chỉ PROCESSING), canComplete (chỉ READY).

4.4 KitchenTicketItemStatuses

Nguồn: core/src/models/schemas/sale/kitchen-ticket-item/constants.ts. Bộ khác với enum cấp ticket.

Giá trịCodeTrigger
PENDING103_PENDINGKhởi tạo
COOKING203_PROCESSINGstartCookingItem
READY302_SUCCESSmarkItemReady — phát Kafka KITCHEN_TICKET_ITEM_STATUS_CHANGED
SERVED303_COMPLETEDmarkItemServed
VOIDED505_CANCELLEDvoidTicketItem

4.5 AllocationUsageStatuses

Giá trịGiai đoạn
ACTIVEĐặt/đang chiếm dụng
SUCCESSOrder đã thanh toán → usage đóng
CANCELLEDOrder/reservation đã hủy
EXPIREDReservation timeout

4.6 ReservationStatuses

Giá trịGiai đoạn
PENDINGĐã tạo, chờ xác nhận
CONFIRMEDHost đã xác nhận
CHECKED_INKhách đã đến; spawn SaleOrder
CANCELLEDTerminal

4.7 PosSessionStatuses

Giá trịGiai đoạn
OPENCa đang active
CLOSEDĐã đối chiếu và đóng

5. Bất biến liên thực thể

Bất biếnÁp đặt
SaleOrder.subtotal/tax/discount/total = Σ(items)Service updateSummaryFromItems sau mỗi lần thay đổi item
Nhiều nhất một OPEN PosSession per (merchantId, deviceId)Service validateAndAttachSession
Tổng SaleCheck = Σ(SaleCheckItem) cho dòng của nóSaleCheckRepository.recalculateTotals
KitchenTicket auto-progress qua PENDING→COOKING→READY→SERVED dựa trên status itemKitchenTicketRepository.evaluateTicketAutoProgression sau mỗi lần đổi status item
KitchenTicket.ticketNumber unique partial per kitchen station (sequence reset khi đổi station)Schema partial unique + getNextSequence
PointTransaction idempotent per (customerId, saleOrderId)Lookup existsBySaleOrderId trước khi ghi
AllocationUsage theo vòng đời order/reservation (cascade hủy)Cấp service trên cancelOrder / hủy
Thao tác merge / split order bảo toàn tổng itemTransaction cấp service; audit transferHistory

6. Hành vi Soft-delete

Thực thểSoft-deleteGhi chú
Tất cả thực thể saleMarker deletedAt; archive cho SaleOrder = soft-delete
KitchenTicket voidedAtlogicalvoidedAt không phải soft-delete; ticket vẫn truy vấn được

7. Trang liên quan

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