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

@@ -23,8 +23,9 @@ from arr_ingestion.direct_contracts import (
)
from arr_ingestion.direct_service import DirectSubmissionService
from arr_ingestion.direct_validation import DirectResultValidator
from arr_processing.policy import load_legacy_direct_processor_policy
from tests.test_arr_ingestion_validation import MemoryStore, policy, processor
from tests.test_arr_opera_daily_ingest import success_xml
from tests.test_arr_opera_daily_ingest import reservation, success_xml, xml_document
GRANT = "G" * 43
@@ -33,6 +34,11 @@ SOURCE_KEY = (
"arr/jobs/arrjob-direct-001/attempts/0001/committed/"
"source_xml/source.xml"
)
PROJECT_ROOT = Path(__file__).resolve().parents[1]
def legacy_policy():
return load_legacy_direct_processor_policy(PROJECT_ROOT)
def run_direct_processor(
@@ -51,6 +57,7 @@ def run_direct_processor(
output_dir=str(output.resolve()),
result_json=str(result.resolve()),
structured_result_json=str(structured.resolve()),
legacy_v3_output=True,
)
)
if exit_code != 0:
@@ -215,6 +222,36 @@ class DirectContractTests(unittest.TestCase):
DirectSubmissionRequest.from_dict(request_dict(oversize))
self.assertEqual(raised.exception.code, "DIRECT_PAYLOAD_TOO_LARGE")
def test_legacy_direct_projection_never_enters_manual_price_review(self) -> None:
source_xml = xml_document(
reservation(1, rate_code="GRPA1", rate_amount="999999")
)
with tempfile.TemporaryDirectory() as temp_dir:
root = Path(temp_dir)
source = root / "source.xml"
output = root / "output"
result = output / "result.json"
structured = output / "structured-result.json"
source.write_text(source_xml, encoding="utf-8")
with contextlib.redirect_stdout(io.StringIO()):
exit_code = processor.process(
argparse.Namespace(
xml=str(source.resolve()),
output_dir=str(output.resolve()),
result_json=str(result.resolve()),
structured_result_json=str(structured.resolve()),
legacy_v3_output=True,
)
)
result_payload = json.loads(result.read_text(encoding="utf-8"))
structured_payload = json.loads(structured.read_text(encoding="utf-8"))
self.assertEqual(exit_code, 2)
self.assertEqual(result_payload["version"], "3.0")
self.assertEqual(result_payload["status"], "failed")
self.assertEqual(structured_payload["result_schema_version"], "3.0")
self.assertEqual(structured_payload["status"], "failed")
self.assertNotIn("review_required", json.dumps(structured_payload))
def test_receipt_round_trip_is_minimal_and_strict(self) -> None:
value = receipt()
payload = value.to_dict()
@@ -232,7 +269,7 @@ class DirectReplayValidationTests(unittest.TestCase):
state = received(payload, source)
validator = DirectResultValidator(
MemoryStore({SOURCE_KEY: source}),
policy(),
legacy_policy(),
)
verified = validator.validate(state)
self.assertEqual(verified.submission.submission_id, 17)
@@ -250,7 +287,7 @@ class DirectReplayValidationTests(unittest.TestCase):
retained["total_price"] += 1
validator = DirectResultValidator(
MemoryStore({SOURCE_KEY: source}),
policy(),
legacy_policy(),
)
with self.assertRaises(IngestionError) as raised:
validator.validate(received(tampered, source))