feat: add daily manual price review workflow

This commit is contained in:
Wyndham ARR
2026-08-06 22:40:18 +08:00
parent aae3d8e1db
commit ca3e8e18fa
77 changed files with 7750 additions and 602 deletions

View File

@@ -151,6 +151,7 @@ SELECT
run.run_key,
CASE run.run_status
WHEN 'accepted' THEN 'succeeded'
WHEN 'awaiting_review' THEN 'needs_review'
WHEN 'rejected' THEN 'failed'
ELSE run.run_status
END AS public_status,
@@ -164,7 +165,12 @@ SELECT
version.retained_rows,
version.version_no,
daily_artifact.sha256,
coalesce(room_totals.no_of_rooms, 0) AS no_of_rooms
coalesce(room_totals.no_of_rooms, 0) AS no_of_rooms,
review_summary.case_key,
review_summary.case_status,
review_summary.revision,
coalesce(review_summary.completed_items, 0) AS review_completed_items,
coalesce(review_summary.total_items, 0) AS review_total_items
FROM ingestion.processing_runs AS run
JOIN ingestion.artifacts AS source
ON source.id = run.source_artifact_id
@@ -178,6 +184,19 @@ LEFT JOIN LATERAL (
WHERE record.daily_version_id = version.id
AND record.outcome = 'retained'
) AS room_totals ON true
LEFT JOIN LATERAL (
SELECT
review.case_key,
review.case_status,
review.revision,
count(item.id) AS total_items,
count(item.id) FILTER (WHERE item.real_price IS NOT NULL) AS completed_items
FROM ingestion.daily_review_cases AS review
LEFT JOIN ingestion.daily_review_items AS item
ON item.review_case_id = review.id
WHERE review.processing_run_id = run.id
GROUP BY review.case_key, review.case_status, review.revision
) AS review_summary ON true
WHERE run.pipeline_type = 'opera_daily'
AND (
(run.business_date >= %s AND run.business_date < %s)
@@ -214,6 +233,7 @@ SELECT
run.run_status,
CASE run.run_status
WHEN 'accepted' THEN 'succeeded'
WHEN 'awaiting_review' THEN 'needs_review'
WHEN 'rejected' THEN 'failed'
ELSE run.run_status
END AS public_status,
@@ -272,11 +292,14 @@ SELECT
delivery.failure_message,
delivery.received_at,
delivery.validated_at,
delivery.committed_at
delivery.committed_at,
review.case_key
FROM ingestion.processing_deliveries AS delivery
LEFT JOIN ingestion.processing_attempts AS attempt
ON attempt.id = delivery.attempt_id
AND attempt.processing_run_id = delivery.processing_run_id
LEFT JOIN ingestion.daily_review_cases AS review
ON review.id = delivery.review_case_id
WHERE delivery.processing_run_id = %s
ORDER BY delivery.received_at, delivery.id
""".strip()
@@ -325,13 +348,62 @@ SELECT
version.created_at,
version.validated_at,
version.activated_at,
version.superseded_at
version.superseded_at,
version.review_case_id,
version.manual_override_sha256,
version.manually_priced_rows
FROM finance.daily_versions AS version
WHERE version.processing_run_id = %s
ORDER BY COALESCE(version.version_no, 0), version.id
""".strip()
JOB_TRACE_REVIEW_CASE_SQL = """
SELECT
review.case_key,
review.case_status,
review.revision,
count(item.id) AS total_items,
count(item.id) FILTER (WHERE item.real_price IS NOT NULL) AS completed_items,
review.manual_override_sha256,
review.failure_code,
review.created_at,
review.updated_at,
review.frozen_at,
review.completed_at,
review.cancelled_at
FROM ingestion.daily_review_cases AS review
LEFT JOIN ingestion.daily_review_items AS item
ON item.review_case_id = review.id
WHERE review.processing_run_id = %s
GROUP BY
review.case_key,
review.case_status,
review.revision,
review.manual_override_sha256,
review.failure_code,
review.created_at,
review.updated_at,
review.frozen_at,
review.completed_at,
review.cancelled_at
""".strip()
JOB_TRACE_REVIEW_EVENTS_SQL = """
SELECT
event.event_type,
event.actor_username,
event.revision,
event.created_at
FROM ingestion.daily_review_events AS event
JOIN ingestion.daily_review_cases AS review
ON review.id = event.review_case_id
WHERE review.processing_run_id = %s
ORDER BY event.created_at, event.id
""".strip()
JOB_TRACE_OUTBOX_SQL = """
SELECT
event.event_key,
@@ -537,6 +609,11 @@ class PostgresPortalRepository:
"version_no": int(row[10]) if row[10] is not None else None,
"daily_report_sha256": str(row[11]) if row[11] else None,
"no_of_rooms": int(row[12] or 0),
"review_case_id": str(row[13]) if row[13] else None,
"review_status": str(row[14]) if row[14] else None,
"review_revision": int(row[15]) if row[15] is not None else None,
"review_completed_items": int(row[16] or 0),
"review_total_items": int(row[17] or 0),
}
for row in rows
], total
@@ -623,6 +700,7 @@ class PostgresPortalRepository:
"received_at": item[10],
"validated_at": item[11],
"committed_at": item[12],
"review_case_id": str(item[13]) if item[13] else None,
}
for item in cursor.fetchall()
]
@@ -672,6 +750,13 @@ class PostgresPortalRepository:
"validated_at": item[14],
"activated_at": item[15],
"superseded_at": item[16],
"review_case_id": (
int(item[17]) if item[17] is not None else None
),
"manual_override_sha256": (
str(item[18]) if item[18] else None
),
"manually_priced_rows": int(item[19] or 0),
}
for item in cursor.fetchall()
]
@@ -690,6 +775,46 @@ class PostgresPortalRepository:
}
for item in cursor.fetchall()
]
cursor.execute(JOB_TRACE_REVIEW_CASE_SQL, (run_id,))
review_case_row = cursor.fetchone()
review_case = (
{
"case_id": str(review_case_row[0]),
"case_status": str(review_case_row[1]),
"revision": int(review_case_row[2]),
"total_items": int(review_case_row[3] or 0),
"completed_items": int(review_case_row[4] or 0),
"manual_override_sha256": (
str(review_case_row[5])
if review_case_row[5]
else None
),
"failure_code": (
str(review_case_row[6])
if review_case_row[6]
else None
),
"created_at": review_case_row[7],
"updated_at": review_case_row[8],
"frozen_at": review_case_row[9],
"completed_at": review_case_row[10],
"cancelled_at": review_case_row[11],
}
if review_case_row is not None
else None
)
cursor.execute(JOB_TRACE_REVIEW_EVENTS_SQL, (run_id,))
review_events = [
{
"event_type": str(item[0]),
"actor_username": str(item[1]),
"revision": int(item[2]),
"created_at": item[3],
}
for item in cursor.fetchall()
]
return build_job_trace(
run,
attempts=attempts,
@@ -697,6 +822,8 @@ class PostgresPortalRepository:
submissions=submissions,
versions=versions,
outbox_events=outbox_events,
review_case=review_case,
review_events=review_events,
)
except PortalDataError:
raise