"""班级表(需求 2.4)。""" from __future__ import annotations from datetime import date from sqlalchemy import Date, ForeignKey, String, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from app.model.assoc import class_teachers from app.model.base import Base, SoftDeleteMixin, TimestampMixin from app.model.constants import CLASS_STATUS_TEXT, ClassStatus class Clazz(Base, TimestampMixin, SoftDeleteMixin): __tablename__ = "clazz" __table_args__ = {"comment": "班级表"} id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) class_no: Mapped[str] = mapped_column(String(30), unique=True, nullable=False, comment="班级编号,如 JAVA2401") name: Mapped[str] = mapped_column(String(50), nullable=False, index=True, comment="班级名称") direction: Mapped[str | None] = mapped_column(String(50), comment="班级方向,如 Java 就业班") open_date: Mapped[date | None] = mapped_column(Date, comment="开课时间") close_date: Mapped[date | None] = mapped_column(Date, comment="结课时间") classroom: Mapped[str | None] = mapped_column(String(30), comment="教室") capacity: Mapped[int | None] = mapped_column(default=40, comment="计划招生人数") status: Mapped[int] = mapped_column(default=int(ClassStatus.RUNNING), nullable=False, comment="班级状态 1=在读 2=已结课 3=已解散") head_teacher_id: Mapped[int | None] = mapped_column(ForeignKey("teacher.id"), comment="班主任(老师)") advisor_id: Mapped[int | None] = mapped_column(ForeignKey("advisor.id"), comment="带班顾问") description: Mapped[str | None] = mapped_column(Text, comment="班级说明") # ---------------- 关系 ---------------- head_teacher: Mapped["Teacher"] = relationship(lazy="joined", foreign_keys=[head_teacher_id]) # noqa: F821 advisor: Mapped["Advisor"] = relationship(lazy="joined") # noqa: F821 teachers: Mapped[list["Teacher"]] = relationship( # noqa: F821 secondary=class_teachers, back_populates="classes", lazy="selectin", ) # viewonly:人数统计走 DAO 的聚合查询,这个关系只在班级详情里用来展开学生 students: Mapped[list["Student"]] = relationship( # noqa: F821 back_populates="klass", viewonly=True, lazy="select", ) # ---------------- 出参派生字段 ---------------- @property def status_text(self) -> str: return CLASS_STATUS_TEXT.get(self.status, "未知") @property def head_teacher_name(self) -> str | None: return self.head_teacher.name if self.head_teacher else None @property def advisor_name(self) -> str | None: return self.advisor.name if self.advisor else None @property def teacher_names(self) -> list[str]: return [t.name for t in self.teachers if t.is_del == 0] @property def teacher_ids(self) -> list[int]: return [t.id for t in self.teachers if t.is_del == 0]