feat: 社保公积金独立配置+版本化缴费记录+月度增减员+补偿金批次

- Schema: 拆分社保/公积金配置,新增EmployeeSocialInsRecord/EmployeeHousingFundRecord/DepartmentRecord模型,扩展SalaryChangeRecord,增加SEVERANCE批次类型
- 后端: createEmployee/rehireEmployee接收社保公积金字段并创建缴费记录版本;createTermination/createResignation接收截止年月并关闭缴费记录;调薪/调部门API+版本记录;月度增减员API;公积金独立CRUD/计算/调基;SEVERANCE批次calcBatchEntry
- 前端: AddEmployeeModal/RehireModal增加社保公积金输入;ResignModal/Termination增加截止年月+日期不一致提醒;花名册增加调薪/调部门弹窗;SocialInsurance.tsx Tab拆分(社保/公积金/月度增减员)+CSV导出;Money.tsx增加补偿金批次类型
- 修复: seed.ts移除housingOrg/housingEmp;risk.service.ts从HousingFundConfig获取公积金费率
This commit is contained in:
freedakgmail
2026-07-23 20:02:59 +08:00
parent ad6800b63c
commit 4f125d309b
15 changed files with 2227 additions and 335 deletions
+101 -7
View File
@@ -55,6 +55,7 @@ enum PayrollBatchType {
REGULAR // 常规发薪
TERMINATION // 离职结算
BONUS // 年终奖/奖金
SEVERANCE // 补偿金按月发放(无社保,个税按政策处理)
}
enum PayrollBatchStatus {
@@ -131,6 +132,10 @@ model Organization {
onboardingLinks OnboardingLink[]
confirmLinks ContractConfirmLink[]
socialInsuranceConfig SocialInsuranceConfig[]
housingFundConfigs HousingFundConfig[]
socialInsRecords EmployeeSocialInsRecord[]
housingFundRecords EmployeeHousingFundRecord[]
departmentRecords EmployeeDepartmentRecord[]
notificationSetting NotificationSetting?
overtimeConfig OvertimeConfig?
notificationLogs NotificationLog[]
@@ -178,8 +183,12 @@ model Employee {
isInMedicalPeriod Boolean @default(false)
isWorkInjured Boolean @default(false)
// 薪税扩展
socialInsBase Float? // 社保缴费基数(按人核定
housingFundBase Float? // 公积金缴费基数(按人核定
socialInsBase Float? // 社保缴费基数(便捷字段,由Record同步
housingFundBase Float? // 公积金缴费基数(便捷字段,由Record同步
socialInsStartMonth String? // 当前社保开始年月(便捷字段)
socialInsEndMonth String? // 当前社保截止年月(便捷字段,null=在保)
housingFundStartMonth String? // 当前公积金开始年月(便捷字段)
housingFundEndMonth String? // 当前公积金截止年月(便捷字段)
specialDeduction Float @default(0) // 专项附加扣除(子女教育、赡养老人等,员工portal端填报)
createdBy String
createdAt DateTime @default(now())
@@ -197,6 +206,9 @@ model Employee {
attendanceRecords AttendanceRecord[]
trainingRecords TrainingRecord[]
performanceRecords PerformanceRecord[]
socialInsRecords EmployeeSocialInsRecord[]
housingFundRecords EmployeeHousingFundRecord[]
departmentRecords EmployeeDepartmentRecord[]
}
model LaborContract {
@@ -256,6 +268,8 @@ model TerminationRecord {
terminationDate DateTime
resignationReason String? // 主动离职原因(type=RESIGNATION时使用)
compensation Float @default(0)
socialInsEndMonth String? // 社保截止缴费年月 YYYY-MM
housingFundEndMonth String? // 公积金截止缴费年月 YYYY-MM
riskLevel RiskAssessment @default(SAFE)
checklist Json
remark String?
@@ -315,14 +329,33 @@ model SocialInsuranceConfig {
unemploymentEmp Float @default(0.5) // 失业保险 个人比例 %
injuryOrg Float @default(0.2) // 工伤保险 企业比例 %
maternityOrg Float @default(0.8) // 生育保险 企业比例 %
housingOrg Float @default(12) // 公积金 企业比例 %
housingEmp Float @default(12) // 公积金 个人比例 %
baseMin Float @default(6326) // 缴费基数下限
baseMax Float @default(33891) // 缴费基数上限
baseMin Float @default(6326) // 社保缴费基数下限
baseMax Float @default(33891) // 社保缴费基数上限
effectiveFrom String // 生效月份 YYYY-MM
effectiveTo String? // 失效月份 YYYY-MMnull=当前有效)
isCurrent Boolean @default(true) // 是否当前生效版本
adjustmentDone Boolean @default(false) // 是否已执行过员工基数调整
adjustmentDone Boolean @default(false) // 是否已执行过社保基数调整
createdBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([orgId, effectiveFrom])
@@index([orgId, isCurrent])
}
model HousingFundConfig {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
city String @default("北京")
housingOrg Float @default(12) // 公积金 企业比例 %
housingEmp Float @default(12) // 公积金 个人比例 %
baseMin Float @default(6326) // 公积金缴费基数下限
baseMax Float @default(33891) // 公积金缴费基数上限
effectiveFrom String // 生效月份 YYYY-MM
effectiveTo String? // 失效月份 YYYY-MMnull=当前有效)
isCurrent Boolean @default(true) // 是否当前生效版本
adjustmentDone Boolean @default(false) // 是否已执行过公积金基数调整
createdBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -613,11 +646,72 @@ model SalaryChangeRecord {
oldSalary Float
newSalary Float
effectiveDate DateTime // 生效日期
effectiveMonth String // 生效年月 YYYY-MM(从 effectiveDate 转换)
endMonth String? // 失效年月 YYYY-MM(null=至今有效,被新版本覆盖时设置)
changeType String @default("SALARY_CHANGE") // ONBOARDING=入职, REHIRE=重新入职, SALARY_CHANGE=调薪
reason String?
createdBy String
createdAt DateTime @default(now())
@@index([orgId, employeeId])
@@index([employeeId, effectiveMonth, endMonth])
}
model EmployeeSocialInsRecord {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
employeeId String
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
startMonth String // 开始缴费年月 YYYY-MM
endMonth String? // 截止缴费年月 YYYY-MMnull=至今有效)
base Float // 缴费基数
changeType String // ONBOARDING=入职, REHIRE=重新入职, ADJUST=调基, TERMINATION=离职/解聘
changeRefId String? // 关联的 TerminationRecord ID(离职/解聘时)
remark String?
createdBy String
createdAt DateTime @default(now())
@@index([orgId, employeeId])
@@index([employeeId, startMonth, endMonth])
}
model EmployeeHousingFundRecord {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
employeeId String
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
startMonth String // 开始缴费年月 YYYY-MM
endMonth String? // 截止缴费年月 YYYY-MMnull=至今有效)
base Float // 缴费基数
changeType String // ONBOARDING=入职, REHIRE=重新入职, ADJUST=调基, TERMINATION=离职/解聘
changeRefId String? // 关联的 TerminationRecord ID(离职/解聘时)
remark String?
createdBy String
createdAt DateTime @default(now())
@@index([orgId, employeeId])
@@index([employeeId, startMonth, endMonth])
}
model EmployeeDepartmentRecord {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
employeeId String
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
oldDepartment String // 调整前部门
newDepartment String // 调整后部门
effectiveMonth String // 生效年月 YYYY-MM
endMonth String? // 失效年月 YYYY-MMnull=至今有效)
reason String? // 调部门原因
changeType String // ONBOARDING=入职, REHIRE=重新入职, TRANSFER=调部门
createdBy String
createdAt DateTime @default(now())
@@index([orgId, employeeId])
@@index([employeeId, effectiveMonth, endMonth])
}
model OnboardingLink {
-2
View File
@@ -109,8 +109,6 @@ async function main() {
unemploymentEmp: 0.5,
injuryOrg: 0.2,
maternityOrg: 0.8,
housingOrg: 7,
housingEmp: 7,
baseMin: 7384,
baseMax: 36921,
effectiveFrom: '2025-07',