Files
wyndham-ARR/.project-docs/50-evidence/topics/2026-07-30-channel-bi-post-update-data-contamination.md
2026-07-31 15:11:42 +08:00

7.1 KiB
Raw Blame History

Evidence Topic: Channel BI post-update data contamination

Metadata

  • Date: 2026-07-30
  • Status: Active
  • Scope: ARR2 local Web port 8766, controlled booking_test, Channel BI and July monthly publication
  • Confidence: Fact
  • Source: source/hash inspection, isolated deterministic replay, live privacy-minimized APIs, repeatable-read read-only PostgreSQL reconciliation and focused tests
  • Last verified: 2026-07-30
  • Stale trigger: any change to July current Finance pins, retirement of fixture version 2, monthly republication, or BI grouping/label behavior

Question

What data does Channel BI consume, and why did its July values look wrong after the latest uploads?

Evidence

Implemented source and formulas

  • The browser calls /api/analytics?month=YYYY-MM; PostgresPortalRepository delegates to PostgresAnalyticsRepository against booking_test.
  • Month/date pins come from finance.current_daily_versions, channel membership/order/count expectations from finance.daily_channel_metrics, and aggregates/detail from current retained finance.v_active_daily_facts.
  • Sold rooms are sum(no_of_rooms), room nights are sum(no_of_rooms * nights), and revenue is sum(total_price) without multiplying the stored total again. Monthly XLSX files are not a BI source.

Live reconciliation

The active ARR2 Web API on port 8766 and direct PostgreSQL reads return the same current projection. Legacy port 8765 is no longer listening.

Business date Daily version Provenance Retained rows Revenue Current role
2026-07-20 5 0720.XML, hash-matched real upload 100 370,500 valid real daily slice
2026-07-21 4 real ARR upload 119 452,000 V01 operational source
2026-07-22 6 0722.XML, hash-matched real upload 88 269,700 valid real daily slice
2026-07-23 7 0723-RES_DETAIL-修正版.xml, hash-matched real upload 109 359,150 valid real daily slice
2026-07-27 2 mvp-v1-fixture-20260727 / synthetic.xml / local_fixture 1 5,400 test contamination
  • The 07-23 upload committed at 16:12:27, after the earlier 15:44 diagnostic snapshot. This explains why that snapshot contained only 307 real rows; it did not prove the four-day business total.
  • Excluding fixture version 2 now yields 416 rows/rooms, 853 room-nights, 1,451,350 revenue, nine room types, six worksheet channels and latest real ARRIVAL 2026-07-23.
  • The live BI includes the fixture and therefore returns 417 rows/rooms, 856 room-nights, 1,456,750 revenue, ten room types and 更新至 2026-07-27. Its extra type is explicitly SYNTHETIC ROOM TYPE.
  • July monthly V04 is active with 417 rows; V01V04 all inherit fixture version 2 and its false operational 7.27 watermark.

Source identity and date attribution

  • Immutable source SHA-256 maps the accepted sources exactly to local originals: 0720.XML is version 5 and 0722.XML is version 6; 0721.XML and 0723-RES_DETAIL-修正版.xml map to versions 4 and 7 respectively.
  • The processor derives business date from agreeing XML GROUPBY1_SORT_COL/GROUPBY1_COL values and requires each retained reservation ARRIVAL to match it; filename and upload order are not date authorities.
  • An isolated replay independently reproduced 0720.XML -> 2026-07-20 -> 100 retained and 0722.XML -> 2026-07-22 -> 88 retained. The user was correct about the 416 total but had those two day counts verbally reversed.

Frontend freshness

  • Channel BI loads at page boot, month change, or first BI-tab entry only. A successful XML upload refreshes daily jobs but not analytics, and later BI-tab entries skip reload once state.analytics exists.
  • Therefore an already-open page can continue showing the pre-07-23 value 308 even though the API has advanced to 417. Unlike the monthly list, Channel BI has no polling or visibility-aware reload.

Exact V01 reconciliation

  • V01 report ID 1 is persisted as superseded, as_of_date=2026-07-27, 120 rows and five channels.
  • Its legitimate OSS source lineage is daily version 4: 119 retained rows, all with ARRIVAL=2026-07-21.
  • Its only later lineage is daily version 2: one retained row with ARRIVAL=2026-07-27, accepted under run mvp-v1-fixture-20260727 from synthetic.xml using provider local_fixture.
  • Reopening the exact registered V01 workbook independently found the same 119/1 ARRIVAL distribution. The file is 20,741 bytes and its SHA-256 a43cdac3f6d97f6b73f635d0f386cffd0ad8b6416e8f92a7b6afc2f79f1e8635 matches the artifact registry.
  • Therefore the user's operational statement “V01 is updated through 2026-07-21” is correct. The stored 7.27 label is the consequence of contaminated report content, not a filename parser or a metadata-only rendering defect.

Channel/company semantics

  • Six channel keys are valid for these real facts: LianTai intentionally splits into LIANTAI-GROUP and LIANTAI-FIT, alongside QBD, DY-AI-Easy-KB, FENGRUN and HanaTour.
  • The BI card renders worksheet-level channel_count but labels it 公司数; six channels can represent five top-level companies, so the label is misleading even after data cleanup.

Regression and mutation boundary

  • The corrected focused run passed 24 analytics-contract, PostgreSQL-provider and Web tests.
  • All database investigations used REPEATABLE READ READ ONLY; no Finance pointer, version, artifact or report was changed during diagnosis.

Finding

Channel BI is correctly reading and aggregating its configured current PostgreSQL facts. One proven cause of the reported mismatch is a data-hygiene incident: a database acceptance fixture remained pinned as a current Finance day after real uploads were enabled. It explains the one-room difference between the correct real total 416 and live API total 417, as well as every false 7.27 watermark. A second frontend defect can leave an open BI view showing 308 after the 07-23 commit. The user's 07-20/07-22 verbal attribution was reversed, but this does not change the 416 total. A smaller UX issue independently mislabels worksheet-channel count as company count.

Impact

  • Business-facing July BI and monthly V04 are not clean acceptance outputs until fixture version 2 is removed from the current projection and a clean July monthly version is published.
  • Historical V01 cannot be truthfully corrected by changing only its as_of_date or filename because the registered workbook itself contains the fixture row. Preserve that immutable artifact as contaminated audit history and publish a clean operational replacement after the current projection is corrected.
  • Remediation should preserve immutable audit history; retire/unpin the fixture instead of deleting its version rows.
  • Production/readiness checks should reject any current Finance source whose provider is local_fixture (or other explicitly non-operational provenance).

Open Items

  • Obtain authorization for the controlled Finance-pointer repair and clean monthly republication.
  • Make Channel BI refresh after successful upload and/or on visible BI-tab re-entry so it cannot retain an old snapshot.
  • Decide whether to relabel the BI card as 渠道/子表数 or add a distinct five-company aggregation.