# 业财一体化自动记账 · 技术方案（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 标准事件契约

```json
{
  "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 投递与幂等

1. 业务主库事务**同写业务记录与 outbox_event**，后台发布器投递；
2. 消费端按 `(tenant_id, source_system, event_id)` 唯一键写 Inbox，**重复投递直接返回已处理结果**；
3. 同单据按 `source_revision` 判序，乱序暂存重建；
4. 至少一次投递 + 持久化唯一约束 = **效果上的一次确认**；错误队列支持重试/死信/人工重放，重放不产生重复事项。

### 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，税率另由独立规则控制）

```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`）；**试运行**抽样对照不写账；表达式引擎白名单，禁任意脚本。

## 六、凭证桥接

1. **状态机**：`待审核 → 已审核 → 已记账(过账) → 已报税(锁定)`；AI/规则凭证默认强制人工复核；制单人不可自审；金额分级审批（>50 万走复杂流程）。
2. **凭证号**：业务关联先用不可变 `voucher_id`，正式编号按账套/期间/凭证字**受控分配**（失败重试不占号）；支持凭证号整理（断号重排、原号留痕）。
3. **冲销与更正**：红字冲销凭证（借贷反向、负金额、关联原凭证）；已入账不可删改；删除仅限前两态进回收站。
4. **期间治理**：四日期分离——`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 精华）

1. **主路径**：金蝶/用友导出「科目余额表」→ 建账向导七步（新建账套 → 选来源 → 上传 → 列映射确认 → 科目对照确认（≥90% 自动）→ 试算平衡 → 完成）；
2. **产出**：科目体系（级次自适应推断 4-2-2-2）+ 初始余额（损益类录本年累计）+（可选）历史凭证**只读**入库（LEGACY 标记）；
3. **兜底**：只有三表时按"报表项目→科目"映射反推（货币资金→现金+银行等），不生成历史凭证；
4. **约束**：试算不平衡阻断；损益期初必须为 0；映射结果存为模板复用；反结账不得越过迁移点。详见《账套迁移建账需求文档.md》。

## 九、对账与期末

1. **业财对账（四组）**：合同履约↔收入、收款↔应收、采购↔应付、银行↔总账；业务口径与账面口径并列，差异行直接闭环（生成事项/前往裁定/查看异常/生成核销）。
2. **三道锁**：业务-资金（流水↔发票自动匹配，金额±0.01+对手方+日期窗）；账证（凭证汇总表=科目余额表发生额）；账实（存货=1403、资产=1601/1602、试算平衡=结账硬门槛）。
3. **期末结账引擎**：8 项检查（**阻断 / 警告 / 例外审批** 三级，未启用模块跳过）→ 结账时生成（计提类）→ 结转损益（系统强制）→ 试算平衡（不平回滚）→ 锁期出正式报表 → 反结账留痕。

## 十、防重与幂等（三层）

| 层 | 唯一键 | 防的是什么 |
|---|---|---|
| 事件层 | Inbox(tenant, event_id) | 重复投递 |
| 事项层 | 六要素（含 slice + version） | 重复确认（支持一单多事项、多次确认） |
| 凭证层 | accounting_event_voucher + 按单生成约束 | 重复出证 |
| 任务层 | 汇总/结账任务幂等（票据状态机排除已生成） | 重跑重复 |
| 回流 | 驳回 → 票据回"未记账" → 重指定模板再生成（旧凭证进回收站） | 驳回后重复 |

## 十一、数据模型（DDL 级）

```sql
-- 新增（事件/事项/规则/关联/对账/异常）
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
```

## 十三、核心流程伪代码

```python
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 | 业财对账、结账分级、双轨验证、灰度切换 | 财务验收 |

## 十七、风险与边界

1. **AI 凭证**：强制人工审核后才入账（硬控制）；低置信强制转人工；AI 不得调用过账/改规则接口；
2. **迁移数据**：试算不平阻断；历史凭证只读，反结账不得越过迁移点；不为可迁移性虚构业务事实；
3. **汇总生成**：跨期票据按票据日期归属期间；锁定期间入池自动挂下一期；
4. **性能**：科目余额事件增量 + 期间快照，万级凭证账簿查询 ≤2s；规则表达式限时执行；
5. **合规**：结转损益禁手工；全部反方向操作留痕；例外审批留痕且可审计。
