7.7 KiB
7.7 KiB
Business Rules
Durable Rules
- Human access to desktop/H5 pages, detailed health, business APIs, uploads, traces and downloads requires an authenticated ARR Web session. Only login assets,
POST /api/loginand no-detail/healthzreadiness are anonymous. - The single-operator login identity is injected as
ARR_WEB_USERNAME/ARR_WEB_PASSWORD; real credentials are never stored in source or returned/logged. Missing credentials fail Web startup closed. - Login failures use a generic message and bounded attempt blocking. Logout revokes the server-side session; authenticated mutations continue to require CSRF.
- The user uploads XML; the user does not submit a report year, report month, cutoff date, or separate monthly-generation request in the primary workflow.
- Daily history and task trace show the validated browser-uploaded XML basename. Canonical internal source name
source.xmlis not user-facing; historical rows with no recorded basename display an unknown marker rather than a guessed filename. - Daily, monthly-publication and company-generation histories have independent viewing months and default to the most
recent month containing that record type. Viewing-month state is read-only: it resets list paging but never changes
monthly derivation or a company generation request. Company
生成月份and history查看月份are separate inputs. - ARR's frozen processor generates complete structured data, which must be independently validated and successfully committed to the database before downstream monthly processing starts.
- The production XML path must not require Agent, MCP, prompts, model-generated JSON, fetch grants, or a public source URL.
- A successful database commit automatically triggers the monthly-report processing program through the business system.
- Automatic monthly processing runs in a dedicated worker process, not inside the Web request process.
- The worker derives the affected month from retained
ARRIVALfacts belonging to the committed daily version. - The monthly
as_of_date/“更新至” is the greatestARRIVALactually included in the current monthly snapshot. The XML filename and wall-clock date are never authorities for it. - Year, month, cutoff/as-of date, and similar fields are internal derived execution/audit values. Their presence in code or metadata does not make them user inputs.
- The monthly output contains the exact business dimension/field
TOTAL PRICE. - Each monthly XLSX data-row
TOTAL PRICEcell is a formula whose business meaning isREAL PRICE × NIGHTS × NO_OF_ROOMS(current layout example:=R2*C2*G2). - A stored database
total_pricemay be used for integrity checking, but it does not replace the required formula in the exported workbook. - Monthly business/guest rows remain derived from current Finance facts. PostgreSQL persists only publication identity, lineage, channel counts and artifact metadata.
- The outbox event is marked published only after a report is active/superseded and both workbook/result artifacts are registered; replay of the same snapshot must not create a duplicate publication.
- A published monthly version automatically appears in the open monthly list; the primary workflow has no manual list-refresh step.
- Company-channel detail generation is allowed for any period in the selected current month and for historical months. A future report month is rejected so the system does not create an intentionally empty future workbook.
- Company-channel C/O periods keep fixed report cutoffs:
01-10uses the 10th,11-20uses the 20th and21-month-enduses the selected month's natural month-end. The workbook uses the current committed Finance snapshot through that cutoff even when the calendar period has not ended; later-arriving facts require a rerun to be included. - The company-channel UI labels calendar status as
周期未结束or周期已结束. These labels describe whether the selected period has reached its Bangkok completion boundary; they are not generation permission states. - In a company-channel detail workbook, a Finance fact with no normalized Group Code remains visible as its own row;
RES_COMMENTandBooking Roomare blank, and this expected blank does not create a warning or duplicate highlight. - A Finance stay segment with a consistent nonblank Group Code keeps that Group Code and its normal aggregation. When
no current accepted Booking room can be resolved, only
Booking Roomis blank; the lookup miss does not create an error or warning and does not block the company's workbook. - The company-report Booking allocation model consists of normalized Group Code, room type and quantity. A raw intake adapter may derive these fields from a source workbook, but raw workbook columns and normalized result dimensions are separate contracts; worksheet, physical row, artifact hash and parse version remain provenance.
- A raw Booking workbook is recognized only on a worksheet containing one Tour Code/Group Code header and the exact
Thai
โรงแรมheader. Tour Codes are Unicode-normalized and all whitespace is removed before matching. - For repeated Tour Codes, the physically last source row replaces earlier rows. A final row with an explicit textual cancellation removes the Tour Code; cell color or other formatting alone never means cancellation.
- Room extraction reads parenthesized hotel segments. A
【label】token takes the following integer as quantity and defaults to one when no following integer exists. Multiple tokens become separate items even when they normalize to the same room type. - Numeric suffix variants of
U-TWNandU-DBLnormalize toU-TWNandU-DBL;高级房TWN/高级房DBLnormalize toTWN/DBL. Unknown bracket labels retain their raw text and parsed/default quantity as pending. Recognized unbracketed names such as6+4,Family Suite,Junior SuiteandSuperior Gardenalso remain pending because the source omitted brackets. Surcharge, child-breakfast and guide-room tokens are not guest-room allocations. - Pending items do not contribute accepted Booking room quantity. Automatic and manual rows are both editable and deletable; activation requires zero pending items and at least one confirmed item. Re-extraction rebuilds the review draft from source and intentionally discards draft-only edits/deletions.
- The review UI pages at 50 records. A delete request contains 1-50 unique item IDs and is all-or-nothing: every item must still be undeleted, belong to the same reviewing draft and be deletable, otherwise the transaction rolls back.
- An open Booking review displays the draft artifact's validated browser-uploaded filename directly below
Booking记录提取. Accepted historical-source readiness is not shown as provenance for draft extraction records. - Once accepted, a manually uploaded Booking workbook replaces the complete current source rather than appending silently to the previous workbook. Migrations 014/015 and the HTTP GET/POST/PATCH/DELETE adapter represent this boundary; the first real draft activation remains a controlled business acceptance action.
- Booking normalizes the complete Group Code and globally aggregates repeated
(Group Code, room type)rows by summed quantity. Worksheet, company/channel and stay dates are not current Booking join dimensions. This contract therefore requires one Group Code to identify one room allocation across those scopes; a different business reality requires a schema/view/report-join change, not merely extra unused Excel columns. - Contradictory Group Code source fields and invalid Finance dates, nights or price details remain strict company-report errors; the blank fallback applies only to absent or unresolved Booking enrichment.
Last Reviewed
2026-07-31