線稿索引所有 spec最後更新 2026-07-02
specs/accounting-module.md

進階會計模組(帳務拆分點)

一句話:帳務系統沿「掛帳台帳(確定性、每家旅行社都有)vs 金流對帳結算損益(複雜、通用性強、會計常用自己的 Excel/SOP)」這條縫拆開——核心 ERP 只負責「訂單應收 + 團控成本掛帳 + payables 應付」且能 Excel 匯出;多帳戶對帳 / 帳戶結算月結互抵 / 內外帳淨利 / 公司損益表 / 成本側多幣別 / 出款批次匯款檔 / 退款執行 全收進一個平台授權可開關的「進階會計模組」module_accounting,比照訂房 / 抽籤的子系統 gate)。不開的租戶用核心掛帳台帳 + 自家 Excel 記帳。

關聯:modules(gate 機制,本模組為第 5 個)· control-finance(掛帳 / payables = 拆分點核心側)· 被收進模組的會計 spec 見 §4。

1. 動機 / 問題

經理 + user(2026-06-28):

  • 傳統旅行社(吉光式)線控 / 團控帳本質是掛帳:訂單產生「應收」(團費 × 人數);團控把成本登成「應付 / 負項訂金單」(如 −100,000 TWD 或 3,000 美金)。到會計階段才用 Excel 紀錄或實際匯款單據整理。這層是確定性的、每家都一樣
  • 「錢實際落哪個帳戶、怎麼對帳、月結互抵、損益表」是金流真相——複雜、雜亂,且大部分旅行社會計傾向自己熟悉的流程 / 自建 SOP。把整個過程都塞進系統,對想用自己流程的會計反而是阻力。
  • 複雜度高 / 通用性強的會計流程適合單獨賣——拆成一個模組,荒野自己全開、未來其他旅行社可只買 ERP 核心 + 用自己的 Excel,或加購會計模組。

這與既有模組化拆售精神(modules:「適度模組化才能拆開販售」)同源——會計深度 = 第 5 個可選模組

範圍:定義拆分點(§2)、核心保留的掛帳台帳 + Excel 匯出介面(§3)、進階會計模組涵蓋(§4)、gate(§5)、既有會計 spec 的歸屬(§6)。 不做:重寫任何會計邏輯(各會計 spec 內容不變,本檔只定邊界與 gate);正式總帳 / 合併財報(未來會計模組更上層)。

2. 拆分點(the seam)

訂單應收 ──┐
團控成本掛帳(departure_costs) ──┤  掛帳台帳(accrual)        ← 核心 ERP(always-on)
payables 應付 ──┘   └─ 派生 per-departure 收入/成本/毛估
                          │
                          │  ⭐ 掛帳台帳 Excel/CSV 匯出(拆分點介面)
                          ▼
        ┌─────────────────────────────────────────────┐
        │  金流真相層(進階會計模組 · module_accounting) │
        │  錢落哪帳戶 → 對帳 → 帳戶間月結互抵 → 內外帳淨利  │
        │  → 公司損益表 → 多幣別精算 → 出款批次匯款檔 → 退款執行 │
        └─────────────────────────────────────────────┘
  • 掛帳(accrual)= 核心:訂單應收、departure_costs 成本掛帳(含代墊 / 憑證兩金額internal-external-ledger §2.1)、payables 出款應付(= 吉光「負項訂金單」)。per-departure「收入 − 成本 = 毛估」直接派生。每家旅行社的線控 / 團控都需要,不 gate
  • 金流真相 = 模組:錢落哪個帳戶、多帳戶對帳、帳戶間月結互抵、內外帳淨利 / 損益表、成本側多幣別精算、出款批次 / 匯款檔、退款執行路由。複雜、通用性強、會計常用自己的流程,整組受 module_accounting gate
  • 介面 = 掛帳台帳 Excel/CSV 匯出(§3.2):核心提供;買模組者由模組消費同一份掛帳資料做進階結算,不買者把匯出帶去自己的帳。

3. 核心保留(always-on)—— 掛帳台帳

3.1 核心財務能力(不 gate,任何租戶都有)

  • 訂單應收orders + order_charge_lines + 收款(order-money-model)。
  • 成本掛帳departure_costs 登記(control-finance §4),含代墊 / 憑證兩金額、有無發票、外幣可填(外幣金額屬掛帳;外幣精算 / WAC 屬模組)。嚮導 portal 現場填(guide-portal)。
  • 出款應付payables 請款核簽(control-finance §5.1–5.4)draft → approved → paid(= 負項訂金單的單據化)。
  • 團控財務區(營運數,不含毛利):per-departure 應收 / 實收 / 待收 / 真實成本合計(control-finance §7)。毛利 / 淨利不在團控 / 嚮導端顯示 —— 屬敏感財務,經 ledger.read(admin / accountant)。毛利「數字」本身是核心資料的算術(成交應收 − 真實成本),故 §3.2 掛帳台帳匯出(ledger.read)含毛利欄;但「跨梯次損益分析 / 可申報外帳 / 證明單核簽」的內外帳 nav 屬模組(internal-external-ledger §4)。

3.2 掛帳台帳匯出(拆分點介面,核心提供)

per-period / per-departure 匯出 Excel/CSV,給不買模組的會計帶去自己的帳:

區塊欄位
梯次彙總團名 / 出團日 / 人數 / 總收入(團費×人數,訂單派生) / 真實成本合計 / 毛利毛估
成本掛帳逐筆類別 / 廠商 / 代墊額 / 憑證額 / 有無發票 / 覆核狀態
應付清單收款對象 / 金額 / 狀態(draft/approved/paid)
應收清單訂單號 / 應收 / 實收 / 待收
  • 匯出走 Excel .xlsx 多分頁exceljs,route handler runtime='nodejs'/admin/accrual-ledger/export?period=YYYY-MM,四分頁=梯次彙總 / 成本掛帳逐筆 / 應付清單 / 應收清單)。資料層 buildAccrualLedger(db,{period})@toko-cloud/core/finance/accrual-ledger)。always-on 頁 /admin/accrual-ledger(期間選擇 + 匯出 + 梯次彙總 preview)。
  • 權限:ledger.read不需 module_accounting——這是核心出口(給不買模組的會計帶去自家 Excel)。毛利欄屬敏感財務,與整份匯出同受 ledger.read 閘;團控 / 嚮導端不出此匯出。

4. 進階會計模組涵蓋(受 module_accounting gate)

spec收進模組的部分
payment-accounts-reconciliation全部(多收款帳戶 + 逐帳戶對帳 + 帳戶幣別)
account-settlement全部(帳戶能力 / 費用路由 / account_transfers / 月結互抵 / 退款執行 / 退款批次匯出)
currency-exchange全部(牌告匯率 / 換匯 / 外幣帳戶 WAC;成本外幣金額留核心掛帳,雙率精算 / WAC進模組)
operating-expenses全部(公司營業費用 + 月損益表 computeCompanyPnL
internal-external-ledger僅分析面(淨利 / 可申報外帳 / 跨梯次損益 / 支出證明單核簽);成本兩金額登記留核心(§3.1)
control-finance §5.5 / §5.6出款批次 / 批次轉帳匯款檔 / 廠商目錄 + 確認;payables 請款核簽(§5.1–5.4)留核心

橫跨邊界的兩份internal-external-ledger(成本登記核心 / 淨利分析模組)與 control-finance(payables 核心 / 出款批次模組)——同一份 spec 兩側都有,gate 只罩分析 / 結算 / 匯出那半,不罩掛帳登記。

5. Gate(module_accounting,比照子系統型)

進階會計是跨功能子系統(非行程能力層、非產品線),gate 只到「整組開不開」,無逐行程旗標(比照訂房 / 抽籤,modules §3.2):

  • 平台層授權control_db.tenant.module_accountingmodules §3.1,provisioning CLI 管、租戶唯讀),預設 false;荒野 = true。經 proxy 注入 x-tenant-modules
  • helperaccountingActive(modules)return modules.accounting);模組所有 server action / 頁開頭過 requireAccountingModule()(off 時即使持 ledger.* / account_transfer.* 等權限也擋下,fail-closed)。
  • UI 顯隱module_accounting off →「對帳 / 內外帳·淨利 / 損益表 / 匯率管理 / 出款批次 / 帳戶結算」整組 nav 與頁不存在;租戶只剩團控財務毛估 + 掛帳台帳匯出(§3)。on → 全組出現。
  • 權限不變ledger.* / account_transfer.* / account_settlement.* / operating_expense.* / fx_exchange.* / supplier.* 仍是 RBAC 角色閘;模組 gate 是其上層的平台授權閘(兩閘皆過才生效,同 lodging 雙閘)。

6. 對既有 spec / roadmap 的影響

  • 各會計 spec 內容不改,只在開頭標「本 spec(或其結算 / 分析面)屬進階會計模組,受 module_accounting gate」。歸屬 SSOT = §4 表。
  • modules:§1 模組表加第 5 列、§2 核心 vs 模組分類加「🟫 進階會計模組」、§3.1 schema 加 module_accounting、§3.3 helper 加 accounting key + accountingActive / requireAccountingModule、§7 影響範圍同步。
  • roadmap:會計 spec 狀態不變(多為未實作草案);新增本拆分點為導覽 / changelog。
  • 已落地(F6,2026-06-28):gate 旗標 module_accounting(F0)+ helper accountingActive / requireAccountingModule@toko-cloud/core/modules)+ 頁閘 requireAccountingModuleOr404apps/web/.../admin/_accounting-guard.ts);掛帳台帳 .xlsx 匯出(核心 always-on);對帳 / 匯率 / 內外帳·淨利 / 出款批次 / 損益表 5 個 standalone 頁 + 其 module 寫 action 掛閘、nav 經 requiresAccounting 顯隱。
  • 已落地(follow-up,2026-07-02)/admin/settings 的三個 module 分頁(收款帳戶+費用路由 accounts / 費用類別 expense-categories / 內外帳費率 ledger-fees)改為 accountingActive(modules) server 端顯隱(module OFF → tab trigger + content 不渲染、目錄資料不抓);其 8 個 write action(create/updateReceivingAccountupsert/setFeeCategoryRoutecreate/update/setActiveExpenseCategoryupdateLedgerFeeRates)補 requireAccountingModule() fail-closed;accountant 於 module OFF 無任何可管設定 → 顯示「尚未開通進階會計模組」。fail-closed 由 apps/web/tests/settings-accounting-gate.test.ts 單元覆蓋(單一 dev 租戶無法 e2e module OFF)。

Changelog

版本日期變更Commit
42026-07-02設定頁 module 分頁 follow-up 落地(§5 / §6):/admin/settings 三個會計 tab(accounts / expense-categories / ledger-fees)改 accountingActive server 端顯隱 + 目錄資料 module OFF 時不抓;8 個對應 write action 補 requireAccountingModule() fail-closed;accountant + module OFF → 「尚未開通進階會計模組」空狀態。單元測試 settings-accounting-gate.test.ts
32026-06-28F6 落地(§3.2 / §5 / §6):掛帳台帳 .xlsx 多分頁匯出(exceljs,核心 always-on,ledger.read掛 module)+ buildAccrualLedger 資料層 + /admin/accrual-ledger 頁;對帳 / 匯率 / 內外帳·淨利 / 出款批次 / 損益表 5 頁掛 requireAccountingModuleOr404(404)+ 其 module 寫 action 掛 requireAccountingModule(fail-closed);nav requiresAccounting 顯隱;成本登記(團控)/ payables 請款核簽 / payments 留核心不 gate。module OFF fail-closed 由 modules.test.ts 單元覆蓋。設定頁 module 分頁顯隱列 follow-up。
22026-06-28金流→會計流程一致性修正 #1(§3.1 / §3.2):團控財務區改列「營運數(應收 / 實收 / 待收 / 成本合計),不含毛利」——收斂與 internal-external-ledger §4「毛利 / 淨利僅 ledger.read、不在團控 / 嚮導端」的矛盾;毛利「數字」是核心算術(成交應收 − 成本),故掛帳台帳匯出(ledger.read)含毛利欄,但跨梯次損益分析 nav 仍屬模組。
12026-06-28初版(經理 + user 拆分點裁決,spec 先行):定義帳務「掛帳台帳(核心)vs 金流對帳結算損益(模組)」拆分點;核心保留訂單應收 + departure_costs 成本掛帳(含代墊 / 憑證兩金額)+ payables 應付 + 團控毛估 + 掛帳台帳 Excel 匯出(拆分點介面);多帳戶對帳 / 帳戶結算月結互抵 / 內外帳淨利 / 公司損益表 / 成本多幣別精算 / 出款批次匯款檔 / 退款執行 收進一個 module_accounting(比照訂房 / 抽籤子系統 gate,無逐行程旗標)。internal-external-ledgercontrol-finance 橫跨邊界(登記核心 / 分析結算模組)。連改 modules(第 5 模組)。未實作。