env_detect_record.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. """环境检测登记 CRUD"""
  2. from __future__ import annotations
  3. from datetime import datetime
  4. from typing import Any, Dict, List, Optional, Tuple
  5. from sqlalchemy import and_, func, or_
  6. from sqlalchemy.orm import Session
  7. from app.core.utils import format_date, generate_uuid
  8. from app.crud import env_detect_item as item_svc
  9. from app.models.models import BizEnvDetectRecord, SysUser
  10. def _split_csv(value: Optional[str]) -> List[str]:
  11. return [x.strip() for x in (value or "").split(",") if x.strip()]
  12. def _join_csv(values: List[str]) -> str:
  13. return ",".join(values)
  14. def _row_to_dict(r: BizEnvDetectRecord) -> Dict[str, Any]:
  15. inspector_ids = _split_csv(r.inspector_ids)
  16. inspector_names = _split_csv(r.inspector_names)
  17. return {
  18. "id": r.id,
  19. "recordNo": r.record_no,
  20. "detectTime": format_date(r.detect_time),
  21. "resultTime": format_date(r.result_time) if r.result_time else "",
  22. "inspectorIds": inspector_ids,
  23. "inspectorNames": inspector_names,
  24. "inspectorDisplay": " / ".join(inspector_names) if inspector_names else "",
  25. "envDetectItemId": r.env_detect_item_id,
  26. "itemCode": r.item_code,
  27. "itemName": r.item_name,
  28. "resultDesc": r.result_desc or "",
  29. "attachmentUrls": r.attachment_urls or "",
  30. "tenantNo": r.tenant_no,
  31. "orderNum": r.order_num if r.order_num is not None else 0,
  32. "remark": r.remark or "",
  33. "createTime": r.create_time.strftime("%Y-%m-%d %H:%M:%S") if r.create_time else "",
  34. "updateTime": r.update_time.strftime("%Y-%m-%d %H:%M:%S") if r.update_time else "",
  35. }
  36. def _generate_record_no(db: Session, tenant_no: str) -> str:
  37. today_str = datetime.now().strftime("%Y%m%d")
  38. prefix = f"HJ{today_str}"
  39. existing = (
  40. db.query(BizEnvDetectRecord.record_no)
  41. .filter(
  42. BizEnvDetectRecord.tenant_no == tenant_no,
  43. BizEnvDetectRecord.record_no.like(f"{prefix}%"),
  44. BizEnvDetectRecord.del_flag == 0,
  45. )
  46. .order_by(BizEnvDetectRecord.record_no.desc())
  47. .first()
  48. )
  49. seq = 1
  50. if existing and existing[0]:
  51. try:
  52. seq = int(existing[0][-4:]) + 1
  53. except ValueError:
  54. seq = 1
  55. return f"{prefix}{seq:04d}"
  56. def _resolve_inspector_snapshots(
  57. db: Session, tenant_no: str, inspector_ids: List[str]
  58. ) -> Tuple[str, str]:
  59. ids: List[str] = []
  60. seen: set = set()
  61. for raw in inspector_ids or []:
  62. uid = (raw or "").strip()
  63. if not uid or uid in seen:
  64. continue
  65. seen.add(uid)
  66. ids.append(uid)
  67. if not ids:
  68. raise ValueError("请至少选择一名检测人")
  69. users = (
  70. db.query(SysUser)
  71. .filter(
  72. SysUser.id.in_(ids),
  73. SysUser.tenant_no == tenant_no,
  74. SysUser.del_flag == 0,
  75. )
  76. .all()
  77. )
  78. user_map = {u.id: u for u in users}
  79. names: List[str] = []
  80. for uid in ids:
  81. user = user_map.get(uid)
  82. if not user:
  83. raise ValueError("检测人无效或不存在")
  84. name = (user.nick_name or user.user_no or "").strip() or uid
  85. names.append(name)
  86. return _join_csv(ids), _join_csv(names)
  87. def _resolve_item_snapshot(
  88. db: Session, item_id: str, tenant_no: str
  89. ) -> Tuple[str, str, str]:
  90. item = item_svc.get_env_detect_item(db, item_id, tenant_no=tenant_no)
  91. if not item:
  92. raise ValueError("检测项目不存在")
  93. if item.status != "1":
  94. raise ValueError("检测项目已停用,请重新选择")
  95. return item.id, item.item_code, item.item_name
  96. def get_env_detect_record(
  97. db: Session, row_id: str, tenant_no: Optional[str] = None
  98. ) -> Optional[BizEnvDetectRecord]:
  99. q = db.query(BizEnvDetectRecord).filter(
  100. and_(BizEnvDetectRecord.id == row_id, BizEnvDetectRecord.del_flag == 0)
  101. )
  102. if tenant_no:
  103. q = q.filter(BizEnvDetectRecord.tenant_no == tenant_no)
  104. return q.first()
  105. def list_env_detect_records(
  106. db: Session,
  107. *,
  108. page: int = 1,
  109. page_size: int = 10,
  110. keyword: Optional[str] = None,
  111. env_detect_item_id: Optional[str] = None,
  112. inspector_id: Optional[str] = None,
  113. detect_time_start: Optional[datetime] = None,
  114. detect_time_end: Optional[datetime] = None,
  115. tenant_no: Optional[str] = None,
  116. ) -> Tuple[List[Dict[str, Any]], int]:
  117. def _filtered():
  118. q0 = db.query(BizEnvDetectRecord).filter(BizEnvDetectRecord.del_flag == 0)
  119. if tenant_no:
  120. q0 = q0.filter(BizEnvDetectRecord.tenant_no == tenant_no)
  121. kw = (keyword or "").strip()
  122. if kw:
  123. like = f"%{kw}%"
  124. q0 = q0.filter(
  125. or_(
  126. BizEnvDetectRecord.record_no.like(like),
  127. BizEnvDetectRecord.inspector_names.like(like),
  128. BizEnvDetectRecord.result_desc.like(like),
  129. )
  130. )
  131. item_id = (env_detect_item_id or "").strip()
  132. if item_id:
  133. q0 = q0.filter(BizEnvDetectRecord.env_detect_item_id == item_id)
  134. insp_id = (inspector_id or "").strip()
  135. if insp_id:
  136. q0 = q0.filter(func.find_in_set(insp_id, BizEnvDetectRecord.inspector_ids) > 0)
  137. if detect_time_start:
  138. q0 = q0.filter(BizEnvDetectRecord.detect_time >= detect_time_start)
  139. if detect_time_end:
  140. q0 = q0.filter(BizEnvDetectRecord.detect_time <= detect_time_end)
  141. return q0
  142. total = (
  143. _filtered()
  144. .order_by(None)
  145. .with_entities(func.count(BizEnvDetectRecord.id))
  146. .scalar()
  147. or 0
  148. )
  149. page = max(1, page)
  150. page_size = min(max(1, page_size), 100)
  151. rows = (
  152. _filtered()
  153. .order_by(BizEnvDetectRecord.detect_time.desc())
  154. .offset((page - 1) * page_size)
  155. .limit(page_size)
  156. .all()
  157. )
  158. return [_row_to_dict(x) for x in rows], int(total)
  159. def create_env_detect_record(
  160. db: Session,
  161. *,
  162. detect_time: datetime,
  163. result_time: Optional[datetime] = None,
  164. inspector_ids: List[str],
  165. env_detect_item_id: str,
  166. result_desc: str,
  167. attachment_urls: Optional[str] = None,
  168. tenant_no: str,
  169. remark: Optional[str] = None,
  170. user_id: Optional[str] = None,
  171. create_dept_id: str = "",
  172. ) -> BizEnvDetectRecord:
  173. desc = (result_desc or "").strip()
  174. if not desc:
  175. raise ValueError("检测结果描述不能为空")
  176. if not detect_time:
  177. raise ValueError("检测时间不能为空")
  178. ids_csv, names_csv = _resolve_inspector_snapshots(db, tenant_no, inspector_ids)
  179. item_id, item_code, item_name = _resolve_item_snapshot(db, env_detect_item_id, tenant_no)
  180. obj = BizEnvDetectRecord(
  181. id=generate_uuid(),
  182. record_no=_generate_record_no(db, tenant_no),
  183. detect_time=detect_time,
  184. result_time=result_time,
  185. inspector_ids=ids_csv,
  186. inspector_names=names_csv,
  187. env_detect_item_id=item_id,
  188. item_code=item_code,
  189. item_name=item_name,
  190. result_desc=desc,
  191. attachment_urls=(attachment_urls or "").strip() or None,
  192. tenant_no=tenant_no,
  193. order_num=0,
  194. remark=(remark or "").strip() or None,
  195. create_by=user_id,
  196. create_dept_id=create_dept_id or "",
  197. create_time=datetime.now(),
  198. update_by=user_id,
  199. update_time=datetime.now(),
  200. del_flag=0,
  201. )
  202. db.add(obj)
  203. db.commit()
  204. db.refresh(obj)
  205. return obj
  206. def update_env_detect_record(
  207. db: Session,
  208. row_id: str,
  209. *,
  210. detect_time: Optional[datetime] = None,
  211. result_time: Optional[datetime] = None,
  212. update_result_time: bool = False,
  213. inspector_ids: Optional[List[str]] = None,
  214. env_detect_item_id: Optional[str] = None,
  215. result_desc: Optional[str] = None,
  216. attachment_urls: Optional[str] = None,
  217. remark: Optional[str] = None,
  218. user_id: Optional[str] = None,
  219. tenant_no: Optional[str] = None,
  220. ) -> BizEnvDetectRecord:
  221. obj = get_env_detect_record(db, row_id, tenant_no=tenant_no)
  222. if not obj:
  223. raise ValueError("登记记录不存在")
  224. if detect_time is not None:
  225. if not detect_time:
  226. raise ValueError("检测时间不能为空")
  227. obj.detect_time = detect_time
  228. if update_result_time:
  229. obj.result_time = result_time
  230. if inspector_ids is not None:
  231. ids_csv, names_csv = _resolve_inspector_snapshots(db, obj.tenant_no, inspector_ids)
  232. obj.inspector_ids = ids_csv
  233. obj.inspector_names = names_csv
  234. if env_detect_item_id is not None:
  235. item_id, item_code, item_name = _resolve_item_snapshot(
  236. db, env_detect_item_id, obj.tenant_no
  237. )
  238. obj.env_detect_item_id = item_id
  239. obj.item_code = item_code
  240. obj.item_name = item_name
  241. if result_desc is not None:
  242. desc = (result_desc or "").strip()
  243. if not desc:
  244. raise ValueError("检测结果描述不能为空")
  245. obj.result_desc = desc
  246. if attachment_urls is not None:
  247. obj.attachment_urls = (attachment_urls or "").strip() or None
  248. if remark is not None:
  249. obj.remark = remark.strip() or None
  250. obj.update_by = user_id
  251. obj.update_time = datetime.now()
  252. db.add(obj)
  253. db.commit()
  254. db.refresh(obj)
  255. return obj
  256. def soft_delete_env_detect_record(
  257. db: Session, row_id: str, tenant_no: Optional[str] = None
  258. ) -> None:
  259. obj = get_env_detect_record(db, row_id, tenant_no=tenant_no)
  260. if not obj:
  261. raise ValueError("登记记录不存在")
  262. obj.del_flag = 1
  263. obj.update_time = datetime.now()
  264. db.add(obj)
  265. db.commit()