Files
wyndham-ARR/.project-docs/40-domain/business-rules.md
2026-08-02 12:56:22 +08:00

7.7 KiB
Raw Blame History

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/login and no-detail /healthz readiness 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.xml is 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 ARRIVAL facts belonging to the committed daily version.
  • The monthly as_of_date/“更新至” is the greatest ARRIVAL actually 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 PRICE cell is a formula whose business meaning is REAL PRICE × NIGHTS × NO_OF_ROOMS (current layout example: =R2*C2*G2).
  • A stored database total_price may 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-10 uses the 10th, 11-20 uses the 20th and 21-month-end uses 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_COMMENT and Booking Room are 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 Room is 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-TWN and U-DBL normalize to U-TWN and U-DBL; 高级房TWN/高级房DBL normalize to TWN/DBL. Unknown bracket labels retain their raw text and parsed/default quantity as pending. Recognized unbracketed names such as 6+4, Family Suite, Junior Suite and Superior Garden also 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