fix: 退回报销支持留痕删除(09-04-reimbursement-state-gap-finance-view)
这个提交包含在:
@@ -5,6 +5,37 @@
|
||||
Read `docs/报销发票附件规则.md` before changing reimbursement, invoice, OCR,
|
||||
duplicate detection or attachment behavior.
|
||||
|
||||
## Retained Reimbursement Deletion
|
||||
|
||||
- DELETE /reimbursements/:id requires expense.delete_own and owner/submitter
|
||||
participation, including idempotent retries. Global reading or wildcard alone
|
||||
never substitutes for participation.
|
||||
- Only draft/rejected may be deleted, with no active workflow/task, non-cancelled
|
||||
payment reservation, paid_at or non-bound associated invoice. Lock the form
|
||||
before invoices, then release only invoices still bound to that form.
|
||||
- A never-submitted draft may be physically deleted. Rejected or any draft with
|
||||
workflow history must retain the form/items/workflow/attachments and set
|
||||
cancelled + deleted_at/deleted_by. Never infer history absence from draft.
|
||||
- Before release, preserve current invoice PDF object references/hash as invoice
|
||||
attachments of the old form; use its existing material authorization, not the
|
||||
invoice's future binding. Storage objects are immutable; any future physical
|
||||
cleanup must account for retained reimbursement attachment references.
|
||||
- Audit, evidence references, release and deletion are one transaction. Failed
|
||||
audit must roll back every database effect. Historical invoices already
|
||||
released before this change are not reconstructed or silently rebound.
|
||||
- Normal reads exclude deleted_at records through shared visibility/ledger
|
||||
filters; raw statistics, portal counts and project summaries must also exclude
|
||||
them. Authorized historical detail/material reads remain, with deletedAt and
|
||||
terminated next-action projection. No role-grant changes.
|
||||
- Verify with RUN_ISOLATED_DB_TEST=1 RUN_RETAINED_DELETE_TEST=1 RUN_BROWSER_TEST=1
|
||||
node scripts/qa/test-invoice-first-http.cjs after building the current client.
|
||||
Uses disposable PostgreSQL, synthetic accounts/files and real auth/HTTP/browser;
|
||||
OCR in this suite is mock-provider, not production Tencent evidence.
|
||||
- Migration adds nullable fields and a deleted-state check. After retained
|
||||
deletion exists, old code can redisplay it; image rollback alone is not
|
||||
behavior-preserving. Prefer forward repair or an explicitly reviewed compatible
|
||||
rollback; do not remove history or reverse current invoice bindings blindly.
|
||||
|
||||
## Rules
|
||||
|
||||
- 隔离串联的 `RUN_JOB_QUEUE=1` 必须运行真实 startPgBossJobs 与上传入口 enqueue,
|
||||
|
||||
在新工单中引用
屏蔽一个用户