Files
test/app/dao/advisor_dao.py
2026-09-21 19:03:31 +08:00

55 lines
1.9 KiB
Python

"""顾问 DAO(需求第 5 节扩展模块,但学生表要用顾问编号,所以一并做了)。"""
from __future__ import annotations
from sqlalchemy import Select, func, or_, select
from sqlalchemy.orm import Session
from app.dao.base_dao import BaseDao
from app.model import Advisor, Student
class AdvisorDao(BaseDao[Advisor]):
model = Advisor
@classmethod
def build_stmt(
cls,
keyword: str | None = None,
dept: str | None = None,
gender: int | None = None,
order_by: str = "id",
order: str = "desc",
) -> Select:
stmt = select(Advisor).where(Advisor.alive())
if keyword:
like = f"%{keyword.strip()}%"
stmt = stmt.where(
or_(Advisor.name.like(like), Advisor.advisor_no.like(like), Advisor.phone.like(like))
)
if dept:
stmt = stmt.where(Advisor.dept == dept)
if gender:
stmt = stmt.where(Advisor.gender == gender)
sortable = {"id": Advisor.id, "advisor_no": Advisor.advisor_no, "name": Advisor.name}
column = sortable.get(order_by or "id", Advisor.id)
stmt = stmt.order_by(column.desc() if (order or "desc").lower() == "desc" else column.asc())
return stmt
@classmethod
def next_advisor_no(cls, db: Session) -> str:
prefix = "A"
last = db.scalar(select(func.max(Advisor.advisor_no)).where(Advisor.advisor_no.like(f"{prefix}%")))
seq = int(last[len(prefix):]) + 1 if last and last[len(prefix):].isdigit() else 1
return f"{prefix}{seq:04d}"
@classmethod
def student_count_map(cls, db: Session) -> dict[int, int]:
stmt = (
select(Student.advisor_id, func.count(Student.id))
.where(Student.alive(), Student.advisor_id.is_not(None))
.group_by(Student.advisor_id)
)
return {row[0]: row[1] for row in db.execute(stmt).all()}