service.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. from typing import Optional, List, Dict, Any
  2. from alipay.aop.api.domain.DepartmentInfoDTO import DepartmentInfoDTO
  3. from alipay.aop.api.domain.AlipayCommerceEcDepartmentCreateModel import AlipayCommerceEcDepartmentCreateModel
  4. from alipay.aop.api.domain.AlipayCommerceEcDepartmentDeleteModel import AlipayCommerceEcDepartmentDeleteModel
  5. from alipay.aop.api.domain.AlipayCommerceEcDepartmentInfoQueryModel import AlipayCommerceEcDepartmentInfoQueryModel
  6. from alipay.aop.api.response.AlipayCommerceEcDepartmentCreateResponse import AlipayCommerceEcDepartmentCreateResponse
  7. from alipay.aop.api.response.AlipayCommerceEcDepartmentDeleteResponse import AlipayCommerceEcDepartmentDeleteResponse
  8. from alipay.aop.api.response.AlipayCommerceEcDepartmentInfoQueryResponse import AlipayCommerceEcDepartmentInfoQueryResponse
  9. from alipay.aop.api.response.AlipayCommerceEcDepartmentSublistQueryResponse import AlipayCommerceEcDepartmentSublistQueryResponse
  10. from alipay.aop.api.request.AlipayCommerceEcDepartmentCreateRequest import AlipayCommerceEcDepartmentCreateRequest
  11. from alipay.aop.api.request.AlipayCommerceEcDepartmentDeleteRequest import AlipayCommerceEcDepartmentDeleteRequest
  12. from alipay.aop.api.request.AlipayCommerceEcDepartmentInfoModifyRequest import AlipayCommerceEcDepartmentInfoModifyRequest
  13. from alipay.aop.api.request.AlipayCommerceEcDepartmentInfoQueryRequest import AlipayCommerceEcDepartmentInfoQueryRequest
  14. from alipay.aop.api.request.AlipayCommerceEcDepartmentSublistQueryRequest import AlipayCommerceEcDepartmentSublistQueryRequest
  15. from app.api.v1.module_system.auth.schema import AuthSchema
  16. from app.core.alipay import AlipayClient
  17. from app.core.logger import log
  18. from app.core.exceptions import CustomException
  19. from .crud import DepartmentCRUD
  20. from .schema import (
  21. DepartmentCreateSchema,
  22. DepartmentUpdateSchema,
  23. DepartmentDetailOutSchema,
  24. DepartmentOperationOutSchema,
  25. DepartmentTreeOutSchema,
  26. DepartmentListOutSchema,
  27. DepartmentOutSchema
  28. )
  29. class DepartmentService:
  30. """部门服务"""
  31. @classmethod
  32. async def create_department_service(
  33. cls, auth: AuthSchema, data: DepartmentCreateSchema
  34. ) -> DepartmentOperationOutSchema:
  35. """创建部门"""
  36. # 调用支付宝接口创建部门
  37. department_create_model = AlipayCommerceEcDepartmentCreateModel()
  38. department_create_model.enterprise_id = data.enterprise_id
  39. department_create_model.department_name = data.department_name
  40. if data.department_code:
  41. department_create_model.department_code = data.department_code
  42. if data.parent_department_id:
  43. department_create_model.parent_department_id = data.parent_department_id or "-1"
  44. client = AlipayClient.get_client()
  45. request = AlipayCommerceEcDepartmentCreateRequest()
  46. request.biz_model = department_create_model
  47. response = client.execute(request)
  48. if not response:
  49. raise CustomException(msg="创建部门失败: 无响应")
  50. result = AlipayCommerceEcDepartmentCreateResponse()
  51. result.parse_response_content(response)
  52. if not result.is_success():
  53. log.error(f"支付宝接口调用失败: {result.code} - {result.msg}")
  54. raise CustomException(msg=f"创建部门失败: {result.sub_code or result.msg or result.code}")
  55. # 保存到数据库
  56. crud = DepartmentCRUD(auth)
  57. department_data = {
  58. "department_id": result.department_id or "",
  59. "department_name": data.department_name,
  60. "department_code": data.department_code,
  61. "parent_department_id": data.parent_department_id or "-1",
  62. "enterprise_id": data.enterprise_id,
  63. "sort_order": data.sort_order,
  64. "leader_employee_id": data.leader_employee_id,
  65. "leader_employee_name": data.leader_employee_name
  66. }
  67. await crud.create(department_data)
  68. return DepartmentOperationOutSchema(
  69. department_id=result.department_id or "",
  70. department_name=data.department_name
  71. )
  72. @classmethod
  73. async def delete_department_service(
  74. cls, auth: AuthSchema, department_id: str, enterprise_id: str
  75. ) -> DepartmentOperationOutSchema:
  76. return DepartmentOperationOutSchema(
  77. department_id=department_id,
  78. department_name=""
  79. )
  80. @classmethod
  81. async def update_department_service(
  82. cls, auth: AuthSchema, department_id: str, enterprise_id: str, data: DepartmentUpdateSchema
  83. ) -> DepartmentOperationOutSchema:
  84. """更新部门"""
  85. return DepartmentOperationOutSchema(
  86. department_id=department_id,
  87. department_name=""
  88. )
  89. @classmethod
  90. async def get_department_service(
  91. cls, auth: AuthSchema, department_id: str, enterprise_id: str
  92. ) -> DepartmentDetailOutSchema:
  93. """查询部门详情 (alipay.commerce.ec.department.info.query)"""
  94. # 调用支付宝接口查询部门详情
  95. model = AlipayCommerceEcDepartmentInfoQueryModel()
  96. model.enterprise_id = enterprise_id
  97. model.department_id = department_id
  98. request = AlipayCommerceEcDepartmentInfoQueryRequest()
  99. request.biz_model = model
  100. client = AlipayClient.get_client()
  101. response = client.execute(request)
  102. if not response:
  103. raise CustomException(msg="查询部门详情失败: 无响应")
  104. result = AlipayCommerceEcDepartmentInfoQueryResponse()
  105. result.parse_response_content(response)
  106. if not result.is_success():
  107. log.error(f"支付宝接口调用失败: {result.code} - {result.msg}")
  108. raise CustomException(msg=f"查询部门详情失败: {result.sub_code or result.msg or result.code}")
  109. # 解析部门信息
  110. department_info = result.department_info
  111. if not department_info:
  112. raise CustomException(msg="部门信息不存在")
  113. # 转换为响应模型
  114. department_out = DepartmentOutSchema(
  115. department_id=department_info.department_id or "",
  116. department_name=department_info.department_name or "",
  117. department_code=department_info.department_code,
  118. parent_department_id=department_info.parent_department_id,
  119. enterprise_id=enterprise_id,
  120. status="NORMAL",
  121. )
  122. return DepartmentDetailOutSchema(
  123. department=department_out,
  124. sub_departments=[]
  125. )
  126. @classmethod
  127. async def get_sub_departments_service(
  128. cls, auth: AuthSchema, parent_department_id: str, enterprise_id: str
  129. ) -> List[str]:
  130. """查询子部门列表"""
  131. return []
  132. @classmethod
  133. async def list_service(
  134. cls,
  135. auth: AuthSchema,
  136. page_no: int = 1,
  137. page_size: int = 20,
  138. search: dict | None = None,
  139. ) -> dict:
  140. """分页查询部门列表"""
  141. log.info(f"查询部门列表: {page_no}, {page_size}, {search}")
  142. crud = DepartmentCRUD(auth)
  143. offset = (page_no - 1) * page_size
  144. return await crud.page(
  145. offset=offset,
  146. limit=page_size,
  147. order_by=[{"id": "desc"}],
  148. search=search or {},
  149. out_schema=DepartmentListOutSchema,
  150. )
  151. @classmethod
  152. async def get_department_tree_service(
  153. cls, auth: AuthSchema, enterprise_id: str
  154. ) -> List[DepartmentTreeOutSchema]:
  155. """获取部门树形结构"""
  156. crud = DepartmentCRUD(auth)
  157. # 查询指定企业下的所有部门
  158. departments = await crud.list({"enterprise_id": enterprise_id})
  159. # 转换为字典,方便查找
  160. department_dict = {dept.department_id: dept for dept in departments}
  161. # 构建树形结构
  162. tree = []
  163. for dept in departments:
  164. # 找到父部门
  165. parent_id = dept.parent_department_id
  166. if not parent_id or parent_id == "-1" or parent_id not in department_dict:
  167. # 没有父部门,作为根节点
  168. tree.append(dept)
  169. else:
  170. # 添加到父部门的子节点
  171. if not hasattr(department_dict[parent_id], 'children'):
  172. department_dict[parent_id].children = []
  173. department_dict[parent_id].children.append(dept)
  174. # 排序子节点
  175. def sort_children(node):
  176. if hasattr(node, 'children') and node.children:
  177. node.children.sort(key=lambda x: (x.sort_order or 0, x.department_name))
  178. for child in node.children:
  179. sort_children(child)
  180. for node in tree:
  181. sort_children(node)
  182. # 转换为响应模型
  183. return [DepartmentTreeOutSchema.model_validate(node) for node in tree]
  184. @classmethod
  185. async def get_all_departments(
  186. cls, auth: AuthSchema, enterprise_id: str
  187. ) -> List[DepartmentOutSchema]:
  188. """获取所有部门列表(不分页)"""
  189. crud = DepartmentCRUD(auth)
  190. departments = await crud.list({"enterprise_id": enterprise_id})
  191. return [DepartmentOutSchema.model_validate(dept) for dept in departments]