ADR-0004. AllocationUsage(usageType, usageId) đa hình dùng chung bởi SaleOrder + Reservation
| Trường | Giá trị |
|---|---|
| Trạng thái | Accepted |
| Ngày | 2026-03-12 |
| Người quyết định | sale-team |
| Thay thế | — |
Bối cảnh
- Một bàn ăn (AllocationUnit) có thể bị chiếm dụng bởi một SaleOrder đang active (khách đang ăn) hoặc một Reservation (đặt chỗ tương lai).
- Cả hai đều cần: unit, time window, status (ACTIVE/SUCCESS/CANCELLED/EXPIRED), assignee.
- Hai bảng song song (
SaleOrderAllocation+ReservationAllocation) duplicate model và phá vỡ truy vấn dùng chung như "có gì trống lúc 7 giờ tối".
Quyết định
Một bảng AllocationUsage duy nhất với cột đa hình (usageType, usageId) được sinh qua generatePrincipalColumnDefs({ discriminator: 'usage' }):
usageType ∈ {SALE_ORDER, RESERVATION}usageIdtham chiếu id của parent- Cùng vòng đời, cùng rooms WebSocket, cùng cascade hủy
Khi một Reservation chuyển sang CHECKED_IN, sale spawn một SaleOrder và usageType của AllocationUsage được cập nhật thành SALE_ORDER + usageId thành id order mới (cùng row usage tiếp tục).
Hệ quả
| Ưu | Nhược |
|---|---|
| Mô hình occupancy duy nhất | Không có DB FK tới parent (đa hình) |
| Truy vấn "trống lúc 7 giờ tối" là một lần scan bảng | Lớp service phải validate usageId tồn tại |
| Cascade hủy đồng nhất | Casts/discriminants trong code service |
Fanout WebSocket qua getAllocationUsageRooms hoạt động cho cả hai | Type-safety dựa trên TS, không phải DB |
Phương án thay thế đã cân nhắc
| Phương án | Ưu | Nhược | Lý do từ chối |
|---|---|---|---|
| Bảng riêng cho mỗi loại usage | DB FK mạnh | Duplicate schema + queries + WS rooms | Đau đầu bảo trì |
AllocationUsage với cả saleOrderId + reservationId (nullable, XOR) | Một bảng, FK được giữ | XOR constraint phức tạp; truy vấn luôn lọc theo type | Pattern half-rejected |
Tham chiếu
core/src/models/schemas/allocation/allocation-usage/schema.tssale/src/services/allocation-usage.service.tssale/src/services/reservation.service.ts(tạo Reservation + AllocationUsage trong một TX)