34 điểm bởi GN⁺ 2024-07-12 | 2 bình luận | Chia sẻ qua WhatsApp
  • Kế toán về cơ bản không thay đổi nhiều trong suốt vài trăm năm qua
  • Mặc dù vậy, vẫn có rất nhiều nhầm lẫn về cách đúng đắn để xây dựng phần mềm cho các hệ thống tài chính
  • Bài viết này chia sẻ những bài học rút ra từ kinh nghiệm xây dựng hệ thống tài chính tại các doanh nghiệp lớn
  • Dù tập trung vào việc xây dựng hệ thống kế toán, các nguyên tắc này cũng áp dụng cho các hệ thống tài chính nói chung

Định nghĩa các thuật ngữ tài chính cơ bản

  • Sổ cái tổng hợp (General Ledger, GL): Sổ kế toán chính của công ty, tóm tắt toàn bộ giao dịch tài chính trong một khoảng thời gian nhất định. Có thể xem đây là phần tổng hợp của các sổ cái phụ tương ứng
  • Sổ cái phụ (Sub-ledger): Chứa thông tin chi tiết về từng giao dịch riêng lẻ liên quan đến một GL cụ thể. Bản ghi trong sổ cái phụ chứa dữ liệu chi tiết hơn nhiều so với sổ cái tổng hợp (ví dụ: khách hàng cụ thể, một hạng mục cụ thể trong đơn hàng, v.v.). Mức chênh lệch dữ liệu giữa sổ cái phụ và GL phụ thuộc vào loại hình kinh doanh và lượng dữ liệu đang xử lý. Một số doanh nghiệp nhỏ có thể vận hành mà không cần sổ cái phụ, nhưng nếu quy mô nhỏ thì khả năng cần phần mềm tùy chỉnh cũng không cao
  • Bản ghi tài chính (Financial Record): Cách gọi chung cho sổ cái tổng hợp và sổ cái phụ
  • Trọng yếu (Material): Cho biết việc sai lệch thông tin trong báo cáo tài chính có ảnh hưởng đến quyết định của một bên liên quan hợp lý hay không. Định nghĩa này được cố ý để hơi mơ hồ, vì mỗi doanh nghiệp có tiêu chí trọng yếu khác nhau. Ví dụ, điều quan trọng với một công ty có doanh thu hằng năm 250.000 USD có thể không quan trọng với một công ty có doanh thu hằng năm 1 tỷ USD. Từ góc độ thiết kế, giá trị chính của khái niệm này là phân loại các nhóm dữ liệu tài chính khác nhau

Luồng dữ liệu cấp cao

Business System --(Financial Events)--> Sub Ledger(s) --(Summarized Accounting Entries)--> General Ledger

Ba mục tiêu chính của hệ thống kế toán

  1. Chính xác (Accurate): Bản ghi tài chính phải phản ánh trạng thái đã biết của doanh nghiệp
  • Ví dụ: nếu bán 10 sản phẩm giá $9.99, thì tổng trong bản ghi tài chính phải là $99.90
  • Điều này có vẻ hiển nhiên, nhưng khi tổng hợp hàng nghìn hay hàng triệu giao dịch, những lỗi cộng dồn đơn giản hoặc lỗi làm tròn giữa các hệ thống có thể tạo ra sai lệch nghiêm trọng
  • Ghi chú của Wasteman

    • Mọi người nói rằng đặt tên là vấn đề khó nhất trong khoa học máy tính, nhưng tôi nghĩ phép cộng là vấn đề khó thứ hai
    • Trong vài năm làm việc với các hệ thống tài chính quy mô lớn, tôi đã chứng kiến vô số trường hợp chỉ một lỗi rất nhỏ cũng tạo ra khác biệt lớn trong dữ liệu
    • Đừng nhắc đến việc tính tổng trên float. Tôi đã phải học một cách đau đớn vì sao luôn nên dùng số nguyên
  • Bản ghi tài chính phải đầy đủ (complete)
    • Cụ thể hơn, sổ cái phụ và sổ cái tổng hợp phải thể hiện đầy đủ mọi hoạt động kinh doanh đã xảy ra tại một thời điểm nhất định
    • Nếu có sự kiện đã xảy ra nhưng không có trong bản ghi tài chính, thì hệ thống không đầy đủ
    • Điều này không có nghĩa là không được phép dùng tính nhất quán cuối cùng (eventual consistency)
    • Cần biết khi nào dữ liệu sẽ trở nên đầy đủ để có thể thông báo cho các bên liên quan rằng dữ liệu đã được chốt
  • Ghi chú của Wasteman

    • Đảm bảo tính đầy đủ cũng là một vấn đề khó đến ngạc nhiên
    • Khi hệ thống mở rộng, dữ liệu có thể vô tình bị biến đổi hoặc bị bỏ sót khi đi qua nhiều hệ thống
  1. Có thể kiểm toán (Auditable): Bản ghi tài chính phải dễ kiểm toán để các bên liên quan có thể phát hiện lỗi và đo lường chính xác hiệu quả kinh doanh
  2. Kịp thời (Timely): Hệ thống kế toán phải đáp ứng các nhu cầu cụ thể của doanh nghiệp
  • Với doanh nghiệp nhỏ, có thể chỉ cần đổ toàn bộ số liệu vào cuối tháng, nhưng doanh nghiệp lớn thường muốn hệ thống gần thời gian thực
    • Điều này giúp theo dõi tình hình tài chính trong suốt tháng, đưa ra quyết định dựa trên dữ liệu tài chính nhanh hơn và giảm áp lực chốt sổ vào đầu tháng/quý
  • Dù nhu cầu là gì, hệ thống kế toán của chúng ta phải đáp ứng đúng yêu cầu của doanh nghiệp và đúng với ý nghĩa kịp thời mà họ cần
  • Ghi chú của Wasteman

    • Mọi người thường bị lạc trong các cuộc tranh luận về hệ thống batch và streaming khi nói đến tính kịp thời
    • Theo quan điểm của tôi, với đa số hệ thống thì đây không phải là khác biệt quan trọng
    • Nó chỉ quan trọng nếu bạn quan tâm đến độ trễ cực ngắn từ vài giây đến vài phút
    • Nhưng tôi ngạc nhiên vì quá thường xuyên nghe mọi người tranh cãi nên làm gì trong khi người dùng thực ra không cần xem cập nhật quá vài lần mỗi ngày
    • Được yêu cầu không có nghĩa là thực sự cần thiết

Ba nguyên tắc kỹ thuật chính mà hệ thống kế toán nên tuân theo

  1. Tính bất biến (Immutability) và độ bền dữ liệu (Durability)
  • Cho phép kiểm toán, từ đó hỗ trợ gỡ lỗi và độ chính xác
  • Khi dữ liệu là bất biến, bạn có thể chụp lại trạng thái hệ thống vào bất kỳ lúc nào
  • Điều này giúp việc tính toán lại toàn bộ trạng thái từ một trạng thái trước đó trở nên rất dễ dàng, vì không có trạng thái nào bị mất
  • Dữ liệu đã được ghi vào bản ghi tài chính thì không thể xóa
  • Mọi chỉnh sửa đối với hệ thống phải được thể hiện dưới dạng giao dịch tài chính mới
    • Ví dụ: nếu hệ thống có lỗi khiến một dịch vụ đáng ra giá $900 lại bị ghi nhận là đã bán với giá $1000
    • Để sửa sai, trước tiên cần đảo bút toán kế toán tương ứng với sai sót đó, rồi ghi lại bút toán với số tiền chính xác
  1. Dữ liệu phải được ghi ở mức chi tiết nhỏ nhất (Data recorded at the smallest grain)
  • Tương tự nguyên tắc ở trên, điều này cũng cực kỳ quan trọng để tạo ra dấu vết kiểm toán rõ ràng
  • Dù báo cáo tài chính và sổ cái tổng hợp là dữ liệu đã được tổng hợp, chúng vẫn được tính từ các sự kiện chi tiết hơn
  • Khi dữ liệu không thể giải thích được, bạn cần dữ liệu ở mức chi tiết nhất để gỡ lỗi vấn đề là gì
  • Lưu dữ liệu ở mức chi tiết thấp nhất cũng giúp việc chỉnh sửa dữ liệu phát sinh từ tập dữ liệu đó trở nên rất dễ dàng
    • Nếu một tập dữ liệu bất biến duy nhất là nguồn sự thật cốt lõi cho mọi cách nhìn của dữ liệu đó,
    • thì để sửa một cách nhìn, bạn chỉ cần sửa dữ liệu rồi chạy lại pipeline tạo ra cách nhìn đó
  • Tương tự, khi kế toán viên chuẩn bị khóa sổ,
    • họ sẽ đối chiếu toàn bộ giao dịch đã phát sinh với số dư tài khoản để xác minh sổ sách là chính xác
    • nếu phát hiện chênh lệch, họ có thể đào sâu đến đúng giao dịch gây ra vấn đề
  1. Phải có tính idempotent (Idempotency)
  • Mỗi sự kiện tài chính chỉ được xử lý một lần, và dữ liệu trùng lặp trong bản ghi tài chính chắc chắn sẽ gây ra sai lệch rõ ràng
  • Vì lý do này, mọi đoạn mã tạo ra bản ghi tài chính đều phải là idempotent
    • Idempotent nghĩa là một phép toán dù được áp dụng nhiều lần thì kết quả vẫn không thay đổi
    • Tức là dù xử lý cùng một sự kiện tài chính nhiều lần, kết quả vẫn phải giống như lần xử lý đầu tiên

Thực hành tốt nhất

  • Ưu tiên dùng số nguyên để biểu diễn số tiền tài chính: các phép toán số học sẽ dễ hơn nhiều. Hãy tránh float
  • Hỗ trợ mức độ chi tiết phù hợp cho số tiền tài chính để giảm thiểu mất độ chính xác khi quy đổi tiền tệ
    • Nếu chỉ xử lý đô la, biểu diễn theo cent có thể là đủ
    • Với doanh nghiệp toàn cầu, nên ưu tiên đơn vị micro hoặc kiểu số thập phân như DECIMAL(19, 4)
    • Trong các hệ thống tài chính nói chung, số thập phân khá phổ biến, nhưng trong hệ thống tài chính quảng cáo thì micro là tiêu chuẩn
  • Sử dụng một phương pháp làm tròn nhất quán: cách làm tròn có thể tạo ra chênh lệch đáng kể so với số tiền kỳ vọng
    • Ví dụ, mọi giá trị từ 5 trở lên thì làm tròn lên chữ số có nghĩa tiếp theo, còn 4 trở xuống thì làm tròn xuống
    • Hoặc luôn làm tròn lên, v.v.
    • Điều quan trọng là phải giữ nhất quán trên toàn hệ thống (nếu lệch 1 cent mỗi giao dịch thì với 10 triệu giao dịch sẽ thành chênh lệch $100k)
  • Trì hoãn việc quy đổi tiền tệ càng lâu càng tốt: quy đổi tiền tệ quá sớm có thể làm mất độ chính xác
    • Hãy trì hoãn việc quy đổi cho đến sau khi đã tổng hợp theo đồng tiền địa phương
  • Sử dụng biểu diễn thời gian bằng số nguyên: hơi gây tranh cãi một chút nhưng rất đáng khuyến nghị
    • Nhiều thư viện khác nhau xử lý việc parse timestamp thành object theo những cách khác nhau
    • Tốt hơn là tránh những rắc rối này và dùng số nguyên
    • Unix timestamp hoặc datetime số nguyên dựa trên UTC đều hoạt động hoàn hảo
    • Càng ít chuyển đổi dữ liệu giữa các hệ thống càng tốt
    • Ghi chú của Wasteman

      • Tôi còn chưa nhắc đến các lỗi liên quan đến giờ tiết kiệm ánh sáng ban ngày. Dùng số nguyên tăng dần sẽ tránh được hoàn toàn
      • Nếu vẫn nhất quyết dùng datetime thì ít nhất hãy dùng UTC. Thật đáng ngạc nhiên là có rất nhiều công ty rất lớn vẫn dùng timestamp không phải UTC

2 bình luận

 
kandk 2024-07-12

Cái này thực sự rất hữu ích. Nếu cứ vô tư chuyển kiểu (decimal, float, double) và làm tròn mà không có thảo luận nghiệp vụ trong thực tế thì sẽ rất nguy hiểm.

 
GN⁺ 2024-07-12
Ý kiến trên Hacker News
  • Nhấn mạnh tầm quan trọng của việc sử dụng phương pháp làm tròn nhất quán

    • Đề cập sự cần thiết phải quản lý chiến lược làm tròn theo mã quốc gia trong mã miền nghiệp vụ
  • Khuyến nghị biểu diễn thời gian bằng số nguyên

    • Khuyên dùng Unix timestamp hoặc ngày giờ UTC dựa trên số nguyên
    • Có hiệu lực cho các mốc thời gian cụ thể trong quá khứ hoặc tương lai
    • Ví dụ: với công ty có chính sách hủy trong 48 giờ, có thể tính toán timestamp trong tương lai
    • Các trường hợp như thời điểm kết thúc năm tài chính theo từng quốc gia thì cần lưu múi giờ
  • Khuyến nghị sử dụng cơ sở dữ liệu quan hệ cho hệ thống kế toán

    • Cung cấp các thuộc tính ACID
    • Cung cấp kiểu dữ liệu số với độ chính xác tùy ý cùng các phép toán và chế độ làm tròn đã được kiểm chứng
    • Có thể tính toán và lập báo cáo thông qua SQL
    • Nếu thuê chuyên gia SQL, có thể tạo ra các báo cáo tinh gọn và đẹp
    • Cung cấp hiệu năng cao cùng các công cụ phòng ngừa và khôi phục thảm họa
    • Chia sẻ kinh nghiệm xây dựng hệ thống tài chính cho doanh nghiệp đa quốc gia
  • Mục tiêu chính của hệ thống kế toán là độ chính xác, khả năng kiểm toán và tính kịp thời

    • Tính nhất quán cũng được nhắc đến như một yếu tố quan trọng
    • Có nhiều chiều thời gian tồn tại, và cần cung cấp góc nhìn nhất quán theo từng chiều
    • Ví dụ: nếu giao dịch đã hoàn tất nhưng chưa được thanh toán bù trừ, thì chỉ được đưa vào kế toán front office
  • Ý kiến về tính toàn vẹn của hệ thống kế toán

    • Giả định rằng không phải mọi giao dịch đều được xử lý đúng hạn
    • Cần xử lý giao dịch qua nhiều lớp sổ cái và có quy trình đối soát
  • Với doanh nghiệp toàn cầu, khuyến nghị dùng ít nhất 8 chữ số thập phân

    • Nhấn mạnh sự cần thiết phải trì hoãn việc quy đổi tỷ giá càng lâu càng tốt
    • Quy đổi tỷ giá là một phần của nghĩa vụ pháp lý và kế toán
  • Đề cập tầm quan trọng của giao diện người dùng (UI)

    • Bày tỏ sự thất vọng với UI của phần mềm kế toán
    • Nhấn mạnh sự cần thiết của các giải pháp UI tốt hơn
  • Giải thích sự khác biệt giữa xử lý theo lô và xử lý dòng

    • Thiết kế của hai hệ thống hoàn toàn khác nhau
    • Có khó khăn trong việc xử lý khối lượng lớn dữ liệu hiện có
  • Chia sẻ kinh nghiệm xây dựng hệ thống hóa đơn bằng TypeScript

    • Giải thích cách ngăn lỗi làm tròn
    • Có cung cấp liên kết liên quan
  • Khuyến nghị sử dụng các lớp trong thư viện chuẩn

    • Khuyên dùng BigDecimal của Java và Decimal của Python
    • Nhấn mạnh sự cần thiết phải áp dụng tiêu chuẩn giữ cùng một scale hoặc lưu trữ scale
  • Giải thích khó khăn trong việc làm tròn và chia sẻ dữ liệu

    • Vấn đề khi chia sẻ dữ liệu với các hệ thống chỉ xử lý được hai chữ số thập phân
  • Chia sẻ kinh nghiệm làm API cho 10 ngân hàng hàng đầu của Mỹ

    • Đề cập vấn đề thiếu nhất quán trong cách lưu trữ lãi suất
    • Nhấn mạnh tầm quan trọng của tính nhất quán
  • Giới thiệu "Accounting Patterns" của Martin Fowler

    • Chia sẻ kinh nghiệm xây dựng hệ thống quản lý sự kiện tài chính
    • Có cung cấp liên kết liên quan