# dao/cls_mgmt_dao.py # 班级管理数据访问层 from typing import List, Optional, Tuple from sqlalchemy.orm import Session from dao.exceptions import ConflictError, NotFoundError from dao.pagination import paginate from dao.teacher_dao import assert_teacher_alive from model.cls_mgmt_model import ClsMgmt def assert_cls_alive(db: Session, cls_id: str, detail: Optional[str] = None) -> ClsMgmt: """ 确认班级存在且未删除,否则抛 NotFoundError。 供学生模块复用作外键校验。 """ cls = db.query(ClsMgmt).filter(ClsMgmt.id == cls_id, ClsMgmt.is_deleted == 0).first() if not cls: raise NotFoundError(detail or f"班级 {cls_id} 不存在") return cls def list_classes( db: Session, page: int, size: int, head_tea_id: Optional[str] = None, lecturer_id: Optional[str] = None, ) -> Tuple[int, List[ClsMgmt]]: """分页查询班级,支持按班主任 / 主讲老师过滤。""" query = db.query(ClsMgmt).filter(ClsMgmt.is_deleted == 0) if head_tea_id: query = query.filter(ClsMgmt.head_tea_id == head_tea_id) if lecturer_id: query = query.filter(ClsMgmt.lecturer_id == lecturer_id) return paginate(query, page, size, order_by=ClsMgmt.id) def create_class(db: Session, data: dict) -> ClsMgmt: """新增班级:校验编号唯一,且班主任与主讲老师都存在。""" # 编号是主键,已软删除的记录同样占用该编号,所以这里不加 is_deleted 过滤 if db.query(ClsMgmt).filter(ClsMgmt.id == data["id"]).first(): raise ConflictError("班级编号已存在") for tea_id in (data["head_tea_id"], data["lecturer_id"]): assert_teacher_alive(db, tea_id) cls = ClsMgmt(**data) db.add(cls) db.commit() db.refresh(cls) return cls def update_class(db: Session, cls_id: str, data: dict) -> ClsMgmt: """更新班级:若更换教师需重新校验教师存在。""" cls = assert_cls_alive(db, cls_id, "班级不存在或已删除") for field in ("head_tea_id", "lecturer_id"): if data.get(field): assert_teacher_alive(db, data[field]) for field, value in data.items(): setattr(cls, field, value) db.commit() db.refresh(cls) return cls def soft_delete_class(db: Session, cls_id: str) -> None: """软删除班级。""" cls = assert_cls_alive(db, cls_id, "班级不存在或已删除") cls.is_deleted = 1 db.commit()