feat: add daily manual price review workflow

This commit is contained in:
Wyndham ARR
2026-08-06 22:40:18 +08:00
parent aae3d8e1db
commit ca3e8e18fa
77 changed files with 7750 additions and 602 deletions

View File

@@ -0,0 +1,49 @@
# ADR-006: PRICE_UNMATCHED uses a frozen, source-replayed manual review
## Status
Accepted
## Date
2026-08-06
## Context
The fixed price table can legitimately lack an exact normalized price key. Treating every such result as a permanent
failure makes staff re-upload unchanged XML after a separate price decision, while accepting edited spreadsheets or
mutable price-table changes would create a second intake path and weaken provenance.
## Decision
Only a non-empty error set entirely composed of `PRICE_UNMATCHED` becomes `review_required`. ARR stores one
privacy-minimized review case per run, grouped missing keys, revisioned actor/price history and candidate comparisons.
It creates no Finance version, daily download, rejected Finance version, `arr.processing_failed`, or monthly event.
After every key has a non-negative integer value, ARR freezes canonical JSON bound to the job, case, original XML
SHA-256, business date, processor version, rule hash and complete issue set. The operator/API surface uses integer text
(including explicit `0`); ARR normalizes that value to exact `numeric(18,2)` and canonical `.00` manifest text before
replay. Finalization re-materializes the registered source XML and replays it with the fixed price table plus that
manifest. Independent validation must accept the same manifest before one atomic Finance-version activation, case
completion and `arr.daily_version_committed` event.
## Consequences
- `POST /api/jobs` remains XML-only; there is no Excel draft/download/upload-back workflow.
- Staff can change only a reviewed missing key's non-negative integer price, including explicit `0`; fixed pricing rules and XML fields
remain immutable.
- Review mutations require session authentication, CSRF and optimistic revision checks. Frozen item/manifest facts are
immutable and permanently audited without free-form notes or guest detail.
- Infrastructure failures after freeze become `generation_failed` and may retry with the identical manifest. A
deterministic final replay failure closes the review and run as failed. Processor/rule identity drift requires cancel
then fresh upload.
- The legacy `direct_mcp` path uses an isolated v3 success/failure projection: it rejects manual overrides and maps
price misses to normal v3 failures, so it cannot gain review behavior from the active v4 processor.
## Related
- `database/017_daily_price_review.sql`
- `database/018_daily_review_manual_override_artifact.sql`
- `arr_web/programmatic.py`
- `arr_ingestion/postgres.py`
- `arr-opera-daily-ingest/scripts/process_daily.py`

View File

@@ -5,6 +5,7 @@
| ID | Decision | Status | Date | Applies To | Detail |
|---|---|---|---|---|---|
| ADR-005 | 手机 H5 看板通过专用只读聚合接口公开访问;桌面及运营接口继续认证 | Accepted | 2026-08-03 | Web access boundary, H5, Channel BI | [ADR-005](ADR-005-public-read-only-h5-dashboard.md) |
| ADR-006 | 仅纯 `PRICE_UNMATCHED` 进入冻结人工价格复核;最终原 XML 重放才可提交 Finance | Accepted | 2026-08-06 | Daily XML, review lifecycle, Finance/outbox, Web | [ADR-006](ADR-006-daily-price-review.md) |
| ADR-004 | ARR2.0 owns deterministic processing, artifact validation and terminal ingestion; no Agent/MCP in production XML flow | Accepted | 2026-07-30 | Upload, processing runtime, OSS ACL, validation, deployment | [ADR-004](ADR-004-arr-owned-programmatic-processing.md) |
| ADR-001 | 月报由独立 worker 自动触发;“更新至”取最新纳入的 `ARRIVAL`;发布后页面自动新增;`TOTAL PRICE` 为公式字段 | Implemented | 2026-07-29 | 月报触发、持久化、页面同步、XLSX 输出 | [ADR-001](ADR-001-automatic-monthly-trigger-and-total-price-formula.md) |