AccOS Pro — Data Flow Diagram

วิเคราะห์เส้นทางการไหลของข้อมูลจาก Source Features สู่ Journal Entries (GL)Tax Forms และ Financial Reports
📋 60+ Thai Tax Forms 📊 6 Financial Reports 🗄 3 Computation Patterns 📄 Single Source of Truth: GL
AccOS Pro — Accounting Software | มิ.ย. 2026
5
Source Documents
1
Journal (Single Source of Truth)
60+
Tax Forms
6
Financial Reports
9
Computation Engines
🔀

ภาพรวม Data Flow Pipeline

Feature → Journal → Tax Forms / Financial Statements — Architecture Diagram

Sub-ledger direct path (Bills/Invoices → Tax Form — fast, pragmatic)
Journal Entry path (Auto-posted GL → Tax Form / Report — authoritative)
Cross-reference path (PND3+PND53 → PND1 combined)
flowchart TB
  subgraph SOURCE["📄 Source Documents"]
    INV["Invoices (AR)"]
    BILL["Bills (AP)
whtRate, whtAmount,
expensePeriod, taxPeriod"] PAY["Payroll
calcMonthlyPIT"] MAN["Manual Journal"] BANK["Bank Transactions"] end subgraph JOURNAL["📒 Journal Entries (GL) — Single Source of Truth"] direction TB JE["<b>journal_entries</b>
sourceType: invoice/bill/payroll/manual
status: draft→posted
taxPeriod, isCrossMonth"] JL["<b>journal_lines</b>
accountId → Chart of Accounts
debit / credit
vatRate/vatAmount
whtRate/whtAmount
costCenterId"] JE -->|1:N| JL end subgraph ENGINES["🧮 Computation Engines"] TE["tax-engine.ts
computePP30 / computePND1/3/53
computePP36 / computePor40"] CIT["cit-rules.ts
12 Add-back Rules
CIT_ADD_BACK_RULES"] BTR["book-tax-recon.ts
Build Book-Tax Differences"] RE["ratio-engine.ts
Financial Ratios"] EE["etax-engine.ts
validateForETax"] end subgraph REPORTS["📊 Financial Reports"] TB["Trial Balance"] WP["Working Paper"] PL["P&L"] BS["Balance Sheet"] CF["Cash Flow"] RATIO["Ratios"] end subgraph TAX["📋 Tax Forms"] PP30["ภ.พ.30 VAT"] PND3["ภ.ง.ด.3 WHT Indiv"] PND53["ภ.ง.ด.53 WHT Corp"] PND1["ภ.ง.ด.1 WHT Summary"] PP36["ภ.พ.36 CIT Half-Yr"] POR40["ภ.ย.40 CIT Annual"] PND50["ภ.ง.ด.50 Annual WHT"] end subgraph SPECIAL["🔖 Special"] ETAX["e-Tax Invoice/Receipt"] WHTCERT["50 ทวิ Cert"] HOTEL["ภ.ร.1/2 Hotel"] MISC["ภ.บ.จ./ภ.ธ.
Misc"] end INV ==>|auto-post| JE BILL ==>|auto-post| JE PAY ==>|auto-post| JE MAN ==>|sourceType manual| JE BANK ==>|reconcile| JE INV -.-> PP30 BILL -.-> PP30 BILL -.->|indiv vendor| PND3 BILL -.->|corp vendor| PND53 PND3 & PND53 -.-> PND1 JE ==>|journals wht lines| PND1 BILL -.-> PND50 JE ==>|revenue - expense - CIT| PP36 JE ==>|revenue - expense - CIT| POR40 JE & JL ==> PL JE & JL ==> BS JE & JL ==> CF JE & JL ==> TB TB & PL & BS ==> WP JE & JL ==o RATIO JE & JL & CIT ==> BTR INV -.->|generate| ETAX BILL -.->|group vendor| WHTCERT style SOURCE fill:#e8f4f8,stroke:#2c7fa0 style JOURNAL fill:#f8d7da,stroke:#b33,stroke-width:3 style ENGINES fill:#fff3cd,stroke:#d4a02b style REPORTS fill:#d4edda,stroke:#28a745 style TAX fill:#d1ecf1,stroke:#17a2b8 style SPECIAL fill:#d1ecf1,stroke:#6c757d
📄

Source Document Layer

เอกสารต้นทางแต่ละประเภท → ส่งข้อมูลเข้าสู่ Journal Entries (GL)

🟦

Invoices (AR) — ลูกหนี้

ใบแจ้งหนี้ขายสินค้า/บริการ — auto-post เข้า journal sourceType='invoice'
issueDate subtotal vatAmount customerId → PP30 Output VAT → e-Tax Invoice
🟨

Bills (AP) — เจ้าหนี้

ใบรับวางบิลซื้อสินค้า/บริการ — auto-post เข้า journal sourceType='bill'
billDate subtotal vatAmount whtRate/whtAmount expensePeriod/taxPeriod → PP30, PND3/53, PND1, PND50
🟪

Payroll — เงินเดือน

คำนวณภาษีเงินเดือนผ่าน Payroll Engine → auto-post journal sourceType='payroll'
salary PIT (monthly) WHT §40(1) → PND1 (ผ่าน journals WHT lines)

Manual Journal + Bank

บันทึก GL โดยตรง (sourceType='manual') + รายการเดินบัญชี (reconcile → journal)
sourceType='manual' sourceType='payment' → PND1 / PP36 / Por40
📒

Journal Entry Schema — Single Source of Truth

โครงสร้างของ journal_entries และ journal_lines ที่เชื่อมโยงทุก Feature สู่ Tax Forms และ Reports

📋 journal_entries

FieldTypePurpose
iduuidPK
companyIduuidMulti-tenant → FK to companies
sourceTypevarchar(30)🏷️ invoice / bill / payroll / manual / payment
sourceIduuid🔗 FK ย้อนกลับไปเอกสารต้นทาง
statusenumdraft / posted / approved / void
datedateวันที่ลงรายการ
taxPeriodvarchar(7)🏷️ YYYY-MM งวดภาษี (cross-month VAT support)
isCrossMonthboolean🚩 VAT ข้ามเดือน flag (→ migration 0011)
sourceBillIduuidFK to bills (สำหรับ VAT-only entries)
totalDebit/ Creditnumericควบคุม debit = credit เสมอ
reversalOfuuidself-reference — รายการกลับรายการ

📝 journal_lines

FieldTypePurpose
journalIduuidFK → journal_entries (CASCADE)
accountIduuid🏷️ FK → accounts (Chart of Accounts)
debit / creditnumeric💵 จำนวนเงิน (18,2)
vatRate / vatAmountvarchar / numeric🧾 '0' / '7' / 'exempt'
whtRate / whtAmountvarchar / numeric💰 '0' / '1' / '2' / '3' / '5'
costCenterIduuid🏢 FK → cost_centers
descriptiontextรายละเอียดบรรทัด
sortOrderintลำดับ
🔑 Key Rule: debit = credit เสมอ — ควบคุมที่ระดับ application
🔗 Source→Journal Traceability: sourceType + sourceId เชื่อมโยงทุกฟอร์มภาษีกลับถึงเอกสารต้นทาง
🏗️

Complete Data Pipeline — Feature → Journal → Output

แผนภาพรวมการไหลของข้อมูลจากทุก Feature สู่ Journal Entries และปลายทางทั้งหมด

flowchart TD
    subgraph DOCS["📦 Source Documents"]
        Q["Quotations
(ใบเสนอราคา)"] PO["Purchase Orders
(ใบสั่งซื้อ)"] INV1["Invoices (AR)
subtotal, vatAmount"] BILL1["Bills (AP)
whtRate, whtAmount,
expensePeriod, taxPeriod"] PAY1["Payroll
salary, PIT, WHT"] INV2["Inventory
Stock Movements"] BANK1["Bank Statements"] FA["Fixed Assets
Depreciation"] VENDOR["Vendors / Customers
taxId, branch"] end Q -->|convert| INV1 PO -->|convert| BILL1 DOCS -.->|auto-post| JE1["📒 Journal Entries
Single Source of Truth
sourceType: invoice/bill/payroll/manual
status: draft→posted"] BILL1 -.->|WHT individual| PND3_1["ภ.ง.ด.3"] BILL1 -.->|WHT corporate| PND53_1["ภ.ง.ด.53"] BILL1 & JE1 -.->|PND1 combine| PND1_1["ภ.ง.ด.1"] BILL1 -.->|annual WHT| PND50_1["ภ.ง.ด.50"] INV1 & BILL1 -.->|VAT| PP30_1["ภ.พ.30"] JE1 ==>|CIT half-year| PP36_1["ภ.พ.36"] JE1 ==>|CIT annual| POR40_1["ภ.ย.40"] BILL1 & VENDOR -.->|cert| CERT1["50 ทวิ Cert"] FA -.->|depreciation| DEP1["Depreciation Sched"] BANK1 -.->|reconcile| RECON1["Bank Recon"] INV2 -.->|valuation| IVAL1["Inventory Val"] INV1 -.->|ETDA/RD| ETAX1["e-Tax Invoice"] JE1 ==>|period filter| PL1["📊 P&L"] JE1 ==>|as-of date| BS1["📊 Balance Sheet"] JE1 ==>|activity class| CF1["📊 Cash Flow"] JE1 ==>|all lines| TB1["📊 Trial Balance"] TB1 & PL1 & BS1 ==> WP1["📊 Working Paper"] PL1 & BS1 ==> RATIO1["📊 Ratios"] style DOCS fill:#e8f4f8,stroke:#2c7fa0 style JE1 fill:#f8d7da,stroke:#b33,stroke-width:3 style PL1,BS1,CF1,TB1,WP1,RATIO1 fill:#d4edda,stroke:#28a745 style PP30_1,PND3_1,PND53_1,PND1_1,PND50_1,PP36_1,POR40_1 fill:#d1ecf1,stroke:#17a2b8 style ETAX1,CERT1 fill:#d1ecf1,stroke:#6c757d
📋

Tax Form Computation Detail

รายละเอียดการคำนวณฟอร์มภาษีแต่ละประเภท — Source Data, Engine, Logic

📥 Source Data

Invoices (AR) — output VAT ฝั่งขาย
Bills (AP) — input VAT ฝั่งซื้อ
Vendors/Customers — taxId (export check)

invoices.issueDateinvoices.subtotalinvoices.vatAmountbills.billDatebills.subtotalbills.vatAmount

⚙️ Computation

computePP30(period, invoices, bills, vendors, customers)

outputVat = Σ invoice.vatAmount (filter: ไม่ใช่ void)
inputVatAllowed = Σ bill.vatAmount — forbidden (entertainment/gift)
vatPayable = outputVat — inputVatAllowed

📐 Export Check: ถ้า customerTaxId ไม่ใช่เลข 13 หลักที่ขึ้นต้นด้วย 0 → ถือเป็น export (zero-rated VAT)

📥 Source Data

Bills (AP) only — filter vendor.type = 'individual'

WHT สำหรับบุคคลธรรมดา (รับเหมา/บริการ/ค่าโฆษณา ฯลฯ)

bills.billDatebills.subtotalbills.whtRatebills.whtAmount

⚙️ Computation

computePND3(period, bills, vendors)

= computeWHTBase(period, bills, vendors, 'individual')

filter bills ในงวด where whtAmount > 0, vendor.type='individual'
จัดกลุ่มตาม IncomeType40 (1-6)

📥 Source Data

Bills (AP) only — filter vendor.type = 'corporate'

WHT สำหรับนิติบุคคล (ค่าจ้างทำของ/บริการ)

bills.billDatebills.subtotalbills.whtRatebills.whtAmount

⚙️ Computation

computePND53(period, bills, vendors)

= computeWHTBase(period, bills, vendors, 'corporate')

filter bills ในงวด where whtAmount > 0, vendor.type='corporate'
จัดกลุ่มตาม IncomeType40 (1-6)

📥 Source Data (HYBRID — 3 Sources)

Bills → PND3 + PND53 (sub-ledger)
Journal Entries (GL)computeWHTFromJournals()
รวม payroll + manual WHT entries

billsvendorsjournals (whtRate>0)

⚙️ Computation

computePND1(period, bills, vendors, branchId, journals)

1️⃣ computePND3() → pnd3
2️⃣ computePND53() → pnd53
3️⃣ computeWHTFromJournals() → journalWHT
4️⃣ Combine all breakdowns by IncomeType40

totalRemitted = pnd3.totalWht + pnd53.totalWht + journalWHT.wht

⚠️ Design Note (AGENTS.md §8.1): ใช้ Bills โดยตรงเป็น shortcut (เร็ว) แต่ conceptual ideal คืออ้างอิงจาก journals ทั้งหมด

📥 Source Data

Journal Entries (GL) 100% — ครึ่งปี

ภ.พ.36 ยื่นภาษีเงินได้นิติบุคคลครึ่งปี (ภายใน 2 เดือนหลังรอบ 6 เดือน)

journals (status=posted, 6-month range)accounts

⚙️ Computation

computePP36(year, half, journals, accounts, estimatedTaxPaid, manualAdjustments)

= computeCIT(year, 'mid_year', journals, accounts, half, ...)

journals → totalRevenue - totalExpense → accountingNetProfit
+ addBacks (CIT_ADD_BACK_RULES auto-detect)
- deductions
= taxNetProfit → calculateCITProgressive() → CIT Amount

📐 CIT Progressive Tax Rates

กำไรสุทธิ ≤ 300,000 → 0% (ยกเว้น)
กำไรสุทธิ ≤ 3,000,000 → 15%
กำไรสุทธิ > 3,000,000 → 20%

📥 Source Data

Journal Entries (GL) 100% — รอบปี

journals (status=posted, full year)accounts

⚙️ Computation

computePor40(year, journals, accounts, exemptions, manualAdjustments, manualDeductions)

= computeCIT(year, 'annual', journals, accounts, undefined, 0, exemptions, ...)

เหมือน PP36 แต่ full year + exemptions

📥 Source Data

Bills (AP) only — รวบรวมทั้งปี

bills (all year)vendors

⚙️ Computation

computePND50Annual(year, bills, vendors)

รวบรวมผู้ถูกหักภาษี ณ ที่จ่ายทั้งหมดในปี (ภ.ง.ด.50 ประจำปี)

📥 Source Data

Invoices (AR) + Customers + Company

invoice.idcustomer.taxIdcustomer.branchcompany.taxIdcompany.vatRegistered

⚙️ Computation

generateETaxFromInvoice() → ETaxInvoice
validateForETax() → ETaxValidation

Validation rules:
✅ customer.taxId = 13 digits
✅ customer.branch = 5 digits
✅ company.vatRegistered = true
✅ invoice.total > 0, lines > 0

simulateRDSubmission() → Mock RD Gateway

🧩

3 Computation Patterns

Tax Forms แต่ละประเภทใช้เส้นทางการคำนวณที่แตกต่างกัน—ขึ้นอยู่กับว่า Source Data อยู่ที่ใด

🔶 Sub-ledger Direct

อ่านจาก Bills/Invoices โดยตรง (เร็วที่สุด—ไม่ต้อง query journals)

PP30 PND3 PND53 PND50
ข้อดี: Query ง่าย, performance ดี
ข้อเสีย: bypass journals — อาจพลาดรายการที่ไม่มีใน sub-ledger

🟢 Pure GL (Journals)

คำนวณจาก Journal Entries 100% — revenue, expense, add-backs

PP36 (ภ.พ.36) Por40 (ภ.ย.40)
ข้อดี: ถูกต้องที่สุด—ทุกอย่างผ่าน GL
ข้อเสีย: ต้อง load journals + accounts → heavy query
CIT Add-back Rules: 5220→entertainment, 5440→provisions, 5500→penalty, 5910→loss-on-sale → auto detect!

🔴 Hybrid

Sub-ledger + Journals — รวมผลลัพธ์จากทั้งสองเส้นทาง

PND1 (ภ.ง.ด.1)
PND1 = PND3 (bills indiv)
+ PND53 (bills corp)
+ computeWHTFromJournals()
— รวมทุก breakdown ตาม IncomeType40
📐

CIT Add-back Rules (12 Rules)

กฎการบวกกลับสำหรับคำนวณกำไรทางภาษี — auto-detect จาก account code ใน journal lines

Rule ID รายการ (Thai) Account Pattern Auto? กฎหมาย
AB-DEP-EXCESSค่าเสื่อมราคาเกินกว่าอัตราที่กฎหมายกำหนด15165010-5030Manualมาตรา 18 ตรี
AB-ENTERTAINMENTค่ารับรอง/เลี้ยงรับรอง5220-5240✅ Autoมาตรา 65 ตรี (4)
AB-DONATIONเงินบริจาคเกิน 2% ของกำไรสุทธิ5310-5320Manualมาตรา 65 ตรี (5)
AB-BAD-DEBTหนี้สูญที่ตัดบัญชีโดยขาดหลักฐาน5410-5420Manualมาตรา 65
AB-PROVISIONSค่าเผื่อ/เงินสำรองที่หักไม่ได้ทางภาษี5440-5450✅ Autoมาตรา 65
AB-AMORT-EXCESSค่าตัดจำหน่ายสินทรัพย์ไม่มีตัวตนเกิน5070-5080Manualมาตรา 18 ตรี
AB-PENALTYค่าปรับและเบี้ยปรับ5500-5510✅ Autoมาตรา 65 ตรี (6)
AB-INTEREST-EXCESSดอกเบี้ยจ่ายเกินอัตราส่วนทุน5610-5620Manualมาตรา 65 ตรี (5)
AB-CONTRIBUTIONเงินสมทบกองทุนสำรองเลี้ยงชีพเกิน 15%5520Manualมาตรา 47 ทวิ
AB-LOSS-SALEขาดทุนจากการขายสินทรัพย์5910✅ Autoมาตรา 18 ตรี
AB-RELATED-PARTYรายการที่เกี่ยวข้องกันไม่เป็นไปตามราคาตลาดManualมาตรา 65 ทวิ
AB-DEFERRED-INCOMEรายได้ที่ยังไม่เกิดขึ้นจริง4310-4320Manualมาตรา 65
🔍 Auto-detect logic: detectAdjustments(journalLineData) ← เปรียบเทียบ account.code กับ accountPatterns → ถ้า match → add-back
📊

Financial Reports Detail

งบการเงินทั้ง 6 ประเภท — ทุก报告คำนวณจาก Journal Entries (GL) 100%

Report Function Source Filter Condition Grouping Logic
📊 P&L
งบกำไรขาดทุน
buildProfitLoss() journals status=posted/approved
date ∈ [periodStart, periodEnd]
subCategory: operating_revenue, cost_of_sales, operating_expense, other_revenue, other_expense
📊 Balance Sheet
งบดุล
buildBalanceSheet() journals status=posted/approved
date ≤ asOf
category: asset=Dr-Cr, liability/equity=Cr-Dr
subCategory: current_asset/fixed_asset...
📊 Cash Flow
งบกระแสเงินสด
buildCashFlow() journals status=posted/approved
date ∈ [periodStart, periodEnd]
subCategory: fixed_asset→investing
long_term/equity→financing
else→operating
📊 Trial Balance
งบทดลอง
buildTrialBalance() journals All journals ทุก account → sum debit/credit
📊 Working Paper
กระดาษทำการ
buildWorkingPaper() journals TB → adjustments → adjusted TB split rows to P&L / BS destination
📊 Ratios
อัตราส่วนทางการเงิน
computeFinancialRatios() journals + accounts balances + P&L totals sumByPrefix(code) → current, D/E, ROA, ROE, DSO, DPO, DIO, CCC

🧮 Balance Sheet Calculation

for each journal line:
  net = debit - credit
  if account.category == "asset" || "expense":
    balance += net       // Dr increases
  else:
    balance -= net       // Cr increases

→ group by subCategory → current/fixed/other assets
→ section.total = sum(items) where balance ≠ 0
→ balanced = |totalAssets - (liabilities + equity)| < 1
      

🧮 P&L Calculation

for each journal line (period filter):
  net = debit - credit
  if account.category == "revenue":
    balance -= net      // Cr = income
  else:
    balance += net      // Dr = expense

→ group by subCategory
→ revenue = Σ operating_revenue
→ cogs = Σ cost_of_sales
→ grossProfit = revenue - cogs
→ netProfit = grossProfit - expenses + otherIncome - otherExp
→ ebitda = operatingProfit + depreciation (acct code 55xx)
      
📊

Complete Feature → Output Matrix

ทุก Feature → Tax Form / Financial Report ที่เกี่ยวข้อง

Feature / Source Auto-post → GL Tax Forms ที่เกี่ยวข้อง Financial Reports บทบาทใน Journal
Invoices (AR) PP30PP36Por40e-Tax Invoice P&L (revenue)BS (AR)Ratios (DSO) sourceType='invoice' → output VAT, revenue
Bills (AP) PP30PND3/53PND1PND5050 ทวิ P&L (cogs/exp)BS (AP)Ratios (DPO) sourceType='bill' → input VAT, WHT, expense
Payroll PND1(via journals) P&L (salary)BS (payable) sourceType='payroll' → WHT §40(1) lines
Manual Journal PND1PP36Por40 P&L / BS ใดๆ sourceType='manual' — ปรับปรุง GL โดยตรง
Bank Transactions (reconcile) BS (cash)CF (operating) reconcile → journal กระทบยอด
Fixed Assets (depr.) PP36/Por40 (add-back) BS (fixed asset)P&L (depreciation) ค่าเสื่อม → expense → CIT add-back
Inventory (COGS) P&L (COGS)BS (inventory)Ratios (DIO) COGS → expense, stock → asset

Tax Filing State Machine

ทุก Tax Form ผ่านสถานะเดียวกัน — draft → ready → reviewing → approved → filed → acknowledged

stateDiagram-v2
    [*] --> draft : create
    draft --> ready : prepare / compute
    ready --> reviewing : submit
    reviewing --> approved : senior approve
    reviewing --> rejected : reject
    rejected --> ready : revise & resubmit
    approved --> filed : file (paper or e-Filing)
    filed --> acknowledged : receive RD number
    acknowledged --> [*]
    note right of filed
        e-Filing: stub — awaiting RD Gateway
    end note
  

👮 Permissions per Step

journal:create → draft/ready
journal:approve → submit/approve/file

📋 Audit Trail (approvalHistory)

prepared → submitted → approved → filed → acknowledged
ทุก step: userId + userName + timestamp
⚙️

Computation Engine Architecture

Engines ทั้งหมดใน packages/shared/src/accounting/ — แยกตามหน้าที่

📐 tax-engine.ts

Engine หลัก: computePP30, computePND1/3/53, computePND50Annual, computePP36, computePor40, computeWHTFromJournals, computeCIT

📐 tax-orchestrator.ts

generateMonthlyForms() — สร้าง PP30+PND3+PND53+PND1 พร้อม cross-ref พร้อมกันใน call เดียว

📐 cit-rules.ts

CIT_ADD_BACK_RULES (12 rules) + detectAdjustments() + calculateCITProgressive()

📐 book-tax-recon.ts

buildReconciliation() — เปรียบเทียบ bookNetProfit vs taxNetProfit → BookTaxDifference[]

📐 tax-pdf.ts

renderPND1PDF(), renderWHTCertPDF(), printTaxForm() — สร้าง HTML พิมพ์ได้

📐 etax-engine.ts

generateETaxFromInvoice(), validateForETax(), simulateRDSubmission() — ETDA/RD standard

📐 ratio-engine.ts

computeFinancialRatios() — Liquidity, Leverage, Profitability, Efficiency ratios

📐 payroll-engine.ts

calcMonthlyPIT(), calcPayrollLine() — ภาษีเงินเดือน → auto-post journal lines

📐 tax-deadlines.ts

getWHTDueDate(), getPP30DueDate() — คำนวณวันที่ครบกำหนดยื่น