protocol_sample_collection.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. """采集协议样本采集信息 API"""
  2. from typing import List, Optional
  3. from fastapi import APIRouter, Depends, Query
  4. from pydantic import BaseModel, ConfigDict, Field
  5. from sqlalchemy.orm import Session
  6. from app.core.database import get_db
  7. from app.core.menu_guard import require_any_menu_code
  8. from app.core.response import error_response, success_response
  9. from app.core.utils import parse_datetime
  10. from app.crud import protocol_sample_collection as svc
  11. from app.crud import sample_info_quick_register as quick_svc
  12. from app.crud.collection_protocol import total_pages
  13. from app.models.models import SysUser
  14. router = APIRouter(prefix="/web/admin", tags=["采集协议样本采集信息"])
  15. _SAMPLE_INFO_MENU = require_any_menu_code(
  16. "cell-storage:sample-info:list",
  17. )
  18. _QUICK_REGISTER_MENU = require_any_menu_code(
  19. "cell-storage:sample-info:list",
  20. "research-donation:sample-info:list",
  21. )
  22. def _get_tenant_no(db: Session, user: dict) -> str:
  23. user_id = user.get("user_id")
  24. if not user_id:
  25. raise PermissionError("用户身份信息缺失,无法确定租户")
  26. sys_user = db.query(SysUser).filter(SysUser.id == user_id).first()
  27. if not sys_user or not sys_user.tenant_no:
  28. raise PermissionError("用户租户信息缺失")
  29. return sys_user.tenant_no
  30. def _page_payload(items: list, total: int, page: int, page_size: int) -> dict:
  31. return {
  32. "list": items,
  33. "total": total,
  34. "page": page,
  35. "pageSize": page_size,
  36. "totalPages": total_pages(total, page_size),
  37. }
  38. @router.get("/protocol-sample-collections/list")
  39. async def list_protocol_sample_collections(
  40. page: int = Query(1, ge=1),
  41. pageSize: int = Query(10, ge=1, le=100),
  42. keyword: Optional[str] = None,
  43. sampleStatus: Optional[str] = Query(None, alias="sampleStatus"),
  44. collectionFlag: Optional[str] = Query(None, alias="collectionFlag"),
  45. receptionFlag: Optional[str] = Query(None, alias="receptionFlag"),
  46. qcFlag: Optional[str] = Query(None, alias="qcFlag"),
  47. storageFlag: Optional[str] = Query(None, alias="storageFlag"),
  48. storageCertHandled: Optional[str] = Query(None, alias="storageCertHandled"),
  49. insuranceHandled: Optional[str] = Query(None, alias="insuranceHandled"),
  50. db: Session = Depends(get_db),
  51. user: dict = Depends(_SAMPLE_INFO_MENU),
  52. ):
  53. try:
  54. tenant_no = _get_tenant_no(db, user)
  55. items, total = svc.list_protocol_sample_collections(
  56. db,
  57. page=page,
  58. page_size=pageSize,
  59. tenant_no=tenant_no,
  60. keyword=keyword,
  61. sample_status=sampleStatus,
  62. collection_flag=collectionFlag,
  63. reception_flag=receptionFlag,
  64. qc_flag=qcFlag,
  65. storage_flag=storageFlag,
  66. storage_cert_handled=storageCertHandled,
  67. insurance_handled=insuranceHandled,
  68. user_info=user,
  69. )
  70. return success_response(_page_payload(items, total, page, pageSize))
  71. except PermissionError as e:
  72. return error_response(403, str(e))
  73. except Exception as e:
  74. return error_response(400, str(e))
  75. def _get_current_user_id(user: dict) -> str:
  76. user_id = user.get("user_id")
  77. if not user_id:
  78. raise PermissionError("用户身份信息缺失")
  79. return str(user_id)
  80. class QuickRegisterItem(BaseModel):
  81. model_config = ConfigDict(populate_by_name=True)
  82. sample_code: str = Field(..., alias="sampleCode")
  83. protocol_id: str = Field(..., alias="protocolId")
  84. class QuickRegisterBody(BaseModel):
  85. model_config = ConfigDict(populate_by_name=True)
  86. kind: str
  87. reception_source: str = Field(..., alias="receptionSource")
  88. items: List[QuickRegisterItem]
  89. handle_time: Optional[str] = Field(None, alias="handleTime")
  90. handler_user_id: Optional[str] = Field(None, alias="handlerUserId")
  91. attachments: Optional[str] = None
  92. remark: Optional[str] = None
  93. @router.post("/sample-info/quick-register")
  94. async def quick_register_sample_info(
  95. body: QuickRegisterBody,
  96. db: Session = Depends(get_db),
  97. user: dict = Depends(_QUICK_REGISTER_MENU),
  98. ):
  99. try:
  100. tenant_no = _get_tenant_no(db, user)
  101. user_id = _get_current_user_id(user)
  102. ht = parse_datetime(body.handle_time) if body.handle_time else None
  103. if ht is None:
  104. return error_response(400, "请填写办理时间")
  105. items = [
  106. {"sampleCode": it.sample_code, "protocolId": it.protocol_id} for it in (body.items or [])
  107. ]
  108. kind = (body.kind or "").strip()
  109. source = (body.reception_source or "").strip()
  110. attachments = body.attachments or ""
  111. remark = body.remark or ""
  112. if kind == "storage":
  113. result = quick_svc.batch_quick_register_storage(
  114. db,
  115. items=items,
  116. reception_source=source,
  117. tenant_no=tenant_no,
  118. user=user,
  119. user_id=user_id,
  120. handle_time=ht,
  121. handler_user_id=body.handler_user_id,
  122. attachments=attachments,
  123. remark=remark,
  124. )
  125. elif kind == "storage_cert":
  126. if source != "cell_storage":
  127. return error_response(400, "储存证仅支持细胞存储样本")
  128. result = quick_svc.batch_handle_storage_certs(
  129. db,
  130. items=items,
  131. tenant_no=tenant_no,
  132. user=user,
  133. user_id=user_id,
  134. handle_time=ht,
  135. handler_user_id=body.handler_user_id,
  136. attachments=attachments,
  137. remark=remark,
  138. )
  139. elif kind == "insurance":
  140. if source != "cell_storage":
  141. return error_response(400, "保险仅支持细胞存储样本")
  142. result = quick_svc.batch_handle_insurance(
  143. db,
  144. items=items,
  145. tenant_no=tenant_no,
  146. user=user,
  147. user_id=user_id,
  148. handle_time=ht,
  149. handler_user_id=body.handler_user_id,
  150. attachments=attachments,
  151. remark=remark,
  152. )
  153. else:
  154. return error_response(400, "登记类型无效")
  155. return success_response(result, message="登记完成")
  156. except PermissionError as e:
  157. return error_response(403, str(e))
  158. except ValueError as e:
  159. return error_response(400, str(e))
  160. except Exception as e:
  161. return error_response(400, str(e))