sample_info_quick_register.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. """样本信息列表快捷登记写入。"""
  2. from __future__ import annotations
  3. from datetime import datetime
  4. from typing import Any, Dict, List, Optional
  5. from sqlalchemy.orm import Session
  6. from app.core.utils import generate_uuid
  7. from app.crud import sample_customer_service as sample_customer_service_crud
  8. from app.crud import sample_insurance as sample_insurance_crud
  9. from app.crud import sample_storage_cert as sample_storage_cert_crud
  10. from app.crud.storage_release_review import _get_user_name
  11. from app.services.sample_customer_service_register import has_any_customer_service_payload
  12. from app.models.models import (
  13. BizCollectionProtocol,
  14. BizProtocolSample,
  15. BizStorageReleaseReview,
  16. )
  17. from app.models.research_donation import BizResearchDonation, BizResearchDonationSample
  18. from app.services.sample_info_quick_register import (
  19. apply_quick_storage_payload,
  20. unique_sample_items,
  21. )
  22. def _protocol_accessible(db: Session, protocol_id: str, tenant_no: str) -> bool:
  23. """登记写入只校验本租户协议存在,不再按数据权限拦截。"""
  24. row = (
  25. db.query(BizCollectionProtocol.id)
  26. .filter(
  27. BizCollectionProtocol.id == protocol_id,
  28. BizCollectionProtocol.del_flag == 0,
  29. BizCollectionProtocol.tenant_no == tenant_no,
  30. )
  31. .first()
  32. )
  33. return row is not None
  34. def _donation_accessible(db: Session, donation_id: str, tenant_no: str) -> bool:
  35. """登记写入只校验本租户捐赠单存在,不再按数据权限拦截。"""
  36. row = (
  37. db.query(BizResearchDonation.id)
  38. .filter(
  39. BizResearchDonation.id == donation_id,
  40. BizResearchDonation.del_flag == 0,
  41. BizResearchDonation.tenant_no == tenant_no,
  42. )
  43. .first()
  44. )
  45. return row is not None
  46. def _pick_latest_review(
  47. rows: List[BizStorageReleaseReview],
  48. ) -> Optional[BizStorageReleaseReview]:
  49. best = None
  50. best_t = None
  51. for rev in rows:
  52. cur_t = rev.storage_time or rev.update_time or rev.create_time
  53. if best is None:
  54. best, best_t = rev, cur_t
  55. continue
  56. if cur_t is None:
  57. continue
  58. if best_t is None or cur_t > best_t:
  59. best, best_t = rev, cur_t
  60. return best
  61. def batch_handle_storage_certs(
  62. db: Session,
  63. *,
  64. items: List[Dict[str, str]],
  65. tenant_no: str,
  66. user_id: str,
  67. handle_time: Optional[datetime],
  68. handler_user_id: Optional[str],
  69. attachments: str,
  70. remark: str,
  71. mail_cert_time: Optional[datetime] = None,
  72. update_mail_cert_time: bool = False,
  73. do_commit: bool = True,
  74. ) -> Dict[str, int]:
  75. pairs = unique_sample_items(items)
  76. if not pairs:
  77. raise ValueError("请选择样本")
  78. success = 0
  79. fail = 0
  80. for sample_code, protocol_id in pairs:
  81. if not protocol_id or not _protocol_accessible(db, protocol_id, tenant_no):
  82. fail += 1
  83. continue
  84. try:
  85. sample_storage_cert_crud.upsert_handle(
  86. db,
  87. tenant_no=tenant_no,
  88. sample_code=sample_code,
  89. collection_protocol_id=protocol_id,
  90. user_id=user_id,
  91. handle_time=handle_time,
  92. handler_user_id=handler_user_id,
  93. cert_image_urls=attachments,
  94. remark=remark,
  95. mail_cert_time=mail_cert_time,
  96. update_mail_cert_time=update_mail_cert_time,
  97. )
  98. success += 1
  99. except ValueError:
  100. fail += 1
  101. if do_commit:
  102. db.commit()
  103. return {"success": success, "fail": fail}
  104. def batch_handle_insurance(
  105. db: Session,
  106. *,
  107. items: List[Dict[str, str]],
  108. tenant_no: str,
  109. user_id: str,
  110. handle_time: Optional[datetime],
  111. handler_user_id: Optional[str],
  112. attachments: str,
  113. remark: str,
  114. policy_send_time: Optional[datetime] = None,
  115. update_policy_send_time: bool = False,
  116. do_commit: bool = True,
  117. ) -> Dict[str, int]:
  118. pairs = unique_sample_items(items)
  119. if not pairs:
  120. raise ValueError("请选择样本")
  121. success = 0
  122. fail = 0
  123. for sample_code, protocol_id in pairs:
  124. if not protocol_id or not _protocol_accessible(db, protocol_id, tenant_no):
  125. fail += 1
  126. continue
  127. try:
  128. sample_insurance_crud.upsert_handle(
  129. db,
  130. tenant_no=tenant_no,
  131. sample_code=sample_code,
  132. collection_protocol_id=protocol_id,
  133. user_id=user_id,
  134. handle_time=handle_time,
  135. handler_user_id=handler_user_id,
  136. insurance_attachments=attachments,
  137. handle_remark=remark,
  138. policy_send_time=policy_send_time,
  139. update_policy_send_time=update_policy_send_time,
  140. )
  141. success += 1
  142. except ValueError:
  143. fail += 1
  144. if do_commit:
  145. db.commit()
  146. return {"success": success, "fail": fail}
  147. def batch_register_customer_service(
  148. db: Session,
  149. *,
  150. items: List[Dict[str, str]],
  151. tenant_no: str,
  152. user_id: str,
  153. incoming: Dict[str, Any],
  154. do_commit: bool = True,
  155. ) -> Dict[str, int]:
  156. if not has_any_customer_service_payload(incoming):
  157. raise ValueError("请至少填写一项客户服务信息")
  158. pairs = unique_sample_items(items)
  159. if not pairs:
  160. raise ValueError("请选择样本")
  161. success = 0
  162. fail = 0
  163. for sample_code, protocol_id in pairs:
  164. if not protocol_id or not _protocol_accessible(db, protocol_id, tenant_no):
  165. fail += 1
  166. continue
  167. try:
  168. sample_customer_service_crud.upsert_by_sample_code(
  169. db,
  170. tenant_no=tenant_no,
  171. sample_code=sample_code,
  172. collection_protocol_id=protocol_id,
  173. user_id=user_id,
  174. incoming=incoming,
  175. )
  176. success += 1
  177. except ValueError:
  178. fail += 1
  179. if do_commit:
  180. db.commit()
  181. return {"success": success, "fail": fail}
  182. def batch_quick_register_storage(
  183. db: Session,
  184. *,
  185. items: List[Dict[str, str]],
  186. reception_source: str,
  187. tenant_no: str,
  188. user_id: str,
  189. handle_time: Optional[datetime],
  190. handler_user_id: Optional[str],
  191. attachments: str,
  192. remark: str,
  193. do_commit: bool = True,
  194. ) -> Dict[str, int]:
  195. source = (reception_source or "").strip()
  196. if source not in ("cell_storage", "research_donation"):
  197. raise ValueError("来源无效")
  198. fields = apply_quick_storage_payload(
  199. handle_time=handle_time,
  200. handler_user_id=handler_user_id,
  201. attachments=attachments,
  202. remark=remark,
  203. )
  204. pairs = unique_sample_items(items)
  205. if not pairs:
  206. raise ValueError("请选择样本")
  207. handler_name = _get_user_name(db, fields["storage_by"] or user_id)
  208. success = 0
  209. fail = 0
  210. now = datetime.now()
  211. for sample_code, protocol_id in pairs:
  212. if source == "cell_storage":
  213. if not protocol_id or not _protocol_accessible(db, protocol_id, tenant_no):
  214. fail += 1
  215. continue
  216. else:
  217. if not protocol_id or not _donation_accessible(db, protocol_id, tenant_no):
  218. fail += 1
  219. continue
  220. rows = (
  221. db.query(BizStorageReleaseReview)
  222. .filter(
  223. BizStorageReleaseReview.tenant_no == tenant_no,
  224. BizStorageReleaseReview.del_flag == 0,
  225. BizStorageReleaseReview.reception_source == source,
  226. BizStorageReleaseReview.sample_code == sample_code,
  227. )
  228. .all()
  229. )
  230. rev = _pick_latest_review(rows)
  231. if rev is None:
  232. rev = BizStorageReleaseReview(
  233. id=generate_uuid(),
  234. sample_code=sample_code,
  235. reception_source=source,
  236. protocol_id=protocol_id,
  237. storage_status="yrk",
  238. tenant_no=tenant_no,
  239. create_by=user_id,
  240. create_dept_id="",
  241. update_by=user_id,
  242. create_time=now,
  243. update_time=now,
  244. del_flag=0,
  245. )
  246. db.add(rev)
  247. rev.storage_status = fields["storage_status"]
  248. rev.storage_time = fields["storage_time"]
  249. rev.storage_by = fields["storage_by"]
  250. rev.storage_by_name = handler_name
  251. rev.remark = fields["remark"] or None
  252. if fields["attachments"]:
  253. rev.review_attachments = fields["attachments"]
  254. rev.update_by = user_id
  255. rev.update_time = now
  256. db.add(rev)
  257. ymd = fields["storage_in_date"]
  258. if source == "cell_storage":
  259. ps = (
  260. db.query(BizProtocolSample)
  261. .filter(
  262. BizProtocolSample.sample_code == sample_code,
  263. BizProtocolSample.tenant_no == tenant_no,
  264. BizProtocolSample.del_flag == 0,
  265. )
  266. .first()
  267. )
  268. if ps:
  269. ps.sample_status = "yrk"
  270. ps.storage_in_date = ymd
  271. ps.update_time = now
  272. db.add(ps)
  273. else:
  274. ds = (
  275. db.query(BizResearchDonationSample)
  276. .filter(
  277. BizResearchDonationSample.sample_code == sample_code,
  278. BizResearchDonationSample.tenant_no == tenant_no,
  279. BizResearchDonationSample.del_flag == 0,
  280. )
  281. .first()
  282. )
  283. if ds:
  284. ds.sample_status = "yrk"
  285. ds.storage_in_date = ymd
  286. ds.update_time = now
  287. db.add(ds)
  288. success += 1
  289. if do_commit:
  290. db.commit()
  291. return {"success": success, "fail": fail}