post.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. """职位 CRUD(sys_post)"""
  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.delete_guard import assert_row_deletable_by_creator
  9. from app.core.utils import generate_uuid
  10. from app.models.models import SysPost
  11. def _row_to_dict(p: SysPost) -> Dict[str, Any]:
  12. return {
  13. "id": p.id,
  14. "postName": p.post_name,
  15. "postCode": p.post_code,
  16. "status": p.status,
  17. "tenantNo": p.tenant_no,
  18. "orderNum": p.order_num if p.order_num is not None else 0,
  19. "remark": p.remark or "",
  20. "createBy": p.create_by or "",
  21. "createTime": p.create_time.strftime("%Y-%m-%d %H:%M:%S") if p.create_time else "",
  22. "updateTime": p.update_time.strftime("%Y-%m-%d %H:%M:%S") if p.update_time else "",
  23. }
  24. def list_posts(
  25. db: Session,
  26. *,
  27. page: int = 1,
  28. page_size: int = 10,
  29. keyword: Optional[str] = None,
  30. post_name: Optional[str] = None,
  31. post_code: Optional[str] = None,
  32. post_name_in: Optional[str] = None,
  33. post_code_in: Optional[str] = None,
  34. status: Optional[str] = None,
  35. status_in: Optional[str] = None,
  36. tenant_no: Optional[str] = None,
  37. ids: Optional[List[str]] = None,
  38. max_page_size: Optional[int] = None,
  39. user_info=None,
  40. ) -> Tuple[List[Dict[str, Any]], int]:
  41. def _filtered():
  42. q0 = db.query(SysPost).filter(SysPost.del_flag == 0)
  43. if tenant_no:
  44. q0 = q0.filter(SysPost.tenant_no == tenant_no)
  45. kw = (keyword or "").strip()
  46. if kw:
  47. like = f"%{kw}%"
  48. q0 = q0.filter(or_(SysPost.post_name.like(like), SysPost.post_code.like(like)))
  49. pn = (post_name or "").strip()
  50. if pn:
  51. q0 = q0.filter(SysPost.post_name.like(f"%{pn}%"))
  52. pc = (post_code or "").strip()
  53. if pc:
  54. q0 = q0.filter(SysPost.post_code.like(f"%{pc}%"))
  55. pns_in = [s.strip() for s in str(post_name_in or "").split(",") if s.strip()]
  56. if pns_in:
  57. q0 = q0.filter(SysPost.post_name.in_(pns_in))
  58. pcs_in = [s.strip() for s in str(post_code_in or "").split(",") if s.strip()]
  59. if pcs_in:
  60. q0 = q0.filter(SysPost.post_code.in_(pcs_in))
  61. statuses = [s.strip() for s in str(status_in or "").split(",") if s.strip()]
  62. if not statuses and status:
  63. statuses = [status]
  64. if statuses:
  65. q0 = q0.filter(SysPost.status.in_(statuses))
  66. if ids:
  67. q0 = q0.filter(SysPost.id.in_(ids))
  68. # 职位为租户主数据,不做 create_by 数据范围过滤
  69. return q0
  70. total = _filtered().order_by(None).with_entities(func.count(SysPost.id)).scalar() or 0
  71. page = max(1, page)
  72. cap = int(max_page_size) if max_page_size else 500
  73. page_size = min(max(1, page_size), cap)
  74. rows = (
  75. _filtered()
  76. .order_by(SysPost.create_time.desc())
  77. .offset((page - 1) * page_size)
  78. .limit(page_size)
  79. .all()
  80. )
  81. return [_row_to_dict(x) for x in rows], int(total)
  82. def get_post(db: Session, post_id: str) -> Optional[SysPost]:
  83. return (
  84. db.query(SysPost)
  85. .filter(and_(SysPost.id == post_id, SysPost.del_flag == 0))
  86. .first()
  87. )
  88. def post_code_exists(db: Session, code: str, tenant_no: str, exclude_id: Optional[str] = None) -> bool:
  89. q = db.query(SysPost).filter(and_(SysPost.post_code == code.strip(), SysPost.tenant_no == tenant_no, SysPost.del_flag == 0))
  90. if exclude_id:
  91. q = q.filter(SysPost.id != exclude_id)
  92. return q.first() is not None
  93. def create_post(
  94. db: Session,
  95. *,
  96. post_name: str,
  97. post_code: str,
  98. status: str = "1",
  99. tenant_no: str = "shanxia2.0",
  100. order_num: Optional[int] = None,
  101. remark: Optional[str] = None,
  102. user_id: Optional[str] = None,
  103. ) -> SysPost:
  104. pc = (post_code or "").strip()
  105. if not pc:
  106. raise ValueError("职位编码不能为空")
  107. if post_code_exists(db, pc, tenant_no):
  108. raise ValueError("职位编码已存在")
  109. obj = SysPost(
  110. id=generate_uuid(),
  111. post_name=(post_name or "").strip() or pc,
  112. post_code=pc,
  113. status=status or "1",
  114. tenant_no=tenant_no,
  115. order_num=order_num if order_num is not None else 0,
  116. remark=(remark or "").strip() or None,
  117. create_by=user_id,
  118. create_dept_id="",
  119. create_time=datetime.now(),
  120. update_by=user_id,
  121. update_time=datetime.now(),
  122. del_flag=0,
  123. )
  124. db.add(obj)
  125. db.commit()
  126. db.refresh(obj)
  127. return obj
  128. def update_post(
  129. db: Session,
  130. post_id: str,
  131. *,
  132. post_name: Optional[str] = None,
  133. post_code: Optional[str] = None,
  134. status: Optional[str] = None,
  135. order_num: Optional[int] = None,
  136. remark: Optional[str] = None,
  137. user_id: Optional[str] = None,
  138. ) -> SysPost:
  139. obj = get_post(db, post_id)
  140. if not obj:
  141. raise ValueError("职位不存在")
  142. if post_code is not None:
  143. new_code = post_code.strip()
  144. if not new_code:
  145. raise ValueError("职位编码不能为空")
  146. if new_code != obj.post_code and post_code_exists(db, new_code, obj.tenant_no, exclude_id=post_id):
  147. raise ValueError("职位编码已存在")
  148. obj.post_code = new_code
  149. if post_name is not None:
  150. obj.post_name = (post_name or "").strip() or obj.post_name
  151. if status is not None:
  152. obj.status = status
  153. if order_num is not None:
  154. obj.order_num = order_num
  155. if remark is not None:
  156. obj.remark = (remark or "").strip() or None
  157. obj.update_by = user_id
  158. obj.update_time = datetime.now()
  159. db.add(obj)
  160. db.commit()
  161. db.refresh(obj)
  162. return obj
  163. def soft_delete_post(db: Session, post_id: str, *, user_info: dict = None) -> None:
  164. obj = get_post(db, post_id)
  165. if not obj:
  166. raise ValueError("职位不存在")
  167. assert_row_deletable_by_creator(obj, user_info)
  168. obj.del_flag = 1
  169. obj.update_time = datetime.now()
  170. db.add(obj)
  171. db.commit()
  172. def total_pages(total: int, page_size: int) -> int:
  173. if total <= 0:
  174. return 0
  175. return int(math.ceil(total / float(page_size)))