69 lines
2.9 KiB
Python
69 lines
2.9 KiB
Python
"""班级表(需求 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]
|