Files
student-management-system/dao/stu_score_dao.py
T
2026-09-18 16:53:21 +08:00

113 lines
3.5 KiB
Python

# dao/stu_score_dao.py
# 学生成绩数据访问层:含成绩等级自动判定的业务规则
from decimal import Decimal
from typing import List, Optional, Tuple
from sqlalchemy.orm import Session
from dao.exceptions import ConflictError, NotFoundError
from dao.pagination import paginate
from dao.stu_dao import assert_stu_alive
from model.stu_score_model import StuScore
def compute_score_level(score: Decimal) -> str:
"""根据分数自动判定等级:>=90 优秀、80-89 良好、60-79 普通、<60 不及格"""
if score >= 90:
return "优秀"
if score >= 80:
return "良好"
if score >= 60:
return "普通"
return "不及格"
def assert_score_alive(db: Session, score_id: int, detail: Optional[str] = None) -> StuScore:
"""确认成绩记录存在且未删除,否则抛 NotFoundError。"""
score = (
db.query(StuScore)
.filter(StuScore.id == score_id, StuScore.is_deleted == False) # noqa: E712 布尔列
.first()
)
if not score:
raise NotFoundError(detail or "成绩记录不存在或已删除")
return score
def list_scores(
db: Session,
page: int,
size: int,
stu_id: Optional[str] = None,
score_level: Optional[str] = None,
) -> Tuple[int, List[StuScore]]:
"""分页查询未删除的成绩,支持按学生 / 等级过滤。"""
query = db.query(StuScore).filter(StuScore.is_deleted == False) # noqa: E712 布尔列
if stu_id:
query = query.filter(StuScore.stu_id == stu_id)
if score_level:
query = query.filter(StuScore.score_level == score_level)
return paginate(query, page, size, order_by=StuScore.id)
def list_scores_by_student(db: Session, stu_id: str) -> List[StuScore]:
"""查询某学生的全部有效成绩,按考试轮次升序。"""
return (
db.query(StuScore)
.filter(StuScore.stu_id == stu_id, StuScore.is_deleted == False) # noqa: E712
.order_by(StuScore.exam_attempt)
.all()
)
def create_score(db: Session, data: dict) -> StuScore:
"""新增成绩:校验学生存在、同轮次不重复,并在未指定等级时自动判定。"""
assert_stu_alive(db, data["stu_id"])
exists = (
db.query(StuScore)
.filter(
StuScore.stu_id == data["stu_id"],
StuScore.exam_attempt == data["exam_attempt"],
StuScore.is_deleted == False, # noqa: E712
)
.first()
)
if exists:
raise ConflictError("该学生此轮次成绩已存在")
# 未显式指定等级时,根据分数自动判定
if not data.get("score_level"):
data["score_level"] = compute_score_level(data["exam_score"])
score = StuScore(**data)
db.add(score)
db.commit()
db.refresh(score)
return score
def update_score(db: Session, score_id: int, data: dict) -> StuScore:
"""更新成绩:若更换学生需校验存在;只改分数没改等级时自动重判等级。"""
score = assert_score_alive(db, score_id)
if data.get("stu_id"):
assert_stu_alive(db, data["stu_id"])
if "exam_score" in data and "score_level" not in data:
data["score_level"] = compute_score_level(data["exam_score"])
for field, value in data.items():
setattr(score, field, value)
db.commit()
db.refresh(score)
return score
def soft_delete_score(db: Session, score_id: int) -> None:
"""软删除成绩记录。"""
score = assert_score_alive(db, score_id)
score.is_deleted = True
db.commit()