业财一体化自动记账 · 技术方案(V3 · 原型对齐版)
版本演进:V1(票据驱动骨架)→ V2(数据流转细节)→ V3 本版:主线正式改为《业财一体化自动记账系统技术方案 V1.0》的业务事件驱动路线;V1/V2 的票据池、字段映射字典、建账迁移等资产降级为"票据兜底模式"与"基础组件"章节并入,全部保留不弃。 本版特点:与已完成的 41 个原型页一一对齐(第十六章对照表),可直接作为开发实现说明。 配套:《业财一体化财务核算需求文档.md》《自动记账任务清单.md》《业财一体化原型设计方案.md》。 日期:2026-10-09
一、总览与设计原则
① 企业业务系统(本平台自身)
合同 · 采购 · 项目 · 费用 · 资金 · 应收应付 · 资产 · 薪资 · 库存
↓ 业务事件(Outbox 可靠投递)
② 业务事件中心 ── 鉴权/标准化/幂等/事件存储/重放
收入确认 · 采购验收入库 · 收付款 · 费用确认 · 薪资计提 · 资产折旧
↓
③ 会计事项中心(枢纽)── 确认/合并/拆分/状态/证据关联/金额分层
↓
④ 智能会计规则引擎 ── 条件判断 → 会计期间 → 科目匹配 → 票据勾稽 → 防重校验
分支:不满足→待补证/待裁定;规则缺失→异常
↓ 生成
⑤ 凭证中心 ── 待审核凭证(AI标记)→ 财务复核 → 正式入账
↓ 入账后
⑥ 总账 · 明细账 · 科目余额表 · 财务报表 · 月末结账 · 业财对账
六原则(详见需求文档 1.3):业务变化≠会计确认;会计确认≠付款;凭证生成≠正式记账;一事多源唯一确认;两种输入一套引擎;行业准则参数化。
二、总体架构
2.1 服务边界
| 服务 | 职责 | 技术建议 |
|---|---|---|
| 业务模块(已有) | 业务数据主存、审批、合同/采购/项目真实状态;同事务写 outbox_event | 现有栈 |
| 事件接入服务 | 事件适配、签名鉴权、标准化、唯一键、去重、事务消息 | 与业务同库 Outbox |
| 会计核算服务(主事务域) | 事项状态、规则计算、凭证落库、过账、核销、对账;保证一致性 | Java 主栈(复用既有后端) |
| AI 识别服务 | 发票 OCR、分类建议、解释输出;不直接写总账 | 可 Python 独立部署 |
| 已有财务模块 | 建账、票据池、凭证、账簿、期末结账;以 API/事件整合 | 复用改造 |
2.2 基础设施(P0 最简可行)
- MySQL 8+/PostgreSQL;Outbox + Worker(消息总线 Kafka/RabbitMQ 非 P0 硬性前置,现有则复用);
- Redis 仅做短时锁与缓存,不作最终防重依据;对象存储存附件;定时调度跑期末任务与对账。
2.3 运行模式适配(业财一体 / 纯记账)
账套级配置 accounting_book.run_mode ∈ {integrated, bookkeeping_only},同一引擎、同一数据模型,差异仅在"事件源"与"UI 启用范围":
| 组件 | integrated(业财一体) | bookkeeping_only(纯记账) |
|---|---|---|
| 事件通道 | recognition / settlement / adjustment 事件全开(业务模块发布) | 仅票据推断与资金事件:bill.inferred、cash.received/paid(票据池与流水直接入池触发);业务事件通道关闭 |
| 事项创建 | 事件 → 候选事项 → 复核 | 引擎自动创建事项(高置信票据直达 VOUCHER_DRAFTED,事项层对用户透明,UI 以"凭证来源"呈现) |
| 期间任务 | 全部(含薪资/资产计提) | 有数据才生成(无薪资/资产数据自动跳过) |
| UI | 41 页全量 | 隐藏业务台账组;业财对账页动态裁剪为"收款↔应收、银行↔总账";其余一致 |
| 模式切换 | 接入业务模块 → 改配置升级,无需数据迁移;停用则降级 | 同左 |
实现要点:① 规则引擎按 applicable.mode 过滤规则集(票据兜底规则两模式通用);② 对账页数据源声明式配置(哪些对账组依赖哪些事件通道);③ 前端按 run_mode 控制菜单渲染(后端返回可见菜单树)。
三、业务事件中心
3.1 标准事件契约
{
"event_id": "evt_01J...", "event_type": "purchase.goods_accepted",
"event_version": 1, "tenant_id": "T001", "legal_entity_id": "LE001",
"source_system": "purchase", "source_type": "receipt", "source_id": "RK202610001",
"source_revision": 2, "occurred_at": "2026-10-09T10:30:00+08:00",
"received_at": "2026-10-09T10:30:03+08:00",
"currency": "CNY",
"payload": {
"supplier_id": "SUP1001", "purchase_order_id": "PO1001",
"accepted_amount_ex_tax": "10000.00", "tax_amount": "1300.00",
"items": [{"sku": "SKU01", "qty": "10", "unit_cost": "1000.00"}],
"evidence_ids": ["evd_receipt_1001"]
},
"trace_id": "trace-xyz"
}
约束:金额一律十进制字符串 / DECIMAL(20,4);事件事实不可编辑,修正走新 revision;occurred_at 不替代会计确认日期。
3.2 投递与幂等
- 业务主库事务同写业务记录与 outbox_event,后台发布器投递;
- 消费端按
(tenant_id, source_system, event_id)唯一键写 Inbox,重复投递直接返回已处理结果; - 同单据按
source_revision判序,乱序暂存重建; - 至少一次投递 + 持久化唯一约束 = 效果上的一次确认;错误队列支持重试/死信/人工重放,重放不产生重复事项。
3.3 事件分类与本系统事件源接入清单
| 分类 | 语义 | 本系统事件(模块 → 事件) |
|---|---|---|
| informational | 只更新关联 | 合同签署(合同模块)、采购下单 |
| recognition_candidate | 进入确认判断 | 履约确认(合同/项目)、货物验收(库存/采购)、费用确认(报销审批通过)、薪资批次确认、资产达到可用状态 |
| settlement | 资金会计事项 | 收款到账 / 付款完成(收付款模块)、核销、退款 |
| adjustment | 更正类 | 退货、折让、发票红冲、撤销验收 |
| periodic | 期末任务 | 工资计提、折旧、摊销、计提税金、结转损益 |
四、会计事项中心(核心枢纽)
4.1 事项唯一性(防重键)
tenant_id + book_id + business_object_type + business_object_id
+ accounting_action + recognition_slice_id + recognition_version
slice_id:分批入库行、进度期次、收付款流水、工资月份等确认粒度;version:更正版本;同期调整通过独立 adjustment 事项关联原事项,只允许一个有效版本入账;- 付款核销(settle)与收入确认(recognize)是不同 accounting_action;
- 汇总凭证经
accounting_event_voucher关联表实现 N:M,不能依赖凭证表的单一 source_id。
4.2 状态机
RECEIVED → EVALUATING → READY → VOUCHER_DRAFTED → POSTED → ADJUSTED
│ ├→ NOT_RECOGNIZED(不确认,保留原因+规则版本)
│ ├→ NEED_EVIDENCE(待补证)→ 补证 → EVALUATING
│ └→ NEED_REVIEW(含待裁定)→ 人工裁定 → READY
POSTED 后不可删;更正走红字/调整事项 + 审计链
4.3 金额分层与证据
事项持有 recognized_amount / settled_amount / invoiced_amount / tax_amount(可不等),经 accounting_event_source(多来源事件)与 accounting_event_evidence(发票/流水/验收 N:M)关联凭据;命中多候选时展示原因与置信度待人工确认。
五、会计规则引擎
5.1 规则样例(YAML,税率另由独立规则控制)
rule_code: PURCHASE_GOODS_ACCEPTED_V1
version: 1
applicable: { accounting_standard: [ENTERPRISE_STANDARD], industry_tags: [TRADE, GENERAL], event_type: purchase.goods_accepted }
priority: 100
recognition:
expression: "event.acceptance_confirmed == true && event.cost_reliable == true"
required_fields: [supplier_id, accepted_amount_ex_tax, goods_category]
measurement: { amount_source: accepted_cost, currency_policy: book_currency }
entries:
- { direction: DEBIT, subject_selector: inventory_subject_by_category, amount_expression: recognized_cost }
- { direction: CREDIT, subject_selector: payable_or_estimated_payable, amount_expression: recognized_cost }
controls: { requires_finance_review: true, confidence_below_threshold: NEED_REVIEW, prohibit_closed_period: true }
5.2 匹配次序与执行步骤
匹配:账套/制度过滤 → 事件类型条件 → 企业定制 → 行业模板 → 系统通用 → 无匹配转人工(AI 仅建议候选,不改政策)。
执行:标准化 → 关联已有事项 → 判断确认条件 → 计量金额/税额 → 科目及辅助核算 → 凭证分录 → 借贷平衡 → 唯一性/期间校验 → 生成待审核凭证。
5.3 版本与发布(对齐原型规则中心)
草稿/测试/已发布/停用四态;版本不可覆盖,按会计期间配生效区间;历史凭证保留 rule_version + 输入快照 + 输出分录 + 执行日志(rule_execution_log);试运行抽样对照不写账;表达式引擎白名单,禁任意脚本。
六、凭证桥接
- 状态机:
待审核 → 已审核 → 已记账(过账) → 已报税(锁定);AI/规则凭证默认强制人工复核;制单人不可自审;金额分级审批(>50 万走复杂流程)。 - 凭证号:业务关联先用不可变
voucher_id,正式编号按账套/期间/凭证字受控分配(失败重试不占号);支持凭证号整理(断号重排、原号留痕)。 - 冲销与更正:红字冲销凭证(借贷反向、负金额、关联原凭证);已入账不可删改;删除仅限前两态进回收站。
- 期间治理:四日期分离——
business_date(业务发生)/recognition_date(会计确认)/voucher_date(凭证日期)/accounting_period(记账期间)+document_date(票面);已关账期间的迟到单据进跨期异常,禁止"保留历史凭证日期但计入下一期间"。
七、票据与流水证据体系(兜底模式,服务无业务数据客户)
定位:V1/V2 方案的精华保留区。财务日常只做"导入流水 + 导入发票",其余全部自动。
7.1 证据中心(票据池)
- 四池:销项票 / 进项票 / 费用票 / 银行对账单;发票按
代码+号码、流水按流水号去重; - 入池前预处理:清洗标准化 → 去重 → 关键词分流(《发票管理.md》黑白名单:项目/工程类强制合同付款票;差旅餐饮办公类归报销票;兜底合同付款票);
- 状态机:未记账 → 审核中 → 已记账(与凭证审核入账同步回写);另有 待定性(流水无业务单)与 待补证(缺履约证据)两个冻结态——不可生成凭证,须经事项裁定/补证。
7.2 三级匹配与生成方式
L1 关键词分流(发票管理.md 定稿库)
L2 票据凭证模板精确匹配(费用 16 类内置模板)
L3 AI 统计推荐(同特征历史票据模板 Top1;低置信 → 标记"未指定"人工指定)
生成方式:按单(收付款类,事件即时)/ 汇总(费用类,月末按模板聚合)/ 结账时(计提结转类)
7.3 字段级映射字典(摘要)
| 来源 | 关键字段 → 分录 |
|---|---|
| 销项发票 | 价税合计→借 1122(赊销)/ 1002(已收款);不含税→贷 6001;税额→贷 2221 销项;购买方→客户辅助 |
| 银行流水 | 方向归一→借/贷 1002;匹配到发票→冲 1122/2202;摘要"工资"→借 2211;"提现"→借 1001;对方户名→客户/供应商辅助 |
| 费用票/报销 | 费用类型→借方科目(模板定);小规模价税不拆;支付方式→贷 1002/1001;未打款→贷 2241;部门/报销人→辅助 |
| 期末计提 | 薪资批次.应发→借 660201 / 贷 2211;资产卡片.月折旧→借 660202 / 贷 1602;销项-进项→借 税金及附加 / 贷 2221;损益净额→结转损益(系统强制) |
7.4 禁止性规则(兜底模式更严)
- 未匹配流水禁止默认认收入/费用:必须先分类为 预收 / 应收回款 / 借款 / 往来 / 内部转账 / 现销收入(人工裁定,理由留痕);
- 票据推断收入须有履约/交付证据(缺 → 待补证);发票仅做税额与凭据关联,不重复确认收入。
八、建账迁移引擎(基础组件,保留 V2 精华)
- 主路径:金蝶/用友导出「科目余额表」→ 建账向导七步(新建账套 → 选来源 → 上传 → 列映射确认 → 科目对照确认(≥90% 自动)→ 试算平衡 → 完成);
- 产出:科目体系(级次自适应推断 4-2-2-2)+ 初始余额(损益类录本年累计)+(可选)历史凭证只读入库(LEGACY 标记);
- 兜底:只有三表时按"报表项目→科目"映射反推(货币资金→现金+银行等),不生成历史凭证;
- 约束:试算不平衡阻断;损益期初必须为 0;映射结果存为模板复用;反结账不得越过迁移点。详见《账套迁移建账需求文档.md》。
九、对账与期末
- 业财对账(四组):合同履约↔收入、收款↔应收、采购↔应付、银行↔总账;业务口径与账面口径并列,差异行直接闭环(生成事项/前往裁定/查看异常/生成核销)。
- 三道锁:业务-资金(流水↔发票自动匹配,金额±0.01+对手方+日期窗);账证(凭证汇总表=科目余额表发生额);账实(存货=1403、资产=1601/1602、试算平衡=结账硬门槛)。
- 期末结账引擎:8 项检查(阻断 / 警告 / 例外审批 三级,未启用模块跳过)→ 结账时生成(计提类)→ 结转损益(系统强制)→ 试算平衡(不平回滚)→ 锁期出正式报表 → 反结账留痕。
十、防重与幂等(三层)
| 层 | 唯一键 | 防的是什么 |
|---|---|---|
| 事件层 | Inbox(tenant, event_id) | 重复投递 |
| 事项层 | 六要素(含 slice + version) | 重复确认(支持一单多事项、多次确认) |
| 凭证层 | accounting_event_voucher + 按单生成约束 | 重复出证 |
| 任务层 | 汇总/结账任务幂等(票据状态机排除已生成) | 重跑重复 |
| 回流 | 驳回 → 票据回"未记账" → 重指定模板再生成(旧凭证进回收站) | 驳回后重复 |
十一、数据模型(DDL 级)
-- 新增(事件/事项/规则/关联/对账/异常)
business_event(id, tenant_id, event_id, event_type, source_system, source_id, revision,
occurred_at, payload_json, process_status, UNIQUE(tenant_id, source_system, event_id))
accounting_event(id, tenant_id, book_id, business_object_type, business_object_id,
action_code, slice_id, revision, recognition_date, accounting_period, currency,
recognized_amount, status, rule_code, rule_version, supersedes_event_id,
UNIQUE(tenant_id, book_id, business_object_type, business_object_id, action_code, slice_id, revision))
accounting_event_source(event_id, business_event_id, relation_type)
accounting_event_evidence(accounting_event_id, evidence_id, relation_type, matched_amount)
accounting_rule(id, code, version, event_type, standard, industry, condition_json, entry_json,
effective_period, status) -- 版本不可覆盖
accounting_event_voucher(accounting_event_id, voucher_id, amount, role) -- N:M
settlement_allocation(id, settlement_event_id, target_event_id, amount, currency, status)
accounting_exception(id, event_id, exception_code, severity, assignee, status, resolution_json)
rule_execution_log(id, event_id, rule_id, rule_version, input_hash, evaluation_json, result, duration_ms)
outbox_event(id, topic, payload, publish_status, attempts)
inbox_consume(consumer_name, event_id, status, result_ref)
-- 复用(升级关联,不重复建设)
subject / opening_balance / bill_pool / voucher / voucher_entry / period_close / op_log
-- 迁移:bill_pool 增加 evidence 映射(status 不再是唯一事实);voucher.source_id 改兼容字段 +
-- 新增 N:M 关联;历史凭证生成 LEGACY 事项关联,不虚构业务事实
十二、API 契约(P0)
POST /api/v1/accounting/business-events 事件接入(幂等头/版本校验;MQ 时 REST 用于运维重放)
GET /api/v1/accounting/events 事项列表(账套/日期/类型/状态/来源)
GET /api/v1/accounting/events/{id} 事项详情(证据/计算解释/关联凭证)
POST /api/v1/accounting/events/{id}/evaluate 人工重评(幂等+留痕)
POST /api/v1/accounting/events/{id}/resolve 补证/裁定(权限+理由)
POST /api/v1/accounting/events/{id}/generate-voucher 生成待审核凭证(禁重复)
GET /api/v1/accounting/exceptions 异常工作台
POST /api/v1/accounting/evidence/match 单据/发票/流水关联确认
POST /api/v1/accounting/settlements/allocate 应收应付拆分核销
GET /api/v1/accounting/reconciliation 业财对账及差异报表
POST /api/v1/accounting/rules/{id}/simulate 规则试运行(不写账)
POST /api/v1/accounting/vouchers/{id}/audit|book|unaudit|unbook|reverse 复核状态机与红字冲销
POST /api/v1/accounting/period/{period}/close|reopen 结账/反结账
错误码:RULE_NOT_FOUND / EVIDENCE_REQUIRED / AMBIGUOUS_MATCH / DUPLICATE_ACCOUNTING_ACTION
/ PERIOD_CLOSED / UNBALANCED_VOUCHER / SUBJECT_MAPPING_MISSING / AUTH_FORBIDDEN
十三、核心流程伪代码
def consume_business_event(raw_event):
verify_auth_tenant_and_schema(raw_event)
with transaction():
if inbox.exists(raw_event.tenant_id, raw_event.event_id):
return inbox.previous_result(raw_event.event_id) # 幂等
event = business_events.insert_immutable(raw_event)
inbox.record_processing(event)
for candidate in classify_event_actions(event): # 0/1/多项
with transaction():
ae = accounting_events.get_or_create_by_action_key(candidate) # 六要素防重
attach_source_and_evidence(ae, event)
rule = rules.resolve(book=ae.book, candidate=candidate)
result = rule.evaluate(ae); log_rule_execution(rule, result)
if result.not_recognized: ae.mark_not_recognized(result.reason)
elif result.needs_review_or_evidence:
ae.mark_pending(result.reason); exceptions.upsert(ae, result)
else:
entries = build_journal_entries(result)
validate_balance_period_subjects_uniqueness(entries, ae)
voucher = vouchers.create_pending_review_idempotently(ae, entries)
event_voucher_links.link(ae, voucher) # N:M
ae.mark_voucher_drafted(); outbox.publish('accounting.voucher_drafted', voucher.id)
inbox.mark_done(event.event_id)
事务边界:单项事项的"事项创建+凭证生成+关联+出站消息"同一数据库事务;长流程不做跨系统分布式大事务;状态回写由异步可靠事件完成且消费幂等。
十四、异常与边界(8 岔路)
| # | 场景 | 处理 |
|---|---|---|
| 1 | OCR 置信度低 | 转待人工补录,缺失字段高亮 |
| 2 | 发票重复导入 | 拦截;旧票已完结丢弃、未完结合并 |
| 3 | 模板"未指定" | 禁生成,人工指定;30 天未处理转异常 |
| 4 | 流水匹配不到发票 | 定性队列(预收/回款/往来/内部转账/现销),禁默认收入 |
| 5 | 部分回款/金额不符 | 差异提示,按拆分核销或生成差异调整事项 |
| 6 | 复核驳回 | 凭证入回收站 → 事项回退 → 票据回未记账 → 重指定模板再生成 |
| 7 | 已结账期间来票 | 跨期异常 + 授权调整(计入本期/下期/重开期间),禁静默改期 |
| 8 | 试算不平衡 | 结账阻断,输出差额科目定位报告 |
十五、非功能与安全
幂等(第十章三层设计);审计(原始事件/版本/规则执行/审批调用全留痕);权限(tenant+legal_entity+book 三重范围;职责分离:业务提交/规则发布/凭证制单/复核/过账/反结账独立权限);敏感字段加密脱敏 + 附件短期授权;AI 仅建议不越权;规则变更/批量审核/跨期调整/反结账触发高风险审计与二次授权。
性能目标:事件接入 p95<500ms;事件→待审核凭证 p95<30s;幂等并发重放 100 次仅一个有效结果;自动凭证 100% 借贷平衡且可回溯。
十六、原型对照与实施路线
16.1 原型对照(41 页已全部实现)
| 技术组件 | 原型页面 |
|---|---|
| 业务事件源 | 合同(父模块)/应收应付/收付款/报销/薪资/社保/资产/库存 等 20 页 |
| 事项中心 | accounting-events(工作台)/ accounting-event-detail(含裁定/补证/驳回) |
| 规则引擎 | accounting-rules(条件编辑器/试运行/版本)+ finance-config(会计政策) |
| 凭证桥接 | accounting(状态机/来源事项 N:M/冲销/回收站) |
| 证据体系 | accounting-bills(证据中心:待定性/待补证/关联事项) |
| 建账迁移 | accounting-import / subjects / initial |
| 对账与结账 | accounting-recon(四组)/ accounting-close(8 项分级)/ reconciliation(拆分核销) |
| 账簿报表 | accounting-books / report / accounting-inspection |
| 运营指标 | finance-dashboard(业财核算区)/ accounting-events(KPI 口径) |
16.2 实施路线(详见任务清单)
| 阶段 | 交付 | 目标 |
|---|---|---|
| 迭代 1 | 决策+文档五件套、账套政策、事件接口、事项状态机、审计基础 | 测试账套跑通单事件全链路 |
| 迭代 2 | 规则引擎、凭证桥接、销售/采购/费用三闭环 | 三条核心闭环 |
| 迭代 3 | 证据匹配、跨期、异常工作台、规则解释 | 凭据与异常闭环 |
| 迭代 4 | 业财对账、结账分级、双轨验证、灰度切换 | 财务验收 |
十七、风险与边界
- AI 凭证:强制人工审核后才入账(硬控制);低置信强制转人工;AI 不得调用过账/改规则接口;
- 迁移数据:试算不平阻断;历史凭证只读,反结账不得越过迁移点;不为可迁移性虚构业务事实;
- 汇总生成:跨期票据按票据日期归属期间;锁定期间入池自动挂下一期;
- 性能:科目余额事件增量 + 期间快照,万级凭证账簿查询 ≤2s;规则表达式限时执行;
- 合规:结转损益禁手工;全部反方向操作留痕;例外审批留痕且可审计。