代码提交
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
"""顾问管理接口(需求第 5 节扩展模块)。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Query
|
||||
|
||||
from app.core.deps import DbSession, ReadAccount, WriteAccount
|
||||
from app.core.exceptions import BusinessError, ConflictError
|
||||
from app.core.response import Resp, ok
|
||||
from app.dao.advisor_dao import AdvisorDao
|
||||
from app.model import Advisor
|
||||
from app.schema.advisor_schema import AdvisorCreate, AdvisorOut, AdvisorUpdate
|
||||
from app.schema.common import PageResult
|
||||
|
||||
router = APIRouter(prefix="/advisors", tags=["2.8 顾问管理(扩展)"])
|
||||
|
||||
|
||||
def _to_out(advisor, count: int | None = None) -> AdvisorOut:
|
||||
out = AdvisorOut.model_validate(advisor)
|
||||
if count is not None:
|
||||
out.student_count = count
|
||||
return out
|
||||
|
||||
|
||||
@router.get("", response_model=Resp[PageResult[AdvisorOut]], summary="顾问列表")
|
||||
def list_advisors(
|
||||
db: DbSession,
|
||||
_: ReadAccount,
|
||||
page: Annotated[int, Query(ge=1)] = 1,
|
||||
page_size: Annotated[int, Query(ge=1, le=200)] = 10,
|
||||
keyword: Annotated[str | None, Query(description="姓名/编号/电话")] = None,
|
||||
dept: Annotated[str | None, Query()] = None,
|
||||
gender: Annotated[int | None, Query(ge=1, le=2)] = None,
|
||||
order_by: Annotated[str, Query()] = "id",
|
||||
order: Annotated[str, Query(pattern="^(asc|desc)$")] = "desc",
|
||||
):
|
||||
stmt = AdvisorDao.build_stmt(keyword=keyword, dept=dept, gender=gender, order_by=order_by, order=order)
|
||||
items, total, page, pages = AdvisorDao.paginate(db, stmt, page, page_size)
|
||||
counts = AdvisorDao.student_count_map(db)
|
||||
return ok({
|
||||
"total": total, "page": page, "page_size": page_size, "pages": pages,
|
||||
"items": [_to_out(a, counts.get(a.id, 0)) for a in items],
|
||||
})
|
||||
|
||||
|
||||
@router.post("", response_model=Resp[AdvisorOut], summary="新增顾问")
|
||||
def create_advisor(db: DbSession, _: WriteAccount, payload: AdvisorCreate):
|
||||
advisor_no = (payload.advisor_no or "").strip() or AdvisorDao.next_advisor_no(db)
|
||||
if AdvisorDao.first_by(db, advisor_no=advisor_no):
|
||||
raise ConflictError(f"顾问编号 {advisor_no} 已存在")
|
||||
advisor = Advisor(
|
||||
advisor_no=advisor_no,
|
||||
name=payload.name,
|
||||
gender=payload.gender,
|
||||
phone=payload.phone,
|
||||
email=payload.email,
|
||||
dept=payload.dept,
|
||||
remark=payload.remark,
|
||||
)
|
||||
db.add(advisor)
|
||||
db.commit()
|
||||
db.refresh(advisor)
|
||||
return ok(_to_out(advisor, 0), msg=f"顾问 {advisor.name} 已创建,编号 {advisor.advisor_no}")
|
||||
|
||||
|
||||
@router.get("/{advisor_id}", response_model=Resp[AdvisorOut], summary="顾问详情")
|
||||
def get_advisor(db: DbSession, _: ReadAccount, advisor_id: int):
|
||||
advisor = AdvisorDao.get_or_404(db, advisor_id, "顾问")
|
||||
counts = AdvisorDao.student_count_map(db)
|
||||
return ok(_to_out(advisor, counts.get(advisor.id, 0)))
|
||||
|
||||
|
||||
@router.put("/{advisor_id}", response_model=Resp[AdvisorOut], summary="更新顾问")
|
||||
def update_advisor(db: DbSession, _: WriteAccount, advisor_id: int, payload: AdvisorUpdate):
|
||||
advisor = AdvisorDao.get_or_404(db, advisor_id, "顾问")
|
||||
for key, value in payload.model_dump(exclude_unset=True).items():
|
||||
if value is not None:
|
||||
setattr(advisor, key, value)
|
||||
db.commit()
|
||||
db.refresh(advisor)
|
||||
counts = AdvisorDao.student_count_map(db)
|
||||
return ok(_to_out(advisor, counts.get(advisor.id, 0)), msg="更新成功")
|
||||
|
||||
|
||||
@router.delete("/{advisor_id}", summary="逻辑删除顾问(名下还有学生时拒绝)")
|
||||
def delete_advisor(db: DbSession, _: WriteAccount, advisor_id: int):
|
||||
advisor = AdvisorDao.get_or_404(db, advisor_id, "顾问")
|
||||
count = AdvisorDao.student_count_map(db).get(advisor_id, 0)
|
||||
if count:
|
||||
raise BusinessError(f"顾问「{advisor.name}」名下还有 {count} 名学生,请先转交后再删除")
|
||||
advisor.soft_delete()
|
||||
db.commit()
|
||||
return ok(msg=f"已删除顾问 {advisor.name}")
|
||||
Reference in New Issue
Block a user