日历

parent 97f10b74
......@@ -3,6 +3,8 @@ package com.aps.service;
import com.aps.entity.ProdEquipSpecialCal;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.Collection;
/**
* <p>
* 设备特殊日历配置表:记录特定工位/设备在指定时间段的特殊日历规则(如节假日、维护期等) 服务类
......@@ -18,4 +20,19 @@ public interface ProdEquipSpecialCalService extends IService<ProdEquipSpecialCal
*/
void copyFromEquipCapacityDef(String sceneId);
}
\ No newline at end of file
/**
* 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 {
}
sceneId = sceneConfig.getSceneId();
prodEquipSpecialCalService.copyFromEquipCapacityDef(sceneId);
List<MesSchedule> mesSchedules = mesScheduleService.lambdaQuery()
.eq(MesSchedule::getIsDeleted, 0)
.eq(MesSchedule::getScheduleUserId, username)
......@@ -844,6 +841,11 @@ public class LanuchServiceImpl implements LanuchService {
}
if (!CollectionUtils.isEmpty(allProdEquipments)) {
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());
......
package com.aps.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aps.common.util.SnowFlackIdWorker;
import com.aps.entity.ProdEquipSpecialCal;
import com.aps.entity.EquipCapacityDef;
import com.aps.entity.EquipShiftCapacity;
import com.aps.entity.ProdEquipSpecialCal;
import com.aps.mapper.ProdEquipSpecialCalMapper;
import com.aps.service.ProdEquipSpecialCalService;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
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.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* <p>
* 设备特殊日历配置表:记录特定工位/设备在指定时间段的特殊日历规则(如节假日、维护期等) 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-11-26
*/
@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
private EquipCapacityDefService equipCapacityDefService;
/**
* 从EquipCapacityDef表中复制is_deleted为0的数据到ProdEquipSpecialCal表
*/
@Autowired
private EquipShiftCapacityService equipShiftCapacityService;
@Override
public void copyFromEquipCapacityDef(String sceneId) {
// 直接通过条件查询,而不是全表查询后过滤
List<EquipCapacityDef> activeCapacityDefs = equipCapacityDefService.lambdaQuery()
.eq(EquipCapacityDef::getIsDeleted, 0)
.isNotNull(EquipCapacityDef::getReferenceId)
.isNotNull(EquipCapacityDef::getEquipId) // 过滤掉 equipId 为 null 的记录
.isNotNull(EquipCapacityDef::getEquipId)
.list();
// 转换对象并设置必要字段
List<ProdEquipSpecialCal> specialCals = activeCapacityDefs.stream()
.map(capacityDef -> convertToProdEquipSpecialCal(capacityDef, sceneId))
.filter(Objects::nonNull) // 过滤掉转换失败的对象
.filter(Objects::nonNull)
.collect(Collectors.toList());
saveBatchIfNeeded(specialCals);
}
// 批量保存到ProdEquipSpecialCal表
if (!specialCals.isEmpty()) {
// 使用分批插入,避免单次插入过多数据
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) {
copyFromEquipShiftCapacity(sceneId, null);
}
@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) {
try {
ProdEquipSpecialCal specialCal = new ProdEquipSpecialCal();
// 设置必填字段,确保不会为空
specialCal.setId(String.valueOf(SnowFlackIdWorker.getId()));
specialCal.setSceneId(sceneId); // sceneId不能为空
// 可选字段的安全转换
specialCal.setSceneId(sceneId);
specialCal.setEquipId(capacityDef.getEquipId() != null ? capacityDef.getEquipId().intValue() : null);
specialCal.setEquipCode(capacityDef.getEquipCode());
specialCal.setStartDate(capacityDef.getEffectiveStartTime());
specialCal.setEndDate(capacityDef.getEffectiveEndTime());
specialCal.setPlanResourceId(capacityDef.getPlanResourceId());
specialCal.setPlanResourceId(capacityDef.getPlanResourceId());
// 处理数值类型转换的空值
if (capacityDef.getEfficiencyCoeff() != null) {
specialCal.setEfficiencyCoeff(capacityDef.getEfficiencyCoeff().doubleValue());
}else {
specialCal.setEfficiencyCoeff(1);
}
specialCal.setEfficiencyCoeff(capacityDef.getEfficiencyCoeff() != null
? capacityDef.getEfficiencyCoeff().doubleValue()
: 1);
specialCal.setReferenceId(capacityDef.getReferenceId());
specialCal.setReferenceName(capacityDef.getReferenceName());
specialCal.setCreatorUserId(capacityDef.getCreatorUserId());
specialCal.setCreationTime(LocalDateTime.now());
specialCal.setReferenceType(capacityDef.getReferenceType());
return specialCal;
} 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;
}
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;
}
}
}
\ No newline at end of file
}
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