|
|
|
|
@ -1,6 +1,7 @@
|
|
|
|
|
package cn.iocoder.yudao.module.mes.service.task;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
|
|
|
|
@ -18,11 +19,13 @@ import cn.iocoder.yudao.module.mes.controller.admin.deviceledger.enums.CapacityT
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanSaveReqVO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanStatusEnum;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.task.vo.*;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.calholiday.CalHolidayDO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDetailDO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.task.ViewTaskProductSummary;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.mysql.calholiday.CalHolidayMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.mysql.plan.PlanMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskDetailMapper;
|
|
|
|
|
@ -41,8 +44,11 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.math.RoundingMode;
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
import java.time.LocalTime;
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
import java.time.temporal.ChronoUnit;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
@ -82,6 +88,9 @@ public class TaskServiceImpl implements TaskService {
|
|
|
|
|
@Resource
|
|
|
|
|
private DeviceLedgerService deviceLedgerService;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private CalHolidayMapper calHolidayMapper;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private AutoCodeUtil autoCodeUtil;
|
|
|
|
|
@Resource
|
|
|
|
|
@ -428,9 +437,35 @@ public class TaskServiceImpl implements TaskService {
|
|
|
|
|
if (reqVO == null || CollUtil.isEmpty(reqVO.getCreateReqVO())) {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<Long, TaskDO> taskCache = new HashMap<>();
|
|
|
|
|
Map<Long, ErpProductDO> productCache = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
//是否跳过节假日
|
|
|
|
|
boolean skipHoliday = Boolean.TRUE.equals(reqVO.getSkipHoliday());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 解析本次请求的工作时段参数
|
|
|
|
|
LocalTime workStart;
|
|
|
|
|
LocalTime workEnd;
|
|
|
|
|
try {
|
|
|
|
|
workStart = LocalTime.parse(reqVO.getWorkStartTime()); // HH:mm
|
|
|
|
|
workEnd = LocalTime.parse(reqVO.getWorkEndTime()); // HH:mm
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw exception(SCHEDULE_TIME_FORMAT_INVALID, reqVO.getWorkStartTime(), reqVO.getWorkEndTime());
|
|
|
|
|
}
|
|
|
|
|
if (!workEnd.isAfter(workStart)) {
|
|
|
|
|
throw exception(SCHEDULE_TIME_RANGE_INVALID, reqVO.getWorkStartTime(), reqVO.getWorkEndTime());
|
|
|
|
|
}
|
|
|
|
|
long dailyWorkMinutes = ChronoUnit.MINUTES.between(workStart, workEnd);
|
|
|
|
|
if (dailyWorkMinutes <= 0) {
|
|
|
|
|
throw exception(SCHEDULE_WORK_HOURS_INVALID, reqVO.getWorkStartTime(), reqVO.getWorkEndTime());
|
|
|
|
|
}
|
|
|
|
|
BigDecimal dailyWorkHours = BigDecimal.valueOf(dailyWorkMinutes)
|
|
|
|
|
.divide(BigDecimal.valueOf(60), 6, RoundingMode.HALF_UP);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1) 先按规则排序
|
|
|
|
|
List<PlanSaveReqVO> sortedPlans = new ArrayList<>(reqVO.getCreateReqVO());
|
|
|
|
|
// 排序前:若明细交期为空,则回填为订单交期
|
|
|
|
|
@ -484,34 +519,30 @@ public class TaskServiceImpl implements TaskService {
|
|
|
|
|
// 构建设备候选(含选中口径的产能 + nextAvailable)
|
|
|
|
|
List<DeviceCandidate> candidates = new ArrayList<>();
|
|
|
|
|
for (ProductRelationRespVO rel : deviceRels) {
|
|
|
|
|
if (rel == null || rel.getId() == null) {
|
|
|
|
|
DeviceLedgerDO device = deviceLedgerMapper.selectById(rel.getId());
|
|
|
|
|
Integer dailyCapacity = capacityType.getCapacity(device); // 每日产能
|
|
|
|
|
if (dailyCapacity == null || dailyCapacity <= 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
Long deviceId = rel.getId();
|
|
|
|
|
DeviceLedgerDO device = deviceLedgerMapper.selectById(deviceId);
|
|
|
|
|
if (device == null) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Integer capacityValue = capacityType.getCapacity(device);
|
|
|
|
|
if (capacityValue == null || capacityValue <= 0) {
|
|
|
|
|
continue; // 当前口径产能无效则跳过
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocalDateTime nextTime = deviceNextAvailableTime.get(deviceId);
|
|
|
|
|
if (nextTime == null) {
|
|
|
|
|
nextTime = queryDeviceNextAvailableTime(deviceId);
|
|
|
|
|
deviceNextAvailableTime.put(deviceId, nextTime);
|
|
|
|
|
}
|
|
|
|
|
LocalDateTime nextAvailable = deviceNextAvailableTime.computeIfAbsent(
|
|
|
|
|
rel.getId(),
|
|
|
|
|
id -> queryDeviceNextAvailableTime(id, workStart, workEnd, skipHoliday)
|
|
|
|
|
);
|
|
|
|
|
nextAvailable = normalizeToWorkTime(nextAvailable, workStart, workEnd, skipHoliday);
|
|
|
|
|
|
|
|
|
|
candidates.add(new DeviceCandidate(deviceId, device.getDeviceName(), capacityValue, nextTime));
|
|
|
|
|
}
|
|
|
|
|
DeviceCandidate c = new DeviceCandidate();
|
|
|
|
|
c.setDeviceId(rel.getId());
|
|
|
|
|
c.setDeviceName(rel.getName());
|
|
|
|
|
c.setCapacityValue(dailyCapacity);
|
|
|
|
|
c.setNextAvailableTime(nextAvailable);
|
|
|
|
|
candidates.add(c); }
|
|
|
|
|
|
|
|
|
|
if (CollUtil.isEmpty(candidates)) {
|
|
|
|
|
throw exception(SCHEDULE_PRODUCT_DEVICE_UNAVAILABLE, item.getProductId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5) 选设备:优先空闲/最早可开工(nextAvailable最小),并列按deviceId升序
|
|
|
|
|
// 5) 选设备:优先空闲/最早可开工(nextAvailable最小),并列按deviceId倒序
|
|
|
|
|
DeviceCandidate chosen = candidates.stream()
|
|
|
|
|
.sorted(Comparator
|
|
|
|
|
.comparing(DeviceCandidate::getNextAvailableTime)
|
|
|
|
|
@ -519,39 +550,23 @@ public class TaskServiceImpl implements TaskService {
|
|
|
|
|
.findFirst()
|
|
|
|
|
.orElseThrow(() -> exception(SCHEDULE_PRODUCT_DEVICE_UNAVAILABLE, item.getProductId()));
|
|
|
|
|
|
|
|
|
|
BigDecimal planNumber = BigDecimal.valueOf(item.getPlanNumber());
|
|
|
|
|
BigDecimal dailyCapacity = BigDecimal.valueOf(chosen.getCapacityValue()); // 每日产能
|
|
|
|
|
// needHours = planNumber * dailyWorkHours / dailyCapacity
|
|
|
|
|
BigDecimal needHours = planNumber.multiply(dailyWorkHours)
|
|
|
|
|
.divide(dailyCapacity, 6, RoundingMode.HALF_UP);
|
|
|
|
|
|
|
|
|
|
// 6) 按 数量/额定产能 计算天数
|
|
|
|
|
int days = (int) Math.ceil((double) item.getPlanNumber() / chosen.getCapacityValue());
|
|
|
|
|
if (days <= 0) {
|
|
|
|
|
days = 1;
|
|
|
|
|
}
|
|
|
|
|
LocalDateTime planStartTime = normalizeToWorkTime(chosen.getNextAvailableTime(), workStart, workEnd, skipHoliday);
|
|
|
|
|
LocalDateTime planEndTime = addWorkingHours(planStartTime, needHours, workStart, workEnd, skipHoliday);
|
|
|
|
|
LocalDate dueDate = LocalDate.from(item.getOrderDetailDeliveryDate() != null
|
|
|
|
|
? item.getOrderDetailDeliveryDate()
|
|
|
|
|
: item.getDeliveryDate());
|
|
|
|
|
LocalDateTime dueEnd = LocalDateTime.of(dueDate, workEnd);
|
|
|
|
|
LocalDateTime latestStartTime = subtractWorkingHours(dueEnd, needHours, workStart, workEnd, skipHoliday);
|
|
|
|
|
|
|
|
|
|
// 7) 计算开始/结束时间(算法生成)
|
|
|
|
|
LocalDate startDate = chosen.getNextAvailableTime().toLocalDate();
|
|
|
|
|
LocalDateTime planStartTime = startDate.atStartOfDay();
|
|
|
|
|
LocalDateTime planEndTime = startDate.plusDays(days - 1).atTime(23, 59, 59);
|
|
|
|
|
|
|
|
|
|
// 7.1) 计算最晚开工时间(优先 orderDetailDeliveryDate,缺失则降级 deliveryDate)
|
|
|
|
|
LocalDate dueDate;
|
|
|
|
|
if (item.getOrderDetailDeliveryDate() != null) {
|
|
|
|
|
dueDate = item.getOrderDetailDeliveryDate().toLocalDate();
|
|
|
|
|
} else if (item.getDeliveryDate() != null) {
|
|
|
|
|
dueDate = item.getDeliveryDate().toLocalDate();; // 如果你的 deliveryDate 是 LocalDateTime,这里改成 toLocalDate()
|
|
|
|
|
} else {
|
|
|
|
|
throw exception(SCHEDULE_DELIVERY_DATE_EMPTY, item.getTaskDetailId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 天数A = (截止日期 - 计划开始日期) - scheduleDays
|
|
|
|
|
long availableDays = ChronoUnit.DAYS.between(startDate, dueDate) + 1;
|
|
|
|
|
// 最晚可向后平移天数
|
|
|
|
|
long dayA = availableDays - days;
|
|
|
|
|
LocalDateTime latestStartTime = dayA <= 0
|
|
|
|
|
? planStartTime
|
|
|
|
|
: planStartTime.plusDays(dayA);
|
|
|
|
|
|
|
|
|
|
// 8) 更新该设备下次可开工时间(下一天00:00:00)
|
|
|
|
|
LocalDateTime nextAvailable = planEndTime.plusSeconds(1);
|
|
|
|
|
deviceNextAvailableTime.put(chosen.getDeviceId(), nextAvailable);
|
|
|
|
|
// 更新设备下次可开工
|
|
|
|
|
LocalDateTime newNextAvailable = normalizeToWorkTime(planEndTime, workStart, workEnd, skipHoliday);
|
|
|
|
|
deviceNextAvailableTime.put(chosen.getDeviceId(), newNextAvailable);
|
|
|
|
|
|
|
|
|
|
// 9) 组装返回(按设备分组)
|
|
|
|
|
TaskOneClickScheduleRespVO deviceResp = deviceResultMap.computeIfAbsent(chosen.getDeviceId(), k -> {
|
|
|
|
|
@ -571,10 +586,6 @@ public class TaskServiceImpl implements TaskService {
|
|
|
|
|
p.setTaskId(item.getTaskId());
|
|
|
|
|
p.setTaskDetailId(item.getTaskDetailId());
|
|
|
|
|
p.setPlanNumber(item.getPlanNumber());
|
|
|
|
|
p.setScheduleDays(days);
|
|
|
|
|
// p.setPlanStartTime(planStartTime);
|
|
|
|
|
// p.setPlanEndTime(planEndTime);
|
|
|
|
|
// p.setLatestStartTime(latestStartTime);
|
|
|
|
|
p.setSourceType("CURRENT");
|
|
|
|
|
p.setTaskCode(taskDO == null ? null : taskDO.getCode());
|
|
|
|
|
p.setProductCode(productDO == null ? null : productDO.getBarCode());
|
|
|
|
|
@ -663,24 +674,166 @@ public class TaskServiceImpl implements TaskService {
|
|
|
|
|
* - 有历史启用计划:取最后结束时间+1秒
|
|
|
|
|
* - 没有历史计划:取当前时间(并对齐到当天开始)
|
|
|
|
|
*/
|
|
|
|
|
private LocalDateTime queryDeviceNextAvailableTime(Long deviceId) {
|
|
|
|
|
// ===================== 6) 替换 queryDeviceNextAvailableTime =====================
|
|
|
|
|
// 文件:TaskServiceImpl.java
|
|
|
|
|
|
|
|
|
|
private LocalDateTime queryDeviceNextAvailableTime(Long deviceId, LocalTime workStart, LocalTime workEnd, boolean skipHoliday) {
|
|
|
|
|
PlanDO lastPlan = planMapper.selectOne(new LambdaQueryWrapper<PlanDO>()
|
|
|
|
|
.eq(PlanDO::getDeviceId, deviceId)
|
|
|
|
|
.eq(PlanDO::getIsEnable, true)
|
|
|
|
|
.orderByDesc(PlanDO::getPlanEndTime)
|
|
|
|
|
.last("limit 1"));
|
|
|
|
|
|
|
|
|
|
LocalDate today = LocalDate.now();
|
|
|
|
|
LocalDate historyNextDate;
|
|
|
|
|
if (lastPlan == null || lastPlan.getPlanEndTime() == null) {
|
|
|
|
|
historyNextDate = today;
|
|
|
|
|
} else {
|
|
|
|
|
historyNextDate = lastPlan.getPlanEndTime().toLocalDate().plusDays(1);
|
|
|
|
|
LocalDateTime base = (lastPlan == null || lastPlan.getPlanEndTime() == null)
|
|
|
|
|
? LocalDateTime.now()
|
|
|
|
|
: lastPlan.getPlanEndTime();
|
|
|
|
|
|
|
|
|
|
return normalizeToWorkTime(base, workStart, workEnd, skipHoliday);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private LocalDateTime normalizeToWorkTime(LocalDateTime time, LocalTime workStart, LocalTime workEnd, boolean skipHoliday) {
|
|
|
|
|
LocalDate date = time.toLocalDate();
|
|
|
|
|
LocalTime t = time.toLocalTime();
|
|
|
|
|
|
|
|
|
|
if (skipHoliday && !isWorkingDay(date)) {
|
|
|
|
|
date = nextWorkingDate(date.plusDays(1));
|
|
|
|
|
return LocalDateTime.of(date, workStart);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (t.isBefore(workStart)) {
|
|
|
|
|
return LocalDateTime.of(date, workStart);
|
|
|
|
|
}
|
|
|
|
|
if (!t.isBefore(workEnd)) {
|
|
|
|
|
LocalDate next = date.plusDays(1);
|
|
|
|
|
if (skipHoliday) {
|
|
|
|
|
next = nextWorkingDate(next);
|
|
|
|
|
}
|
|
|
|
|
return LocalDateTime.of(next, workStart);
|
|
|
|
|
}
|
|
|
|
|
return time;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private LocalDateTime addWorkingHours(LocalDateTime start, BigDecimal hours,
|
|
|
|
|
LocalTime workStart, LocalTime workEnd,
|
|
|
|
|
boolean skipHoliday) {
|
|
|
|
|
LocalDateTime cursor = normalizeToWorkTime(start, workStart, workEnd, skipHoliday);
|
|
|
|
|
long remainMinutes = hours.multiply(BigDecimal.valueOf(60))
|
|
|
|
|
.setScale(0, RoundingMode.HALF_UP)
|
|
|
|
|
.longValue();
|
|
|
|
|
|
|
|
|
|
while (remainMinutes > 0) {
|
|
|
|
|
if (skipHoliday && !isWorkingDay(cursor.toLocalDate())) {
|
|
|
|
|
cursor = LocalDateTime.of(nextWorkingDate(cursor.toLocalDate().plusDays(1)), workStart);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocalDateTime dayEnd = LocalDateTime.of(cursor.toLocalDate(), workEnd);
|
|
|
|
|
long available = ChronoUnit.MINUTES.between(cursor, dayEnd);
|
|
|
|
|
|
|
|
|
|
if (available <= 0) {
|
|
|
|
|
LocalDate next = cursor.toLocalDate().plusDays(1);
|
|
|
|
|
if (skipHoliday) {
|
|
|
|
|
next = nextWorkingDate(next);
|
|
|
|
|
}
|
|
|
|
|
cursor = LocalDateTime.of(next, workStart);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (remainMinutes <= available) {
|
|
|
|
|
return cursor.plusMinutes(remainMinutes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remainMinutes -= available;
|
|
|
|
|
LocalDate next = cursor.toLocalDate().plusDays(1);
|
|
|
|
|
if (skipHoliday) {
|
|
|
|
|
next = nextWorkingDate(next);
|
|
|
|
|
}
|
|
|
|
|
cursor = LocalDateTime.of(next, workStart);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 取 max(今天, 历史下一天)
|
|
|
|
|
LocalDate nextDate = historyNextDate.isBefore(today) ? today : historyNextDate;
|
|
|
|
|
return nextDate.atStartOfDay();
|
|
|
|
|
return cursor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private LocalDateTime subtractWorkingHours(LocalDateTime end, BigDecimal hours,
|
|
|
|
|
LocalTime workStart, LocalTime workEnd,
|
|
|
|
|
boolean skipHoliday) {
|
|
|
|
|
LocalDateTime cursor = end;
|
|
|
|
|
LocalTime t = cursor.toLocalTime();
|
|
|
|
|
|
|
|
|
|
if (t.isAfter(workEnd)) {
|
|
|
|
|
cursor = LocalDateTime.of(cursor.toLocalDate(), workEnd);
|
|
|
|
|
} else if (!t.isAfter(workStart)) {
|
|
|
|
|
LocalDate prev = cursor.toLocalDate().minusDays(1);
|
|
|
|
|
if (skipHoliday) {
|
|
|
|
|
prev = prevWorkingDate(prev);
|
|
|
|
|
}
|
|
|
|
|
cursor = LocalDateTime.of(prev, workEnd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (skipHoliday && !isWorkingDay(cursor.toLocalDate())) {
|
|
|
|
|
LocalDate prev = prevWorkingDate(cursor.toLocalDate().minusDays(1));
|
|
|
|
|
cursor = LocalDateTime.of(prev, workEnd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long remainMinutes = hours.multiply(BigDecimal.valueOf(60))
|
|
|
|
|
.setScale(0, RoundingMode.HALF_UP)
|
|
|
|
|
.longValue();
|
|
|
|
|
|
|
|
|
|
while (remainMinutes > 0) {
|
|
|
|
|
if (skipHoliday && !isWorkingDay(cursor.toLocalDate())) {
|
|
|
|
|
LocalDate prev = prevWorkingDate(cursor.toLocalDate().minusDays(1));
|
|
|
|
|
cursor = LocalDateTime.of(prev, workEnd);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocalDateTime dayStart = LocalDateTime.of(cursor.toLocalDate(), workStart);
|
|
|
|
|
long available = ChronoUnit.MINUTES.between(dayStart, cursor);
|
|
|
|
|
|
|
|
|
|
if (available <= 0) {
|
|
|
|
|
LocalDate prev = cursor.toLocalDate().minusDays(1);
|
|
|
|
|
if (skipHoliday) {
|
|
|
|
|
prev = prevWorkingDate(prev);
|
|
|
|
|
}
|
|
|
|
|
cursor = LocalDateTime.of(prev, workEnd);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (remainMinutes <= available) {
|
|
|
|
|
return cursor.minusMinutes(remainMinutes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remainMinutes -= available;
|
|
|
|
|
LocalDate prev = cursor.toLocalDate().minusDays(1);
|
|
|
|
|
if (skipHoliday) {
|
|
|
|
|
prev = prevWorkingDate(prev);
|
|
|
|
|
}
|
|
|
|
|
cursor = LocalDateTime.of(prev, workEnd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cursor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 规则:周末默认上班;仅 HOLIDAY 休息
|
|
|
|
|
private boolean isWorkingDay(LocalDate date) {
|
|
|
|
|
return !isHolidayByDate(date);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private LocalDate nextWorkingDate(LocalDate date) {
|
|
|
|
|
LocalDate d = date;
|
|
|
|
|
while (!isWorkingDay(d)) {
|
|
|
|
|
d = d.plusDays(1);
|
|
|
|
|
}
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private LocalDate prevWorkingDate(LocalDate date) {
|
|
|
|
|
LocalDate d = date;
|
|
|
|
|
while (!isWorkingDay(d)) {
|
|
|
|
|
d = d.minusDays(1);
|
|
|
|
|
}
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Set<Long> queryDeviceIdsFromCurrentMonth() {
|
|
|
|
|
@ -725,4 +878,10 @@ public class TaskServiceImpl implements TaskService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean isHolidayByDate(LocalDate day) {
|
|
|
|
|
LocalDateTime start = day.atStartOfDay();
|
|
|
|
|
LocalDateTime end = day.plusDays(1).atStartOfDay();
|
|
|
|
|
Integer cnt = calHolidayMapper.countHolidayInRange(start, end);
|
|
|
|
|
return cnt != null && cnt > 0;
|
|
|
|
|
}
|
|
|
|
|
}
|