Mô hình dữ liệu kế toán — Báo cáo kép IFRS + VAS
Quyết định
Phần tiêu đề “Quyết định”Kho sự kiện kinh tế chung với quy tắc ghi sổ kép: một bộ cho IFRS, một bộ cho VAS.
Một bảng AccountingEvents bất biến ghi nhận điều đã xảy ra (sự kiện kinh tế). Hai engine ghi sổ riêng biệt — một theo quy tắc ghi nhận IFRS, một theo quy tắc VAS Thông tư 200/Thông tư 133 — đọc sự kiện và ghi bút toán vào sổ cái tương ứng. Bút toán IFRS và VAS được lưu riêng biệt. Báo cáo được tạo từ mỗi sổ cái độc lập.
Bối cảnh
Phần tiêu đề “Bối cảnh”BPO ERP phải tạo ra:
- Báo cáo tài chính IFRS (bảng cân đối kế toán, báo cáo lãi lỗ, lưu chuyển tiền tệ) làm đầu ra chính
- Báo cáo theo pháp định VAS (Thông tư 200/2014/TT-BTC cho doanh nghiệp vừa và lớn, Thông tư 133/2016/TT-BTC cho doanh nghiệp nhỏ) để nộp cho cơ quan quản lý Việt Nam
IFRS và VAS không chỉ đơn giản là các định dạng báo cáo khác nhau trên cùng số liệu. Chúng có quy tắc ghi nhận, cơ sở đo lường và định dạng trình bày bắt buộc khác nhau. Cùng một sự kiện kinh tế có thể yêu cầu các bút toán khác nhau theo mỗi chuẩn mực.
Điều lệ dự án đánh giá độ phức tạp của yêu cầu báo cáo kép này là Tác động cao và yêu cầu chuyên gia lĩnh vực xem xét thiết kế trước khi schema được xác nhận. Tài liệu này ghi lại quyết định kiến trúc; bảng ánh xạ mã tài khoản chi tiết phải được xác nhận riêng.
Tại sao đây là thách thức
Phần tiêu đề “Tại sao đây là thách thức”Ba ví dụ cụ thể về sự khác biệt IFRS / VAS mà phương pháp đơn giản “thêm view báo cáo VAS” không thể xử lý:
| Tình huống | Xử lý theo IFRS | Xử lý theo VAS |
|---|---|---|
| Thuê tài sản vận hành | IFRS 16: tài sản quyền sử dụng + nợ thuê tài chính trên bảng cân đối; chi phí khấu hao + lãi vay | Không có quy định VAS tương đương — chỉ ghi chi phí thuê |
| Ghi nhận doanh thu | IFRS 15: mô hình 5 bước; ghi nhận khi (hoặc khi) nghĩa vụ thực hiện được thỏa mãn | Đơn giản hơn; thường ghi nhận tại thời điểm xuất hóa đơn hoặc giao hàng |
| Hệ thống tài khoản | Không có mã tài khoản bắt buộc — đơn vị tự xác định cấu trúc | Mã bắt buộc theo Thông tư 200 (ví dụ: 111 Tiền mặt, 112 Tiền gửi, 131 Phải thu, 331 Phải trả) |
Ví dụ về thuê tài sản: một bút toán IFRS ghi nợ tài sản quyền sử dụng (tài khoản IFRS) và có nợ thuê tài chính (tài khoản IFRS). Không có bút toán VAS tương đương — VAS chỉ ghi chi phí thuê khi tiền mặt được thanh toán. Phương pháp chuyển đổi (suy ra VAS từ bút toán IFRS) không thể tạo ra xử lý VAS đúng vì bút toán VAS không tương ứng với bất kỳ bút toán IFRS nào.
Các phương án đã xem xét
Phần tiêu đề “Các phương án đã xem xét”Phương án 1: IFRS Chính, Suy ra VAS bằng chuyển đổi
Phần tiêu đề “Phương án 1: IFRS Chính, Suy ra VAS bằng chuyển đổi”Chỉ lưu bút toán IFRS. Tại thời điểm báo cáo, áp dụng bảng ánh xạ để chuyển đổi mã tài khoản IFRS sang VAS và tạo đầu ra VAS.
Lý do bị loại: Ánh xạ IFRS → VAS không phải là dịch thuật 1:1. Với các sự kiện ghi nhận khác nhau (thuê tài sản, một số dự phòng, doanh thu hoãn lại), bút toán VAS không tồn tại hoặc khác biệt đáng kể. Quy tắc chuyển đổi không thể tạo ra bút toán VAS không có đối tác IFRS. Phương pháp này tạo ra báo cáo pháp định VAS không chính xác cho bất kỳ tenant nào có hợp đồng thuê hoặc các khác biệt tương tự.
Phương án 2: Sổ cái song song (Ghi đồng thời cả hai)
Phần tiêu đề “Phương án 2: Sổ cái song song (Ghi đồng thời cả hai)”Mỗi giao dịch ghi đồng thời vào sổ cái IFRS và sổ cái VAS. Mỗi module (AP, AR, Kho hàng, v.v.) phải triển khai hai bộ quy tắc ghi sổ.
Đã xem xét nhưng không chọn: Đây là kiến trúc hợp lý nhưng đặt logic ghi sổ kép vào mỗi module nghiệp vụ. Module AP phải biết quy tắc AP IFRS và quy tắc AP VAS. Lương phải biết quy tắc IFRS và VAS. Kiến thức quy tắc ghi sổ bị phân tán trong codebase thay vì được tập trung. Việc đồng bộ hai bộ quy tắc khi quy định thay đổi có rủi ro vận hành cao.
Phương án 3: Sự kiện kinh tế chung + Engine ghi sổ kép ✓ Được chọn
Phần tiêu đề “Phương án 3: Sự kiện kinh tế chung + Engine ghi sổ kép ✓ Được chọn”Sự kiện kinh tế thô được ghi một lần, bất biến. Hai engine ghi sổ — chạy như domain service — đọc sự kiện và mỗi engine ghi bút toán theo bộ quy tắc riêng của mình. Engine IFRS áp dụng quy tắc ghi nhận IFRS; engine VAS áp dụng quy tắc VAS Thông tư 200. Cả hai ghi vào bảng bút toán riêng biệt phục vụ các bộ tạo báo cáo tương ứng.
Lý do được chọn:
- Quy tắc ghi sổ được tập trung trong engine IFRS và engine VAS, không phân tán qua các module
- Hai sổ cái được tạo từ cùng nguồn sự kiện — không cần đối chiếu giữa sự kiện và sổ cái
- Khi quy định VAS thay đổi (ví dụ: thông tư mới), chỉ engine VAS cần cập nhật — kho sự kiện và engine IFRS không thay đổi
- Xử lý ghi nhận khác nhau rõ ràng: engine IFRS tạo tài sản quyền sử dụng + nợ thuê tài chính; engine VAS không tạo gì (xử lý VAS đúng với thuê vận hành)
- Kho sự kiện cung cấp audit trail sạch độc lập với lựa chọn chuẩn mực kế toán
Mô hình dữ liệu
Phần tiêu đề “Mô hình dữ liệu”Đây là phác thảo thiết kế. Tên cột, kiểu dữ liệu và chiến lược index phải được hoàn thiện với kế toán viên có chứng chỉ người Việt và lập trình viên EF Core cao cấp trước khi triển khai.
Các bảng cốt lõi
Phần tiêu đề “Các bảng cốt lõi”AccountingEvents (Sự kiện kế toán)────────────────────────────────────────────────EventId UNIQUEIDENTIFIER PKTenantId UNIQUEIDENTIFIER NOT NULL (RLS bắt buộc)EventType NVARCHAR(100) NOT NULL -- ví dụ: 'SupplierInvoiceReceived'EventDate DATE NOT NULLFiscalPeriodId UNIQUEIDENTIFIER NOT NULL FK → FiscalPeriodsSourceModule NVARCHAR(50) NOT NULL -- 'AP', 'AR', 'Inventory', 'Sales'SourceDocumentId UNIQUEIDENTIFIER NOT NULL -- FK đến tài liệu gốcCurrencyCode CHAR(3) NOT NULLAmountFunctional DECIMAL(18,4) NOT NULL -- theo đồng tiền chức năng của tenantExchangeRate DECIMAL(18,6) NULL -- NULL nếu là đồng tiền chức năngPayload NVARCHAR(MAX) NOT NULL -- JSON: các trường đặc thù của sự kiệnPostedAt DATETIMEOFFSET NOT NULLPostedByUserId UNIQUEIDENTIFIER NOT NULLIsReversed BIT NOT NULL DEFAULT 0ReversalOfEventId UNIQUEIDENTIFIER NULL FK → AccountingEventsJournalEntries (Bút toán IFRS)────────────────────────────────────────────────EntryId UNIQUEIDENTIFIER PKTenantId UNIQUEIDENTIFIER NOT NULL (RLS bắt buộc)EventId UNIQUEIDENTIFIER NOT NULL FK → AccountingEventsAccountId UNIQUEIDENTIFIER NOT NULL FK → ChartOfAccountsDebitAmount DECIMAL(18,4) NOT NULL DEFAULT 0CreditAmount DECIMAL(18,4) NOT NULL DEFAULT 0CurrencyCode CHAR(3) NOT NULLDescription NVARCHAR(500) NULLFiscalPeriodId UNIQUEIDENTIFIER NOT NULL FK → FiscalPeriodsVasJournalEntries (Bút toán VAS)────────────────────────────────────────────────EntryId UNIQUEIDENTIFIER PKTenantId UNIQUEIDENTIFIER NOT NULL (RLS bắt buộc)EventId UNIQUEIDENTIFIER NOT NULL FK → AccountingEventsVasAccountId UNIQUEIDENTIFIER NOT NULL FK → VasChartOfAccountsDebitAmount DECIMAL(18,4) NOT NULL DEFAULT 0CreditAmount DECIMAL(18,4) NOT NULL DEFAULT 0CurrencyCode CHAR(3) NOT NULLDescription NVARCHAR(500) NULLFiscalPeriodId UNIQUEIDENTIFIER NOT NULL FK → FiscalPeriodsChartOfAccounts (Hệ thống tài khoản IFRS — tenant có thể tùy chỉnh trong nguyên tắc IFRS)────────────────────────────────────────────────AccountId UNIQUEIDENTIFIER PKTenantId UNIQUEIDENTIFIER NOT NULL (RLS bắt buộc)AccountCode NVARCHAR(50) NOT NULLAccountName NVARCHAR(200) NOT NULLAccountType NVARCHAR(50) NOT NULL -- Tài sản, Nợ phải trả, Vốn chủ, Doanh thu, Chi phíParentAccountId UNIQUEIDENTIFIER NULL FK → ChartOfAccounts (phân cấp)IsSystemAccount BIT NOT NULL -- tài khoản hệ thống không thể xóaVasChartOfAccounts (Hệ thống tài khoản VAS Thông tư 200 / 133 — mã bắt buộc được thực thi)────────────────────────────────────────────────VasAccountId UNIQUEIDENTIFIER PKTenantId UNIQUEIDENTIFIER NOT NULL (RLS bắt buộc)AccountCode NVARCHAR(10) NOT NULL -- ví dụ: '111', '112', '131', '331'AccountName NVARCHAR(200) NOT NULL -- tên tiếng Việt theo Thông tư 200AccountType NVARCHAR(50) NOT NULLCircularVersion NVARCHAR(20) NOT NULL -- 'Circular200' hoặc 'Circular133'ParentAccountId UNIQUEIDENTIFIER NULL FK → VasChartOfAccountsIsSystemAccount BIT NOT NULLFiscalPeriods (Kỳ kế toán)────────────────────────────────────────────────FiscalPeriodId UNIQUEIDENTIFIER PKTenantId UNIQUEIDENTIFIER NOT NULL (RLS bắt buộc)PeriodName NVARCHAR(50) NOT NULL -- ví dụ: '2026-03'StartDate DATE NOT NULLEndDate DATE NOT NULLStatus NVARCHAR(20) NOT NULL -- Mở, Đang đóng, Đã đóngClosedAt DATETIMEOFFSET NULLClosedByUserId UNIQUEIDENTIFIER NULLExchangeRates (Tỷ giá hối đoái)────────────────────────────────────────────────RateId UNIQUEIDENTIFIER PKTenantId UNIQUEIDENTIFIER NOT NULL (RLS bắt buộc)FromCurrency CHAR(3) NOT NULLToCurrency CHAR(3) NOT NULLRateDate DATE NOT NULLRate DECIMAL(18,6) NOT NULLSource NVARCHAR(100) NULL -- 'Thủ công', 'VCB', 'NHNN'Thiết kế engine ghi sổ
Phần tiêu đề “Thiết kế engine ghi sổ”Mỗi engine ghi sổ là một domain service:
- Nhận một
AccountingEvent - Tra cứu quy tắc ghi sổ cho
EventType(lưu trong bảng cấu hình) - Phân giải mã tài khoản cho quy tắc (sử dụng hệ thống tài khoản của tenant)
- Ghi các bút toán kết quả vào
JournalEntries(IFRS) hoặcVasJournalEntries(VAS) - Cả hai engine được gọi trong cùng một transaction cơ sở dữ liệu với việc tạo sự kiện — hoặc cả hai thành công hoặc không cái nào
Quy tắc ghi sổ được lưu dưới dạng cấu hình (không hardcode), cho phép cập nhật quy định mà không cần deploy mã:
PostingRules (Quy tắc ghi sổ)────────────────────────────────────────────────RuleId UNIQUEIDENTIFIER PKStandard NVARCHAR(10) NOT NULL -- 'IFRS' hoặc 'VAS'EventType NVARCHAR(100) NOT NULLDebitAccountCode NVARCHAR(50) NOT NULL -- mã tài khoản (có thể tham số hóa)CreditAccountCode NVARCHAR(50) NOT NULLAmountExpression NVARCHAR(200) NOT NULL -- cách tính số tiền từ payload sự kiệnEffectiveFrom DATE NOT NULLEffectiveTo DATE NULLẢnh hưởng đến các module khác
Phần tiêu đề “Ảnh hưởng đến các module khác”Mỗi module tạo giao dịch tài chính phải phát sự kiện AccountingEvent — không ghi trực tiếp vào sổ cái.
| Module | Loại sự kiện được phát |
|---|---|
| Phải trả (AP) | SupplierInvoiceReceived, SupplierInvoicePaid, SupplierCreditNoteReceived |
| Phải thu (AR) | CustomerInvoiceIssued, CustomerPaymentReceived, CustomerCreditNoteIssued |
| Kho hàng | StockPurchased, StockSold, StockAdjustment, StockTransfer |
| Mua hàng | (sự kiện phát khi xác nhận nhận hàng — kích hoạt sự kiện AP) |
| Bán hàng | (sự kiện phát khi xác nhận phiếu giao hàng — kích hoạt sự kiện AR) |
| Đối chiếu ngân hàng | BankTransactionMatched, UnreconciledItemFlagged |
| HR & Lương (Giai đoạn 2) | PayrollRun, SocialInsuranceContribution |
Các vấn đề chưa giải quyết — Cần xem xét của chuyên gia lĩnh vực
Phần tiêu đề “Các vấn đề chưa giải quyết — Cần xem xét của chuyên gia lĩnh vực”Những điều sau không thể hoàn thiện mà không có đầu vào từ kế toán viên có chứng chỉ người Việt và cố vấn kế toán của dự án:
-
Bảng ánh xạ quy tắc ghi sổ — với mỗi
EventType, các tài khoản ghi nợ/có IFRS đúng và các tài khoản ghi nợ/có VAS Thông tư 200 đúng. Đây là cốt lõi của hệ thống báo cáo kép và phải chính xác trước khi bất kỳ module kế toán nào ra mắt. -
Bút toán điều chỉnh cuối kỳ đặc thù VAS — một số bút toán cuối kỳ VAS (ví dụ: đánh giá lại ngoại tệ theo VAS 10, một số dự phòng theo Thông tư 200) không có đối tác IFRS. Các loại sự kiện này phải được xác định và quy tắc ghi sổ phải được định nghĩa.
-
Đồng tiền chức năng vs. đồng tiền trình bày (IAS 21) — phương pháp chính xác cho các tenant có đồng tiền chức năng khác VND (ví dụ: doanh nghiệp xuất khẩu với đồng tiền chức năng USD báo cáo bằng VND). Bảng
ExchangeRatesở trên chỉ là placeholder; cơ chế chuyển đổi cần được chỉ định. -
Sự khác biệt giữa Thông tư 133 và Thông tư 200 — một số quy tắc ghi sổ khác nhau giữa hai thông tư VAS. Cột
VasChartOfAccounts.CircularVersionxử lý điều này, nhưng các quy tắc khác biệt cụ thể cần được lập danh mục. -
Dữ liệu seed Hệ thống tài khoản VAS — các mã tài khoản và tên bắt buộc từ Thông tư 200/Thông tư 133 phải được cung cấp bởi cố vấn kế toán và nạp như dữ liệu seed hệ thống.
Không được hoàn thiện schema hoặc bắt đầu triển khai module Kế toán mà không hoàn thành việc xem xét này.