知识全景图/ 软件工程与系统/ 端到端业务系统案例

端到端业务系统案例:报销、审批与支付账务

用一条真实业务链,把对象建模、状态机、接口契约、幂等、对账、权限审计和生产修复接起来

阅读边界: 这页不是报销、审批或支付账务的领域专题替代品,而是一张工程案例页。它关心的是:当一笔费用从提交、审批、预算、支付、回单、凭证到归档走完时,系统边界怎样设计才不会在生产里散架。

一句话判断: 端到端业务系统的难点不在“每个模块都能跑”,而在跨模块状态、资金动作、账务证据、权限审计和异常修复能否形成一条可解释的链。
一、端到端链路
费用事实 / 报销单 审批流 预算占用 支付申请 支付执行 回单回写 凭证 / 账务 归档 / 审计 异常补偿
阶段核心事实工程风险最低设计要求
费用事实票据、附件、项目、人员、供应商、收款账户事实只存在图片或备注里,后续无法校验关键事实结构化,附件有哈希、版本和来源链
审批流谁在什么权限下同意了什么金额和用途审批状态和业务状态分裂审批结果只推进允许的业务状态,不直接替代支付或记账结果
预算占用预算指标、项目额度、占用金额、释放规则审批通过但预算未占,或驳回后预算未释放占用、释放、撤销和重提都要有明确幂等键
支付执行支付指令、银行流水、回单、失败原因超时未知、重复提交、回调延迟、状态悬挂支付订单状态机、外部查询补偿、重复提交防护
账务凭证会计分录、凭证号、规则版本、来源单据钱付了但凭证缺失,或凭证无法解释来源账务分录可追到业务单、支付结果和规则版本
归档审计附件、审批轨迹、回单、凭证、修复记录事后追问时只剩导出文件和聊天记录形成不可随意覆盖的证据包和审计事件
二、核心对象:别让一张表承包世界
expense_fact
费用事实,承接票据、合同、行程、项目、人员和附件来源,回答“这笔钱为什么发生”。
reimbursement_order
报销主单,负责金额、收款人、费用归属、状态和跨对象关联,不直接承包所有附件与审批明细。
workflow_instance
审批实例,记录节点、参与人、动作、意见和权限快照,输出审批结论但不伪装成业务终态。
budget_hold
预算占用对象,记录指标、额度、占用、释放、冲销和失败原因,是预算正确性的核心账本。
payment_order
支付订单,负责外部资金动作的幂等、状态、回调、查询和重试,不让报销单直接调用银行接口。
payment_result
支付结果,保存银行或支付通道返回的权威结果、回单、错误码和查询时间线。
ledger_entry
账务分录和凭证来源链,记录业务单、支付结果、会计科目、规则版本和凭证号。
audit_event
审计事件,记录每一次提交、审批、支付、修复、重放和人工操作,让事后追问有证据。
三、状态模型:看起来长,但比隐式状态便宜
draft submitted approving rejected approved budget_held payment_pending paying paid accounting_posted archived failed cancelled
状态边界允许动作禁止偷懒
审批中撤回、驳回、转交、加签、审批通过不能提前生成真实支付指令;最多做预校验
已审批预算占用、支付申请创建、重新校验权限和额度不能把“审批通过”展示成“已付款”
预算已占用创建支付订单、释放预算、进入异常队列不能在支付失败后忘记释放或保留占用原因
支付中等待回调、主动查询、超时转人工、幂等重试不能用简单失败覆盖“外部结果未知”
已支付生成凭证、回单归档、发起对账不能再允许普通撤回或驳回,只能走冲正 / 订正流程
已记账 / 已归档订正、冲正、补充归档、审计查询不能直接改历史金额或覆盖原附件
四、最容易裂开的工程缝
工程缝典型坏味道更稳的设计
审批状态 vs 业务状态审批引擎显示通过,但业务单仍不可支付,前台解释不清审批结果是事件,业务单按状态机消费事件并记录失败原因
预算占用 / 释放驳回、撤回、支付失败后额度卡死预算占用做成独立对象,所有释放动作可幂等、可对账
支付幂等页面重复点击、接口超时重试导致重复付款以业务单号、支付批次、收款账户、金额构造幂等键,并隔离外部未知态
账务来源链凭证生成了,但财务追不到是哪张单、哪次支付、哪个规则版本凭证保存来源对象、规则版本、操作人和生成批次
附件 / 归档完整性附件被覆盖、导出包和线上数据不一致附件版本化、哈希校验、归档批次和导出快照都要入审计
权限和审计证据只知道“系统自动处理”,不知道当时谁有权、为什么能操作关键动作保存 actor、role、permission_snapshot、policy_version 和审批证据
五、故障剧本:先写失败路径,再写成功路径
故障场景如果没设计会怎样处理剧本
审批通过但预算占用失败用户以为能付,财务端无法继续业务单进入 approved 后的待处理异常,展示预算失败原因,可重试或退回补正
预算已占但支付失败额度长期被锁,报销单卡在中间态区分可重试失败、外部未知、明确失败;明确失败释放预算,未知态先查权威结果
支付成功但回调延迟系统重复发起支付,造成二次付款风险支付中状态先主动查询外部结果,禁止在未知窗口内新建同幂等键支付
支付重复提交同一笔报销被多次付款支付订单唯一约束、幂等表、通道侧请求号和人工复核共同兜底
凭证生成失败钱已经出去,但账务系统缺凭证支付成功后建立待记账队列,凭证生成失败可重试、可补录、可对账
下游状态已变后用户撤回撤回动作把支付或账务历史直接抹掉超过边界后禁止普通撤回,改走红冲、退款、订正或人工审批流程
六、最小可观测字段
字段用途不要缺在哪里
business_id / trace_id把报销、审批、预算、支付、账务串成一条排障线日志、消息、API 请求、后台任务、人工修复单
workflow_instance_id定位审批版本、节点、操作者和权限快照审批回调、业务单状态变更、审计事件
payment_order_id定位资金动作、通道请求和外部权威结果支付请求、支付回调、主动查询、对账任务
ledger_entry_id定位凭证、分录、规则版本和账务修复自动凭证、账务对账、关账检查
status_timeline解释什么时候从哪个状态变到哪个状态前台查询、客服解释、审计复盘、事故分析
retry_count / repair_batch_id区分自动重试、人工修复和批量补偿异步任务、对账补偿、生产数据修复
七、设计评审清单
API 契约
每个跨系统调用是否定义请求号、幂等键、状态码、错误分类、超时语义和回调验签。
数据契约
报销、审批、预算、支付、凭证之间是否有稳定字段、枚举版本和兼容策略。
幂等与补偿
重复提交、重复消息、重复回调、重复修复是否不会产生二次资金或账务副作用。
权限与审计
关键动作是否保存操作者、角色、权限快照、审批证据和人工修复理由。
发布与回滚
状态机、凭证规则、支付通道变更是否有灰度、回滚、双写对账和旧数据兼容方案。
生产修复
是否有 dry-run、影响范围、审批、执行记录、复核对账和禁止直接改终态的规则。
八、端到端交付门禁与证据包
交付证据必须交出什么缺失后的风险
链路状态图报销单、审批实例、预算占用、支付订单、支付结果、账务凭证和归档状态之间的推进关系、终态和异常态。模块各自正确,但跨模块状态解释不通,客服、财务和研发各说一套。
资金动作清单哪些动作会真正触发付款、退款、冲正、预算释放或凭证生成;每个动作的幂等键、权限和审批要求。重复点击、重试、补偿或人工修复可能产生二次资金副作用。
权威来源说明审批结论、预算余额、支付结果、银行回单、账务凭证分别以哪个系统或对象为权威。发生差异时不知道听谁的,补偿动作容易把错误状态继续扩散。
异常剧本与 owner预算失败、支付未知、重复支付、凭证失败、附件缺失、权限争议等场景的处理队列、SLA、owner 和升级路径。异常只靠研发临时查库,业务等待时间不可控,责任边界模糊。
审计与归档包提交事实、审批轨迹、权限快照、支付回单、账务凭证、修复记录、导出快照和附件哈希。事后审计只能靠聊天记录和截图,无法证明当时谁有权、钱为什么付、凭证从哪里来。
上线门禁最低要求失败时动作
状态机门禁所有终态、可补偿态、人工介入态和禁止回退边界都经过评审,并有测试样例覆盖。阻断上线,先补状态迁移表和失败路径用例。
支付幂等门禁支付请求号、业务幂等键、通道请求号、回调验签和主动查询策略可被复核。不允许接入真实支付通道,只能停留在沙箱或灰度环境。
对账闭环门禁业务单、支付结果、银行流水、账务凭证和预算占用有定时对账、差异分类和处理队列。不能宣告闭环,必须补对账任务和差异 owner。
权限审计门禁高风险动作有角色、权限快照、审批证据、操作原因和不可覆盖审计事件。冻结高风险入口,先补权限证据和审计写入。
修复演练门禁至少演练一条支付未知、一条凭证失败、一条预算卡死的 dry-run 修复路径,并留复核记录。上线范围收窄或推迟,避免生产第一次遇到异常时靠手工救火。
九、和现有图谱怎么互链
相关页连接关系
报销与费用管理提供费用事实、报销单、借款冲销、归档追溯等领域背景
审批流 / BPM解释审批实例、节点、权限和流程状态,不替代业务状态机
支付 / 账务承接支付状态、回单、凭证和账务来源链
失败处理与业务一致性处理支付未知、凭证缺失、预算占用异常和历史事件重放
数据契约支撑跨系统字段、状态、枚举和事件版本稳定演进
认证 / IAM支撑角色、权限快照、审批权限和高风险操作控制
生产数据修复与运维操作承接自动补偿处理不了的异常修复、复核和审计闭环
可观测性 / SRE让业务链路能按 trace、状态时间线和异常队列被排查