sop_document.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. """SOP文档 CRUD(biz_sop_document)"""
  2. from __future__ import annotations
  3. import math
  4. from datetime import datetime
  5. from typing import Any, Dict, List, Optional, Tuple
  6. from sqlalchemy import and_, func, or_
  7. from sqlalchemy.orm import Session
  8. from app.core.utils import generate_uuid
  9. from app.crud.collection_protocol import urls_to_attachment_list
  10. from app.models.models import BizSopDocument
  11. def _row_to_dict(
  12. s: BizSopDocument,
  13. db: Optional[Session] = None,
  14. tenant_no: Optional[str] = None,
  15. ) -> Dict[str, Any]:
  16. tn = tenant_no or s.tenant_no
  17. return {
  18. "id": s.id,
  19. "sopCode": s.sop_code,
  20. "sopName": s.sop_name,
  21. "versionNo": s.version_no or "",
  22. "sopAttachments": s.sop_attachments or "",
  23. "attachmentFiles": urls_to_attachment_list(s.sop_attachments, db, tn) if db else [],
  24. "tenantNo": s.tenant_no,
  25. "orderNum": s.order_num if s.order_num is not None else 0,
  26. "remark": s.remark or "",
  27. "createTime": s.create_time.strftime("%Y-%m-%d %H:%M:%S") if s.create_time else "",
  28. "updateTime": s.update_time.strftime("%Y-%m-%d %H:%M:%S") if s.update_time else "",
  29. }
  30. def list_sop_documents(
  31. db: Session,
  32. *,
  33. page: int = 1,
  34. page_size: int = 10,
  35. keyword: Optional[str] = None,
  36. tenant_no: Optional[str] = None,
  37. user_info=None,
  38. ) -> Tuple[List[Dict[str, Any]], int]:
  39. def _filtered():
  40. q0 = db.query(BizSopDocument).filter(BizSopDocument.del_flag == 0)
  41. if tenant_no:
  42. q0 = q0.filter(BizSopDocument.tenant_no == tenant_no)
  43. kw = (keyword or "").strip()
  44. if kw:
  45. like = f"%{kw}%"
  46. q0 = q0.filter(
  47. or_(
  48. BizSopDocument.sop_code.like(like),
  49. BizSopDocument.sop_name.like(like),
  50. )
  51. )
  52. if user_info:
  53. from app.core.data_scope import apply_data_scope
  54. q0 = apply_data_scope(q0, BizSopDocument, user_info, db, tenant_no)
  55. return q0
  56. total = _filtered().order_by(None).with_entities(func.count(BizSopDocument.id)).scalar() or 0
  57. page = max(1, page)
  58. page_size = min(max(1, page_size), 100)
  59. rows = (
  60. _filtered()
  61. .order_by(BizSopDocument.create_time.desc())
  62. .offset((page - 1) * page_size)
  63. .limit(page_size)
  64. .all()
  65. )
  66. return [_row_to_dict(x, db, tenant_no) for x in rows], int(total)
  67. def get_sop_document(db: Session, sop_id: str) -> Optional[BizSopDocument]:
  68. return (
  69. db.query(BizSopDocument)
  70. .filter(and_(BizSopDocument.id == sop_id, BizSopDocument.del_flag == 0))
  71. .first()
  72. )
  73. def sop_code_exists(db: Session, code: str, tenant_no: str, exclude_id: Optional[str] = None) -> bool:
  74. q = db.query(BizSopDocument).filter(
  75. and_(BizSopDocument.sop_code == code.strip(), BizSopDocument.tenant_no == tenant_no, BizSopDocument.del_flag == 0)
  76. )
  77. if exclude_id:
  78. q = q.filter(BizSopDocument.id != exclude_id)
  79. return q.first() is not None
  80. def create_sop_document(
  81. db: Session,
  82. *,
  83. sop_code: str,
  84. sop_name: str,
  85. version_no: Optional[str] = None,
  86. sop_attachments: Optional[str] = None,
  87. tenant_no: str = "zkxw",
  88. order_num: Optional[int] = None,
  89. remark: Optional[str] = None,
  90. user_id: Optional[str] = None,
  91. ) -> BizSopDocument:
  92. sc = (sop_code or "").strip()
  93. if not sc:
  94. raise ValueError("SOP编码不能为空")
  95. if sop_code_exists(db, sc, tenant_no):
  96. raise ValueError("SOP编码已存在")
  97. obj = BizSopDocument(
  98. id=generate_uuid(),
  99. sop_code=sc,
  100. sop_name=(sop_name or "").strip() or sc,
  101. version_no=(version_no or "").strip() or None,
  102. sop_attachments=(sop_attachments or "").strip() or None,
  103. tenant_no=tenant_no,
  104. order_num=order_num if order_num is not None else 0,
  105. remark=(remark or "").strip() or None,
  106. create_by=user_id,
  107. create_dept_id="",
  108. create_time=datetime.now(),
  109. update_by=user_id,
  110. update_time=datetime.now(),
  111. del_flag=0,
  112. )
  113. db.add(obj)
  114. db.commit()
  115. db.refresh(obj)
  116. return obj
  117. def update_sop_document(
  118. db: Session,
  119. sop_id: str,
  120. *,
  121. sop_code: Optional[str] = None,
  122. sop_name: Optional[str] = None,
  123. version_no: Optional[str] = None,
  124. sop_attachments: Optional[str] = None,
  125. order_num: Optional[int] = None,
  126. remark: Optional[str] = None,
  127. user_id: Optional[str] = None,
  128. ) -> BizSopDocument:
  129. obj = get_sop_document(db, sop_id)
  130. if not obj:
  131. raise ValueError("SOP文档不存在")
  132. if sop_code is not None:
  133. new_code = sop_code.strip()
  134. if not new_code:
  135. raise ValueError("SOP编码不能为空")
  136. if new_code != obj.sop_code and sop_code_exists(db, new_code, obj.tenant_no, exclude_id=sop_id):
  137. raise ValueError("SOP编码已存在")
  138. obj.sop_code = new_code
  139. if sop_name is not None:
  140. obj.sop_name = (sop_name or "").strip() or obj.sop_name
  141. if version_no is not None:
  142. obj.version_no = (version_no or "").strip() or None
  143. if sop_attachments is not None:
  144. obj.sop_attachments = (sop_attachments or "").strip() or None
  145. if order_num is not None:
  146. obj.order_num = order_num
  147. if remark is not None:
  148. obj.remark = (remark or "").strip() or None
  149. obj.update_by = user_id
  150. obj.update_time = datetime.now()
  151. db.add(obj)
  152. db.commit()
  153. db.refresh(obj)
  154. return obj
  155. def soft_delete_sop_document(db: Session, sop_id: str) -> None:
  156. obj = get_sop_document(db, sop_id)
  157. if not obj:
  158. raise ValueError("SOP文档不存在")
  159. obj.del_flag = 1
  160. obj.update_time = datetime.now()
  161. db.add(obj)
  162. db.commit()
  163. def total_pages(total: int, page_size: int) -> int:
  164. if total <= 0:
  165. return 0
  166. return int(math.ceil(total / float(page_size)))