57 lines
4.3 KiB
Markdown
57 lines
4.3 KiB
Markdown
# System Overview
|
|
|
|
## Current Architecture
|
|
|
|
ARR2.0 accepts Opera XML plus a separate Booking Tour Code/`โรงแรม` workbook and owns both deterministic processing
|
|
lifecycles. It writes immutable private
|
|
objects, runs the frozen processor locally, independently validates the complete artifacts, and atomically commits
|
|
accepted facts to PostgreSQL. Downstream analytics and report programs read committed facts.
|
|
Successful daily commits also create a durable outbox event. A separate worker derives the affected month and watermark
|
|
from committed `ARRIVAL` facts, publishes a validated workbook, and records metadata-only report state in PostgreSQL.
|
|
|
|
## Main Components
|
|
|
|
| Component | Responsibility |
|
|
|---|---|
|
|
| `arr_web.auth` / authenticated `SessionLedger` | Environment-owned operator credentials, bounded login attempts, random server-side sessions, CSRF and logout revocation |
|
|
| `arr_web.programmatic` | Terminal upload orchestration and safe public error mapping |
|
|
| `arr_processing.local` / `arr_processing.policy` | Isolated frozen processor execution and approved version/rule identity |
|
|
| `arr_storage` | Immutable staged/committed OSS workflow; all object ACLs private |
|
|
| `arr_ingestion.validation` | Strict delivery/result/structured validation plus independent daily validation |
|
|
| `arr_ingestion.postgres` | Job lifecycle, artifact registration, atomic Finance version commit and outbox |
|
|
| `booking_ingestion.excel` | Bounded Tour Code/`โรงแรม` extraction, latest-row/cancellation semantics and room-item normalization |
|
|
| `booking_ingestion.excel_review_postgres` | Durable editable draft state and zero-pending atomic current-source activation |
|
|
| `arr_web.booking_uploads` | Private Booking workbook upload, draft review orchestration and privacy-minimized source summaries |
|
|
| `arr_web.job_trace` | Read-only programmatic trace from persisted run/attempt/delivery/version/outbox facts |
|
|
| `monthly_reports.worker` | Dedicated leased outbox consumer with retry/dead-letter behavior |
|
|
| `monthly_reports.repository` / `reporting` schema | ARRIVAL-derived snapshots, report versions, lineage, manifests and artifact identities |
|
|
| `monthly_reports`, `channel_analytics`, `company_reports` | Deterministic downstream consumers of committed facts; company reports build official XLSX files in Python/openpyxl inside Web |
|
|
| Web + Caddy Compose | Web-owned login/session boundary behind Caddy HTTPS; no browser-native Basic Auth and no MCP service |
|
|
|
|
## Important Boundaries
|
|
|
|
- The uploaded source is re-materialized from committed object storage before processing.
|
|
- Login documents/assets, the H5 read-only page/assets, purpose-built public H5 aggregate endpoints, `POST /api/login`
|
|
and minimal `/healthz` readiness are anonymous Web routes. The desktop portal redirects to login; generic business
|
|
APIs, detailed health, uploads, traces and downloads return `401` without an authenticated server-side session.
|
|
- Operator credentials come only from runtime `ARR_WEB_USERNAME` / `ARR_WEB_PASSWORD`; the application fails closed when either is absent. Authenticated mutations also require the per-session CSRF token.
|
|
- Processor exit code and JSON status must agree; output paths are confined to an isolated temporary directory.
|
|
- Validation completes before the database transaction; any transaction failure leaves no partial active version.
|
|
- Booking uploads create review drafts first. Only an explicit activation with no retained pending items can atomically
|
|
create immutable Booking facts and switch `booking.current_source_batch`; an open draft blocks company-report creation.
|
|
- Only recognized transient PostgreSQL concurrency errors receive bounded transaction retries.
|
|
- PostgreSQL state, not HTTP/console output, is authoritative for success.
|
|
- Daily and new report downloads are read from OSS and rechecked; historical local report artifacts remain readable through
|
|
the controlled project-root fallback with the same size and SHA-256 checks.
|
|
- Fresh uploads are new jobs/versions; exact delivery replay is idempotent.
|
|
- Monthly success is acknowledged only after both artifacts are registered and the publication is active; replay of the same snapshot returns the existing report.
|
|
|
|
## Related Decisions
|
|
|
|
- [ADR-004](../10-decisions/ADR-004-arr-owned-programmatic-processing.md)
|
|
- [ADR-001](../10-decisions/ADR-001-automatic-monthly-trigger-and-total-price-formula.md)
|
|
|
|
## Last Updated
|
|
|
|
2026-08-03
|