feat(wms): 添加倒班跨天考勤记录处理功能

- 新增 isBackwardCrossDay 方法判断倒班跨天情况
- 修改 sliceRecordsForDay 方法支持 backward 参数
- 更新 buildCheck 方法传递 crossDay 参数
- 实现倒班跨天情况下调整考勤时间窗口逻辑
- 优化跨天班次的时间范围计算规则
This commit is contained in:
2026-05-14 17:41:04 +08:00
parent c043d6674a
commit 9f12a57b26

View File

@@ -130,11 +130,12 @@ public class WmsAttendanceCheckServiceImpl implements IWmsAttendanceCheckService
List<WmsAttendanceCheck> checksToInsert = new ArrayList<>(toProcess.size()); List<WmsAttendanceCheck> checksToInsert = new ArrayList<>(toProcess.size());
for (WmsAttendanceScheduleVo schedule : toProcess) { for (WmsAttendanceScheduleVo schedule : toProcess) {
boolean crossDay = isCrossDayShift(schedule); boolean crossDay = isCrossDayShift(schedule);
boolean backward = isBackwardCrossDay(schedule);
List<AttendanceRecords> records = sliceRecordsForDay( List<AttendanceRecords> records = sliceRecordsForDay(
recordsByEmployee.get(schedule.getEmployeeName()), recordsByEmployee.get(schedule.getEmployeeName()),
schedule.getWorkDate(), schedule.getWorkDate(),
crossDay); crossDay, backward);
checksToInsert.add(buildCheck(schedule, rule, records)); checksToInsert.add(buildCheck(schedule, rule, records, crossDay));
} }
baseMapper.insertBatch(checksToInsert, BATCH_SIZE); baseMapper.insertBatch(checksToInsert, BATCH_SIZE);
@@ -146,6 +147,12 @@ public class WmsAttendanceCheckServiceImpl implements IWmsAttendanceCheckService
return schedule.getShiftIsCrossDay() != null && schedule.getShiftIsCrossDay() == 1; return schedule.getShiftIsCrossDay() != null && schedule.getShiftIsCrossDay() == 1;
} }
private boolean isBackwardCrossDay(WmsAttendanceScheduleVo schedule) {
if (!isCrossDayShift(schedule)) return false;
if (schedule.getShiftStartTime() == null || schedule.getShiftEndTime() == null) return false;
return toLocalTime(schedule.getShiftStartTime()).getHour() >= 16;
}
private WmsAttendanceRule getActiveRule() { private WmsAttendanceRule getActiveRule() {
LambdaQueryWrapper<WmsAttendanceRule> wrapper = Wrappers.lambdaQuery(); LambdaQueryWrapper<WmsAttendanceRule> wrapper = Wrappers.lambdaQuery();
wrapper.eq(WmsAttendanceRule::getDelFlag, 0); wrapper.eq(WmsAttendanceRule::getDelFlag, 0);
@@ -207,13 +214,13 @@ public class WmsAttendanceCheckServiceImpl implements IWmsAttendanceCheckService
/** /**
* 与原先 {@code getRecords(ename, workDate, crossDay)} 的时间窗口一致。 * 与原先 {@code getRecords(ename, workDate, crossDay)} 的时间窗口一致。
*/ */
private List<AttendanceRecords> sliceRecordsForDay(List<AttendanceRecords> prefetched, Date workDate, boolean crossDay) { private List<AttendanceRecords> sliceRecordsForDay(List<AttendanceRecords> prefetched, Date workDate, boolean crossDay, boolean backward) {
if (prefetched == null || prefetched.isEmpty()) { if (prefetched == null || prefetched.isEmpty()) {
return new ArrayList<>(); return new ArrayList<>();
} }
LocalDate ld = toLocalDate(workDate); LocalDate ld = toLocalDate(workDate);
LocalDateTime rangeStart = ld.atStartOfDay(); LocalDateTime rangeStart = ld.atStartOfDay();
LocalDateTime rangeEnd = crossDay LocalDateTime rangeEnd = crossDay && !backward
? ld.plusDays(1).atTime(LocalTime.of(23, 59, 59)) ? ld.plusDays(1).atTime(LocalTime.of(23, 59, 59))
: ld.atTime(LocalTime.of(23, 59, 59)); : ld.atTime(LocalTime.of(23, 59, 59));
return prefetched.stream() return prefetched.stream()
@@ -238,7 +245,7 @@ public class WmsAttendanceCheckServiceImpl implements IWmsAttendanceCheckService
} }
private WmsAttendanceCheck buildCheck(WmsAttendanceScheduleVo schedule, WmsAttendanceRule rule, private WmsAttendanceCheck buildCheck(WmsAttendanceScheduleVo schedule, WmsAttendanceRule rule,
List<AttendanceRecords> records) { List<AttendanceRecords> records, boolean crossDay) {
WmsAttendanceCheck check = new WmsAttendanceCheck(); WmsAttendanceCheck check = new WmsAttendanceCheck();
check.setScheduleId(schedule.getScheduleId()); check.setScheduleId(schedule.getScheduleId());
check.setUserId(schedule.getUserId()); check.setUserId(schedule.getUserId());
@@ -249,7 +256,6 @@ public class WmsAttendanceCheckServiceImpl implements IWmsAttendanceCheckService
check.setShiftType(schedule.getShiftType()); check.setShiftType(schedule.getShiftType());
boolean hasPeriod2 = schedule.getShiftStartTime2() != null && schedule.getShiftEndTime2() != null; boolean hasPeriod2 = schedule.getShiftStartTime2() != null && schedule.getShiftEndTime2() != null;
boolean crossDay = isCrossDayShift(schedule);
if (records.isEmpty()) { if (records.isEmpty()) {
check.setOverallStatus("absent_full"); check.setOverallStatus("absent_full");
@@ -303,7 +309,12 @@ public class WmsAttendanceCheckServiceImpl implements IWmsAttendanceCheckService
LocalDateTime windowStart; LocalDateTime windowStart;
LocalDateTime windowEnd; LocalDateTime windowEnd;
if (crossDay) { boolean backward = st != null && et != null && st.getHour() >= 16 && crossDay;
if (crossDay && backward) {
windowStart = LocalDateTime.of(ld, et).minusHours(2);
windowEnd = LocalDateTime.of(ld, et).plusHours(2);
} else if (crossDay) {
windowStart = LocalDateTime.of(ld, st).minusHours(2); windowStart = LocalDateTime.of(ld, st).minusHours(2);
windowEnd = LocalDateTime.of(ld.plusDays(1), et).plusHours(2); windowEnd = LocalDateTime.of(ld.plusDays(1), et).plusHours(2);
} else if (st != null && et != null) { } else if (st != null && et != null) {