52 lines
2.2 KiB
Python
52 lines
2.2 KiB
Python
"""成绩表(需求 2.2):一个学生 N 次考核,一对多。
|
|
|
|
红线预警:录入分数低于及格线时 flag=1,并往学生备注里追加一条提醒,
|
|
统计模块的"多次不及格"直接按 flag 聚合,不用每次临时算阈值。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
from decimal import Decimal
|
|
|
|
from sqlalchemy import Date, ForeignKey, Numeric, SmallInteger, String, UniqueConstraint
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.model.base import Base, SoftDeleteMixin, TimestampMixin
|
|
from app.model.constants import ScoreFlag
|
|
|
|
|
|
class Score(Base, TimestampMixin, SoftDeleteMixin):
|
|
__tablename__ = "score"
|
|
__table_args__ = (
|
|
UniqueConstraint("stu_id", "exam_seq", name="uk_score_stu_seq"),
|
|
{"comment": "学生考核成绩表"},
|
|
)
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
stu_id: Mapped[int] = mapped_column(ForeignKey("student.id"), nullable=False, index=True, comment="学生ID")
|
|
exam_seq: Mapped[int] = mapped_column(SmallInteger, nullable=False, index=True, comment="考核序次(第几次考核)")
|
|
exam_name: Mapped[str | None] = mapped_column(String(50), comment="考核名称,如 阶段一考试")
|
|
exam_date: Mapped[date | None] = mapped_column(Date, comment="考核日期")
|
|
score: Mapped[Decimal] = mapped_column(Numeric(5, 2), nullable=False, comment="成绩")
|
|
flag: Mapped[int] = mapped_column(
|
|
SmallInteger, default=int(ScoreFlag.NORMAL), nullable=False, index=True,
|
|
comment="预警标记 0=正常 1=低于红线需重点关注",
|
|
)
|
|
remark: Mapped[str | None] = mapped_column(String(255), comment="备注")
|
|
|
|
student: Mapped["Student"] = relationship(back_populates="scores", lazy="joined") # noqa: F821
|
|
|
|
# ---------------- 出参派生字段 ----------------
|
|
@property
|
|
def is_warning(self) -> bool:
|
|
return self.flag == int(ScoreFlag.WARNING)
|
|
|
|
@property
|
|
def student_name(self) -> str | None:
|
|
return self.student.name if self.student else None
|
|
|
|
@property
|
|
def class_name(self) -> str | None:
|
|
return self.student.class_name if self.student else None
|