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()