Bladeren bron

feat(storage-release): add readyForReviewOnly list filter

Default pending list can exclude rows with unfinished QC or production work orders via SQL NOT EXISTS.

Co-authored-by: Cursor <cursoragent@cursor.com>
zlwu 3 maanden geleden
bovenliggende
commit
9e5cc9188b

+ 2 - 0
backend/app/api/storage_release_review.py

@@ -44,6 +44,7 @@ async def list_storage_release_reviews(
     storageStatus: Optional[str] = None,
     reviewPhase: Optional[str] = None,
     qcWorkOrderCompleted: Optional[bool] = Query(None),
+    readyForReviewOnly: Optional[bool] = Query(None),
     db: Session = Depends(get_db),
     user: dict = Depends(require_menu_code("biz:storageReleaseReview:list")),
 ):
@@ -60,6 +61,7 @@ async def list_storage_release_reviews(
             keyword=keyword,
             review_phase=reviewPhase,
             qc_work_order_completed=qcWorkOrderCompleted,
+            ready_for_review_only=readyForReviewOnly,
             user_info=user,
         )
         return success_response(result)

+ 42 - 0
backend/app/crud/storage_release_review.py

@@ -148,6 +148,18 @@ def normalize_qc_work_order_completed(raw) -> Optional[bool]:
     return None
 
 
+def normalize_ready_for_review_only(raw) -> Optional[bool]:
+    """Return True when ready-only filter should apply; None means no filter."""
+    if raw is None:
+        return None
+    if isinstance(raw, bool):
+        return True if raw else None
+    s = str(raw).strip().lower()
+    if s in ("true", "1", "yes"):
+        return True
+    return None
+
+
 def _qc_work_order_exists_for_review_sample(
     tenant_no: str, *, unfinished_only: bool = False
 ):
@@ -171,6 +183,27 @@ def _qc_work_order_exists_for_review_sample(
     )
 
 
+def _production_work_order_unfinished_exists_for_review_sample(tenant_no: str):
+    """True if sample has any unfinished inbound-side production WO (dpz/jxz)."""
+    conds = [
+        BizProductionWorkOrder.tenant_no == tenant_no,
+        BizProductionWorkOrder.del_flag == 0,
+        BizProductionWorkOrder.sample_code.isnot(None),
+        BizProductionWorkOrder.sample_code != "",
+        eq_unicode(
+            BizProductionWorkOrder.sample_code, BizStorageReleaseReview.sample_code
+        ),
+        BizStorageReleaseReview.sample_code.isnot(None),
+        BizStorageReleaseReview.sample_code != "",
+        BizProductionWorkOrder.work_order_status.in_(("dpz", "jxz")),
+    ]
+    return (
+        exists()
+        .where(and_(*conds))
+        .correlate(BizStorageReleaseReview)
+    )
+
+
 def list_reviews(
     db: Session,
     *,
@@ -183,6 +216,7 @@ def list_reviews(
     keyword: Optional[str] = None,
     review_phase: Optional[str] = None,
     qc_work_order_completed=None,
+    ready_for_review_only=None,
     user_info=None,
 ) -> Dict[str, Any]:
     q0 = db.query(BizStorageReleaseReview).filter(
@@ -246,6 +280,14 @@ def list_reviews(
                 ),
             )
         )
+    if normalize_ready_for_review_only(ready_for_review_only) is True:
+        # 无未完成质检/生产工单 ⇒ 该侧完成(含零工单)
+        q0 = q0.filter(
+            ~_qc_work_order_exists_for_review_sample(
+                tenant_no, unfinished_only=True
+            ),
+            ~_production_work_order_unfinished_exists_for_review_sample(tenant_no),
+        )
     if user_info:
         from app.core.data_scope import apply_data_scope
         q0 = apply_data_scope(q0, BizStorageReleaseReview, user_info, db, tenant_no)

+ 21 - 0
backend/tests/test_storage_release_review_ready_filter.py

@@ -0,0 +1,21 @@
+from app.crud.storage_release_review import normalize_ready_for_review_only
+
+
+def test_normalize_ready_for_review_only_true_values():
+    assert normalize_ready_for_review_only(True) is True
+    assert normalize_ready_for_review_only("true") is True
+    assert normalize_ready_for_review_only("TRUE") is True
+    assert normalize_ready_for_review_only("1") is True
+    assert normalize_ready_for_review_only("yes") is True
+    assert normalize_ready_for_review_only(" YES ") is True
+
+
+def test_normalize_ready_for_review_only_non_true_is_none():
+    """Only explicit true enables the filter; false/unknown/absent → no filter."""
+    assert normalize_ready_for_review_only(None) is None
+    assert normalize_ready_for_review_only(False) is None
+    assert normalize_ready_for_review_only("") is None
+    assert normalize_ready_for_review_only("false") is None
+    assert normalize_ready_for_review_only("0") is None
+    assert normalize_ready_for_review_only("no") is None
+    assert normalize_ready_for_review_only("maybe") is None