Explorar o código

fix(pl): 三方车辆与人员保存跳过必备证书校验

Co-authored-by: Cursor <cursoragent@cursor.com>
zlwu hai 3 meses
pai
achega
b071687a71

+ 5 - 0
backend/app/api/pl/base_data.py

@@ -706,6 +706,7 @@ def create_personnel(
     validate_personnel_required_certs(
         payload.cert_list,
         payload.personnel_type,
+        personnel_affiliation=payload.personnel_affiliation,
         subject_label=f"「{payload.personnel_name}」",
     )
 
@@ -770,6 +771,9 @@ def update_personnel(
     data = payload.model_dump(exclude_unset=True, exclude={"cert_list"})
 
     effective_personnel_type = data.get("personnel_type", personnel.personnel_type)
+    effective_personnel_affiliation = data.get(
+        "personnel_affiliation", personnel.personnel_affiliation
+    )
     effective_cert_rows = (
         cert_list
         if cert_list is not None
@@ -780,6 +784,7 @@ def update_personnel(
     validate_personnel_required_certs(
         effective_cert_rows,
         effective_personnel_type,
+        personnel_affiliation=effective_personnel_affiliation,
         subject_label=f"「{subject_name}」",
     )
 

+ 7 - 3
backend/app/services/pl_cert_required_service.py

@@ -153,8 +153,13 @@ def validate_personnel_required_certs(
     cert_rows: Sequence[CertRow | dict],
     personnel_type: str | None,
     *,
+    personnel_affiliation: str | None = None,
     subject_label: str = "",
 ) -> None:
+    affiliation = (personnel_affiliation or VEHICLE_TYPE_SELF).strip()
+    if affiliation == VEHICLE_TYPE_CARRIER:
+        return
+
     ptype = (personnel_type or "").strip()
     if not ptype:
         raise HTTPException(status_code=400, detail="人员类型不能为空")
@@ -301,10 +306,9 @@ def validate_vehicle_save_certs(
     vtype = (vehicle_type or "").strip()
     if vtype == VEHICLE_TYPE_SELF:
         validate_self_vehicle_required_certs(cert_rows, trailer_no=trailer_no)
-    elif vtype == VEHICLE_TYPE_CARRIER:
-        validate_carrier_vehicle_required_certs(cert_rows, trailer_no=trailer_no)
     if vtype in (VEHICLE_TYPE_SELF, VEHICLE_TYPE_CARRIER) and personnel_rows:
         validate_vehicle_personnel_affiliation(
             db, tenant_no, vtype, personnel_rows
         )
-        validate_vehicle_personnel_cert_links(db, tenant_no, personnel_rows)
+        if vtype == VEHICLE_TYPE_SELF:
+            validate_vehicle_personnel_cert_links(db, tenant_no, personnel_rows)

+ 67 - 0
backend/tests/test_pl_tripartite_cert_gates.py

@@ -0,0 +1,67 @@
+"""三方不强制证书;山峡仍强制。"""
+from __future__ import annotations
+
+import pytest
+from fastapi import HTTPException
+
+from app.services.pl_cert_required_service import (
+    validate_personnel_required_certs,
+    validate_vehicle_save_certs,
+)
+
+
+def test_carrier_personnel_skips_required_certs():
+    validate_personnel_required_certs(
+        [],
+        "driver",
+        personnel_affiliation="carrier",
+        subject_label="「张三」",
+    )
+
+
+def test_self_personnel_still_requires_certs():
+    with pytest.raises(HTTPException) as ei:
+        validate_personnel_required_certs(
+            [],
+            "driver",
+            personnel_affiliation="self",
+            subject_label="「李四」",
+        )
+    assert ei.value.status_code == 400
+    assert "必备证书" in ei.value.detail
+
+
+def test_validate_vehicle_save_certs_carrier_skips_vehicle_and_personnel_certs(monkeypatch):
+    """carrier 车:不跑车辆必备、不跑关联人员证书;仍可跑归属。"""
+    called = {"self": 0, "carrier": 0, "links": 0}
+
+    import app.services.pl_cert_required_service as svc
+
+    monkeypatch.setattr(
+        svc,
+        "validate_self_vehicle_required_certs",
+        lambda *a, **k: called.__setitem__("self", called["self"] + 1),
+    )
+    monkeypatch.setattr(
+        svc,
+        "validate_carrier_vehicle_required_certs",
+        lambda *a, **k: called.__setitem__("carrier", called["carrier"] + 1),
+    )
+    monkeypatch.setattr(
+        svc,
+        "validate_vehicle_personnel_cert_links",
+        lambda *a, **k: called.__setitem__("links", called["links"] + 1),
+    )
+    monkeypatch.setattr(svc, "validate_vehicle_personnel_affiliation", lambda *a, **k: None)
+
+    validate_vehicle_save_certs(
+        db=None,
+        tenant_no="t1",
+        vehicle_type="carrier",
+        trailer_no="皖LP359",
+        cert_rows=[],
+        personnel_rows=[],
+    )
+    assert called["carrier"] == 0
+    assert called["self"] == 0
+    assert called["links"] == 0