Kế toán NH 8 — Dữ liệu kế toán cho Data & báo cáo

13 thg 7, 2026 2 lượt xem
#banking
#sql
#data
#accounting
#general-ledger
#reporting

Kế toán NH 8 — Dữ liệu kế toán cho Data & báo cáo

Đây là bài khép lại series Kế toán ngân hàng chuyên sâu. Bảy bài trước đi từ nguyên lý ghi sổ kép, hệ thống tài khoản, sổ cái, dự thu lãi, dự phòng, đến báo cáo tài chính và đối soát. Bài cuối này đổi góc nhìn: không còn hỏi "hạch toán thế nào cho đúng" mà hỏi "làm sao khai thác kho dữ liệu kế toán để phục vụ báo cáo, đối soát và phân tích lợi nhuận" — tức góc nhìn của một kỹ sư dữ liệu / analyst làm việc với dữ liệu ngân hàng.

Với dân Data, dữ liệu kế toán là nguồn giá trị nhất nhưng cũng khó nhất trong ngân hàng: khối lượng lớn, nhiều chiều, và — quan trọng nhất — có một bất biến toán học phải luôn đúng (tổng Nợ = tổng Có), cho bạn công cụ kiểm soát chất lượng mạnh hơn hầu hết các miền dữ liệu khác.

Bài này giả định bạn đã nắm Sổ cái & sổ phụ, Báo cáo tài chínhĐối soát & kiểm soát. Ở đây ta nối chúng lại dưới lăng kính mô hình dữ liệu và SQL.


1. Vì sao dữ liệu kế toán là "vàng"

Dữ liệu kế toán là nguồn sự thật tài chính (financial source of truth) của ngân hàng. Gần như mọi con số quan trọng cuối cùng đều quy về nó:

  • Báo cáo tài chính (BCTC): Bảng cân đối, Báo cáo kết quả kinh doanh, Lưu chuyển tiền tệ đều lắp ráp từ số dư và phát sinh trên sổ cái — xem Báo cáo tài chính.
  • Báo cáo NHNN & tuân thủ: các mẫu biểu chế độ báo cáo thống kê (Thông tư 11/2018 và các văn bản kế thừa), báo cáo phân loại nợ, an toàn vốn... phần lớn lấy từ dữ liệu kế toán/GL.
  • Quản trị (MIS): Ban lãnh đạo cần biết lợi nhuận theo chi nhánh, theo sản phẩm, theo phân khúc — tất cả xây trên phát sinh GL được gắn chiều (dimension).
  • Đối soát: GL là mốc để đối soát với sổ phụ (subledger), với sao kê ngân hàng đại lý (nostro), với hệ thống thanh toán.
  • Phân tích lợi nhuận & rủi ro: NIM, cost of risk, ROA/ROE đều bắt đầu từ các con số kế toán.

Điểm mấu chốt: nếu dữ liệu kế toán sai, mọi báo cáo tải trên đó đều sai — nên chất lượng của nó là điều kiện tồn tại của cả tầng báo cáo.


2. Mô hình dữ liệu kế toán

Khi mô hình hoá dữ liệu kế toán cho kho dữ liệu, ta cần tách rõ bảng fact (phát sinh)bảng dimension (chiều). Đây chính là tư duy data modeling áp dụng cho kế toán.

2.1. GL entry (bút toán sổ cái) — bảng fact trung tâm

Mỗi dòng bút toán sổ cái tối thiểu gồm:

TrườngÝ nghĩa
entry_idKhoá dòng bút toán
journal_id / voucher_idNhóm bút toán cùng một giao dịch (dùng để kiểm cân)
gl_accountTài khoản sổ cái (khoá nối sang chart of accounts)
dr_crChiều Nợ (D) hay Có (C) — hoặc dùng amount có dấu
amountSố tiền
currencyLoại tiền (VND/USD/...)
value_date / posting_dateNgày hiệu lực / ngày hạch toán
branch_id, company_idChi nhánh, pháp nhân (đa công ty)
referenceTham chiếu sang giao dịch nguồn (số hợp đồng vay, số lệnh thanh toán...)

Đây là hạt mịn nhất (grain) của dữ liệu tài chính. Một quyết định thiết kế: lưu dr_cr + amount dương, hay amount có dấu (Nợ +, Có −)? Kiểu có dấu tiện tính net; kiểu dr_cr gần nghiệp vụ và dễ kiểm cân hơn.

2.2. Subledger entry (bút toán sổ phụ)

Sổ cái tổng hợp; sổ phụ giữ chi tiết theo từng đối tượng: từng khoản vay, từng tài khoản tiền gửi, từng thẻ. Một tài khoản GL "Cho vay khách hàng" có thể ánh xạ tới hàng triệu dòng sổ phụ. Quan hệ này là nền của đối soát GL↔subledger (mục 5). Chi tiết kiến trúc hai tầng này ở Sổ cái & sổ phụ.

2.3. Chart of accounts (COA) — dimension

Bảng danh mục tài khoản: mã tài khoản, tên, loại (Tài sản/Nợ phải trả/Vốn/Thu nhập/Chi phí), cấp bậc cây tài khoản (parent). Đây là dimension quan trọng nhất vì nó quyết định con số rơi vào dòng nào của BCTC.

2.4. Sản phẩm → tài khoản mapping

Core banking không để nhân viên chọn tay tài khoản GL. Thay vào đó có bảng mapping quy định: sản phẩm/loại giao dịch nào → sinh bút toán vào tài khoản GL nào (ví dụ "giải ngân vay tiêu dùng" → Nợ TK cho vay / Có TK tiền gửi khách; "thu phí" → Có TK thu nhập phí). Hiểu bảng này là chìa khoá để truy ngược một con số GL về sản phẩm sinh ra nó. Trong T24, cơ chế này gắn với category/transaction codes — xem T24 core operations.

2.5. Snapshot số dư theo ngày

Phát sinh (flow) cho biết biến động; báo cáo lại thường cần số dư tại một thời điểm (stock). Hai cách: (a) cộng dồn phát sinh — chính xác nhưng đắt; (b) lưu snapshot số dư cuối ngày theo tài khoản × chi nhánh × loại tiền. Kho dữ liệu tài chính gần như luôn cần snapshot, vì báo cáo lịch sử ("số dư huy động ngày 31/12 năm ngoái") không thể tính lại nếu thiếu lịch sử.

Nối T24: dữ liệu phát sinh trong T24 nằm ở STMT.ENTRY (bút toán ảnh hưởng số dư tài khoản khách) và CATEG.ENTRY (bút toán vào tài khoản nội bộ/GL theo category). Đây là hai bảng nguồn quan trọng nhất khi trích dữ liệu kế toán từ T24 — chi tiết ở T24 core operations.


3. Bất biến cốt lõi: tổng Nợ = tổng Có

Đây là điều làm dữ liệu kế toán khác biệt so với mọi dữ liệu khác trong ngân hàng. Nguyên lý ghi sổ kép (double-entry) bảo đảm: với mỗi giao dịch, tổng số tiền ghi Nợ đúng bằng tổng số tiền ghi Có. Suy rộng ra: với mỗi kỳ, mỗi chi nhánh, mỗi loại tiền, tổng Nợ phải bằng tổng Có.

Với mọi journal/voucher:   Σ Nợ  =  Σ Có
Với mọi kỳ (cùng currency): Σ Nợ  =  Σ Có

Đây là kiểm tra chất lượng dữ liệu mạnh nhất bạn có. Nếu pipeline nạp bút toán mà tổng Nợ ≠ tổng Có, chắc chắn có lỗi: mất dòng khi ETL, làm tròn sai, hoặc trộn loại tiền. Vài cạm bẫy khi kiểm cân:

  • Trộn loại tiền: không được cộng VND với USD. Luôn kiểm cân trong từng currency, hoặc quy đổi hết về đơn vị chung trước.
  • Làm tròn: hạch toán ngoại tệ quy đổi có thể lệch vài đồng — cần ngưỡng dung sai (tolerance) hợp lý, không so bằng tuyệt đối.
  • Ranh giới kỳ: bút toán "gối đầu" giữa hai ngày (posting date ≠ value date) dễ làm lệch nếu cắt kỳ theo sai cột ngày.

Gắn kiểm cân này thành test tự động trong pipeline (ví dụ dbt test) là thực hành chuẩn — xem mục 6. Các kiểm tra khác: không có gl_account mồ côi (không có trong COA), không có ngày tương lai, không có amount âm ở nơi không cho phép.


4. Kiến trúc dữ liệu: từ core tới báo cáo

Bức tranh tổng thể của một luồng dữ liệu kế toán trong ngân hàng hiện đại:

Đường đi tiêu biểu: bút toán sinh ở core/subledger → tổng hợp về GL (đã cân) → đưa vào kho/lakehouse qua CDC hoặc batch cuối ngày (COB) → từ đó chạy song song kiểm tra chất lượng, đối soát, báo cáoBI. Về nền tảng lưu trữ & biến đổi:

  • Kho/lakehouse: đưa fact GL entry + các dimension lên nền như BigQuery; CDC bắt thay đổi từ core để có dữ liệu gần thời gian thực.
  • Transform & test: mô hình hoá và kiểm thử bằng dbt — mỗi lớp mô hình kèm test (kể cả test cân Nợ=Có).
  • Dashboard tài chính: dựng báo cáo quản trị trên Power BI hoặc Looker, lấy trực tiếp từ kho.

5. Ứng dụng phân tích trên dữ liệu kế toán

Khi đã có fact GL entry gắn dimension, các phân tích tài chính trở thành truy vấn nhóm (group-by) theo chiều:

  • P&L theo sản phẩm / chi nhánh: lọc các tài khoản thu nhập & chi phí, nhóm theo product / branch_id. Đây là nền của báo cáo lợi nhuận từng đơn vị.
  • NIM (Net Interest Margin): (thu nhập lãi − chi phí lãi) / tài sản sinh lời bình quân — tất cả cấu phần đều từ GL (thu/chi lãi) và snapshot số dư (tài sản bình quân).
  • Cost of risk: chi phí dự phòng / dư nợ bình quân — lấy phát sinh tài khoản chi phí dự phòng.
  • Đối soát GL ↔ subledger: tổng số dư sổ phụ của một sản phẩm phải khớp số dư tài khoản GL tương ứng; lệch là dấu hiệu lỗi hạch toán hoặc mất dữ liệu.
  • Aging tài khoản treo (suspense): các tài khoản trung gian phải về 0; theo dõi tuổi nợ các khoản treo để phát hiện bút toán chưa được làm sạch — nối Đối soát & kiểm soát.
  • Báo cáo NHNN & MIS/profitability: cùng kho dữ liệu, thêm logic phân bổ. Ở tầng MIS nâng cao có FTP (funds transfer pricing) phân bổ chi phí/lợi ích vốn nội bộ giữa các đơn vị — một lớp chồng lên số liệu kế toán thô.

6. Use case thực tế — kiểm cân & đối soát bằng SQL

Phần này minh hoạ tư duy kế toán/đối soát bằng SQL chạy trực tiếp trên SQL Builder của trang.

Lưu ý quan trọng — đây là PROXY minh hoạ. Sandbox là PostgreSQL với schema đơn giản (customers, accounts, transactions, employees, departments) và chỉ chạy một câu SELECT/WITH. Bảng transactions(amount, kind) không phải GL thật — ta coi mỗi dòng như một "entry" với kind mô phỏng chiều Nợ/Có ('credit'/'debit') để minh hoạ khái niệm, không phải để tái hiện sổ cái ngân hàng thực. Tư duy mới là điều cần rút ra, không phải con số.

Ví dụ 1 — Tổng phát sinh theo chiều (mô phỏng kiểm cân)

Nhóm theo kind để xem tổng số dòng và tổng tiền mỗi chiều — bước đầu tiên khi kiểm tra một tập bút toán.

▶ Chạy được trong SQL Builder

SELECT
  t.kind,
  COUNT(*)      AS so_but_toan,
  SUM(t.amount) AS tong_tien
FROM transactions t
GROUP BY t.kind
ORDER BY t.kind;

Ý nghĩa: trên GL thật, hai chiều Nợ/Có phải cho ra tổng bằng nhau. Đây là dạng đơn giản nhất của kiểm tra "hai vế".

Ví dụ 2 — Chênh lệch Nợ/Có (mô phỏng bất biến cân đối)

Tính tổng "ghi có" và "ghi nợ" trên cùng một hàng rồi lấy hiệu. Trên dữ liệu GL đã cân, cột chenh_lech phải bằng 0; khác 0 là báo động chất lượng dữ liệu.

▶ Chạy được trong SQL Builder

SELECT
  SUM(CASE WHEN t.kind = 'credit' THEN t.amount ELSE 0 END) AS tong_ghi_co,
  SUM(CASE WHEN t.kind = 'debit'  THEN t.amount ELSE 0 END) AS tong_ghi_no,
  SUM(CASE WHEN t.kind = 'credit' THEN t.amount ELSE 0 END)
    - SUM(CASE WHEN t.kind = 'debit' THEN t.amount ELSE 0 END) AS chenh_lech
FROM transactions t;

Ý nghĩa: đây chính là mẫu SQL bạn sẽ biến thành test cân Nợ=Có trong pipeline (nhóm thêm theo journal_id, currency, period và assert chenh_lech = 0). Lưu ý dữ liệu proxy này không bắt buộc bằng 0 vì transactions không phải sổ cái.

Ví dụ 3 — Số dư & dòng tiền theo tài khoản (join sang khách hàng)

Nối transactions → accounts → customers để gắn phát sinh với chủ tài khoản. Chú ý dùng đúng khoá: transactions.account_id → accounts.id, accounts.customer_id → customers.id (schema không có cột customer_name — tên khách nằm ở customers.full_name).

▶ Chạy được trong SQL Builder

SELECT
  a.account_no,
  c.full_name,
  a.currency,
  a.balance,
  SUM(CASE WHEN t.kind = 'credit' THEN t.amount ELSE 0 END) AS tong_ghi_co,
  SUM(CASE WHEN t.kind = 'debit'  THEN t.amount ELSE 0 END) AS tong_ghi_no
FROM accounts a
JOIN customers c ON c.id = a.customer_id
LEFT JOIN transactions t ON t.account_id = a.id
GROUP BY a.account_no, c.full_name, a.currency, a.balance
ORDER BY a.account_no;

Ý nghĩa: đây là khung của một báo cáo phát sinh — số dư theo tài khoản. Trong thực tế, cột balance (số dư sổ cái) sẽ được đối chiếu với net phát sinh (ví dụ 5) để phát hiện lệch.

Ví dụ 4 — Phát sinh theo ngày (bảng kê nhật ký)

Gom bút toán theo ngày hạch toán bằng to_char(created_at, 'YYYY-MM-DD') — dạng "nhật ký chứng từ" theo ngày, thường là điểm khởi đầu để cắt kỳ và đối chiếu số phát sinh trong kỳ.

▶ Chạy được trong SQL Builder

SELECT
  to_char(t.created_at, 'YYYY-MM-DD') AS ngay_hach_toan,
  COUNT(*)                            AS so_but_toan,
  SUM(t.amount)                       AS tong_phat_sinh
FROM transactions t
GROUP BY to_char(t.created_at, 'YYYY-MM-DD')
ORDER BY ngay_hach_toan;

Ý nghĩa: cột ngày là chiều thời gian tối quan trọng của kế toán — mọi báo cáo đều gắn kỳ. Chú ý phân biệt posting_datevalue_date khi cắt kỳ trên hệ thống thật.

Ví dụ 5 — Đối soát GL ↔ subledger (mô phỏng bằng WITH)

Mô phỏng đối soát: coi accounts.balance như "số dư sổ cái", còn net phát sinh gom từ transactions như "tổng sổ phụ". Cột chenh_lech_doi_soatkhoản lệch cần điều tra.

▶ Chạy được trong SQL Builder

WITH sub AS (
  SELECT
    t.account_id,
    SUM(CASE WHEN t.kind = 'credit' THEN t.amount ELSE -t.amount END) AS net_phat_sinh
  FROM transactions t
  GROUP BY t.account_id
)
SELECT
  a.account_no,
  a.balance                              AS so_du_so_cai,
  COALESCE(sub.net_phat_sinh, 0)         AS net_subledger,
  a.balance - COALESCE(sub.net_phat_sinh, 0) AS chenh_lech_doi_soat
FROM accounts a
LEFT JOIN sub ON sub.account_id = a.id
ORDER BY chenh_lech_doi_soat DESC;

Ý nghĩa: đây chính là hình dạng của một truy vấn đối soát thật: gom một nguồn về cùng khoá, LEFT JOIN với nguồn kia, và lấy hiệu. Dòng có chenh_lech_doi_soat ≠ 0 là danh sách việc cần đội đối soát xử lý. Trên dữ liệu proxy, con số lệch không có ý nghĩa nghiệp vụ — chỉ mẫu truy vấn là điều cần học.


7. Ghi nhớ

  • Dữ liệu kế toán là nguồn sự thật tài chính: BCTC, báo cáo NHNN, MIS, đối soát và phân tích lợi nhuận đều quy về nó. Sai ở đây thì sai toàn bộ tầng báo cáo.
  • Mô hình dữ liệu = fact GL entry (grain mịn: tài khoản, chiều, tiền, ngày, chi nhánh, tham chiếu) + các dimension (COA, chi nhánh, sản phẩm), cộng sản phẩm→tài khoản mappingsnapshot số dư theo ngày để phục vụ báo cáo lịch sử.
  • Bất biến vàng: tổng Nợ = tổng Có, đúng cho mọi giao dịch/kỳ/chi nhánh trong cùng loại tiền. Biến nó thành test tự động; coi chừng trộn currency, làm tròn, và ranh giới kỳ.
  • Đối soát = gom + join + lấy hiệu: GL ↔ subledger, GL ↔ nostro; theo dõi aging tài khoản treo (suspense) để không tích lỗi.
  • Nền tảng: đưa GL/entry vào kho/lakehouse qua CDC/batch, transform & test bằng dbt, phục vụ Power BI cho dashboard tài chính.
  • SQL sandbox chỉ là proxy minh hoạ tư duytransactions không phải GL thật; giá trị nằm ở khuôn mẫu truy vấn (kiểm cân, đối soát, phát sinh theo ngày), không phải con số.

Kết thúc series: bạn đã đi từ nguyên lý ghi sổ kép đến việc khai thác dữ liệu kế toán ở quy mô kho dữ liệu. Với dân Data, thông điệp lớn nhất là — hãy tôn trọng bất biến Nợ=Có: nó vừa là ràng buộc, vừa là công cụ kiểm soát chất lượng mạnh nhất bạn có trong tay.

Bài viết liên quan

Dòng chảy dữ liệu core -> ODS -> DWH -> BI, mô hình dữ liệu cốt lõi và bộ ví dụ SQL thực hành chạy được.

13 thg 7, 2026 7

Bản chất kinh doanh của ngân hàng: trung gian tài chính, bảng cân đối, NIM và vì sao dữ liệu quan trọng.

13 thg 7, 2026 5

Kiến trúc core banking, CIF, các phân hệ và xử lý online vs batch/EOD.

13 thg 7, 2026 5

Nguyên lý hạch toán kép, Nợ/Có, hệ thống tài khoản và cách mọi giao dịch ngân hàng luôn cân sổ.

13 thg 7, 2026 5