"""样本信息列表快捷登记写入。""" from __future__ import annotations from datetime import datetime from typing import Any, Dict, List, Optional from sqlalchemy.orm import Session from app.core.utils import generate_uuid from app.crud import sample_customer_service as sample_customer_service_crud from app.crud import sample_insurance as sample_insurance_crud from app.crud import sample_storage_cert as sample_storage_cert_crud from app.crud.storage_release_review import _get_user_name from app.services.sample_customer_service_register import has_any_customer_service_payload from app.models.models import ( BizCollectionProtocol, BizProtocolSample, BizStorageReleaseReview, ) from app.models.research_donation import BizResearchDonation, BizResearchDonationSample from app.services.sample_info_quick_register import ( apply_quick_storage_payload, unique_sample_items, ) def _protocol_accessible(db: Session, protocol_id: str, tenant_no: str) -> bool: """登记写入只校验本租户协议存在,不再按数据权限拦截。""" row = ( db.query(BizCollectionProtocol.id) .filter( BizCollectionProtocol.id == protocol_id, BizCollectionProtocol.del_flag == 0, BizCollectionProtocol.tenant_no == tenant_no, ) .first() ) return row is not None def _donation_accessible(db: Session, donation_id: str, tenant_no: str) -> bool: """登记写入只校验本租户捐赠单存在,不再按数据权限拦截。""" row = ( db.query(BizResearchDonation.id) .filter( BizResearchDonation.id == donation_id, BizResearchDonation.del_flag == 0, BizResearchDonation.tenant_no == tenant_no, ) .first() ) return row is not None def _pick_latest_review( rows: List[BizStorageReleaseReview], ) -> Optional[BizStorageReleaseReview]: best = None best_t = None for rev in rows: cur_t = rev.storage_time or rev.update_time or rev.create_time if best is None: best, best_t = rev, cur_t continue if cur_t is None: continue if best_t is None or cur_t > best_t: best, best_t = rev, cur_t return best def batch_handle_storage_certs( db: Session, *, items: List[Dict[str, str]], tenant_no: str, user_id: str, handle_time: Optional[datetime], handler_user_id: Optional[str], attachments: str, remark: str, mail_cert_time: Optional[datetime] = None, update_mail_cert_time: bool = False, do_commit: bool = True, ) -> Dict[str, int]: pairs = unique_sample_items(items) if not pairs: raise ValueError("请选择样本") success = 0 fail = 0 for sample_code, protocol_id in pairs: if not protocol_id or not _protocol_accessible(db, protocol_id, tenant_no): fail += 1 continue try: sample_storage_cert_crud.upsert_handle( db, tenant_no=tenant_no, sample_code=sample_code, collection_protocol_id=protocol_id, user_id=user_id, handle_time=handle_time, handler_user_id=handler_user_id, cert_image_urls=attachments, remark=remark, mail_cert_time=mail_cert_time, update_mail_cert_time=update_mail_cert_time, ) success += 1 except ValueError: fail += 1 if do_commit: db.commit() return {"success": success, "fail": fail} def batch_handle_insurance( db: Session, *, items: List[Dict[str, str]], tenant_no: str, user_id: str, handle_time: Optional[datetime], handler_user_id: Optional[str], attachments: str, remark: str, policy_send_time: Optional[datetime] = None, update_policy_send_time: bool = False, do_commit: bool = True, ) -> Dict[str, int]: pairs = unique_sample_items(items) if not pairs: raise ValueError("请选择样本") success = 0 fail = 0 for sample_code, protocol_id in pairs: if not protocol_id or not _protocol_accessible(db, protocol_id, tenant_no): fail += 1 continue try: sample_insurance_crud.upsert_handle( db, tenant_no=tenant_no, sample_code=sample_code, collection_protocol_id=protocol_id, user_id=user_id, handle_time=handle_time, handler_user_id=handler_user_id, insurance_attachments=attachments, handle_remark=remark, policy_send_time=policy_send_time, update_policy_send_time=update_policy_send_time, ) success += 1 except ValueError: fail += 1 if do_commit: db.commit() return {"success": success, "fail": fail} def batch_register_customer_service( db: Session, *, items: List[Dict[str, str]], tenant_no: str, user_id: str, incoming: Dict[str, Any], do_commit: bool = True, ) -> Dict[str, int]: if not has_any_customer_service_payload(incoming): raise ValueError("请至少填写一项客户服务信息") pairs = unique_sample_items(items) if not pairs: raise ValueError("请选择样本") success = 0 fail = 0 for sample_code, protocol_id in pairs: if not protocol_id or not _protocol_accessible(db, protocol_id, tenant_no): fail += 1 continue try: sample_customer_service_crud.upsert_by_sample_code( db, tenant_no=tenant_no, sample_code=sample_code, collection_protocol_id=protocol_id, user_id=user_id, incoming=incoming, ) success += 1 except ValueError: fail += 1 if do_commit: db.commit() return {"success": success, "fail": fail} def batch_quick_register_storage( db: Session, *, items: List[Dict[str, str]], reception_source: str, tenant_no: str, user_id: str, handle_time: Optional[datetime], handler_user_id: Optional[str], attachments: str, remark: str, do_commit: bool = True, ) -> Dict[str, int]: source = (reception_source or "").strip() if source not in ("cell_storage", "research_donation"): raise ValueError("来源无效") fields = apply_quick_storage_payload( handle_time=handle_time, handler_user_id=handler_user_id, attachments=attachments, remark=remark, ) pairs = unique_sample_items(items) if not pairs: raise ValueError("请选择样本") handler_name = _get_user_name(db, fields["storage_by"] or user_id) success = 0 fail = 0 now = datetime.now() for sample_code, protocol_id in pairs: if source == "cell_storage": if not protocol_id or not _protocol_accessible(db, protocol_id, tenant_no): fail += 1 continue else: if not protocol_id or not _donation_accessible(db, protocol_id, tenant_no): fail += 1 continue rows = ( db.query(BizStorageReleaseReview) .filter( BizStorageReleaseReview.tenant_no == tenant_no, BizStorageReleaseReview.del_flag == 0, BizStorageReleaseReview.reception_source == source, BizStorageReleaseReview.sample_code == sample_code, ) .all() ) rev = _pick_latest_review(rows) if rev is None: rev = BizStorageReleaseReview( id=generate_uuid(), sample_code=sample_code, reception_source=source, protocol_id=protocol_id, storage_status="yrk", tenant_no=tenant_no, create_by=user_id, create_dept_id="", update_by=user_id, create_time=now, update_time=now, del_flag=0, ) db.add(rev) rev.storage_status = fields["storage_status"] rev.storage_time = fields["storage_time"] rev.storage_by = fields["storage_by"] rev.storage_by_name = handler_name rev.remark = fields["remark"] or None if fields["attachments"]: rev.review_attachments = fields["attachments"] rev.update_by = user_id rev.update_time = now db.add(rev) ymd = fields["storage_in_date"] if source == "cell_storage": ps = ( db.query(BizProtocolSample) .filter( BizProtocolSample.sample_code == sample_code, BizProtocolSample.tenant_no == tenant_no, BizProtocolSample.del_flag == 0, ) .first() ) if ps: ps.sample_status = "yrk" ps.storage_in_date = ymd ps.update_time = now db.add(ps) else: ds = ( db.query(BizResearchDonationSample) .filter( BizResearchDonationSample.sample_code == sample_code, BizResearchDonationSample.tenant_no == tenant_no, BizResearchDonationSample.del_flag == 0, ) .first() ) if ds: ds.sample_status = "yrk" ds.storage_in_date = ymd ds.update_time = now db.add(ds) success += 1 if do_commit: db.commit() return {"success": success, "fail": fail}