日历

parent 97f10b74
...@@ -3,6 +3,8 @@ package com.aps.service; ...@@ -3,6 +3,8 @@ package com.aps.service;
import com.aps.entity.ProdEquipSpecialCal; import com.aps.entity.ProdEquipSpecialCal;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import java.util.Collection;
/** /**
* <p> * <p>
* 设备特殊日历配置表:记录特定工位/设备在指定时间段的特殊日历规则(如节假日、维护期等) 服务类 * 设备特殊日历配置表:记录特定工位/设备在指定时间段的特殊日历规则(如节假日、维护期等) 服务类
...@@ -18,4 +20,19 @@ public interface ProdEquipSpecialCalService extends IService<ProdEquipSpecialCal ...@@ -18,4 +20,19 @@ public interface ProdEquipSpecialCalService extends IService<ProdEquipSpecialCal
*/ */
void copyFromEquipCapacityDef(String sceneId); void copyFromEquipCapacityDef(String sceneId);
/**
* Copy calculated equipment shift capacity rows into the scene calendar table.
*/
void copyFromEquipShiftCapacity(String sceneId);
/**
* Copy calculated equipment shift capacity rows for the scene's plan resources.
*/
void copyFromEquipShiftCapacity(String sceneId, Collection<Long> planResourceIds);
/**
* Prefer calculated equipment shift capacity rows, then fall back to legacy capacity definitions.
*/
void copyCalendarWithFallback(String sceneId, Collection<Long> planResourceIds);
} }
...@@ -121,9 +121,6 @@ public class LanuchServiceImpl implements LanuchService { ...@@ -121,9 +121,6 @@ public class LanuchServiceImpl implements LanuchService {
} }
sceneId = sceneConfig.getSceneId(); sceneId = sceneConfig.getSceneId();
prodEquipSpecialCalService.copyFromEquipCapacityDef(sceneId);
List<MesSchedule> mesSchedules = mesScheduleService.lambdaQuery() List<MesSchedule> mesSchedules = mesScheduleService.lambdaQuery()
.eq(MesSchedule::getIsDeleted, 0) .eq(MesSchedule::getIsDeleted, 0)
.eq(MesSchedule::getScheduleUserId, username) .eq(MesSchedule::getScheduleUserId, username)
...@@ -844,6 +841,11 @@ public class LanuchServiceImpl implements LanuchService { ...@@ -844,6 +841,11 @@ public class LanuchServiceImpl implements LanuchService {
} }
if (!CollectionUtils.isEmpty(allProdEquipments)) { if (!CollectionUtils.isEmpty(allProdEquipments)) {
prodEquipmentService.saveBatch(allProdEquipments, 500); prodEquipmentService.saveBatch(allProdEquipments, 500);
Set<Long> planResourceIds = allProdEquipments.stream()
.map(ProdEquipment::getEquipId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
prodEquipSpecialCalService.copyCalendarWithFallback(sceneId, planResourceIds);
} }
log.info("完成{}个工单的工序转换",order.size()); log.info("完成{}个工单的工序转换",order.size());
......
package com.aps.service.impl; package com.aps.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aps.common.util.SnowFlackIdWorker; import com.aps.common.util.SnowFlackIdWorker;
import com.aps.entity.ProdEquipSpecialCal;
import com.aps.entity.EquipCapacityDef; import com.aps.entity.EquipCapacityDef;
import com.aps.entity.EquipShiftCapacity;
import com.aps.entity.ProdEquipSpecialCal;
import com.aps.mapper.ProdEquipSpecialCalMapper; import com.aps.mapper.ProdEquipSpecialCalMapper;
import com.aps.service.ProdEquipSpecialCalService;
import com.aps.service.EquipCapacityDefService; import com.aps.service.EquipCapacityDefService;
import com.aps.service.EquipShiftCapacityService;
import com.aps.service.ProdEquipSpecialCalService;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/**
* <p>
* 设备特殊日历配置表:记录特定工位/设备在指定时间段的特殊日历规则(如节假日、维护期等) 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-11-26
*/
@Service @Service
public class ProdEquipSpecialCalServiceImpl extends ServiceImpl<ProdEquipSpecialCalMapper, ProdEquipSpecialCal> implements ProdEquipSpecialCalService { public class ProdEquipSpecialCalServiceImpl extends ServiceImpl<ProdEquipSpecialCalMapper, ProdEquipSpecialCal>
implements ProdEquipSpecialCalService {
private static final int BATCH_SIZE = 100;
private static final DateTimeFormatter TIME_PERIOD_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Autowired @Autowired
private EquipCapacityDefService equipCapacityDefService; private EquipCapacityDefService equipCapacityDefService;
/** @Autowired
* 从EquipCapacityDef表中复制is_deleted为0的数据到ProdEquipSpecialCal表 private EquipShiftCapacityService equipShiftCapacityService;
*/
@Override @Override
public void copyFromEquipCapacityDef(String sceneId) { public void copyFromEquipCapacityDef(String sceneId) {
// 直接通过条件查询,而不是全表查询后过滤
List<EquipCapacityDef> activeCapacityDefs = equipCapacityDefService.lambdaQuery() List<EquipCapacityDef> activeCapacityDefs = equipCapacityDefService.lambdaQuery()
.eq(EquipCapacityDef::getIsDeleted, 0) .eq(EquipCapacityDef::getIsDeleted, 0)
.isNotNull(EquipCapacityDef::getReferenceId) .isNotNull(EquipCapacityDef::getReferenceId)
.isNotNull(EquipCapacityDef::getEquipId) // 过滤掉 equipId 为 null 的记录 .isNotNull(EquipCapacityDef::getEquipId)
.list(); .list();
// 转换对象并设置必要字段
List<ProdEquipSpecialCal> specialCals = activeCapacityDefs.stream() List<ProdEquipSpecialCal> specialCals = activeCapacityDefs.stream()
.map(capacityDef -> convertToProdEquipSpecialCal(capacityDef, sceneId)) .map(capacityDef -> convertToProdEquipSpecialCal(capacityDef, sceneId))
.filter(Objects::nonNull) // 过滤掉转换失败的对象 .filter(Objects::nonNull)
.collect(Collectors.toList()); .collect(Collectors.toList());
saveBatchIfNeeded(specialCals);
}
// 批量保存到ProdEquipSpecialCal表 @Override
if (!specialCals.isEmpty()) { public void copyFromEquipShiftCapacity(String sceneId) {
// 使用分批插入,避免单次插入过多数据 copyFromEquipShiftCapacity(sceneId, null);
int batchSize = 100;
for (int i = 0; i < specialCals.size(); i += batchSize) {
int end = Math.min(i + batchSize, specialCals.size());
this.saveBatch(specialCals.subList(i, end), batchSize);
} }
@Override
public void copyFromEquipShiftCapacity(String sceneId, Collection<Long> planResourceIds) {
List<EquipShiftCapacity> activeCapacities = queryEquipShiftCapacities(planResourceIds);
List<ProdEquipSpecialCal> specialCals = activeCapacities.stream()
.flatMap(capacity -> convertToProdEquipSpecialCals(capacity, sceneId).stream())
.collect(Collectors.toList());
saveBatchIfNeeded(specialCals);
}
@Override
public void copyCalendarWithFallback(String sceneId, Collection<Long> planResourceIds) {
if (planResourceIds == null || planResourceIds.isEmpty()) {
copyFromEquipShiftCapacity(sceneId);
return;
} }
List<EquipShiftCapacity> shiftCapacities = queryEquipShiftCapacities(planResourceIds);
List<ProdEquipSpecialCal> shiftCapacityCals = shiftCapacities.stream()
.flatMap(capacity -> convertToProdEquipSpecialCals(capacity, sceneId).stream())
.collect(Collectors.toList());
saveBatchIfNeeded(shiftCapacityCals);
Set<Long> planResourcesWithShiftCapacity = shiftCapacities.stream()
.map(EquipShiftCapacity::getPlanResourceId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Set<Long> fallbackPlanResourceIds = new HashSet<>(planResourceIds);
fallbackPlanResourceIds.removeAll(planResourcesWithShiftCapacity);
if (fallbackPlanResourceIds.isEmpty()) {
return;
}
List<ProdEquipSpecialCal> fallbackCals = equipCapacityDefService.lambdaQuery()
.eq(EquipCapacityDef::getIsDeleted, 0)
.isNotNull(EquipCapacityDef::getReferenceId)
.isNotNull(EquipCapacityDef::getEquipId)
.in(EquipCapacityDef::getPlanResourceId, fallbackPlanResourceIds)
.list()
.stream()
.map(capacityDef -> convertToProdEquipSpecialCal(capacityDef, sceneId))
.filter(Objects::nonNull)
.collect(Collectors.toList());
saveBatchIfNeeded(fallbackCals);
}
private List<EquipShiftCapacity> queryEquipShiftCapacities(Collection<Long> planResourceIds) {
LambdaQueryChainWrapper<EquipShiftCapacity> query = equipShiftCapacityService.lambdaQuery()
.eq(EquipShiftCapacity::getIsDeleted, 0)
.isNotNull(EquipShiftCapacity::getPlanResourceId)
.isNotNull(EquipShiftCapacity::getEquipId);
if (planResourceIds != null && !planResourceIds.isEmpty()) {
query.in(EquipShiftCapacity::getPlanResourceId, planResourceIds);
}
return query.list();
} }
/**
* 将EquipCapacityDef转换为ProdEquipSpecialCal
* @param capacityDef 源对象
* @return 转换后的对象
*/
private ProdEquipSpecialCal convertToProdEquipSpecialCal(EquipCapacityDef capacityDef, String sceneId) { private ProdEquipSpecialCal convertToProdEquipSpecialCal(EquipCapacityDef capacityDef, String sceneId) {
try { try {
ProdEquipSpecialCal specialCal = new ProdEquipSpecialCal(); ProdEquipSpecialCal specialCal = new ProdEquipSpecialCal();
// 设置必填字段,确保不会为空
specialCal.setId(String.valueOf(SnowFlackIdWorker.getId())); specialCal.setId(String.valueOf(SnowFlackIdWorker.getId()));
specialCal.setSceneId(sceneId); // sceneId不能为空 specialCal.setSceneId(sceneId);
// 可选字段的安全转换
specialCal.setEquipId(capacityDef.getEquipId() != null ? capacityDef.getEquipId().intValue() : null); specialCal.setEquipId(capacityDef.getEquipId() != null ? capacityDef.getEquipId().intValue() : null);
specialCal.setEquipCode(capacityDef.getEquipCode()); specialCal.setEquipCode(capacityDef.getEquipCode());
specialCal.setStartDate(capacityDef.getEffectiveStartTime()); specialCal.setStartDate(capacityDef.getEffectiveStartTime());
specialCal.setEndDate(capacityDef.getEffectiveEndTime()); specialCal.setEndDate(capacityDef.getEffectiveEndTime());
specialCal.setPlanResourceId(capacityDef.getPlanResourceId()); specialCal.setPlanResourceId(capacityDef.getPlanResourceId());
specialCal.setPlanResourceId(capacityDef.getPlanResourceId()); specialCal.setEfficiencyCoeff(capacityDef.getEfficiencyCoeff() != null
// 处理数值类型转换的空值 ? capacityDef.getEfficiencyCoeff().doubleValue()
if (capacityDef.getEfficiencyCoeff() != null) { : 1);
specialCal.setEfficiencyCoeff(capacityDef.getEfficiencyCoeff().doubleValue());
}else {
specialCal.setEfficiencyCoeff(1);
}
specialCal.setReferenceId(capacityDef.getReferenceId()); specialCal.setReferenceId(capacityDef.getReferenceId());
specialCal.setReferenceName(capacityDef.getReferenceName()); specialCal.setReferenceName(capacityDef.getReferenceName());
specialCal.setCreatorUserId(capacityDef.getCreatorUserId()); specialCal.setCreatorUserId(capacityDef.getCreatorUserId());
specialCal.setCreationTime(LocalDateTime.now()); specialCal.setCreationTime(LocalDateTime.now());
specialCal.setReferenceType(capacityDef.getReferenceType()); specialCal.setReferenceType(capacityDef.getReferenceType());
return specialCal; return specialCal;
} catch (Exception e) { } catch (Exception e) {
log.error("转换EquipCapacityDef到ProdEquipSpecialCal失败", e); log.error("Convert EquipCapacityDef to ProdEquipSpecialCal failed", e);
return null;
}
}
private List<ProdEquipSpecialCal> convertToProdEquipSpecialCals(EquipShiftCapacity capacity, String sceneId) {
List<TimePeriod> periods = parseTimePeriods(capacity);
List<ProdEquipSpecialCal> result = new ArrayList<>();
for (TimePeriod period : periods) {
ProdEquipSpecialCal specialCal = new ProdEquipSpecialCal();
specialCal.setId(String.valueOf(SnowFlackIdWorker.getId()));
specialCal.setSceneId(sceneId);
specialCal.setEquipId(capacity.getEquipId() != null ? capacity.getEquipId().intValue() : null);
specialCal.setEquipCode(capacity.getEquipCode());
specialCal.setStartDate(period.startTime);
specialCal.setEndDate(period.endTime);
specialCal.setPlanResourceId(capacity.getPlanResourceId());
specialCal.setEfficiencyCoeff(capacity.getEfficiencyCoeff() != null ? capacity.getEfficiencyCoeff() : 1);
specialCal.setCreatorUserId(capacity.getCreatorUserId());
specialCal.setCreationTime(LocalDateTime.now());
applyReference(capacity, specialCal);
result.add(specialCal);
}
return result;
}
private List<TimePeriod> parseTimePeriods(EquipShiftCapacity capacity) {
String periodsJson = firstNotBlank(capacity.getValidTimePeriods(),
capacity.getShiftTimePeriods(),
capacity.getSpecialTimePeriods(),
capacity.getHolidayTimePeriods());
List<TimePeriod> periods = parseTimePeriods(periodsJson);
if (periods.isEmpty() && capacity.getCapacityDate() != null) {
periods.add(new TimePeriod(capacity.getCapacityDate(),
capacity.getCapacityDate().plusDays(1).minusSeconds(1)));
}
return periods;
}
private List<TimePeriod> parseTimePeriods(String periodsJson) {
List<TimePeriod> periods = new ArrayList<>();
if (periodsJson == null || periodsJson.trim().isEmpty()) {
return periods;
}
try {
JSONArray array = JSONArray.parseArray(periodsJson);
for (int i = 0; i < array.size(); i++) {
JSONObject item = array.getJSONObject(i);
LocalDateTime startTime = parseDateTime(item.getString("StartTime"));
LocalDateTime endTime = parseDateTime(item.getString("EndTime"));
if (startTime != null && endTime != null && startTime.isBefore(endTime)) {
periods.add(new TimePeriod(startTime, endTime));
}
}
} catch (Exception e) {
log.warn("Parse equip shift capacity time periods failed: " + periodsJson + ", " + e.getMessage());
}
return periods;
}
private void applyReference(EquipShiftCapacity capacity, ProdEquipSpecialCal specialCal) {
if (capacity.getShiftId() != null) {
specialCal.setReferenceType(1);
specialCal.setReferenceId(capacity.getShiftId());
specialCal.setReferenceName(capacity.getShiftName());
specialCal.setPeriodDesc(capacity.getShiftName());
return;
}
if (capacity.getHolidayId() != null) {
specialCal.setReferenceType(2);
specialCal.setReferenceId(capacity.getHolidayId());
specialCal.setReferenceName(capacity.getHolidayName());
specialCal.setPeriodDesc(capacity.getHolidayName());
return;
}
if (capacity.getSpecialId() != null) {
specialCal.setReferenceType(3);
specialCal.setReferenceId(capacity.getSpecialId());
specialCal.setReferenceName(capacity.getSpecialName());
specialCal.setPeriodDesc(capacity.getSpecialName());
}
}
private LocalDateTime parseDateTime(String value) {
if (value == null || value.trim().isEmpty()) {
return null;
}
return LocalDateTime.parse(value.trim(), TIME_PERIOD_FORMATTER);
}
private String firstNotBlank(String... values) {
for (String value : values) {
if (value != null && !value.trim().isEmpty()) {
return value;
}
}
return null; return null;
} }
private void saveBatchIfNeeded(List<ProdEquipSpecialCal> specialCals) {
if (specialCals == null || specialCals.isEmpty()) {
return;
}
for (int i = 0; i < specialCals.size(); i += BATCH_SIZE) {
int end = Math.min(i + BATCH_SIZE, specialCals.size());
this.saveBatch(specialCals.subList(i, end), BATCH_SIZE);
}
}
private static class TimePeriod {
private final LocalDateTime startTime;
private final LocalDateTime endTime;
private TimePeriod(LocalDateTime startTime, LocalDateTime endTime) {
this.startTime = startTime;
this.endTime = endTime;
}
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment