Exclude PM room types from shared daily report processing

This commit is contained in:
Wyndham ARR committed 2026-10-08 22:30:04 +08:00
1 parent d3902dd857
commit f46efd6d9a
32 files changed
+968 -69

No files matched your search

+42 -4
View File
@@ -158,16 +158,20 @@ def _is_transient_database_error(error: Exception) -> bool:
return isinstance(sqlstate, str) and sqlstate in TRANSIENT_SQLSTATES
def _outcome_counts(payload: Mapping[str, Any]) -> Tuple[int, int, int, int, int, int]:
def _outcome_counts(payload: Mapping[str, Any]) -> Tuple[int, int, int, int, int, int, int]:
values = payload.get("outcome_counts")
if not isinstance(values, Mapping):
raise IngestionError(
"RESULT_CONTRACT_INVALID",
"structured outcome counts are invalid",
)
if payload.get("processor_version") == "4.4.0" and not {
"excluded_cancelled", "excluded_pm"
}.issubset(values):
raise IngestionError("RESULT_CONTRACT_INVALID", "structured outcome counts are invalid")
try:
counts = tuple(
int(values.get(name, 0) if name == "excluded_cancelled" else values[name])
int(values.get(name, 0) if name in {"excluded_cancelled", "excluded_pm"} else values[name])
for name in (
"retained",
"excluded_rate_code",
@@ -175,6 +179,7 @@ def _outcome_counts(payload: Mapping[str, Any]) -> Tuple[int, int, int, int, int
"validation_failed",
"price_unmatched",
"excluded_cancelled",
"excluded_pm",
)
)
except (KeyError, TypeError, ValueError):
@@ -339,6 +344,7 @@ class PostgresIngestionRepository(IngestionRepository):
raise IngestionError("DATABASE_MIGRATION_MISSING", "direct data entry requires migration 019")
self._run_transaction(check, "direct data schema could not be checked")
self.assert_cancelled_scope_schema()
self.assert_pm_scope_schema()
def assert_cancelled_scope_schema(self) -> None:
"""Require the count and outcome constraints before either input is enabled."""
@@ -365,6 +371,36 @@ class PostgresIngestionRepository(IngestionRepository):
"ARR processing requires migration 020")
self._run_transaction(check, "ARR cancellation schema could not be checked")
def assert_pm_scope_schema(self) -> None:
"""Require PM auditing before enabling the processor 4.4 entrypoints."""
def check(cursor):
cursor.execute("""SELECT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'finance' AND table_name = 'daily_versions'
AND column_name = 'excluded_pm_rows'
AND data_type = 'integer' AND is_nullable = 'NO'
), (
SELECT pg_get_constraintdef(oid) FROM pg_constraint
WHERE conrelid = 'finance.daily_versions'::regclass
AND conname = 'daily_versions_counts_reconcile'
), (
SELECT pg_get_constraintdef(oid) FROM pg_constraint
WHERE conrelid = 'finance.daily_records'::regclass
AND conname = 'daily_records_outcome_check'
), (
SELECT pg_get_constraintdef(oid) FROM pg_constraint
WHERE conrelid = 'finance.daily_records'::regclass
AND conname = 'daily_records_pm_exclusion_shape'
)""")
row = cursor.fetchone()
if (not row or row[0] is not True
or "excluded_pm_rows" not in str(row[1] or "")
or "excluded_pm" not in str(row[2] or "")
or "ROOM_TYPE_PM_EXCLUDED" not in str(row[3] or "")):
raise IngestionError("DATABASE_MIGRATION_MISSING",
"ARR processing requires migration 021")
self._run_transaction(check, "ARR PM schema could not be checked")
def register_job(self, registration: JobRegistration) -> None:
if (
registration.source.role not in {"source_xml", "source_data"}
@@ -1837,13 +1873,14 @@ class PostgresIngestionRepository(IngestionRepository):
validation_failed_rows,
price_unmatched_rows,
excluded_cancelled_rows,
excluded_pm_rows,
failure_code,
failure_message,
validated_at
)
VALUES (
NULL, NULL, %s, %s, %s, %s, %s, 'rejected',
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s, 'deterministic processing failed', now()
)
RETURNING id
@@ -2076,11 +2113,12 @@ class PostgresIngestionRepository(IngestionRepository):
validation_failed_rows,
price_unmatched_rows,
excluded_cancelled_rows,
excluded_pm_rows,
validated_at
)
VALUES (
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'validated',
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, now()
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, now()
)
RETURNING id
""",