Files
test/app/schema/statistics_schema.py
T
2026-09-21 19:03:31 +08:00

152 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""统计分析模块出入参(需求 2.6)。"""
from __future__ import annotations
from datetime import date
from typing import Any
from pydantic import BaseModel, Field
class ClassOverviewItem(BaseModel):
"""2.6.1 多维度班级统计:每班总人数 + 男女分布。"""
class_id: int
class_no: str
class_name: str
status_text: str | None = None
head_teacher_name: str | None = None
total: int = Field(0, description="总人数")
male: int = Field(0, description="男生数")
female: int = Field(0, description="女生数")
other: int = Field(0, description="未标注性别人数")
class AllAboveItem(BaseModel):
"""2.6.2 每次考试都过线的学生。"""
stu_id: int
stu_no: str
name: str
class_name: str | None = None
exam_count: int = Field(0, description="参加考核次数")
min_score: float = Field(0, description="最低分(就是它决定了过线)")
avg_score: float = Field(0, description="平均分")
scores: list[dict[str, Any]] = Field(default_factory=list, description="各次成绩明细")
class FailDetailItem(BaseModel):
"""2.6.2 不及格明细。"""
stu_id: int
stu_no: str
name: str
class_name: str | None = None
fail_times: int = Field(0, description="不及格次数")
fail_details: list[dict[str, Any]] = Field(default_factory=list, description="不及格场次明细")
class ClassAvgScoreItem(BaseModel):
"""2.6.2 每场考试每个班级的平均分。"""
exam_seq: int
class_id: int | None = None
class_name: str | None = None
student_count: int = Field(0, description="参考人数")
avg_score: float = Field(0, description="平均分")
max_score: float = 0
min_score: float = 0
pass_rate: float = Field(0, description="及格率 %")
class SalaryTopItem(BaseModel):
"""2.6.3 就业薪资 Top N。"""
rank: int
stu_id: int
stu_no: str
name: str
class_name: str | None = None
company: str | None = None
salary: float = 0
salary_wan: float = 0
offer_date: date | None = None
duration_days: int | None = None
class StudentDurationItem(BaseModel):
"""2.6.3 每个学生的就业时长。"""
stu_id: int
stu_no: str
name: str
class_name: str | None = None
company: str | None = None
open_date: date | None = None
offer_date: date | None = None
duration_days: int | None = Field(None, description="offer 时间 - 开放时间(天)")
state: str = Field("", description="就业中 / 已拿到 offer")
class ClassAvgDurationItem(BaseModel):
"""2.6.3 每个班级的平均就业时长。"""
class_id: int | None = None
class_name: str | None = None
student_count: int = Field(0, description="班级总人数")
open_count: int = Field(0, description="已开放就业的人数(统计基数)")
offer_count: int = Field(0, description="已下发 offer 的人数")
avg_duration_days: float | None = Field(None, description="平均就业时长(天)")
min_duration_days: int | None = None
max_duration_days: int | None = None
class VolatilityItem(BaseModel):
"""2.7.2 成绩波动分析。"""
rank: int
stu_id: int
stu_no: str
name: str
class_name: str | None = None
exam_count: int = 0
avg_score: float = 0
stddev: float = Field(0, description="成绩标准差")
score_range: float = Field(0, description="最大分差 max-min")
trend: str = Field("", description="上升 / 下降 / 基本持平(按最小二乘斜率,阈值 ±1 分/场)")
trend_slope: float = Field(0, description="成绩趋势斜率,单位:分/场(对考核序次做最小二乘拟合)")
scores: list[float] = Field(default_factory=list, description="按序次排列的成绩")
class FunnelItem(BaseModel):
"""2.7.2 班级就业漏斗。"""
class_id: int
class_no: str
class_name: str
total: int = Field(0, description="总人数")
employed: int = Field(0, description="已就业人数(拿到 offer)")
high_salary: int = Field(0, description="高薪人数(>= 高薪线)")
employment_rate: float = Field(0, description="就业率 %")
high_salary_rate: float = Field(0, description="高薪占已就业比例 %")
avg_salary: float | None = Field(None, description="已就业学生平均薪资")
avg_duration_days: float | None = Field(None, description="平均就业时长(天)")
class OverviewOut(BaseModel):
"""仪表盘概览。"""
student_total: int = 0
student_by_status: dict[str, int] = Field(default_factory=dict, description="各状态人数")
class_total: int = 0
teacher_total: int = 0
advisor_total: int = 0
employment_total: int = 0
employment_rate: float = Field(0, description="整体就业率 %")
avg_salary: float | None = None
high_salary_count: int = 0
score_record_total: int = 0
score_avg: float | None = None
warning_student_count: int = Field(0, description="存在红线预警的学生数")
top_classes: list[dict[str, Any]] = Field(default_factory=list, description="就业率前 5 班级")