feat: 选票自动生成报销明细并支持集中分类(08-29-reimbursement-expense-policy-invoice-guard)
这个提交包含在:
@@ -7,6 +7,57 @@ duplicate detection or attachment behavior.
|
||||
|
||||
## Rules
|
||||
|
||||
- 隔离串联的 `RUN_JOB_QUEUE=1` 必须运行真实 startPgBossJobs 与上传入口 enqueue,
|
||||
等对应 invoiceId 的队列任务 completed,再校验发票状态和页面,不用直接调用
|
||||
worker 冒充调度。只连接脚本新建数据库;非关注周期任务不得在测试期间改其他对象。
|
||||
认证使用真实登录/JWT/refresh 和合成账号时,仍需区分导航壳适配、OAuth、
|
||||
页面登录表单、云端 provider 与生产定时器时序的证据范围。
|
||||
|
||||
- 隔离串联可用 `RUN_ISOLATED_DB_TEST=1 RUN_BROWSER_TEST=1 node scripts/qa/test-invoice-first-http.cjs`,
|
||||
前置为当前候选已构建 client/dist。浏览器业务请求必须走真实后端/数据库;
|
||||
合成认证、mock provider、手动 worker、真实云端识别分别报告,不能互相替代。
|
||||
刷新持久化验证先等保存响应、再查库、再刷新定位可见明细,避免隐藏的批量
|
||||
分类文字或同名“编辑”按钮造成误报;上传与 OCR 完成不能触发隐式绑定。
|
||||
|
||||
- 所有报销 bind/unbind 与提交遵循“报销单锁 → 发票锁”,不能只让新动作
|
||||
遵循而保留旧路径反序。解绑先读关联快照定位报销单,取单锁后再取票锁;
|
||||
若票据当前关联已变化,409 拒绝,不按旧快照解绑也不转锁其他单据。
|
||||
验证命令:`RUN_ISOLATED_DB_TEST=1 node scripts/qa/test-invoice-first-http.cjs`,
|
||||
用真实 PostgreSQL 锁屏障复现并发;正常基线为同单重试仅一条明细,
|
||||
反例为旧反序路径产生 500,修复后重试/解绑均成功。该脚本合成认证与
|
||||
OCR 字段不构成真实登录、OCR 调用或完整审批验收证据。
|
||||
|
||||
- 报销“我的发票”面板上传/OCR 完成仅默认勾选,点击添加才创建明细或占用。
|
||||
用户取消的票不得被回调重新勾选,手改目标不得被回调覆盖;退出不删除池票。
|
||||
已有明细入口只传 linkedItemId,返回整单入口恢复创建新明细的默认值,
|
||||
成功关闭与手动关闭均须清理目标。部分失败只保留失败项,重试不重复发送成功票。
|
||||
- 浏览器接口拦截回归证明交互和请求合同,不证明真实 OCR、Prisma 锁或数据库
|
||||
回滚;这些证据需分别验证,不能把页面成功提示视为业务全链路通过。
|
||||
|
||||
- 新选票动作显式传 `createItem: true`,与 linkedItemId 互斥;不复用旧绑定
|
||||
的单明细/同金额猜测。新动作先锁报销单再锁票据,事务内重验参与人、状态、
|
||||
票据归属与可用性,一票建一明细并占用;同单重试重验权限与现有明细归属,
|
||||
不再次创建或覆盖已编辑数据。旧接口未默认切换,页面接入完成前不宣称生效。
|
||||
- 无票面项目依据时可保存空说明草稿,不用文件名或商户名假装业务用途;
|
||||
预检和提交集中提示缺少说明的明细。编辑器保存空字符串必须明确传空,
|
||||
不能转成 undefined 导致 PATCH 没有清除旧值。
|
||||
- 批量设类必须按用户选择的明细 ID 集合和单据 ID 双重限定、同事务全量校验,
|
||||
任一异单/失效明细或停用类型拒绝整批;不顺手改金额、日期、说明、批准依据
|
||||
或发票关系,不扩大对象维护权限。既有资产提示/审批规则仍按实际代码处理,
|
||||
不以旧文档声称存在未实现的硬门禁。
|
||||
|
||||
- 自动建明细后类型无法可靠确定时,允许 draft/rejected 明细保存空费用类型,
|
||||
不填任意启用类型或“其他”占位。API PATCH 的 null 与省略字段必须区分;
|
||||
DTO 与 PC/移动编辑器均保留待补值,不因打开编辑器默认选中第一项。
|
||||
- 待补或已停用费用类型必须在报销提交进入费用、预算、审批服务前按明细 ID
|
||||
阻断;不能用可选链把缺少类型解释为免票。分类来自持久化 OCR 证据及启用
|
||||
类型,不来自客户端票种、销售方关键词、文件名、金额或历史 provider 默认值。
|
||||
- 类型可空迁移不放宽金额、日期和外键约束,也不授权生产应用。保存过待补数据
|
||||
后回滚旧应用需评估非空假设;恢复 NOT NULL 前必须核实空值,不得猜类型回填。
|
||||
- 本地结构验收使用显式开启的一次性 PostgreSQL:
|
||||
`RUN_ISOLATED_DB_TEST=1 bash scripts/qa/test-reimbursement-draft-migration.sh`。
|
||||
该测试验证迁移和合成记录,不证明浏览器、真实 OCR 或生产恢复通过。
|
||||
|
||||
- PDF invoice OCR is the maintained main path.
|
||||
- Image OCR remains frozen unless a later Trellis task explicitly reopens it.
|
||||
- Do not write raw invoice images, sensitive form values or full OCR payloads to
|
||||
|
||||
在新工单中引用
屏蔽一个用户