完善差旅补助规定与费用类型(07-28-travel-reimbursement-guide)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-07-29 20:04:35 +08:00
父节点 5df5f12ad6
当前提交 13a3f4b57d
共修改 10 个文件,包含 201 行新增和 15 行删除
@@ -383,6 +383,96 @@ node scripts/qa/check-ocr-provider-samples.mjs \
The caller records stdout before applying the exit-code gate; it never uses a
`set -e` assignment whose non-zero status exits before the JSON is emitted.
## Scenario: Travel Allowance Expense-Type Boundary
### 1. Scope / Trigger
- Trigger: adding or changing travel reimbursement types, travel-request
transport mappings, allowance policies or expense standards.
- Purpose: keep intercity transport reimbursed by evidence separate from the
two daily lump-sum allowances, and avoid false over-limit results until the
reimbursement item model supports a day count.
### 2. Signatures
- Seed contract in `server/src/scripts/seed-config.js`:
- `travel_bus` -> `大巴车票`.
- `travel_meal` -> `伙食补助费`.
- `travel_local_transport_allowance` -> `市内交通补助费`.
- Travel conversion contract in `server/src/routes/reimbursements.js`:
`TRAVEL_TRANSPORT_EXPENSE_TYPE_CODES.bus === "travel_bus"`.
- Current item data boundary: `ReimbursementItem` stores expense type, date,
amount and description, but no quantity or eligible-day count.
### 3. Contracts
- `travel_bus` always means an intercity bus/coach ticket created from or used
with a travel segment. It must not represent local transport allowance.
- Meal allowance is CNY 100 per eligible person-day; local transport allowance
is CNY 80 per eligible person-day. Both are lump-sum items without an invoice.
- Employees create one item per allowance, set the amount to eligible days
multiplied by the rate, and write the date range, day count, rate and formula
in the description. Supervisor and finance review that calculation.
- Departure and return dates each count as one natural day; same-day return is
one day. Personal extensions do not count. Meals or vehicles paid directly
by the company or another organization exclude the corresponding allowance.
- Claiming meal allowance excludes separate personal meal reimbursement;
claiming local transport allowance excludes bus, metro, taxi and ride-hailing
reimbursement during the trip. Intercity transport, accommodation and other
approved necessary expenses remain evidence-based actual reimbursement.
- `ExpenseStandard.per_unit=day` currently does not multiply `max_amount` by a
day count. Do not seed or configure CNY 100/CNY 80 warn/block standards until
item quantity/day multiplication is implemented end to end.
### 4. Validation & Error Matrix
- Travel segment `bus` maps to an allowance type -> block the change; preserve
`travel_bus` and add/use the separate allowance code.
- CNY 100 or CNY 80 daily rate configured as the current item-level maximum ->
remove/disable it because a multi-day allowance would be falsely over limit.
- Allowance item lacks date range, eligible-day count, rate or formula -> return
for completion during supervisor/finance review; do not invent a day count.
- Company/other party directly bore the corresponding cost -> exclude those
days from the applicable allowance and record the reason.
### 5. Good/Base/Bad Cases
- Good: a three-day eligible trip uses separate meal and local-transport items
whose descriptions show `3 天 × 单价`, while rail/hotel items carry PDFs and
required payment evidence.
- Base: intercity coach travel uses `travel_bus` / `大巴车票` and remains an
actual-expense item with valid evidence.
- Bad: rename `travel_bus` to local transport allowance, or configure a CNY 80
item maximum and thereby reject a valid multi-day allowance.
### 6. Tests Required
- Seed-default unit test asserts all three codes and Chinese names are distinct.
- Travel-request conversion test asserts `transport_type=bus` produces an item
whose expense type code is `travel_bus` and description identifies `大巴`.
- When automatic day calculation is later implemented, add service and route
tests for same-day, multi-day, personal-extension and directly-borne cases
before enabling any daily standard.
- Documentation checks must keep the employee guide, reimbursement fact source
and production expense-type names aligned.
### 7. Wrong vs Correct
#### Wrong
```js
const TRAVEL_TRANSPORT_EXPENSE_TYPE_CODES = { bus: "travel_local_transport_allowance" };
// Current fee control compares the whole multi-day item directly with 80.
```
#### Correct
```js
const TRAVEL_TRANSPORT_EXPENSE_TYPE_CODES = { bus: "travel_bus" };
// Local transport allowance is a separate manually calculated item until the
// model and fee-control service both support eligible-day multiplication.
```
## Scenario: Payment Batch Receipt Attention Count
### 1. Scope / Trigger