feat: 节假日配置、排班管理独立页面、考勤加班显示优化
- 新增 HolidayConfig 模型,支持法定节假日和调休工作日配置 - 加班费同步逻辑改用 HolidayConfig 判断日期类型 - 员工端考勤显示加班工时、费率和日期类型 - 周末/节假日出勤状态显示为"周末出勤"/"节假日出勤" - 新增 Employee.defaultShiftId 字段,支持长期排班(工作日班次) - 排班管理拆分为独立页面(班次管理+排班),考勤管理保留出勤相关功能 - 排班和每日出勤页面增加身份证号列 - 修复岗位和部门编辑失败问题(POST 改 PUT) - 新增 backfill 脚本:合同薪资回填、默认班次回填 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -401,6 +401,8 @@ export async function createEmployee(orgId: string, userId: string, data: any) {
|
||||
// 默认密码:手机号后6位(员工可在员工端自行修改)
|
||||
const defaultPassword = data.phone ? data.phone.slice(-6) : '123456'
|
||||
const passwordHash = await bcrypt.hash(defaultPassword, 10)
|
||||
// 查找该组织的第一个班次作为默认排班(长期=工作日班次)
|
||||
const firstShift = await tx.shift.findFirst({ where: { orgId }, orderBy: { createdAt: 'asc' } })
|
||||
const emp = await tx.employee.create({
|
||||
data: {
|
||||
orgId,
|
||||
@@ -420,6 +422,7 @@ export async function createEmployee(orgId: string, userId: string, data: any) {
|
||||
isPregnant: data.isPregnant || false,
|
||||
isInMedicalPeriod: data.isInMedicalPeriod || false,
|
||||
isWorkInjured: data.isWorkInjured || false,
|
||||
defaultShiftId: firstShift?.id || null,
|
||||
socialInsBase,
|
||||
housingFundBase,
|
||||
socialInsStartMonth,
|
||||
@@ -1027,6 +1030,25 @@ export async function addContract(orgId: string, userId: string, data: any) {
|
||||
throw { code: 'DUPLICATE', message: '该员工已存在相同日期的合同,请勿重复添加' }
|
||||
}
|
||||
|
||||
// 工资结构:baseSalary 为 0 时,用员工档案月工资填充
|
||||
let contractBase = Number(data.baseSalary) || 0
|
||||
let contractPerf = Number(data.performanceSalary) || 0
|
||||
if (contractBase === 0 && contractPerf === 0) {
|
||||
const emp = await prisma.employee.findFirst({
|
||||
where: { id: data.employeeId, orgId },
|
||||
select: { monthlySalary: true, baseSalary: true, performanceSalary: true },
|
||||
})
|
||||
if (emp) {
|
||||
try {
|
||||
contractBase = emp.baseSalary ? Number(decrypt(emp.baseSalary)) || 0 : 0
|
||||
contractPerf = emp.performanceSalary ? Number(decrypt(emp.performanceSalary)) || 0 : 0
|
||||
} catch {}
|
||||
if (contractBase === 0 && contractPerf === 0) {
|
||||
try { contractBase = Number(decrypt(emp.monthlySalary)) || 0 } catch {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const contractMonths = data.endDate
|
||||
? Math.ceil(daysBetween(new Date(data.endDate), new Date(data.startDate)) / 30.44)
|
||||
: data.contractYears * 12
|
||||
@@ -1048,8 +1070,8 @@ export async function addContract(orgId: string, userId: string, data: any) {
|
||||
contractYears: data.contractYears || 3,
|
||||
probationMonths: data.probationMonths || 0,
|
||||
probationSalary: data.probationSalary || 0,
|
||||
baseSalary: data.baseSalary || 0,
|
||||
performanceSalary: data.performanceSalary || 0,
|
||||
baseSalary: contractBase,
|
||||
performanceSalary: contractPerf,
|
||||
attachmentName: data.attachmentUrl ? '合同扫描件' : null,
|
||||
attachmentUrl: data.attachmentUrl || null,
|
||||
electronicContractNo: data.electronicContractNo || null,
|
||||
|
||||
Reference in New Issue
Block a user