post.py 4.9 KB

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