feat: add daily manual price review workflow
This commit is contained in:
105
tests/test_daily_price_review_migration.py
Normal file
105
tests/test_daily_price_review_migration.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
UP_PATH = PROJECT_ROOT / "database" / "017_daily_price_review.sql"
|
||||
DOWN_PATH = PROJECT_ROOT / "database" / "017_daily_price_review.down.sql"
|
||||
|
||||
|
||||
class DailyPriceReviewMigrationTests(unittest.TestCase):
|
||||
def test_forward_migration_adds_only_review_lifecycle_and_manual_lineage(self) -> None:
|
||||
sql = UP_PATH.read_text(encoding="utf-8")
|
||||
lowered = sql.lower()
|
||||
|
||||
for required in (
|
||||
"current_database() <> 'booking_test'",
|
||||
"migrations 008 through 016 must be applied before 017",
|
||||
"CREATE TABLE ingestion.daily_review_cases",
|
||||
"CREATE TABLE ingestion.daily_review_items",
|
||||
"CREATE TABLE ingestion.daily_review_events",
|
||||
"processing_run_id bigint NOT NULL UNIQUE",
|
||||
"daily_review_items_key_unique",
|
||||
"'awaiting_review'",
|
||||
"'review_required'",
|
||||
"'recorded_review'",
|
||||
"numeric(18,2)",
|
||||
"'manual_review'",
|
||||
"manual_override_sha256",
|
||||
"manually_priced_rows",
|
||||
"daily_versions_source_rule_override_unique",
|
||||
"daily_review_items_mutability_guard",
|
||||
"daily_review_cases_immutability_guard",
|
||||
"daily_review_events_immutability_guard",
|
||||
"PRICE_REVIEW_REQUIRED",
|
||||
"PRICE_REVIEW_UPDATED",
|
||||
"PRICE_REVIEW_FINALIZED",
|
||||
"PRICE_REVIEW_CANCELLED",
|
||||
"PRICE_REVIEW_GENERATION_FAILED",
|
||||
"PRICE_REVIEW_FAILED",
|
||||
"result_delivery_mode = 'artifact_callback'",
|
||||
"result_delivery_mode = 'direct_mcp'",
|
||||
):
|
||||
with self.subTest(required=required):
|
||||
self.assertIn(required, sql)
|
||||
|
||||
review_section = lowered[
|
||||
lowered.index("create table ingestion.daily_review_cases") : lowered.index(
|
||||
"alter table finance.daily_versions"
|
||||
)
|
||||
]
|
||||
for forbidden in ("full_name", "confirmation_no", "res_comment", "trace_text", "remarks"):
|
||||
with self.subTest(forbidden=forbidden):
|
||||
self.assertNotIn(forbidden, review_section)
|
||||
self.assertIn(
|
||||
"GRANT SELECT, INSERT, UPDATE ON ingestion.daily_review_cases, ingestion.daily_review_items TO arr_app",
|
||||
sql,
|
||||
)
|
||||
self.assertIn(
|
||||
"GRANT SELECT, INSERT ON ingestion.daily_review_events TO arr_app",
|
||||
sql,
|
||||
)
|
||||
self.assertNotIn("DROP SCHEMA", sql)
|
||||
|
||||
def test_down_migration_refuses_to_discard_review_or_manual_facts(self) -> None:
|
||||
sql = DOWN_PATH.read_text(encoding="utf-8")
|
||||
for required in (
|
||||
"current_database() <> 'booking_test'",
|
||||
"SELECT 1 FROM ingestion.daily_review_cases",
|
||||
"review_case_id IS NOT NULL",
|
||||
"manual_override_sha256 IS NOT NULL",
|
||||
"run_status = 'awaiting_review'",
|
||||
"attempt_status = 'review_required'",
|
||||
"delivery_status = 'recorded_review'",
|
||||
"refusing destructive rollback: daily review or manual-pricing facts exist",
|
||||
"DROP TABLE ingestion.daily_review_events",
|
||||
"DROP TABLE ingestion.daily_review_items",
|
||||
"DROP TABLE ingestion.daily_review_cases",
|
||||
"daily_review_events_immutability_guard",
|
||||
"result_delivery_mode = 'artifact_callback'",
|
||||
"result_delivery_mode = 'direct_mcp'",
|
||||
):
|
||||
with self.subTest(required=required):
|
||||
self.assertIn(required, sql)
|
||||
|
||||
def test_followup_artifact_kind_migration_is_forward_only_after_manifest_facts(self) -> None:
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
up = (root / "database" / "018_daily_review_manual_override_artifact.sql").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
down = (
|
||||
root / "database" / "018_daily_review_manual_override_artifact.down.sql"
|
||||
).read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn("ARR migration 017 must be applied first", up)
|
||||
self.assertIn("'manual_override_json'", up)
|
||||
self.assertIn("artifacts_artifact_kind_check", up)
|
||||
self.assertIn("ARR migration 018 is already applied", up)
|
||||
self.assertIn("artifact_kind = 'manual_override_json'", down)
|
||||
self.assertIn("refusing rollback: immutable manual-override artifacts exist", down)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
Reference in New Issue
Block a user