ソースを参照

feat(pl): enforce at most one contract per plan stop

Co-authored-by: Cursor <cursoragent@cursor.com>
zlwu 2 ヶ月 前
親
コミット
eb1bfc5732

+ 13 - 0
backend/app/services/pl_plan_stop_service.py

@@ -467,6 +467,18 @@ def _normalize_contract_links(links: Optional[list[PlanContractLink]]) -> list[P
     return out
 
 
+def assert_at_most_one_contract(
+    links: list[PlanContractLink],
+    side_label: str,
+) -> list[PlanContractLink]:
+    if len(links) > 1:
+        raise HTTPException(
+            status_code=422,
+            detail=f"{side_label}只能选择 1 份",
+        )
+    return links
+
+
 def _resolve_stop_contracts(
     db: Session,
     tenant_no: str,
@@ -478,6 +490,7 @@ def _resolve_stop_contracts(
     if is_internal_customer_name(customer_name):
         return []
     links = _normalize_contract_links(contracts)
+    links = assert_at_most_one_contract(links, side_label)
     if not links:
         return []
     resolved: list[PlanContractLink] = []

+ 22 - 0
backend/tests/test_pl_plan_single_contract_rules.py

@@ -0,0 +1,22 @@
+import pytest
+from fastapi import HTTPException
+
+from app.schemas.pl.plan import PlanContractLink
+from app.services.pl_plan_stop_service import assert_at_most_one_contract
+
+
+def test_assert_at_most_one_contract_allows_zero_or_one():
+    assert assert_at_most_one_contract([], "装货合同") == []
+    one = [PlanContractLink(contractId="c1", contractNo="N1")]
+    assert assert_at_most_one_contract(one, "装货合同") == one
+
+
+def test_assert_at_most_one_contract_rejects_two():
+    links = [
+        PlanContractLink(contractId="c1", contractNo="N1"),
+        PlanContractLink(contractId="c2", contractNo="N2"),
+    ]
+    with pytest.raises(HTTPException) as exc:
+        assert_at_most_one_contract(links, "装货合同")
+    assert exc.value.status_code == 422
+    assert "只能选择 1 份" in str(exc.value.detail)