fix(hrm): 已清除的排班日期重新排班时报唯一键冲突
hrm_employee_schedule 的唯一索引 uk_employee_date(employee_id,date) 不含 deleted,
排班清除走逻辑删除后,再给同员工同日期排班会插入重复键,整批保存事务回滚,
表现为「排了班但保存后查不到」。
改为插入前先复活同员工同日期的已删除记录(save / batch-save 两条路径)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
| | |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmEmployeeScheduleDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.apache.ibatis.annotations.Update; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.util.Collection; |
| | |
| | | .eq(HrmEmployeeScheduleDO::getShiftId, shiftId)); |
| | | } |
| | | |
| | | /** |
| | | * 复活一条已被逻辑删除的排班(唯一索引 uk_employee_date 不含 deleted, |
| | | * 逻辑删除后再插入同员工同日期会撞唯一键,这里改为把旧行改回有效) |
| | | * |
| | | * @return 更新行数,0 表示不存在已删除的同员工同日期记录 |
| | | */ |
| | | @Update("UPDATE hrm_employee_schedule SET deleted = 0, shift_id = #{shiftId}, remark = #{remark}, " |
| | | + "update_time = NOW() WHERE employee_id = #{employeeId} AND date = #{date} AND deleted = 1") |
| | | int reviveDeletedSchedule(@Param("employeeId") Long employeeId, @Param("date") LocalDate date, |
| | | @Param("shiftId") Long shiftId, @Param("remark") String remark); |
| | | |
| | | } |
| | |
| | | } |
| | | } else { |
| | | if (existing == null) { |
| | | employeeScheduleMapper.insert(BeanUtils.toBean(reqVO, HrmEmployeeScheduleDO.class)); |
| | | // 该员工该日期可能是之前被清除(逻辑删除)的排班,唯一索引不含 deleted,直接 insert 会撞唯一键 |
| | | if (employeeScheduleMapper.reviveDeletedSchedule(reqVO.getEmployeeId(), reqVO.getDate(), |
| | | reqVO.getShiftId(), reqVO.getRemark()) == 0) { |
| | | employeeScheduleMapper.insert(BeanUtils.toBean(reqVO, HrmEmployeeScheduleDO.class)); |
| | | } |
| | | } else { |
| | | existing.setShiftId(reqVO.getShiftId()); |
| | | existing.setRemark(reqVO.getRemark()); |
| | |
| | | continue; |
| | | } |
| | | if (existing == null) { |
| | | // 已被清除(逻辑删除)的日期直接 insert 会撞唯一索引,优先复活旧行 |
| | | if (employeeScheduleMapper.reviveDeletedSchedule(employee.getId(), date, |
| | | reqVO.getShiftId(), null) > 0) { |
| | | itemCount++; |
| | | continue; |
| | | } |
| | | HrmEmployeeScheduleDO schedule = new HrmEmployeeScheduleDO(); |
| | | schedule.setEmployeeId(employee.getId()); |
| | | schedule.setDate(date); |