56 lines
4.1 KiB
Markdown
56 lines
4.1 KiB
Markdown
# Error Contract
|
|
|
|
## Atomic failure rule
|
|
|
|
Treat each invocation as one transaction. If any input, price, processing, or output-validation error occurs:
|
|
|
|
- do not return a formal daily workbook;
|
|
- do not return a formal monthly workbook;
|
|
- do not modify the supplied monthly base;
|
|
- remove candidates created by the failed invocation;
|
|
- write `异常清单.xlsx`, `result.json`, and (when the requested output path is valid) `structured-result.json` with failed status and `activation_eligible: false`.
|
|
|
|
The structured failure payload must still retain every reservation that was parsed, including whitelist exclusions, duplicate lineage, row validation failures, and price-unmatched rows. It must not reference a daily or monthly artifact.
|
|
|
|
## Exit codes
|
|
|
|
| Exit | Meaning |
|
|
|---:|---|
|
|
| `0` | Successful processing and independent output validation |
|
|
| `2` | Business-data failure, including price or workbook-contract failure |
|
|
| `3` | Invocation/input contract failure |
|
|
| `4` | Unexpected internal or dependency failure |
|
|
|
|
## Exception workbook columns
|
|
|
|
`ERROR_CODE`, `STAGE`, `SOURCE_LOCATION`, `COMPANY_NAME`, `RATE_CODE`, `EFFECTIVE_RATE_AMOUNT`, `CONFIRMATION_NO`, `MESSAGE`.
|
|
|
|
Leave unavailable location fields blank. Write one row per independently actionable error.
|
|
|
|
## Stable error-code families
|
|
|
|
- `INPUT_*`: missing file, wrong extension, unsafe XML declaration, unreadable XLSX, or output-path violation.
|
|
- `XML_*`: parse error, root/structure mismatch, missing rate code, multiple business dates, missing/invalid retained fields, or invalid dates. Same-day arrival/departure is valid; a departure before arrival is `XML_NEGATIVE_NIGHTS`.
|
|
- `PRICE_*`: price-header error, missing/non-numeric value, ambiguous company keyword identity, duplicate normalized key, or unmatched reservation.
|
|
- `MONTHLY_*`: missing standard sheet, 19/20-column header mismatch, ambiguous company keyword identity, mixed/wrong month, inconsistent company sheet, invalid existing row, or invalid derived monthly total/KB value.
|
|
- `OUTPUT_*`: missing output, header/type/formula/order/routing/count mismatch, derived daily or monthly total/KB mismatch, or filename mismatch.
|
|
- `STRUCTURED_*` / `OUTPUT_STRUCTURED_*`: invalid all-source reconciliation, derived key, artifact hash, file metadata, outcome, or Finance payload field.
|
|
- `INTERNAL_ERROR`: unexpected exception; include a concise diagnostic without secrets.
|
|
|
|
## Result invariants
|
|
|
|
- `status` is exactly `success` or `failed`.
|
|
- All output filenames are basenames relative to the caller-provided output directory.
|
|
- Daily-mode v2 success has a non-null daily filename, a null monthly filename, and a null exception filename.
|
|
- Legacy daily-monthly v1 success has non-null daily and monthly filenames and a null exception filename.
|
|
- Failure has null daily/monthly filenames and a non-null exception filename.
|
|
- `errors` is empty on success and non-empty on failure.
|
|
- `metrics.channels` is a deterministic array of `{ "worksheet": string, "rows": integer }` entries. Standard worksheets use the fixed workbook order; additional company worksheets follow in name order. This array form is required so Codex structured output can validate future company names without dynamic JSON keys.
|
|
- Never place guest detail in `message`; keep row-specific data inside the downloadable exception workbook and structured error entries only.
|
|
- `structured-result.json` success requires `activation_eligible: true`, zero `validation_failed/price_unmatched` rows, exact artifact hashes, and a balanced all-source outcome count.
|
|
- `structured-result.json` failure requires `activation_eligible: false`, `output_rows: 0`, no daily/monthly artifact, and a non-empty error array.
|
|
|
|
## Database atomicity boundary
|
|
|
|
This processor never writes or changes database state. A downstream adapter may begin a database transaction only after processor exit `0` and successful revalidation of `structured-result.json`. That transaction must insert all file/version/record/channel rows, perform exact Group Code lookup, and switch the current daily version as its final step. Any adapter failure rolls back completely and leaves the previous current version unchanged.
|