60 lines
4.1 KiB
Markdown
60 lines
4.1 KiB
Markdown
# Report artifact deployability repair
|
|
|
|
## Metadata
|
|
|
|
- Date: 2026-08-04
|
|
- Status: Implemented locally; CentOS/Docker deployment acceptance pending operator execution
|
|
- Scope: monthly openpyxl builder, monthly/company OSS publication, OSS/local download routing, migration 016
|
|
- Confidence: High for code/tests; Docker image and live OSS acceptance intentionally not run on this workstation
|
|
- Source: local source inspection, filesystem-backed object-store tests, Python unit/integration tests
|
|
|
|
## Implementation facts
|
|
|
|
- `monthly_reports/publishing.py` now builds monthly workbooks with Python/openpyxl, reopens each sheet, checks
|
|
sheet names, headers, row counts, exact `TOTAL PRICE` formulas, formula count and semantic SHA-256. Each data row
|
|
uses `=R[row]*C[row]*G[row]`.
|
|
- The monthly and company publishers use the existing `ManagedObjectStore` seam when composed for deployment. New
|
|
workbook and `result.json` objects are committed under report-specific immutable roles and registered with
|
|
`storage_provider='oss'`, bucket alias `arr-private`, object key, SHA-256, byte size and MIME type.
|
|
- `arr_web/downloads.py` routes `oss`/`s3` descriptors through the managed-object reader and keeps old local
|
|
descriptors on the controlled project-root reader. Both routes recheck stored/actual identity.
|
|
- `.web-jobs` remains local queue state. It is not uploaded to OSS.
|
|
- `database/016_monthly_report_oss_artifacts.sql` updates the 012 publication trigger to accept OSS/S3 or historical
|
|
local monthly artifacts. The down migration refuses to restore local-only validation while published non-local
|
|
artifacts exist.
|
|
- The stale Node builders, package manifests and old optional Node test were removed. Production entrypoints and
|
|
deployment docs no longer expose Node/npm/module-path flags.
|
|
- The Docker root dependency chain now installs `openpyxl==3.1.5` through `requirements-monthly-reports.txt`; no
|
|
separate npm or Codex-runtime bootstrap is needed.
|
|
|
|
## Follow-up: 2026-08-03 monthly validation failure
|
|
|
|
- Operator-provided production evidence showed a 440-row, multi-sheet 2026-08-03 workbook whose sheet names and
|
|
channel counts matched, and which passed manual validation when reopened non-read-only with numeric tolerance. The
|
|
worker nevertheless emitted `MONTHLY_REPORT_OUTPUT_VALIDATION_FAILED`; outbox event 31 became `dead` and event 30
|
|
remained pending/retrying. This isolates the failure to the workbook-validation implementation rather than
|
|
container, worker startup, database or OSS publication.
|
|
- `_validate_workbook` no longer calls `worksheet.cell(row, column)` on a `read_only=True` workbook. It consumes each
|
|
sheet header and data row in order with `iter_rows`, rejects missing/extra rows or columns, and keeps strict formula
|
|
and semantic checks. Excel-decimal values now use a finite-Decimal absolute tolerance of `0.000001`.
|
|
- Regression coverage builds 440 rows across all five standard sheets over three daily versions, with decimal rate and
|
|
price values plus KB rows. The builder validates 440 formulas successfully; the dedicated XLSX class passes 2/2 and
|
|
the monthly builder/publishing/worker/service/repository slice passes 18/18.
|
|
|
|
## Verification
|
|
|
|
- Targeted report/web/storage/migration suite: 41 tests passed; builder/company integration slice: 15 tests passed
|
|
(56/56 together).
|
|
- Full local discovery: 315 tests executed; 307 passed, 3 skipped, and 8 environment errors were limited to the
|
|
pre-existing missing `httpx` Agent modules and unavailable Aliyun SDK/client construction. No failure was caused by
|
|
the report/OSS changes.
|
|
- Docker build/Compose and real Aliyun OSS were not run because the development environment has no Docker and the user
|
|
explicitly requested fake/in-memory storage tests instead.
|
|
|
|
## Operator acceptance still required
|
|
|
|
Apply migration 016 on the isolated `booking_test` database, rebuild the clean image, start Web and the independent
|
|
worker with the existing OSS/DB secrets, submit one controlled XML, wait for monthly publication, and verify that
|
|
monthly/company downloads still work after the local report cache is removed. The exact commands are in `deploy/README.md`
|
|
and the final task handoff.
|