文件
hyb-oa/.trellis/tasks/08-29-reimbursement-expense-policy-invoice-guard/design.md
T

3.4 KiB

设计:报销费用口径与票据明细门禁

边界

Task B-1 合并交付费用主数据政策和提交门禁代码,但运行时分成两级:B1 数据模型/主数据/表单字段随部署生效,B2 强关联和金额阻断由默认关闭的双闸 feature flag 控制。B3 财务一页式另建任务,等待 B2 在真实或专用数据上验证后开始。

数据模型

  • ExpenseType.requires_invoice Boolean @default(true):用 migration 为既有类型回填 true,再定向把两项补助设为 false。
  • ReimbursementItem.asset_prior_approval_basis String?:仅 assets 明细要求,保存批准人、批准时间和简短依据;非 assets 明细应保持 null 或忽略空白值。
  • 不为 account_code_default 新增字段;财务提供映射前保持 null。重复执行 seed/init 的 update 分支不覆盖已有科目映射,避免后续部署抹掉财务回填。
  • 费用类型停用只改 enabled,不删除记录、不迁移历史明细外键。

费用类型迁移

当前类型 动作 新提交口径 历史口径
business_client_meal 客户招待 原 code 改名 业务招待费 追溯显示新名称
business_training 培训会议 停用旧类型并新建两个 code 会议费、培训费 保持培训会议
assets_it_hardware IT 硬件 停用旧类型并新建 code 低值配件选办公用品;需登记的选择办公电子设备 保持 IT 硬件

新 code 在实施前按现有命名规则固定并写入 migration/seed 测试,不复用旧 code 承载不同语义。

写入和提交数据流

  1. 员工建立或编辑明细,服务端读取权威 ExpenseType。
  2. assets 类型必须校验 asset_prior_approval_basis;前端提示只是辅助,服务端是最终门禁。
  3. 办公用品明细金额达到 2,000 元时生成非阻断类型提示,员工端和财务审核视图消费同一服务端事实;该阈值不作为会计资产确认结论。
  4. 发票上传/绑定显式携带目标明细 ID。B2 flag 开启时禁止无法唯一匹配后的自动建明细。
  5. 提交事务重新读取明细、有效发票及关联关系,按明细计算票面合计。
  6. requires_invoice=false 跳过票面比较;true 类型执行缺票和超票面阻断。
  7. flag 关闭只选择旧提交/匹配路径,关联表中的既有数据不做逆向写入。

Feature Flag

  • 新增独立 key,不复用 budget_precheck_v1 或 project_linking_v1。
  • 配置层新增 env hard gate,默认 false;服务白名单注册 key;seed/受控配置提供 DB force_off 初值。
  • 后续开启先使用专用账号或部门 allowlist(如现场组织结构允许),再全局开启。
  • flag 状态必须进入诊断/审计输出,但不向普通员工显示内部 key。

兼容和回滚

  • schema 只做向前兼容的 nullable/default 字段新增,不在应用回滚时逆迁移。
  • 旧草稿保留;B2 开启后提交时补齐,不批量伪造关联或批准依据。
  • 应用异常时先关闭 B2 flag;这不会删除既有关系。B1 名称/字段回滚只通过新 migration 或后续主数据动作,不直接删列。
  • OCR 仍可给出候选匹配,但 B2 开启时最终绑定必须由用户确认,不能静默创建业务明细。

延后项

  • PurchaseRequest 强关联、资产自动建卡、数量/单价、B3 一页式审批和财务科目表治理不混入本轮核心门禁。