收敛报销详情并展示五阶段进度(07-27-yang-jun-reimbursement-readiness)
这个提交包含在:
@@ -93,3 +93,91 @@ if (!hasPermission(actor, "payment.batch.review")
|
||||
throw forbidden();
|
||||
}
|
||||
```
|
||||
|
||||
## Scenario: Reimbursement End-To-End Processing Projection
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
- Trigger: showing one reimbursement's progress across approval workflow,
|
||||
payment-batch review, payment execution and receipt retention.
|
||||
- This is a read-only projection for diagnosis. It must not merge the workflow
|
||||
and payment state machines or create synthetic workflow tasks.
|
||||
|
||||
### 2. Signatures
|
||||
|
||||
- Detail API: `GET /api/reimbursements/:id`.
|
||||
- Response: `processingProgress.stages[]` with `key`, `label`, `state`,
|
||||
nullable `actorName`, `occurredAt`, `result`, `comment`, `detail` and
|
||||
permission-gated `targetHref`.
|
||||
- Stable stage keys: `submitted`, `manager_approval`, `finance_review`,
|
||||
`payment_batch_review`, `payment_and_receipt`.
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- Always return the five stages in the stable order above. UI labels describe
|
||||
responsibilities and never expose step IDs, role codes or enum values.
|
||||
- Completed stages use the actual completer/actor and completion time. Current
|
||||
workflow stages use the actual pending assignee when available. Future stages
|
||||
keep `actorName=null`; never guess a person from today's role holders.
|
||||
- A reimbursement approved without a batch makes `payment_batch_review` the
|
||||
current stage with `detail="待财务创建付款批次"`. A draft batch says
|
||||
`所在付款批次待非制单人复核`; shared-batch wording must not imply that this
|
||||
reimbursement alone is being reviewed again.
|
||||
- Missing workflow, batch or receipt facts degrade only their stages. Earlier
|
||||
known stages remain visible; missing downstream objects are normal, not 5xx.
|
||||
- `targetHref` is returned only when the viewer already has one of the existing
|
||||
payment-batch read permissions. The projection never returns batch peers,
|
||||
aggregate amount, other materials or bank receipt contents.
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
- No workflow instance -> submission/applicant state remains readable; approval
|
||||
and payment stages stay pending.
|
||||
- Workflow approved + no batch -> payment-batch stage is current, future actor
|
||||
remains null.
|
||||
- Batch `draft|reviewed|executed|failed|cancelled` -> map to explicit current,
|
||||
completed or exception states without changing the batch.
|
||||
- Executed payment + zero active receipts -> completed payment with
|
||||
`付款已完成,回单待留存`; positive count -> `付款与回单已留存`.
|
||||
- Viewer lacks batch-read permission -> `targetHref=null`; do not return 403 for
|
||||
the reimbursement detail itself.
|
||||
- Database/query failure -> existing 5xx behavior and server logging; do not
|
||||
fabricate a completed or pending business fact.
|
||||
|
||||
### 5. Good/Base/Bad Cases
|
||||
|
||||
- Good: `财务复核=通过` followed by current `待财务创建付款批次`, so the owner
|
||||
can diagnose the exact responsibility without asking three people.
|
||||
- Base: a newly submitted reimbursement shows known submission/current approval
|
||||
and three future stages with no future names.
|
||||
- Bad: display an expected checker before batch creation, label a shared batch
|
||||
as `您的报销待复核`, or hide the whole timeline because no receipt exists.
|
||||
|
||||
### 6. Tests Required
|
||||
|
||||
- Route tests for no workflow, pending/completed/returned/rejected tasks, all
|
||||
five batch statuses, receipt count zero/positive and paid-without-batch legacy
|
||||
data.
|
||||
- Assert future stages have null actors and ordinary applicants receive no
|
||||
batch link or batch-adjacent business data.
|
||||
- PC/mobile tests assert five responsibility labels, no `第 N 步`, comments on
|
||||
exception nodes, four-block order and no loss of earlier stages when a
|
||||
downstream source is absent.
|
||||
|
||||
### 7. Wrong vs Correct
|
||||
|
||||
#### Wrong
|
||||
|
||||
```js
|
||||
return workflowInstance ? buildTimeline(workflowInstance) : null;
|
||||
```
|
||||
|
||||
#### Correct
|
||||
|
||||
```js
|
||||
return buildProcessingProgress({
|
||||
reimbursement,
|
||||
workflowInstance: workflowInstance ?? null,
|
||||
paymentBatchItem: paymentBatchItem ?? null,
|
||||
});
|
||||
```
|
||||
|
||||
在新工单中引用
屏蔽一个用户