feat: add daily manual price review workflow
This commit is contained in:
@@ -37,9 +37,36 @@ class LocalDailyProcessor:
|
||||
if not (self.policy.skill_root / "scripts" / "process_daily.py").is_file():
|
||||
raise ValueError("ARR daily processor is unavailable")
|
||||
|
||||
def run(self, source_xml: Path, output_dir: Path) -> LocalProcessingOutput:
|
||||
def run(
|
||||
self,
|
||||
source_xml: Path,
|
||||
output_dir: Path,
|
||||
*,
|
||||
manual_overrides: Optional[Path] = None,
|
||||
review_job_id: Optional[str] = None,
|
||||
review_case_id: Optional[str] = None,
|
||||
manual_override_sha256: Optional[str] = None,
|
||||
) -> LocalProcessingOutput:
|
||||
if not source_xml.is_file():
|
||||
raise IngestionError("SOURCE_NOT_FOUND", "registered source XML is unavailable")
|
||||
manual_arguments = (
|
||||
manual_overrides,
|
||||
review_job_id,
|
||||
review_case_id,
|
||||
manual_override_sha256,
|
||||
)
|
||||
if any(value is not None for value in manual_arguments):
|
||||
if (
|
||||
manual_overrides is None
|
||||
or not manual_overrides.is_file()
|
||||
or not review_job_id
|
||||
or not review_case_id
|
||||
or not manual_override_sha256
|
||||
):
|
||||
raise IngestionError(
|
||||
"MANUAL_OVERRIDE_INVALID",
|
||||
"frozen manual-price overrides are unavailable",
|
||||
)
|
||||
output_dir.mkdir(parents=True, exist_ok=False, mode=0o700)
|
||||
result_path = output_dir / "result.json"
|
||||
structured_path = output_dir / "structured-result.json"
|
||||
@@ -55,6 +82,19 @@ class LocalDailyProcessor:
|
||||
"--structured-result-json",
|
||||
str(structured_path.resolve()),
|
||||
]
|
||||
if manual_overrides is not None:
|
||||
command.extend(
|
||||
(
|
||||
"--manual-override-json",
|
||||
str(manual_overrides.resolve()),
|
||||
"--review-job-id",
|
||||
str(review_job_id),
|
||||
"--review-case-id",
|
||||
str(review_case_id),
|
||||
"--manual-override-sha256",
|
||||
str(manual_override_sha256),
|
||||
)
|
||||
)
|
||||
try:
|
||||
completed = subprocess.run(
|
||||
command,
|
||||
@@ -68,20 +108,22 @@ class LocalDailyProcessor:
|
||||
raise IngestionError(
|
||||
"PROCESSOR_TIMEOUT",
|
||||
"deterministic XML processing exceeded its time limit",
|
||||
retryable=True,
|
||||
) from None
|
||||
except OSError:
|
||||
raise IngestionError(
|
||||
"PROCESSOR_UNAVAILABLE",
|
||||
"deterministic XML processing could not start",
|
||||
retryable=True,
|
||||
) from None
|
||||
|
||||
result = strict_json_file(result_path, "processor result")
|
||||
structured = strict_json_file(structured_path, "structured processor result")
|
||||
status = result.get("status")
|
||||
if (
|
||||
status not in {"success", "failed"}
|
||||
status not in {"success", "failed", "review_required"}
|
||||
or structured.get("status") != status
|
||||
or (completed.returncode == 0) != (status == "success")
|
||||
or (completed.returncode == 0) != (status in {"success", "review_required"})
|
||||
):
|
||||
raise IngestionError(
|
||||
"PROCESSOR_RESULT_INVALID",
|
||||
@@ -121,6 +163,15 @@ class LocalDailyProcessor:
|
||||
raise IngestionError(
|
||||
"PROCESSOR_RESULT_INVALID", "successful processor output is incomplete"
|
||||
)
|
||||
elif status == "review_required":
|
||||
if (
|
||||
business_date is None
|
||||
or outputs.get("daily_report") is not None
|
||||
or outputs.get("exception_report") is not None
|
||||
):
|
||||
raise IngestionError(
|
||||
"PROCESSOR_RESULT_INVALID", "review processor output is inconsistent"
|
||||
)
|
||||
else:
|
||||
artifacts["exception_report"] = self._output_path(
|
||||
output_dir, outputs.get("exception_report"), ".xlsx"
|
||||
|
||||
Reference in New Issue
Block a user