|
|
@@ -219,6 +219,107 @@ def _production_work_order_unfinished_exists_for_review_sample(tenant_no: str):
|
|
|
)
|
|
|
|
|
|
|
|
|
+def _inactive_protocol_exists_for_review():
|
|
|
+ """True when linked collection/donation protocol is yzf or sdfq."""
|
|
|
+ inactive_cell = and_(
|
|
|
+ or_(
|
|
|
+ BizStorageReleaseReview.reception_source == "cell_storage",
|
|
|
+ BizStorageReleaseReview.reception_source.is_(None),
|
|
|
+ BizStorageReleaseReview.reception_source == "",
|
|
|
+ ),
|
|
|
+ BizStorageReleaseReview.protocol_id.isnot(None),
|
|
|
+ BizStorageReleaseReview.protocol_id != "",
|
|
|
+ exists()
|
|
|
+ .where(
|
|
|
+ and_(
|
|
|
+ eq_unicode(
|
|
|
+ BizCollectionProtocol.id, BizStorageReleaseReview.protocol_id
|
|
|
+ ),
|
|
|
+ BizCollectionProtocol.del_flag == 0,
|
|
|
+ BizCollectionProtocol.protocol_status.in_(INACTIVE_PROTOCOL_STATUSES),
|
|
|
+ )
|
|
|
+ )
|
|
|
+ .correlate(BizStorageReleaseReview),
|
|
|
+ )
|
|
|
+ inactive_donation = and_(
|
|
|
+ BizStorageReleaseReview.reception_source == "research_donation",
|
|
|
+ BizStorageReleaseReview.protocol_id.isnot(None),
|
|
|
+ BizStorageReleaseReview.protocol_id != "",
|
|
|
+ exists()
|
|
|
+ .where(
|
|
|
+ and_(
|
|
|
+ eq_unicode(
|
|
|
+ BizResearchDonation.id, BizStorageReleaseReview.protocol_id
|
|
|
+ ),
|
|
|
+ BizResearchDonation.del_flag == 0,
|
|
|
+ BizResearchDonation.donation_status.in_(INACTIVE_PROTOCOL_STATUSES),
|
|
|
+ )
|
|
|
+ )
|
|
|
+ .correlate(BizStorageReleaseReview),
|
|
|
+ )
|
|
|
+ return or_(inactive_cell, inactive_donation)
|
|
|
+
|
|
|
+
|
|
|
+def _inbound_qc_all_void_for_review_sample(tenant_no: str):
|
|
|
+ """True when sample has ≥1 inbound QC WO and every such WO is yzf."""
|
|
|
+ base = [
|
|
|
+ BizQcWorkOrder.tenant_no == tenant_no,
|
|
|
+ BizQcWorkOrder.del_flag == 0,
|
|
|
+ BizQcWorkOrder.qc_biz_type == "inbound",
|
|
|
+ BizQcWorkOrder.sample_code.isnot(None),
|
|
|
+ BizQcWorkOrder.sample_code != "",
|
|
|
+ eq_unicode(BizQcWorkOrder.sample_code, BizStorageReleaseReview.sample_code),
|
|
|
+ BizStorageReleaseReview.sample_code.isnot(None),
|
|
|
+ BizStorageReleaseReview.sample_code != "",
|
|
|
+ ]
|
|
|
+ any_inbound = exists().where(and_(*base)).correlate(BizStorageReleaseReview)
|
|
|
+ any_non_void = (
|
|
|
+ exists()
|
|
|
+ .where(
|
|
|
+ and_(
|
|
|
+ *base,
|
|
|
+ or_(
|
|
|
+ BizQcWorkOrder.work_order_status.is_(None),
|
|
|
+ BizQcWorkOrder.work_order_status != "yzf",
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ )
|
|
|
+ .correlate(BizStorageReleaseReview)
|
|
|
+ )
|
|
|
+ return and_(any_inbound, ~any_non_void)
|
|
|
+
|
|
|
+
|
|
|
+def _inbound_production_all_void_for_review_sample(tenant_no: str):
|
|
|
+ """True when sample has ≥1 inbound production WO and every such WO is yzf."""
|
|
|
+ base = [
|
|
|
+ BizProductionWorkOrder.tenant_no == tenant_no,
|
|
|
+ BizProductionWorkOrder.del_flag == 0,
|
|
|
+ BizProductionWorkOrder.work_order_type == "inbound",
|
|
|
+ BizProductionWorkOrder.sample_code.isnot(None),
|
|
|
+ BizProductionWorkOrder.sample_code != "",
|
|
|
+ eq_unicode(
|
|
|
+ BizProductionWorkOrder.sample_code, BizStorageReleaseReview.sample_code
|
|
|
+ ),
|
|
|
+ BizStorageReleaseReview.sample_code.isnot(None),
|
|
|
+ BizStorageReleaseReview.sample_code != "",
|
|
|
+ ]
|
|
|
+ any_inbound = exists().where(and_(*base)).correlate(BizStorageReleaseReview)
|
|
|
+ any_non_void = (
|
|
|
+ exists()
|
|
|
+ .where(
|
|
|
+ and_(
|
|
|
+ *base,
|
|
|
+ or_(
|
|
|
+ BizProductionWorkOrder.work_order_status.is_(None),
|
|
|
+ BizProductionWorkOrder.work_order_status != "yzf",
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ )
|
|
|
+ .correlate(BizStorageReleaseReview)
|
|
|
+ )
|
|
|
+ return and_(any_inbound, ~any_non_void)
|
|
|
+
|
|
|
+
|
|
|
def list_reviews(
|
|
|
db: Session,
|
|
|
*,
|
|
|
@@ -303,6 +404,14 @@ def list_reviews(
|
|
|
),
|
|
|
~_production_work_order_unfinished_exists_for_review_sample(tenant_no),
|
|
|
)
|
|
|
+ # 协议无效 或 入库质检/生产「有工单且全部 yzf」→ 列表隐藏(两 Tab 常驻)
|
|
|
+ q0 = q0.filter(
|
|
|
+ ~or_(
|
|
|
+ _inactive_protocol_exists_for_review(),
|
|
|
+ _inbound_qc_all_void_for_review_sample(tenant_no),
|
|
|
+ _inbound_production_all_void_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)
|