Skip to content

PRD: Đơn mua hàng

ModuleKho (CORE-06)PRD IDPRD-PO-001
StatusShippedOwnerInventory squad
Date2026-02-24Versionv1.0
Packages@nx/inventory · @nx/core · @nx/finance · apps/clientURDPO · POI

TL;DR

Cho phép một merchant ghi nhận những gì họ mua từ một vendor dưới dạng đơn mua hàng (PO), đưa nó qua một vòng đời rõ ràng, và nhận hàng vào tồn với một audit trail có thể kiểm chứng. Việc nhận hàng làm tăng tồn tại một địa điểm, ghi các bản ghi biến động bất biến, và có thể ghi một finance transaction để một lần mua hiện lên trong sổ sách. Kết quả: mọi lần tăng tồn đều được gắn lại với một vendor, một đơn giá, và phân tách discount/thuế - không còn các lần nhập tồn tùy tiện, không truy vết được.

1. Context & Problem

Các merchant nhập hàng bằng cách mua hàng từ vendor, và số hàng đó phải vào tồn với một dấu vết giấy tờ mà chủ có thể audit. Không có tài liệu đơn mua hàng, tồn chỉ có thể được di chuyển qua các phiếu tùy tiện: một lần tăng tồn không thể gắn lại với một vendor, một đơn giá, hay phân tách discount/thuế, và không có trạng thái được kiểm soát nào giữa "đã đặt" và "đã nhận". Điều này khiến việc theo dõi chi phí, đối soát vendor, và báo cáo thuế trở nên không tin cậy - một rào cản lớn cho mảng kế toán HKD/SME mà KICKO nhắm đến.

Increment này xây luồng PO trên nền danh mục vendor sẵn có cùng các primitive tồn/theo dõi của kho, và kết nối việc nhận hàng với lớp finance.

2. Goals & Non-Goals

Goals

  • Một tài liệu PO thuộc về một vendor, được tạo trong một thao tác duy nhất (vendor + các dòng mục; vendor bắt buộc).
  • Một vòng đời được kiểm soát với việc sửa dòng chỉ cho phép khi còn nháp.
  • Nhận hàng làm tăng tồn và ghi các bản ghi biến động bất biến, hỗ trợ nhận đầy đủ và nhận tăng dần.
  • Tổng theo dòng và theo PO chính xác với discount/thuế phân biệt rõ thủ công và hệ thống.
  • Liên kết finance: một PO đã nhận có thể ghi một finance transaction kèm một payment tùy chọn.

Non-Goals

  • Nhập tồn đầu kỳ / nhập tồn di trú - thuộc về Nhập tồn đầu kỳ.
  • Định giá tồn đa tiền tệ.
  • Một cổng gửi-cho-vendor / phê duyệt bên ngoài.

3. Success Metrics

MetricMục tiêu / tín hiệu
Truy vết100% lần nhập tồn từ vendor đi qua một PO (không phải phiếu tùy tiện)
Độ chính xác nhận hàngTồn on-hand sau khi nhận = số lượng đã đặt/đã nhận; không có dòng tồn nào không có bản ghi biến động khớp
Độ phủ financeSố PO đã nhận có ghi một finance transaction (khi có chi phí được ghi nhận)
Cycle timeThời gian trung vị DRAFT → RECEIVED theo từng merchant có xu hướng giảm

4. Personas & Use Cases

PersonaMục tiêu trong tính năng này
ChủKiểm soát việc mua hàng, xem chi phí & lịch sử vendor, đối soát với finance
Nhân viên khoTạo PO, sửa dòng, nhận hàng vào đúng địa điểm
Kế toán (qua Finance)Xem các lần mua được ghi dưới dạng finance transaction

Các kịch bản cốt lõi: tạo một PO cho một vendor → điều chỉnh dòng khi còn nháp → chuyển sang processing → nhận hàng (đầy đủ hoặc một phần) → tồn tăng kèm audit trail và một lần ghi finance tùy chọn → đóng PO.

5. User Stories

  • nhân viên kho, tôi muốn tạo một PO với một vendor cùng các dòng mục trong một bước, để đơn được gắn với một nhà cung cấp và một mức giá.
  • nhân viên kho, tôi muốn sửa các dòng PO khi PO ở trạng thái DRAFT, để tôi có thể chỉnh số lượng và giá trước khi chốt.
  • nhân viên kho, tôi muốn nhận hàng theo một PO, để tồn tăng tại địa điểm đã chọn kèm một bản ghi biến động.
  • nhân viên kho, tôi muốn nhận tăng dần hoặc thay thế một số lượng đã nhận, để các đợt giao hàng một phần được xử lý đúng.
  • Là một chủ, tôi muốn một PO đã nhận ghi một finance transaction (tùy chọn kèm một payment), để các lần mua phản ánh trong sổ sách.
  • Là một chủ, tôi muốn hủy một PO chưa ở trạng thái kết thúc, để các đơn nhầm không làm bẩn tồn hay finance.

6. Functional Requirements

#Yêu cầuURD ref
FR-1Tạo một PO thuộc về một vendor (vendor bắt buộc) với các dòng mục trong một aggregate operationURD-PO-001..003
FR-2Vòng đời DRAFT → PROCESSING → RECEIVED → COMPLETED → CLOSED; hủy từ bất kỳ trạng thái chưa kết thúc nào; revert PROCESSING → DRAFTURD-PO-004..006
FR-3Dòng mục chỉ sửa được trong DRAFT; aggregate create/edit (PO + dòng) trong một lời gọi duy nhấtURD-PO-007 · URD-POI-001
FR-4Nhận hàng tăng tồn tại địa điểm và ghi các bản ghi biến động bất biếnURD-PO-008..009
FR-5Hai chế độ nhận: OVERRIDE (thay thế số lượng đã nhận) và ACCUMULATIVE (cộng dồn vào số lượng đã nhận)URD-PO-010
FR-6Tổng mỗi dòng = price × qty × multiplier + tax − discount; các dòng gộp theo (itemType, itemId, uom); một dòng về 0 sẽ bị soft-deleteURD-POI-002..004
FR-7Tổng PO = subtotal − discount + tax; discount/thuế chấp nhận ghi đè thủ công, được đánh dấu thủ công-vs-hệ thốngURD-PO-011
FR-8inventoryLocationId tùy chọn; mặc định về địa điểm mặc định của merchantURD-POI-005
FR-9Một PO đã nhận có thể ghi một finance transaction kèm một payment tùy chọn và một finance category mặc địnhURD-PO-012
FR-10Một số PO duy nhất được gán theo từng merchantURD-PO-002

Toàn văn yêu cầu và tiêu chí chấp nhận nằm trong Inventory URD. PRD này tham chiếu chúng thay vì lặp lại.

7. Non-Functional Requirements

Lĩnh vựcYêu cầu
Toàn vẹn dữ liệuViệc tăng tồn và bản ghi biến động của nó được ghi cùng nhau - không có thay đổi tồn nào mà không có một mục audit bất biến khớp
Bất biếnBản ghi biến động chỉ-thêm; việc sửa lỗi diễn ra qua các mục mới, không bao giờ sửa
Tenancy & authzMọi thao tác được scope theo từng merchant (x-merchant-id); được kiểm soát bởi inventory permission
Độ chính xácPhép toán tiền/số lượng dùng float(value, 4)
Nhất quánAggregate create/edit và nhận hàng là transactional; lỗi một phần không để lại PO ghi dở
i18nNhãn/trạng thái hiển thị cho người dùng là song ngữ ({ en, vi })

8. UX & Flows

Các màn hình chính (trong apps/client): danh sách PO, tạo PO, sửa PO, control luồng trạng thái, và một xác nhận hủy đơn.

9. Data & Domain

EntityVai trò
PurchaseOrderTài liệu đơn - vendor, status, các tổng, địa điểm, relation financeTransaction tùy chọn
PurchaseOrderItemMột dòng - tham chiếu mục (itemType, itemId, uom), qty, price, multiplier, tax, discount, tổng dòng
PO configThiết lập PO theo từng merchant, seed lúc khởi động
Bản ghi biến độngMục biến động tồn (tracking) bất biến được ghi khi nhận hàng

Chỉ ở mức khái niệm - toàn bộ schema và bất biến nằm trong inventory domain model.

10. Dependencies & Assumptions

Phụ thuộc vào

  • Vendors (URD-VEN) - một PO cần một vendor sẵn có.
  • Mức tồn & audit biến động (URD-STK · URD-TRK) - việc nhận hàng xây trên các primitive tồn và tracking.
  • Inventory locations (URD-LOC) - tồn vào một địa điểm; phải tồn tại một địa điểm mặc định của merchant.
  • Finance (@nx/finance) - cho việc ghi transaction/payment tùy chọn.

Giả định

  • Merchant có ít nhất một vendor và một địa điểm kho mặc định.
  • Tồn tại một finance category để phân loại lần ghi mua hàng.

11. Risks & Open Questions

Rủi ro / câu hỏiGiảm thiểu / trạng thái
Việc nhận hàng và ghi tồn có thể lệch nhau khi lỗi một phầnĐược ghi transactional; tồn không có mục nào mà không có một bản ghi biến động
Không hỗ trợ đa tiền tệNgoài phạm vi; ghi nhận như một ràng buộc cho vendor xuyên biên giới
Không có cổng phê duyệt trước khi processingChấp nhận cho quy mô SME; xem lại nếu cần phê duyệt cấp doanh nghiệp
Revert một PO đã nhận so với finance đã ghiMở: định nghĩa đường đảo ngược/bù trừ cho các mục finance

12. Release Plan & Launch Criteria

Khía cạnhKế hoạch
PhaseP1 (nền tảng) - xem URD feature catalog
RolloutTất cả merchant; không feature flag
MigrationKhông (entity mới; PO config seed lúc khởi động)
Tiêu chí phát hànhTạo→nhận→tồn+biến động được kiểm chứng đầu-cuối; ghi finance được kiểm chứng; các tổng khớp phép toán kỳ vọng
Giám sátLượng PO theo từng merchant, tỉ lệ lỗi nhận hàng, các kiểm tra nhất quán tồn-vs-biến động

13. FAQ

Một PO có thể đổi sau khi rời DRAFT không? Không - dòng mục chỉ sửa được trong DRAFT. Dùng revert PROCESSING → DRAFT để chỉnh sửa, hoặc hủy.

Nhận hàng OVERRIDE vs ACCUMULATIVE - khác gì nhau? OVERRIDE thay thế số lượng đã nhận trên dòng; ACCUMULATIVE cộng dồn vào nó (cho các đợt giao đến trong nhiều lần).

Nhận một PO có trả tiền cho vendor không? Không tự động - một PO đã nhận có thể ghi một finance transaction kèm một payment tùy chọn. Ghi nhận một chi phí và trả nó là hai việc riêng.

Nếu không cho địa điểm thì sao? PO mặc định về địa điểm kho mặc định của merchant.

Tôi có thể nhập tồn đầu kỳ qua một PO không? Không - tồn đầu kỳ được xử lý bởi tính năng riêng Nhập tồn đầu kỳ; không có cách lách bằng vendor ảo.

References

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