diff --git a/backend/app/crud/storage_release_review.py b/backend/app/crud/storage_release_review.py index c0d41c7a..f93391f0 100644 --- a/backend/app/crud/storage_release_review.py +++ b/backend/app/crud/storage_release_review.py @@ -8,6 +8,7 @@ from sqlalchemy import and_, exists, func, or_ from sqlalchemy.orm import Session from app.core.db_collation import eq_unicode +from app.core.protocol_status_display import INACTIVE_PROTOCOL_STATUSES from app.core.utils import generate_uuid from app.utils.sample_special import sample_special_to_dict from app.models.models import ( @@ -160,6 +161,20 @@ def normalize_ready_for_review_only(raw) -> Optional[bool]: return None +def is_inactive_protocol_status_for_hide(status) -> bool: + """True when protocol/donation status is yzf or sdfq (list-hide rule).""" + code = (status or "").strip().lower() + return code in INACTIVE_PROTOCOL_STATUSES + + +def inbound_work_orders_all_void(statuses) -> bool: + """True when there is ≥1 non-empty status and every one equals yzf.""" + cleaned = [(s or "").strip() for s in (statuses or [])] + if not cleaned or not any(s for s in cleaned): + return False + return all(s.lower() == "yzf" for s in cleaned) + + def _qc_work_order_exists_for_review_sample( tenant_no: str, *, unfinished_only: bool = False ): diff --git a/backend/tests/test_storage_release_review_hide_voided.py b/backend/tests/test_storage_release_review_hide_voided.py new file mode 100644 index 00000000..3ec42c22 --- /dev/null +++ b/backend/tests/test_storage_release_review_hide_voided.py @@ -0,0 +1,35 @@ +from app.core.protocol_status_display import INACTIVE_PROTOCOL_STATUSES +from app.crud.storage_release_review import ( + inbound_work_orders_all_void, + is_inactive_protocol_status_for_hide, +) + + +def test_inactive_protocol_statuses_match_shared_constant(): + assert is_inactive_protocol_status_for_hide("yzf") is True + assert is_inactive_protocol_status_for_hide("sdfq") is True + assert is_inactive_protocol_status_for_hide(" SDFQ ") is True + assert is_inactive_protocol_status_for_hide("sxz") is False + assert is_inactive_protocol_status_for_hide("zky") is False + assert is_inactive_protocol_status_for_hide("") is False + assert is_inactive_protocol_status_for_hide(None) is False + assert set(INACTIVE_PROTOCOL_STATUSES) == {"yzf", "sdfq"} + + +def test_inbound_work_orders_all_void_requires_at_least_one(): + assert inbound_work_orders_all_void([]) is False + assert inbound_work_orders_all_void([""]) is False + assert inbound_work_orders_all_void([" "]) is False + + +def test_inbound_work_orders_all_void_true_when_every_status_is_yzf(): + assert inbound_work_orders_all_void(["yzf"]) is True + assert inbound_work_orders_all_void(["yzf", "yzf"]) is True + assert inbound_work_orders_all_void([" YZF ", "yzf"]) is True + + +def test_inbound_work_orders_all_void_false_when_any_non_void(): + assert inbound_work_orders_all_void(["yzf", "ywc"]) is False + assert inbound_work_orders_all_void(["dpz"]) is False + assert inbound_work_orders_all_void(["ywc"]) is False + assert inbound_work_orders_all_void(["yzf", ""]) is False