school.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from typing import Optional
  4. from fastapi import APIRouter, Depends, Path, Query
  5. from sqlalchemy import text
  6. from sqlalchemy.ext.asyncio import AsyncSession
  7. from starlette.background import BackgroundTasks
  8. from bgtask.tasks import delete_related_object, async_create_grade
  9. from crud.school import crud_school, crud_system
  10. from crud.sysdata.region import crud_region
  11. from models.user import SysUser
  12. from schemas.base import OrderByField, ReturnField
  13. from schemas.school.school import (SchoolItemList, SchoolDetail, UpdateSchool,
  14. NewSchoolInfo, SchoolInDB)
  15. from utils.depends import get_async_db, get_current_user
  16. router = APIRouter()
  17. # 学校列表
  18. @router.get("/schools",
  19. response_model=SchoolItemList,
  20. response_model_exclude_none=True,
  21. summary="学校列表")
  22. async def get_schools(
  23. page: Optional[int] = None,
  24. size: Optional[int] = None,
  25. name: str = "",
  26. area: str = "",
  27. created_at: str = Query("", description="YYYY-MM-DD,YYYY-MM-DD,时间范围用逗号分隔"),
  28. order: OrderByField = Query("-created_at",
  29. description="排序字段,用逗号分隔,升降序以-判断,默认-created_at"),
  30. res: ReturnField = Query("", description="返回字段,默认列表展示字段。返回字段:id,name"),
  31. db: AsyncSession = Depends(get_async_db),
  32. current_user: SysUser = Depends(get_current_user)):
  33. filters = [text("is_active = 1")]
  34. if name:
  35. filters.append(text(f"name LIKE '%{name}%'"))
  36. if area:
  37. filters.append(text(f"area = '{area}'"))
  38. if created_at:
  39. created_at_s = created_at.split(",")[0]
  40. created_at_e = created_at.split(",")[0]
  41. filters.append(
  42. text(
  43. f"created_at > '{created_at_s}' and created_at < '{created_at_e}'"
  44. ))
  45. if ((page is not None) and page >= 1) and ((size is not None)
  46. and size >= 1):
  47. offset = (page - 1) * size
  48. else:
  49. offset = size = None
  50. if isinstance(order, str):
  51. order = [text(order)]
  52. total, items = await crud_school.find_all(db,
  53. filters=filters,
  54. offset=offset,
  55. limit=size,
  56. order_by=order,
  57. return_fields=res)
  58. for item in items:
  59. item.area = item.area_name.split(",")
  60. return {"total": total, "data": items}
  61. # 学校详情
  62. @router.get("/schools/{sid}",
  63. response_model=SchoolDetail,
  64. response_model_exclude_none=True,
  65. summary="学校详情")
  66. async def get_school(sid: int = Path(..., description="学校ID"),
  67. db: AsyncSession = Depends(get_async_db),
  68. current_user: SysUser = Depends(get_current_user)):
  69. db_obj = await crud_school.find_one(db, {"id": sid})
  70. if db_obj:
  71. db_obj.area = db_obj.area_code.split(",")
  72. else:
  73. return {"errcode": 404, "mess": "学校不存在!"}
  74. return {"data": db_obj}
  75. # 新建学校
  76. @router.post("/schools",
  77. response_model=SchoolDetail,
  78. response_model_exclude_none=True,
  79. summary="新建学校")
  80. async def create_school(info: NewSchoolInfo,
  81. bg_task: BackgroundTasks,
  82. db: AsyncSession = Depends(get_async_db),
  83. current_user: SysUser = Depends(get_current_user)):
  84. info_dict = info.dict()
  85. # 判断学制是否正确
  86. existed = await crud_system.count(db, filters={"id": info_dict["category"]})
  87. if not existed:
  88. return {"errcode": 400, "mess": "学制不存在!"}
  89. # 判断区域是否存在
  90. area_code = ",".join(info_dict["area_code"])
  91. total, db_regions = await crud_region.find_all(
  92. db, filters=[text(f"code in ({area_code})")], return_fields=["name"])
  93. if total != len(info_dict["area_code"]):
  94. return {"errcode": 400, "mess": "地区不存在!"}
  95. else:
  96. area_name = ",".join([x.name for x in db_regions])
  97. info_dict["area_code"] = area_code
  98. info_dict["area_name"] = area_name
  99. existed = await crud_school.count(db, {
  100. "name": info_dict["name"],
  101. "area_code": area_code
  102. })
  103. if not existed:
  104. db_obj = SchoolInDB(**info_dict,
  105. creator_id=current_user.id,
  106. creator_name=current_user.username,
  107. editor_id=current_user.id,
  108. editor_name=current_user.username)
  109. school = await crud_school.insert_one(db, db_obj)
  110. bg_task.add_task(async_create_grade, db, school.id, school.category)
  111. school.area = info_dict["area_code"].split(",")
  112. return {"data": school}
  113. else:
  114. return {"errcode": 100, "mess": "学校已存在!"}
  115. # 更新学校
  116. @router.put("/schools/{sid}",
  117. response_model=SchoolDetail,
  118. response_model_exclude_none=True,
  119. summary="更新学校")
  120. async def update_school(info: UpdateSchool,
  121. bg_task: BackgroundTasks,
  122. sid: int = Path(..., description="学校ID"),
  123. db: AsyncSession = Depends(get_async_db),
  124. current_user: SysUser = Depends(get_current_user)):
  125. # 判断提交参数
  126. info_dict = info.dict(exclude_none=True)
  127. if not info_dict:
  128. return {"errcode": 400, "mess": "提交参数为空!"}
  129. # 判断学校是否存在
  130. db_obj = await crud_school.find_one(db, {"id": sid})
  131. if not db_obj:
  132. return {"errcode": 404, "mess": "学校不存在!"}
  133. # 判断地区是否存在
  134. area_code = ",".join(info_dict.get("area_code", []))
  135. if area_code and db_obj.area_code != area_code:
  136. total, db_regions = await crud_region.find_all(
  137. db,
  138. filters=[text(f"code in ({area_code})")],
  139. return_fields=["name"])
  140. if total != len(info_dict["area_code"]):
  141. return {"errcode": 400, "mess": "地区不存在!"}
  142. else:
  143. info.area_code = area_code
  144. info.area_name = ",".join([x.name for x in db_regions])
  145. else:
  146. delattr(info, "area_code")
  147. # 判断学制是否正确
  148. if "category" in info_dict:
  149. existed = await crud_system.count(db,
  150. filters={"id": info_dict["category"]})
  151. if not existed:
  152. return {"errcode": 400, "mess": "学制不存在!"}
  153. if db_obj.category < info_dict["category"]:
  154. bg_task.add_task(async_create_grade, db, sid, info_dict["category"])
  155. elif db_obj.category == info_dict["category"]:
  156. delattr(info, "category")
  157. else:
  158. return {"errcode": 400, "mess": "学制不允许降级!"}
  159. # 更新学校
  160. info.editor_id = current_user.id
  161. info.editor_name = current_user.username
  162. school = await crud_school.update(db, db_obj, info)
  163. school.area = school.area_code.split(",")
  164. return {"data": school}
  165. # 删除学校
  166. @router.delete("/schools/{sid}",
  167. response_model=SchoolDetail,
  168. response_model_exclude_none=True,
  169. summary="删除学校")
  170. async def delete_school(bg_task: BackgroundTasks,
  171. sid: int = Path(..., description="学校ID"),
  172. db: AsyncSession = Depends(get_async_db),
  173. current_user: SysUser = Depends(get_current_user)):
  174. existed = await crud_school.count(db, {"id": sid})
  175. if not existed:
  176. return {"errcode": 404, "mess": "学校不存在!"}
  177. else:
  178. await crud_school.delete(db, obj_id=sid)
  179. bg_task.add_task(delete_related_object, db, sid=sid)
  180. return {"data": None}