Import ClientFlow production v4928.1.5.132.4
This commit is contained in:
193
app/work_center_action_policy.py
Normal file
193
app/work_center_action_policy.py
Normal file
@@ -0,0 +1,193 @@
|
||||
"""Canonical work-center action precedence and reconstructed review state.
|
||||
|
||||
The operator must see one first safe action across the work center and the
|
||||
opportunity board. This module intentionally contains no database access so
|
||||
it can be reused by UI/view-model code and tested in isolation.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Mapping
|
||||
|
||||
|
||||
ASSOCIATION_ACTION_CODES = {
|
||||
"ASSOCIATE_OPPORTUNITY",
|
||||
"REVIEW_ASSOCIATION",
|
||||
"LINK_DOCUMENT",
|
||||
}
|
||||
|
||||
RECONSTRUCTED_SENSITIVE_ACTIONS = {
|
||||
"SEND_PROFORMA",
|
||||
"SEND_INVOICE",
|
||||
"CONFIRM_PAYMENT",
|
||||
"CONFIRM_PAYMENT_AND_PREPARE_SHIPMENT",
|
||||
"PREPARE_ORDER",
|
||||
"VALIDATE_PHYSICAL_ORDER",
|
||||
"CREATE_SHIPMENT",
|
||||
"SHIP_ORDER",
|
||||
}
|
||||
|
||||
RECONSTRUCTED_RECORD_MODES = {
|
||||
"reconstructed_invoice_review",
|
||||
"historical_reconstructed",
|
||||
"legacy_review",
|
||||
}
|
||||
|
||||
ACTION_ALIASES = {"SHIP_ORDER": "CREATE_SHIPMENT"}
|
||||
|
||||
|
||||
def _s(value: Any) -> str:
|
||||
return str(value or "").strip()
|
||||
|
||||
|
||||
def _lower(value: Any) -> str:
|
||||
return _s(value).casefold()
|
||||
|
||||
|
||||
def _upper(value: Any) -> str:
|
||||
return _s(value).upper()
|
||||
|
||||
|
||||
def _as_mapping(value: Any) -> Mapping[str, Any]:
|
||||
return value if isinstance(value, Mapping) else {}
|
||||
|
||||
|
||||
def _truthy(value: Any) -> bool:
|
||||
if value is True:
|
||||
return True
|
||||
return _lower(value) in {"1", "true", "yes", "sim", "required", "validated", "waived"}
|
||||
|
||||
|
||||
def _explicit_false(value: Any) -> bool:
|
||||
if value is False:
|
||||
return True
|
||||
return _lower(value) in {"0", "false", "no", "não", "nao", "cleared", "validated", "waived"}
|
||||
|
||||
|
||||
def canonical_action_code(value: Any) -> str:
|
||||
code = _upper(value)
|
||||
return ACTION_ALIASES.get(code, code)
|
||||
|
||||
|
||||
def is_reconstructed_record(metadata: Any) -> bool:
|
||||
data = _as_mapping(metadata)
|
||||
return _lower(data.get("clientflow_record_mode")) in RECONSTRUCTED_RECORD_MODES
|
||||
|
||||
|
||||
def reconstructed_review_status(metadata: Any) -> str:
|
||||
"""Return required/validated/waived/legacy_unset/not_applicable.
|
||||
|
||||
v132 persists ``reconstructed_review_status``. Legacy keys are still read
|
||||
so upgrades do not re-open a review that was already completed.
|
||||
"""
|
||||
|
||||
data = _as_mapping(metadata)
|
||||
nested = _as_mapping(data.get("reconstructed_review"))
|
||||
direct = _lower(nested.get("status") or data.get("reconstructed_review_status"))
|
||||
if direct in {"required", "validated", "waived"}:
|
||||
return direct
|
||||
|
||||
validated_keys = (
|
||||
"reconstructed_process_validated",
|
||||
"historical_evidence_validated",
|
||||
"reconstructed_review_validated",
|
||||
)
|
||||
if any(_truthy(data.get(key)) for key in validated_keys):
|
||||
return "validated"
|
||||
|
||||
required_keys = (
|
||||
"historical_evidence_review_required",
|
||||
"reconstructed_process_review_required",
|
||||
"reconstructed_review_required",
|
||||
)
|
||||
if any(_truthy(data.get(key)) for key in required_keys):
|
||||
return "required"
|
||||
|
||||
# Some older repair scripts cleared the boolean instead of writing a
|
||||
# validated marker. Only interpret that as validated for a known legacy
|
||||
# reconstructed record.
|
||||
if is_reconstructed_record(data) and any(
|
||||
key in data and _explicit_false(data.get(key)) for key in required_keys
|
||||
):
|
||||
return "validated"
|
||||
|
||||
return "legacy_unset" if is_reconstructed_record(data) else "not_applicable"
|
||||
|
||||
|
||||
def reconstructed_review_required(metadata: Any) -> bool:
|
||||
return reconstructed_review_status(metadata) == "required"
|
||||
|
||||
|
||||
def reconstructed_review_cleared(metadata: Any) -> bool:
|
||||
return reconstructed_review_status(metadata) in {"validated", "waived"}
|
||||
|
||||
|
||||
def association_review_required(*, action_code: Any = "", linking_status: Any = "") -> bool:
|
||||
code = canonical_action_code(action_code)
|
||||
linking = _lower(linking_status)
|
||||
return code in ASSOCIATION_ACTION_CODES or linking in {
|
||||
"ambiguous",
|
||||
"review_required",
|
||||
"required",
|
||||
"conflict",
|
||||
}
|
||||
|
||||
|
||||
def effective_action_code(
|
||||
action_code: Any,
|
||||
*,
|
||||
metadata: Any = None,
|
||||
linking_status: Any = "",
|
||||
) -> str:
|
||||
"""Return the first explicitly supported operator action.
|
||||
|
||||
Titles and free text are deliberately ignored. A blocker must be
|
||||
persisted as an action/linking status or reconstructed review state.
|
||||
"""
|
||||
|
||||
code = canonical_action_code(action_code)
|
||||
if association_review_required(action_code=code, linking_status=linking_status):
|
||||
return "ASSOCIATE_OPPORTUNITY"
|
||||
if reconstructed_review_required(metadata) and code in {
|
||||
canonical_action_code(item) for item in RECONSTRUCTED_SENSITIVE_ACTIONS
|
||||
}:
|
||||
return "REVIEW_RECONSTRUCTED_PROCESS"
|
||||
return code
|
||||
|
||||
|
||||
def reconstructed_review_metadata_patch(
|
||||
status: str,
|
||||
*,
|
||||
actor: str,
|
||||
reason: str = "",
|
||||
blocked_action_code: str = "",
|
||||
) -> dict[str, Any]:
|
||||
normalized = _lower(status)
|
||||
if normalized not in {"required", "validated", "waived"}:
|
||||
raise ValueError(f"Unsupported reconstructed review status: {status}")
|
||||
now = datetime.now(timezone.utc).isoformat()
|
||||
nested: dict[str, Any] = {
|
||||
"status": normalized,
|
||||
"updated_at": now,
|
||||
"updated_by": actor,
|
||||
}
|
||||
if reason:
|
||||
nested["reason"] = reason
|
||||
if blocked_action_code:
|
||||
nested["blocked_action_code"] = canonical_action_code(blocked_action_code)
|
||||
if normalized == "required":
|
||||
nested["required_at"] = now
|
||||
elif normalized == "validated":
|
||||
nested["validated_at"] = now
|
||||
nested["validated_by"] = actor
|
||||
else:
|
||||
nested["waived_at"] = now
|
||||
nested["waived_by"] = actor
|
||||
|
||||
patch: dict[str, Any] = {
|
||||
"reconstructed_review_status": normalized,
|
||||
"reconstructed_review": nested,
|
||||
"reconstructed_review_required": normalized == "required",
|
||||
"reconstructed_review_validated": normalized == "validated",
|
||||
}
|
||||
return patch
|
||||
Reference in New Issue
Block a user