You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
7.4 KiB

from datetime import date
from typing import List, Optional, Dict
from copy import deepcopy
from model.student import Student
from DAL.clear_all_student import IStudentDAL
class StudentBLL:
def __init__(self, dal: IStudentDAL):
self.dal = dal
def add_student(self, student: Student) -> bool:
"""添加学生信息,进行完整校验和唯一性检查"""
# 1. 数据校验
if not student.is_valid:
raise ValueError(f"学生数据校验不通过。错误信息: {student.get_errors()}")
# 2. 唯一性检查
if self.dal.check_student_exists_by_id_card(student.id_card):
raise ValueError(f"身份证号 {student.id_card} 已存在")
if self.dal.check_student_exists_by_stu_id(student.stu_id):
raise ValueError(f"学号 {student.stu_id} 已存在")
# 3. 业务规则检查
today = date.today()
if student.birth_date and student.birth_date > today:
raise ValueError("出生日期不能晚于当前日期")
if student.enrollment_date and student.enrollment_date > today:
raise ValueError("入学日期不能晚于当前日期")
if student.height and (student.height <= 0 or student.height > 250):
raise ValueError("身高必须在0-250厘米之间")
if student.weight and (student.weight <= 0 or student.weight > 300):
raise ValueError("体重必须在0-300公斤之间")
# 4. 添加学生
return self.dal.add_student(student)
def delete_student_by_id_card(self, id_card: str) -> bool:
"""根据身份证号删除学生信息"""
if not self.dal.check_student_exists_by_id_card(id_card):
raise ValueError(f"身份证号 {id_card} 不存在")
return self.dal.delete_student_by_id_card(id_card)
def delete_student_by_stu_id(self, stu_id: str) -> bool:
"""根据学号删除学生信息"""
if not self.dal.check_student_exists_by_stu_id(stu_id):
raise ValueError(f"学号 {stu_id} 不存在")
return self.dal.delete_student_by_stu_id(stu_id)
def update_student(self, id_card: str, student: Student) -> bool:
"""完整更新学生信息"""
# 1. 存在性检查
if not self.dal.check_student_exists_by_id_card(id_card):
raise ValueError(f"身份证号 {id_card} 不存在")
# 2. 数据校验
if not student.is_valid:
raise ValueError(f"学生数据校验不通过。错误信息: {student.get_errors()}")
# 3. 业务规则检查
today = date.today()
if student.birth_date and student.birth_date > today:
raise ValueError("出生日期不能晚于当前日期")
if student.enrollment_date and student.enrollment_date > today:
raise ValueError("入学日期不能晚于当前日期")
if student.height and (student.height <= 0 or student.height > 250):
raise ValueError("身高必须在0-250厘米之间")
if student.weight and (student.weight <= 0 or student.weight > 300):
raise ValueError("体重必须在0-300公斤之间")
# 4. 执行更新
return self.dal.update_student(id_card, student)
def update_student_partial(self, id_card: str, **kwargs) -> bool:
"""部分更新学生信息"""
# 1. 存在性检查
student = self.dal.find_student_by_id_card(id_card)
if not student:
raise ValueError(f"身份证号 {id_card} 不存在")
# 2. 保护关键字段 - 身份证号不可更改
if 'id_card' in kwargs:
raise ValueError("身份证号不可更改")
# 3. 创建更新后的学生对象
updated_student = deepcopy(student)
for key, value in kwargs.items():
if hasattr(updated_student, key):
setattr(updated_student, key, value)
# 4. 数据校验
if not updated_student.is_valid:
raise ValueError(f"学生数据校验不通过。错误信息: {updated_student.get_errors()}")
# 5. 业务规则检查
today = date.today()
if updated_student.birth_date and updated_student.birth_date > today:
raise ValueError("出生日期不能晚于当前日期")
if updated_student.enrollment_date and updated_student.enrollment_date > today:
raise ValueError("入学日期不能晚于当前日期")
if updated_student.height and (updated_student.height <= 0 or updated_student.height > 250):
raise ValueError("身高必须在0-250厘米之间")
if updated_student.weight and (updated_student.weight <= 0 or updated_student.weight > 300):
raise ValueError("体重必须在0-300公斤之间")
# 6. 学号唯一性检查(如果学号有变化)
if 'stu_id' in kwargs and kwargs['stu_id'] != student.stu_id:
if self.dal.check_student_exists_by_stu_id(kwargs['stu_id']):
raise ValueError(f"学号 {kwargs['stu_id']} 已存在")
# 7. 执行更新
return self.dal.update_student(id_card, updated_student)
def get_student_by_id_card(self, id_card: str) -> Optional[Student]:
"""根据身份证号查询学生信息"""
return self.dal.find_student_by_id_card(id_card)
def get_student_by_stu_id(self, stu_id: str) -> Optional[Student]:
"""根据学号查询学生信息"""
return self.dal.find_student_by_stu_id(stu_id)
def get_students_by_name(self, name: str) -> List[Student]:
"""根据姓名查询学生信息(模糊匹配)"""
return self.dal.find_students_by_name(name)
def get_students_by_class_name(self, class_name: str) -> List[Student]:
"""根据班级名称查询学生信息(模糊匹配)"""
return self.dal.find_students_by_class_name(class_name)
def get_students_by_major(self, major: str) -> List[Student]:
"""根据专业查询学生信息(模糊匹配)"""
return self.dal.find_students_by_major(major)
def get_all_students(self) -> List[Student]:
"""获取所有学生信息"""
return self.dal.get_all_students()
def get_student_count(self) -> int:
"""获取学生总数"""
return self.dal.get_student_count()
def get_students_by_height_range(self, min_height: int, max_height: int) -> List[Student]:
"""按身高范围查询学生"""
return self.dal.get_students_by_height_range(min_height, max_height)
def get_students_by_enrollment_year(self, year: int) -> List[Student]:
"""按入学年份查询学生"""
return self.dal.get_students_by_enrollment_year(year)
def get_students_by_age_range(self, min_age: int, max_age: int) -> List[Student]:
"""按年龄范围查询学生"""
return self.dal.get_students_by_age_range(min_age, max_age)
def get_students_by_major_group(self) -> Dict[str, List[Student]]:
"""按专业分组学生"""
return self.dal.get_students_by_major_group()
def get_average_height(self) -> float:
"""计算平均身高"""
return self.dal.get_average_height()
def get_average_weight(self) -> float:
"""计算平均体重"""
return self.dal.get_average_weight()
def get_gender_ratio(self) -> Dict[Optional[bool], float]:
"""计算性别比例"""
return self.dal.get_gender_ratio()
def clear_all_students(self) -> None:
"""清空所有学生信息"""
self.dal.clear_all_students()