school.py 8.5 KB

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