Files
wyndham-ARR/.project-docs/20-architecture/data-flow.md

5.6 KiB

Data Flow

Web Access Boundary

  1. An anonymous browser requesting / is redirected to /login with an allowlisted return target. /h5 and its H5 assets are public; anonymous access is limited to /api/public/h5/months, /api/public/h5/analytics and the no-detail /healthz signal. Other anonymous API/download requests receive JSON 401 AUTH_REQUIRED.
  2. POST /api/login accepts strict same-origin JSON, verifies runtime-owned credentials under a bounded per-client attempt ledger and issues a random server-side session plus CSRF token in an HttpOnly, SameSite=Strict cookie.
  3. Every desktop portal page, detailed health response, generic read API, upload/mutation, task trace and artifact download validates the authenticated session. Public H5 endpoints return only sanitized aggregate dashboard data; mutations additionally validate the session CSRF token.
  4. POST /api/logout validates CSRF, revokes the server-side session and expires the cookie. /healthz remains a no-detail anonymous readiness signal for container orchestration.
  5. GET /api/history-months is an authenticated read-only discovery path. It combines daily processing/monthly publication counts from PostgreSQL with durable company-job counts; each desktop history then reads its selected month through the existing paged list endpoint.

Primary XML Flow

Step Source Destination Gate
1 Browser XML upload Uploaded-basename task provenance + private canonical source object + queued DB job Filename/content/size and immutable object identity
2 Committed source object Isolated processor input Materialization rechecks stored bytes
3 Fixed process_daily.py Daily/result/structured or failure artifacts Timeout, confined paths, exit/JSON agreement
4 Local artifacts Private committed OSS objects Role, MIME, size and SHA-256
5 Canonical DeliveryEnvelope DeliveryValidator Strict Schema, reconciliation, source/artifact hashes and independent validation
6 Verified delivery PostgreSQL Finance facts Serializable atomic commit/version activation
7 Accepted/failed run Task trace and outbox Persisted state is authoritative
8 arr.daily_version_committed Dedicated monthly worker Lease, SKIP LOCKED, bounded retry/dead-letter
9 Retained Finance ARRIVAL facts Monthly snapshot request Affected month from event version; “更新至” is max included ARRIVAL
10 Monthly snapshot XLSX/result + reporting metadata Formula reopen-validation, current-pin recheck, atomic activation
11 Registered active report Web list/download + outbox acknowledgement Real report ID; visible monthly tab polls automatically; path/size/SHA-256 recheck before download

State Ownership

  • PostgreSQL owns job/attempt/delivery state, Finance facts, current version and outbox.
  • PostgreSQL reporting owns monthly publication versions, daily-version lineage, channel manifest and artifact identities; it does not duplicate monthly business rows.
  • OSS owns immutable source/output bytes; ARR stores only controlled object identities in the database.
  • processing_runs.uploaded_filename owns the user-facing browser basename; the source artifact remains canonically named source.xml for processing and validation.
  • Temporary processor/validator paths are deleted after each request.
  • Monthly XLSX/result bytes live in immutable local archive paths on the current shared output volume; generated report artifacts are derived outputs, not an alternative business fact source.

Booking Source And Company-Report Flow

Step Source Destination Gate
1 Authenticated Booking XLSX upload Bounded parser 2.0 Requires Tour Code + exact โรงแรม, latest-row/cancellation semantics and room-item extraction/review
2 Parsed raw items Private artifact + extraction draft Live migration 015 preserves source coordinates, confirmed/pending/deleted item state and extracted values
3 Human review Draft item updates Confirm/edit or atomically soft-delete 1-50 unique selected items while canonical current Booking source remains unchanged
4 Fully reviewed draft Accepted canonical batch + booking.current_source_batch Live 014/015 plus repository zero-pending/atomic activation; real PostgreSQL transaction-only vertical slice passes
5 Current Finance facts Company-report stay segments Finance supplies company/channel/dates/pricing; normalized Group Code is the Booking lookup key; open draft blocks new job
6 Current Booking room summary Booking Room output Sum by Group Code + room type; missing or unmatched Group Code leaves Booking Room blank

Migrations 014/015 are formally applied: batch 1 is the current source and the draft tables are empty. The source contains a PostgreSQL draft repository, backend routes, browser editor and GET/POST/PATCH/DELETE transport coverage. A real-PostgreSQL transaction-only probe created a draft, confirmed its pending item, activated immutable facts and then rolled everything back, preserving the current source and leaving no synthetic residue. First activation of an actual operator workbook remains a controlled business action.

Monthly Derivation Boundary

The worker never infers a date from an XML filename or the current clock. It treats the event's daily_version_id only as a lookup key, derives scope from retained Finance ARRIVAL, and verifies that the generated report's maximum arrival equals its persisted as_of_date. Every data-row TOTAL PRICE cell is =R[row]*C[row]*G[row].

Last Updated

2026-07-31