Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| from typing import Any | |
| VALID_TYPES = {"first_submission", "revised_submission", "final_submission", "model_only_review"} | |
| def normalize_submission_type(value: str) -> str: | |
| key = str(value or "first_submission").strip().lower().replace(" ", "_") | |
| aliases = { | |
| "first": "first_submission", | |
| "revision": "revised_submission", | |
| "revised": "revised_submission", | |
| "final": "final_submission", | |
| "model": "model_only_review", | |
| } | |
| key = aliases.get(key, key) | |
| if key not in VALID_TYPES: | |
| raise ValueError(f"submission_type must be one of {sorted(VALID_TYPES)}") | |
| return key | |
| def _missing(checks: list[dict[str, Any]], stages: set[str]) -> list[dict[str, Any]]: | |
| return [ | |
| row for row in checks | |
| if row.get("status") == "Missing" and row.get("stage") in stages | |
| ] | |
| def readiness_register( | |
| *, | |
| submission_type: str, | |
| has_model: bool, | |
| has_results: bool, | |
| has_pcswmm_package: bool, | |
| has_revision: bool, | |
| has_city_comments: bool, | |
| response_matrix: list[dict[str, Any]] | None = None, | |
| certified_checklist_attached: bool = False, | |
| no_objections_letter_attached: bool = False, | |
| prior_approved_report_attached: bool = False, | |
| correspondence_appendix_attached: bool = False, | |
| clean_copy: bool = False, | |
| ) -> dict[str, Any]: | |
| """Return draft, engineer-review, and final-submission readiness. | |
| The professional engineer-certified checklist is required for final municipal | |
| submission, but it does not block deterministic draft generation. | |
| """ | |
| stype = normalize_submission_type(submission_type) | |
| checks: list[dict[str, Any]] = [ | |
| { | |
| "check": "SWMM model available", | |
| "status": "Complete" if has_model else "Missing", | |
| "stage": "draft", | |
| }, | |
| { | |
| "check": "Usable simulation results", | |
| "status": "Complete" if has_results else "Missing", | |
| "stage": "draft", | |
| }, | |
| { | |
| "check": "Deterministic engineering evidence package", | |
| "status": "Complete" if has_pcswmm_package else "Missing", | |
| "stage": "draft", | |
| }, | |
| { | |
| "check": "Professional engineer-certified SWMR checklist", | |
| "status": "Complete" if certified_checklist_attached else "Missing", | |
| "stage": "submission", | |
| }, | |
| ] | |
| if stype in {"revised_submission", "final_submission"}: | |
| checks.extend([ | |
| { | |
| "check": "Baseline-to-revised comparison", | |
| "status": "Complete" if has_revision else "Missing", | |
| "stage": "engineer_review", | |
| }, | |
| { | |
| "check": "City review comments", | |
| "status": "Complete" if has_city_comments else "Missing", | |
| "stage": "engineer_review", | |
| }, | |
| ]) | |
| matrix = response_matrix or [] | |
| unresolved = sum( | |
| 1 for row in matrix | |
| if row.get("status") not in {"Resolved", "Not applicable"} | |
| ) | |
| checks.append({ | |
| "check": "Comment response closure", | |
| "status": "Complete" if matrix and unresolved == 0 else f"Review ({unresolved} unresolved)", | |
| "stage": "submission", | |
| }) | |
| if stype == "final_submission": | |
| checks.extend([ | |
| { | |
| "check": "Clean report copy without mark-ups", | |
| "status": "Complete" if clean_copy else "Missing", | |
| "stage": "submission", | |
| }, | |
| { | |
| "check": "No Objections letter as first page", | |
| "status": "Complete" if no_objections_letter_attached else "Missing", | |
| "stage": "submission", | |
| }, | |
| { | |
| "check": "Relevant correspondence appendix", | |
| "status": "Complete" if correspondence_appendix_attached else "Missing", | |
| "stage": "submission", | |
| }, | |
| ]) | |
| if has_revision: | |
| checks.append({ | |
| "check": "Previously approved report included as appendix", | |
| "status": "Complete" if prior_approved_report_attached else "Missing", | |
| "stage": "submission", | |
| }) | |
| draft_blocking = _missing(checks, {"draft"}) | |
| review_blocking = _missing(checks, {"draft", "engineer_review"}) | |
| submission_blocking = _missing(checks, {"draft", "engineer_review", "submission"}) | |
| ready_for_draft = not draft_blocking | |
| ready_for_engineer_review = not review_blocking | |
| ready_for_submission = not submission_blocking | |
| if ready_for_submission: | |
| overall_status = "SUBMISSION READY" | |
| elif ready_for_engineer_review: | |
| overall_status = "ENGINEER-REVIEW READY" | |
| elif ready_for_draft: | |
| overall_status = "DRAFT READY" | |
| else: | |
| overall_status = "NOT READY" | |
| return { | |
| "submission_type": stype, | |
| "ready_for_draft": ready_for_draft, | |
| "ready_for_engineer_review": ready_for_engineer_review, | |
| "ready_for_submission": ready_for_submission, | |
| "status": overall_status, | |
| "checks": checks, | |
| "draft_blocking_items": [row["check"] for row in draft_blocking], | |
| "engineer_review_blocking_items": [row["check"] for row in review_blocking], | |
| "submission_blocking_items": [row["check"] for row in submission_blocking], | |
| # Backward compatibility for clients expecting blocking_items. | |
| "blocking_items": [row["check"] for row in submission_blocking], | |
| "disclaimer": ( | |
| "Draft and engineer-review readiness indicate workflow completeness only. " | |
| "Final submission requires responsible professional authentication and City acceptance." | |
| ), | |
| } | |