leave.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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_, or_
  6. from sqlalchemy.orm import Session
  7. from app.core.delete_guard import assert_row_deletable_by_creator
  8. from app.core.utils import generate_uuid
  9. from app.models.models import BizLeaveRequest
  10. def total_pages(total: int, page_size: int) -> int:
  11. return (total + page_size - 1) // page_size if page_size else 0
  12. def _row_to_dict(row: BizLeaveRequest) -> Dict[str, Any]:
  13. return {
  14. "id": row.id,
  15. "leaveType": row.leave_type,
  16. "startDate": row.start_date,
  17. "endDate": row.end_date,
  18. "days": row.days,
  19. "reason": row.reason or "",
  20. "wfInstanceId": row.wf_instance_id or "",
  21. "status": row.status,
  22. "tenantNo": row.tenant_no,
  23. "orderNum": row.order_num if row.order_num is not None else 0,
  24. "remark": row.remark or "",
  25. "createBy": row.create_by or "",
  26. "createTime": row.create_time.strftime("%Y-%m-%d %H:%M:%S") if row.create_time else "",
  27. "updateBy": row.update_by or "",
  28. "updateTime": row.update_time.strftime("%Y-%m-%d %H:%M:%S") if row.update_time else "",
  29. }
  30. def apply_leave_list_filters(
  31. q,
  32. db: Session,
  33. *,
  34. keyword: Optional[str] = None,
  35. status: Optional[str] = None,
  36. reason_in: Optional[str] = None,
  37. tenant_no: Optional[str] = None,
  38. create_by: Optional[str] = None,
  39. user_info=None,
  40. ):
  41. """列表和列头候选值共用本人、数据权限及搜索条件。"""
  42. q = q.filter(BizLeaveRequest.del_flag == 0)
  43. if tenant_no:
  44. q = q.filter(BizLeaveRequest.tenant_no == tenant_no)
  45. if status:
  46. q = q.filter(BizLeaveRequest.status == status)
  47. if create_by:
  48. q = q.filter(BizLeaveRequest.create_by == create_by)
  49. kw = (keyword or "").strip()
  50. if kw:
  51. like = f"%{kw}%"
  52. q = q.filter(or_(BizLeaveRequest.reason.like(like), BizLeaveRequest.leave_type.like(like)))
  53. reasons_in = [s.strip() for s in str(reason_in or "").split(",") if s.strip()]
  54. if reasons_in:
  55. q = q.filter(BizLeaveRequest.reason.in_(reasons_in))
  56. if user_info:
  57. from app.core.data_scope import apply_data_scope
  58. q = apply_data_scope(q, BizLeaveRequest, user_info, db, tenant_no)
  59. return q
  60. def list_leaves(
  61. db: Session,
  62. *,
  63. page: int = 1,
  64. page_size: int = 10,
  65. keyword: Optional[str] = None,
  66. status: Optional[str] = None,
  67. reason_in: Optional[str] = None,
  68. tenant_no: Optional[str] = None,
  69. create_by: Optional[str] = None,
  70. ids: Optional[List[str]] = None,
  71. max_page_size: Optional[int] = None,
  72. user_info=None,
  73. ) -> Tuple[List[Dict[str, Any]], int]:
  74. q = apply_leave_list_filters(
  75. db.query(BizLeaveRequest), db,
  76. keyword=keyword, status=status, reason_in=reason_in,
  77. tenant_no=tenant_no, create_by=create_by, user_info=user_info,
  78. )
  79. if ids:
  80. q = q.filter(BizLeaveRequest.id.in_(ids))
  81. total = q.count()
  82. page = max(1, page)
  83. cap = int(max_page_size) if max_page_size else 500
  84. page_size = min(max(1, page_size), cap)
  85. rows = (
  86. q.order_by(BizLeaveRequest.create_time.desc())
  87. .offset((page - 1) * page_size)
  88. .limit(page_size)
  89. .all()
  90. )
  91. return [_row_to_dict(r) for r in rows], total
  92. def get_leave(db: Session, leave_id: str) -> Optional[Dict[str, Any]]:
  93. row = db.query(BizLeaveRequest).filter(BizLeaveRequest.id == leave_id, BizLeaveRequest.del_flag == 0).first()
  94. return _row_to_dict(row) if row else None
  95. def create_leave(
  96. db: Session,
  97. *,
  98. leave_type: str,
  99. start_date: str,
  100. end_date: str,
  101. days: int,
  102. reason: str = "",
  103. tenant_no: str = "shanxia2.0",
  104. user_id: str = "",
  105. dept_id: str = "",
  106. remark: str = "",
  107. ) -> BizLeaveRequest:
  108. row = BizLeaveRequest(
  109. id=generate_uuid(),
  110. leave_type=leave_type,
  111. start_date=start_date,
  112. end_date=end_date,
  113. days=days,
  114. reason=reason,
  115. status="draft",
  116. tenant_no=tenant_no,
  117. create_by=user_id,
  118. create_dept_id=dept_id,
  119. remark=remark,
  120. )
  121. db.add(row)
  122. db.flush()
  123. return row
  124. def update_leave(db: Session, leave_id: str, *, user_id: str = "", **fields) -> None:
  125. row = db.query(BizLeaveRequest).filter(BizLeaveRequest.id == leave_id, BizLeaveRequest.del_flag == 0).first()
  126. if not row:
  127. return
  128. mapping = {
  129. "leaveType": "leave_type",
  130. "startDate": "start_date",
  131. "endDate": "end_date",
  132. "days": "days",
  133. "reason": "reason",
  134. "remark": "remark",
  135. }
  136. for camel, snake in mapping.items():
  137. if camel in fields and fields[camel] is not None:
  138. setattr(row, snake, fields[camel])
  139. row.update_by = user_id
  140. row.update_time = datetime.now()
  141. db.flush()
  142. def update_leave_status(db: Session, leave_id: str, status: str, wf_instance_id: str = "", user_id: str = "") -> None:
  143. row = db.query(BizLeaveRequest).filter(BizLeaveRequest.id == leave_id, BizLeaveRequest.del_flag == 0).first()
  144. if not row:
  145. return
  146. row.status = status
  147. if wf_instance_id:
  148. row.wf_instance_id = wf_instance_id
  149. row.update_by = user_id
  150. row.update_time = datetime.now()
  151. db.flush()
  152. def soft_delete_leave(db: Session, leave_id: str, user_id: str = "", *, user_info: dict = None) -> None:
  153. row = db.query(BizLeaveRequest).filter(BizLeaveRequest.id == leave_id, BizLeaveRequest.del_flag == 0).first()
  154. if not row:
  155. return
  156. assert_row_deletable_by_creator(row, user_info)
  157. row.del_flag = 1
  158. row.update_by = user_id
  159. row.update_time = datetime.now()
  160. db.flush()