Skip to content

ADR-0001. Mô hình phiếu ghi sổ kép + sổ cái

FieldValue
StatusAccepted
Date2026-04-22
DecidersPhat Nguyen
Supersedes-

Bối cảnh

  • Mô hình trước ghi nhận biến động tiền dưới dạng các dòng FinanceTransaction phẳng, kèm một loại INCOME/EXPENSE/TRANSFER và một tài khoản duy nhất - không có nhóm chứng từ, không có vế đối ứng, và không có phiếu sẵn sàng cho kiểm toán.
  • Sổ sách kế toán POS Việt Nam đòi hỏi các chứng từ nhận diện được: Phiếu thu, Phiếu chi, Phiếu chuyển khoản, Phiếu kế toán (điều chỉnh), mỗi loại có số chạy riêng theo từng merchant.
  • Biến động giá vốn (COGS) và tài sản tồn kho cần một vế đối ứng cân bằng (ghi Nợ một tài khoản, ghi Có tài khoản khác) - điều không thể làm với giao dịch một vế.
  • Số dư tài khoản phải tái dựng được và chống giả mạo.

Quyết định

Chúng tôi sẽ mô hình hóa finance theo ghi sổ kép: một header FinanceVoucher (loại RECEIPT / PAYMENT / TRANSFER / ADJUSTMENT) sở hữu N dòng FinanceTransaction, mỗi dòng là một bút toán DEBIT (100_DEBIT, làm số dư tăng) hoặc CREDIT (200_CREDIT, làm số dư giảm) trên một FinanceAccount.

Hướng của dòng được suy ra đối với RECEIPT (toàn bộ là DEBIT) và PAYMENT (toàn bộ là CREDIT), và phải tường minh + cân bằng đối với TRANSFER (Σdebit == Σcredit) và ADJUSTMENT. Số chứng từ được cấp theo (merchantId, type, yearMonth) qua FinanceVoucherSequence với tiền tố PT/PC/PCK/PKT. Mỗi dòng đã ghi sổ lưu snapshot balanceBefore/balanceAfter và một postingSequence tăng đơn điệu; dòng tài khoản được khóa FOR UPDATE trong suốt quá trình ghi sổ.

Hệ quả

ƯuNhược
Chứng từ sẵn sàng cho kiểm toán với số ổn định theo từng merchantNhiều bảng hơn + một công cụ ghi sổ cần duy trì
Vế đối ứng cân bằng cho phép hạch toán giá vốn / tài sản tồn khoBên gọi TRANSFER/ADJUSTMENT phải cung cấp các dòng cân bằng
Snapshot số dư theo từng dòng + posting sequence khiến sổ cái chống giả mạoGhi sổ một phiếu là một transaction nhiều dòng (tranh chấp khóa khi tải cao)
Việc hủy trở thành bút toán đảo cân bằng, không bao giờ là chỉnh sửa phá hủyMỗi phiếu chỉ dùng một loại tiền tệ (đa tiền tệ hoãn lại)

Các phương án đã cân nhắc

Phương ánƯuNhượcLý do loại bỏ
Giao dịch một vế phẳng (mô hình trước)Đơn giản nhấtKhông chứng từ, không vế đối ứng, không hỗ trợ giá vốnKhông thể biểu diễn bút toán cân bằng
Sổ cái tổng đầy đủ với hệ thống tài khoản kế toánHoàn chỉnh về kế toánQuá mức cho POS quy mô nhỏ; trải nghiệm vận hành phức tạpQuá nặng so với phạm vi hiện tại
Sổ cái dạng event-sourced (ghi nối tiếp sự kiện, dựng lại số dư)Khả năng kiểm toán mạnhHạ tầng mới; độ trễ khi dựng lại số dưpostingSequence + snapshot đã đáp ứng kiểm toán mà không tốn chi phí dựng lại

Tham chiếu

  • packages/core/src/services/finance/finance-voucher.service.ts (_performIssue, postLines, resolveLineDirection, computeHeaderAmount)
  • packages/core/src/models/schemas/finance/finance-voucher/, finance-transaction/, finance-voucher-sequence/
  • Domain Model

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