import datetime from django.db import models from django.db.models import Sum from application.org_mgnt.models import PrimaryDepartment, SecondaryDepartment # 岗位表 class Position(models.Model): position_id = models.AutoField(primary_key=True, verbose_name='岗位ID') position_name = models.CharField(max_length=255, verbose_name='岗位名称') position_description = models.TextField(verbose_name='岗位描述') class Meta: verbose_name = '岗位表' verbose_name_plural = '岗位表' def __str__(self): return self.position_name # 职级表 class Rank(models.Model): rank_id = models.AutoField(primary_key=True, verbose_name='职级ID') rank_name = models.CharField(max_length=255, verbose_name='职级名称') rank_description = models.TextField(verbose_name='职级描述') class Meta: verbose_name = '职级表' verbose_name_plural = '职级表' def __str__(self): return self.rank_name # 人员基本信息表 class EmployeeInformation(models.Model): GENDER_CHOICES = [ ('男', '男'), ('女', '女'), ('其他', '其他') ] BLOOD_TYPE_CHOICES = [ ('A', 'A'), ('B', 'B'), ('AB', 'AB'), ('O', 'O'), ('其他', '其他') ] MARITAL_STATUS_CHOICES = [ ('未婚', '未婚'), ('已婚未育', '已婚未育'), ('已婚已育', '已婚已育'), ('离婚', '离婚'), ('其他', '其他') ] POLITICAL_AFFILIATION_CHOICES = [ ('共产党员', '共产党员'), ('共青团员', '共青团员'), ('群众', '群众'), ('民主党派', '民主党派'), ('其他', '其他') ] EMPLOYMENT_TYPE_CHOICES = [ ('全职', '全职'), ('兼职', '兼职'), ('实习', '实习') ] STATUS_CHOICES = [ ('在职', '在职'), ('离职', '离职') ] EDUCATION_CHOICES = [ ('高中', '高中'), ('大专', '大专'), ('本科', '本科'), ('硕士研究生', '硕士研究生'), ('博士研究生', '博士研究生'), ('其他', '其他') ] RESIGNATION_TYPE_CHOICES = [ ('合同期满', '合同期满'), ('主动辞职', '主动辞职'), ('无条件辞职', '无条件辞职'), ('试用未通过', '试用未通过'), ('辞退', '辞退'), ('其他', '其他') ] employee_id = models.AutoField(primary_key=True) name = models.CharField(max_length=255, verbose_name='姓名') id_number = models.CharField(max_length=255, verbose_name='身份证号', unique=True, blank=True, null=True) gender = models.CharField(max_length=10, choices=GENDER_CHOICES, verbose_name='性别', blank=True, null=True) birthday = models.DateField(verbose_name='生日', blank=True, null=True) age = models.IntegerField(verbose_name='年龄', blank=True, null=True) height = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='身高(cm)', blank=True, null=True) weight = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='体重(kg)', blank=True, null=True) blood_type = models.CharField(max_length=3, choices=BLOOD_TYPE_CHOICES, verbose_name='血型', blank=True, null=True) ethnicity = models.CharField(max_length=255, verbose_name='民族', blank=True, null=True) domicile = models.CharField(max_length=255, verbose_name='户籍地', blank=True, null=True) marital_status = models.CharField(max_length=50, choices=MARITAL_STATUS_CHOICES, verbose_name='婚姻状态', blank=True, null=True) political_affiliation = models.CharField(max_length=50, choices=POLITICAL_AFFILIATION_CHOICES, verbose_name='政治面貌', blank=True, null=True) entry_date = models.DateField(verbose_name='入职日期', blank=True, null=True) regularization_date = models.DateField(verbose_name='转正日期', blank=True, null=True) employment_type = models.CharField(max_length=50, choices=EMPLOYMENT_TYPE_CHOICES, verbose_name='用工性质', blank=True, null=True) status = models.CharField(max_length=50, choices=STATUS_CHOICES, verbose_name='状态', blank=True, null=True) primary_department = models.CharField(max_length=255, verbose_name='一级部门', blank=True, null=True) secondary_department = models.CharField(max_length=255, verbose_name='二级部门', blank=True, null=True) position = models.CharField(max_length=255, verbose_name='岗位') rank = models.CharField(max_length=255, verbose_name='职级') contract_end_date = models.DateField(verbose_name='当前合同到期日期', blank=True, null=True) mobile_number = models.CharField(max_length=255, verbose_name='手机号', blank=True, null=True) email = models.EmailField(verbose_name='邮箱', blank=True, null=True) mailing_address = models.CharField(max_length=255, verbose_name='通信地址', blank=True, null=True) emergency_contact = models.CharField(max_length=255, verbose_name='紧急联系人', blank=True, null=True) relation_with_contact = models.CharField(max_length=255, verbose_name='与本人关系', blank=True, null=True) emergency_contact_phone = models.CharField(max_length=255, verbose_name='紧急联系人电话', blank=True, null=True) education = models.CharField(max_length=50, choices=EDUCATION_CHOICES, verbose_name='学历', blank=True, null=True) undergraduate_school = models.CharField(max_length=255, verbose_name='本科毕业院校', blank=True, null=True) graduate_school = models.CharField(max_length=255, verbose_name='研究生毕业院校', blank=True, null=True) major = models.CharField(max_length=255, verbose_name='专业', blank=True, null=True) technical_title = models.CharField(max_length=255, verbose_name='技术职称', blank=True, null=True) base_salary = models.TextField(verbose_name='基础工资(元)', blank=True, null=True) salary_account_number = models.CharField(max_length=255, verbose_name='工资卡号', blank=True, null=True) bank_of_salary_account = models.CharField(max_length=255, verbose_name='工资卡开户行', blank=True, null=True) resignation_type = models.CharField(max_length=50, choices=RESIGNATION_TYPE_CHOICES, verbose_name='离职类型', blank=True, null=True) resignation_reason = models.TextField(verbose_name='离职原因', blank=True, null=True) resignation_date = models.DateField(verbose_name='离职日期', blank=True, null=True) def save(self, *args, **kwargs): primary_department_name = PrimaryDepartment.objects.filter(department_name=self.primary_department).first() secondary_department = SecondaryDepartment.objects.filter(secondary_department_name=self.secondary_department).first() position = Position.objects.filter(position_name=self.position).first() rank = Rank.objects.filter(rank_name=self.rank).first() if not primary_department_name: raise ValueError("一级部门不存在") if not secondary_department: raise ValueError("二级部门不存在") if not position: raise ValueError("岗位不存在") if not rank: raise ValueError("职级不存在") super(EmployeeInformation, self).save(*args, **kwargs) class Meta: verbose_name = '人员基本信息表' verbose_name_plural = '人员基本信息表' def __str__(self): return self.name # 工资变更记录表 class SalaryChangeRecord(models.Model): employee = models.ForeignKey(EmployeeInformation, on_delete=models.CASCADE, related_name='salary_change_records') change_date = models.DateField(verbose_name='变更日期') previous_value = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='前值') new_value = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='最新值') approved_by = models.CharField(max_length=255, verbose_name='核准人') class Meta: verbose_name = '工资变更记录表' verbose_name_plural = '工资变更记录表' def __str__(self): return f"{self.employee.name} - {self.change_date}" # 员工考勤记录表 class EmployeeAttendanceRecord(models.Model): record_id = models.AutoField(primary_key=True) employee = models.CharField(max_length=255, verbose_name='姓名') primary_department = models.CharField(max_length=255, verbose_name='一级部门', blank=True, null=True) year_month = models.DateField(verbose_name='年月') late = models.IntegerField(default=0, verbose_name='迟到') early_leave = models.IntegerField(default=0, verbose_name='早退') absenteeism = models.IntegerField(default=0, verbose_name='旷工') annual_leave = models.IntegerField(default=0, verbose_name='年假') personal_leave = models.IntegerField(default=0, verbose_name='事假') sick_leave = models.IntegerField(default=0, verbose_name='病假') def save(self, *args, **kwargs): primary_department_name = PrimaryDepartment.objects.filter(department_name=self.primary_department).first() employee = EmployeeInformation.objects.filter(name=self.employee).first() if not employee: raise ValueError("人员不存在") if not primary_department_name: raise ValueError("一级部门不存在") super(EmployeeAttendanceRecord, self).save(*args, **kwargs) class Meta: verbose_name = '员工考勤记录表' verbose_name_plural = '员工考勤记录表' def __str__(self): return f"{self.employee} - {self.year_month.strftime('%Y-%m')}" @property def total_other_leave_days(self): # 使用聚合函数计算所有相关 other_leaves 的 days 总和 total_days = self.other_leaves.aggregate(total_days=Sum('days'))['total_days'] return total_days if total_days else 0 # 如果没有数据,返回 0 # 其他假期详细记录表 class OtherLeaveDetails(models.Model): LEAVE_TYPE_CHOICES = [ ('事假', '事假'), ('年假', '年假'), ('病假', '病假'), ('婚假', '婚假'), ('丧假', '丧假'), ] record_id = models.AutoField(primary_key=True) attendance_record = models.ForeignKey(EmployeeAttendanceRecord, on_delete=models.CASCADE, related_name='other_leaves', verbose_name='考勤记录') leave_type = models.CharField(max_length=255, choices=LEAVE_TYPE_CHOICES, verbose_name='假期类型') days = models.IntegerField(verbose_name='天数') description = models.TextField(verbose_name='说明') class Meta: verbose_name = '其他假期详细记录' verbose_name_plural = '其他假期详细记录' def __str__(self): return f"{self.leave_type} - {self.days} days" # 年假使用记录 class AnnualLeaveRecord(models.Model): record_id = models.AutoField(primary_key=True, verbose_name='记录编号') year = models.IntegerField(verbose_name='年份') employee_name = models.CharField(max_length=255, verbose_name='姓名') primary_department = models.CharField(max_length=255, verbose_name='一级部门') total_annual_leave = models.IntegerField(verbose_name='年假天数') used_annual_leave = models.IntegerField(verbose_name='已请年假数') remaining_annual_leave = models.IntegerField(verbose_name='剩余年假数') def save(self, *args, **kwargs): employee_name = EmployeeInformation.objects.filter(name=self.employee_name).first() if not employee_name: raise ValueError("人员不存在") super(AnnualLeaveRecord, self).save(*args, **kwargs) class Meta: verbose_name = '年假使用记录' verbose_name_plural = '年假使用记录表' def __str__(self): return f"{self.employee_name} - {self.year}" # 员工绩效 class PerformanceEvaluation(models.Model): YEAR_CHOICES = [(r, r) for r in range(2020, datetime.date.today().year + 1)] PERFORMANCE_CHOICES = ( ('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D') ) performance_id = models.AutoField(primary_key=True) employee = models.CharField(max_length=255, verbose_name='员工') year = models.IntegerField(choices=YEAR_CHOICES, verbose_name='年度') performance_score = models.CharField(max_length=255, choices=PERFORMANCE_CHOICES, verbose_name='年度绩效') def save(self, *args, **kwargs): employee = EmployeeInformation.objects.filter(name=self.employee).first() if not employee: raise ValueError("人员不存在") super(PerformanceEvaluation, self).save(*args, **kwargs) class Meta: verbose_name = '员工绩效' verbose_name_plural = '员工绩效表' unique_together = ('employee', 'year') def __str__(self): return f"{self.employee.name} - {self.year} - {self.performance_score}"