|
@@ -192,7 +192,8 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
BigDecimal lastRunningTime = bom.getLastRunningTime(); // 上次保养运行时间
|
|
|
BigDecimal runningTimePeriod = bom.getNextRunningTime(); // 运行时间周期
|
|
|
BigDecimal timePeriodLead = bom.getTimePeriodLead(); // 运行时间周期提前量
|
|
|
- runningTimeDistance = (lastRunningTime.add(runningTimePeriod).subtract(timePeriodLead)).subtract(totalRunTime);
|
|
|
+ // runningTimeDistance = (lastRunningTime.add(runningTimePeriod).subtract(timePeriodLead)).subtract(totalRunTime);
|
|
|
+ runningTimeDistance = runningTimePeriod.subtract(totalRunTime.subtract(lastRunningTime));
|
|
|
}
|
|
|
}
|
|
|
if (0 == bom.getMileageRule()) {
|
|
@@ -202,7 +203,8 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
BigDecimal lastRunningKilo = bom.getLastRunningKilometers(); // 上次保养运行里程
|
|
|
BigDecimal runningKiloPeriod = bom.getNextRunningKilometers(); // 运行里程周期
|
|
|
BigDecimal kiloCycleLead = bom.getKiloCycleLead(); // 运行里程周期提前量
|
|
|
- runningKiloDistance = (lastRunningKilo.add(runningKiloPeriod).subtract(kiloCycleLead)).subtract(totalMileage);
|
|
|
+ // runningKiloDistance = (lastRunningKilo.add(runningKiloPeriod).subtract(kiloCycleLead)).subtract(totalMileage);
|
|
|
+ runningKiloDistance = runningKiloPeriod.subtract(totalMileage.subtract(lastRunningKilo));
|
|
|
}
|
|
|
}
|
|
|
if (0 == bom.getNaturalDateRule()) {
|
|
@@ -212,13 +214,13 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
BigDecimal natualDateLead = bom.getNaturalDatePeriodLead(); // 自然日周期提前量
|
|
|
if (ObjUtil.isNotEmpty(lastNaturalDate) && ObjUtil.isNotEmpty(naturalDatePeriod) && ObjUtil.isNotEmpty(natualDateLead)) {
|
|
|
// 计算有效天数 = 自然日周期 - 提前量
|
|
|
- long days = naturalDatePeriod.subtract(natualDateLead).longValue(); // 转为长整型天数
|
|
|
+ long days = naturalDatePeriod.longValue(); // 转为长整型天数
|
|
|
// 计算目标日期:上次保养日期 + 有效天数(注意:LocalDateTime加天数会自动处理日期进位)
|
|
|
LocalDateTime targetDate = lastNaturalDate.plusDays(days);
|
|
|
// 获取当前日期时间
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
// 计算日期差值(以天为单位)
|
|
|
- naturalDateDistance = new BigDecimal(ChronoUnit.DAYS.between(targetDate, now));
|
|
|
+ naturalDateDistance = new BigDecimal(ChronoUnit.DAYS.between(now, targetDate));
|
|
|
}
|
|
|
}
|
|
|
// 找出距离0最近的数,作为工单的最近保养距离数据
|
|
@@ -256,7 +258,8 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
BigDecimal lastRunningTime = bom.getLastRunningTime(); // 上次保养运行时间
|
|
|
BigDecimal runningTimePeriod = bom.getNextRunningTime(); // 运行时间周期
|
|
|
BigDecimal timePeriodLead = bom.getTimePeriodLead(); // 运行时间周期提前量
|
|
|
- runningTimeDistance = (lastRunningTime.add(runningTimePeriod).subtract(timePeriodLead)).subtract(totalRunTime);
|
|
|
+ // runningTimeDistance = (lastRunningTime.add(runningTimePeriod).subtract(timePeriodLead)).subtract(totalRunTime);
|
|
|
+ runningTimeDistance = runningTimePeriod.subtract(totalRunTime.subtract(lastRunningTime));
|
|
|
}
|
|
|
}
|
|
|
if (0 == bom.getMileageRule()) {
|
|
@@ -267,7 +270,8 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
BigDecimal lastRunningKilo = bom.getLastRunningKilometers(); // 上次保养运行里程
|
|
|
BigDecimal runningKiloPeriod = bom.getNextRunningKilometers(); // 运行里程周期
|
|
|
BigDecimal kiloCycleLead = bom.getKiloCycleLead(); // 运行里程周期提前量
|
|
|
- runningKiloDistance = (lastRunningKilo.add(runningKiloPeriod).subtract(kiloCycleLead)).subtract(totalMileage);
|
|
|
+ // runningKiloDistance = (lastRunningKilo.add(runningKiloPeriod).subtract(kiloCycleLead)).subtract(totalMileage);
|
|
|
+ runningKiloDistance = runningKiloPeriod.subtract(totalMileage.subtract(lastRunningKilo));
|
|
|
}
|
|
|
}
|
|
|
if (0 == bom.getNaturalDateRule()) {
|
|
@@ -277,13 +281,13 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
BigDecimal natualDateLead = bom.getNaturalDatePeriodLead(); // 自然日周期提前量
|
|
|
if (ObjUtil.isNotEmpty(lastNaturalDate) && ObjUtil.isNotEmpty(naturalDatePeriod) && ObjUtil.isNotEmpty(natualDateLead)) {
|
|
|
// 计算有效天数 = 自然日周期 - 提前量
|
|
|
- long days = naturalDatePeriod.subtract(natualDateLead).longValue(); // 转为长整型天数
|
|
|
+ long days = naturalDatePeriod.longValue(); // 转为长整型天数
|
|
|
// 计算目标日期:上次保养日期 + 有效天数(注意:LocalDateTime加天数会自动处理日期进位)
|
|
|
LocalDateTime targetDate = lastNaturalDate.plusDays(days);
|
|
|
// 获取当前日期时间
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
// 计算日期差值(以天为单位)
|
|
|
- naturalDateDistance = new BigDecimal(ChronoUnit.DAYS.between(targetDate, now));
|
|
|
+ naturalDateDistance = new BigDecimal(ChronoUnit.DAYS.between(now, targetDate));
|
|
|
}
|
|
|
}
|
|
|
// 找出距离0最近的数,作为工单的最近保养距离数据
|
|
@@ -363,7 +367,7 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
* @return
|
|
|
*/
|
|
|
private List<Long> sortByNumericValue(Map<Long, String> map) {
|
|
|
- return map.entrySet().stream()
|
|
|
+ /* return map.entrySet().stream()
|
|
|
// 转换数值并保留原始entry
|
|
|
.map(entry -> {
|
|
|
try {
|
|
@@ -385,6 +389,30 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
)
|
|
|
// 提取排序后的key
|
|
|
.map(AbstractMap.SimpleEntry::getKey)
|
|
|
+ .collect(Collectors.toList()); */
|
|
|
+ return map.entrySet().stream()
|
|
|
+ .map(entry -> {
|
|
|
+ String[] parts = entry.getValue().split("\\s+");
|
|
|
+ if (parts.length < 2) {
|
|
|
+ return new AbstractMap.SimpleEntry<>(entry.getKey(), Double.MAX_VALUE);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ BigDecimal value = new BigDecimal(parts[0]);
|
|
|
+ // 单位转换:H→天,KM/D保持不变
|
|
|
+ if ("H".equals(parts[1])) {
|
|
|
+ value = value.divide(BigDecimal.valueOf(24), 2, BigDecimal.ROUND_HALF_UP);
|
|
|
+ }
|
|
|
+ return new AbstractMap.SimpleEntry<>(entry.getKey(), value.doubleValue());
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ return new AbstractMap.SimpleEntry<>(entry.getKey(), Double.MAX_VALUE);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .sorted(Comparator
|
|
|
+ .<AbstractMap.SimpleEntry<Long, Double>>comparingDouble(AbstractMap.SimpleEntry::getValue) // 按转换值升序
|
|
|
+ .thenComparingLong(AbstractMap.SimpleEntry::getKey) // 值相同时按键升序
|
|
|
+ )
|
|
|
+ .map(AbstractMap.SimpleEntry::getKey)
|
|
|
.collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
@@ -395,30 +423,40 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
private Map<Long, String> findClosestToZero(Map<Long, List<Map<String, Object>>> orderDistancePair) {
|
|
|
Map<Long, String> result = new HashMap<>();
|
|
|
for (Map.Entry<Long, List<Map<String, Object>>> entry : orderDistancePair.entrySet()) {
|
|
|
- Long key = entry.getKey();
|
|
|
+ Long workOrderId = entry.getKey();
|
|
|
List<Map<String, Object>> mapList = entry.getValue();
|
|
|
-
|
|
|
- // 初始化最小距离和对应的Map
|
|
|
- BigDecimal minAbsDistance = null;
|
|
|
- Map<String, Object> closestMap = null;
|
|
|
-
|
|
|
- for (Map<String, Object> currentMap : mapList) {
|
|
|
- // 计算当前Map所有值的最小绝对值
|
|
|
- BigDecimal currentMinAbs = calculateMinAbsolute(currentMap);
|
|
|
-
|
|
|
- // 跳过无效Map(无有效值)
|
|
|
- if (currentMinAbs == null) continue;
|
|
|
-
|
|
|
- // 比较并更新最小值
|
|
|
- if (minAbsDistance == null || currentMinAbs.compareTo(minAbsDistance) < 0) {
|
|
|
- minAbsDistance = currentMinAbs;
|
|
|
- closestMap = currentMap;
|
|
|
+ // 存储所有有效值(原始值、单位、转换值)
|
|
|
+ List<Triple<BigDecimal, String, BigDecimal>> allValues = new ArrayList<>();
|
|
|
+ // 收集所有值并进行单位转换
|
|
|
+ for (Map<String, Object> map : mapList) {
|
|
|
+ for (Map.Entry<String, Object> valueEntry : map.entrySet()) {
|
|
|
+ if (valueEntry.getValue() instanceof BigDecimal) {
|
|
|
+ BigDecimal value = (BigDecimal) valueEntry.getValue();
|
|
|
+ String unit = valueEntry.getKey();
|
|
|
+ BigDecimal convertedValue;
|
|
|
+ // 小时转换为天
|
|
|
+ if ("H".equals(unit)) {
|
|
|
+ convertedValue = value.divide(BigDecimal.valueOf(24), 2, BigDecimal.ROUND_HALF_UP);
|
|
|
+ } else {
|
|
|
+ convertedValue = value;
|
|
|
+ }
|
|
|
+ allValues.add(new Triple<>(value, unit, convertedValue));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- // 将有效结果放入最终Map
|
|
|
- if (closestMap != null) {
|
|
|
- result.put(key, convertMapToString(closestMap));
|
|
|
+ // 如果没有有效值,跳过
|
|
|
+ if (allValues.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 找到转换后值最小的值
|
|
|
+ Triple<BigDecimal, String, BigDecimal> minTriple = allValues.get(0);
|
|
|
+ for (Triple<BigDecimal, String, BigDecimal> triple : allValues) {
|
|
|
+ if (triple.getThird().compareTo(minTriple.getThird()) < 0) {
|
|
|
+ minTriple = triple;
|
|
|
+ }
|
|
|
}
|
|
|
+ // 格式化为字符串: "原始值 单位"
|
|
|
+ result.put(workOrderId, minTriple.getFirst() + " " + minTriple.getSecond());
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
@@ -473,50 +511,32 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
* @return
|
|
|
*/
|
|
|
private BigDecimal chooseNearestDistance(BigDecimal runningTimeDistance, BigDecimal runningKiloDistance, BigDecimal naturalDateDistance) {
|
|
|
- // 存储当前找到的最小绝对值的变量
|
|
|
- BigDecimal closest = null;
|
|
|
- // 存储当前最小绝对值(BigDecimal 类型)
|
|
|
- BigDecimal minAbs = null;
|
|
|
- // 比较第一个变量
|
|
|
+ List<Triple<BigDecimal, String, BigDecimal>> values = new ArrayList<>();
|
|
|
if (runningTimeDistance != null) {
|
|
|
- closest = runningTimeDistance;
|
|
|
- minAbs = runningTimeDistance.abs();
|
|
|
+ // 转换为天数用于比较,但保留原始值
|
|
|
+ BigDecimal converted = runningTimeDistance.divide(BigDecimal.valueOf(24), 2, BigDecimal.ROUND_HALF_UP);
|
|
|
+ values.add(new Triple<>(runningTimeDistance, "H", converted));
|
|
|
}
|
|
|
- // 比较第二个变量
|
|
|
if (runningKiloDistance != null) {
|
|
|
- if (minAbs == null) {
|
|
|
- // 如果之前没有有效值,直接使用 b
|
|
|
- closest = runningKiloDistance;
|
|
|
- minAbs = runningKiloDistance.abs();
|
|
|
- } else {
|
|
|
- // 比较绝对值大小
|
|
|
- BigDecimal absB = runningKiloDistance.abs();
|
|
|
- int cmp = absB.compareTo(minAbs);
|
|
|
- if (cmp < 0 || (cmp == 0 && runningKiloDistance.compareTo(closest) > 0)) {
|
|
|
- // 如果 b 的绝对值更小,或绝对值相等但 b 是正数(更大值表示正数)
|
|
|
- closest = runningKiloDistance;
|
|
|
- minAbs = absB;
|
|
|
- }
|
|
|
- }
|
|
|
+ // 公里值不转换
|
|
|
+ values.add(new Triple<>(runningKiloDistance, "KM", runningKiloDistance));
|
|
|
}
|
|
|
- // 比较第三个变量
|
|
|
if (naturalDateDistance != null) {
|
|
|
- if (minAbs == null) {
|
|
|
- // 如果之前没有有效值,直接使用 c
|
|
|
- closest = naturalDateDistance;
|
|
|
- minAbs = naturalDateDistance.abs();
|
|
|
- } else {
|
|
|
- // 比较绝对值大小
|
|
|
- BigDecimal absC = naturalDateDistance.abs();
|
|
|
- int cmp = absC.compareTo(minAbs);
|
|
|
- if (cmp < 0 || (cmp == 0 && naturalDateDistance.compareTo(closest) > 0)) {
|
|
|
- // 如果 c 的绝对值更小,或绝对值相等但 c 是正数
|
|
|
- closest = naturalDateDistance;
|
|
|
- minAbs = absC;
|
|
|
- }
|
|
|
+ // 自然日值不转换
|
|
|
+ values.add(new Triple<>(naturalDateDistance, "D", naturalDateDistance));
|
|
|
+ }
|
|
|
+ // 如果没有有效值,返回null
|
|
|
+ if (values.isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ // 找到转换后值最小的原始值
|
|
|
+ Triple<BigDecimal, String, BigDecimal> minTriple = values.get(0);
|
|
|
+ for (Triple<BigDecimal, String, BigDecimal> triple : values) {
|
|
|
+ if (triple.getThird().compareTo(minTriple.getThird()) < 0) {
|
|
|
+ minTriple = triple;
|
|
|
}
|
|
|
}
|
|
|
- return closest; // 可能返回 null(当所有输入均为 null 时)
|
|
|
+ return minTriple.getFirst(); // 返回原始值
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -612,7 +632,7 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
mainCompleted.set(false);
|
|
|
}
|
|
|
if (bom.getDelayKilometers().compareTo(BigDecimal.ZERO)==0
|
|
|
- || bom.getDelayDuration().compareTo(BigDecimal.ZERO)==0 || bom.getDelayNaturalDate().compareTo(BigDecimal.ZERO)==0) {
|
|
|
+ && bom.getDelayDuration().compareTo(BigDecimal.ZERO)==0 && bom.getDelayNaturalDate().compareTo(BigDecimal.ZERO)==0) {
|
|
|
// 如果保养项没有设置延时保养 则查询当前设备的 累计运行公里数 累计运行时间 当前时间日期 赋值到 关联保养计划 明细 的 对应保养规则数据上
|
|
|
deviceIds.add(bom.getDeviceId());
|
|
|
// 保养项下如果已经添加了物料 说明该保养项已经保养完成
|
|
@@ -672,26 +692,28 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- // 将当前工单的关联工单 一并关闭 是否需要将当前工单选择的物料及费用也复制到 关联工单?
|
|
|
- IotMainWorkOrderPageReqVO orderReqVO = new IotMainWorkOrderPageReqVO();
|
|
|
- orderReqVO.setOrderGroupId(updateObj.getOrderGroupId());
|
|
|
- List<IotMainWorkOrderDO> associateOrders = iotMainWorkOrderMapper.selectList(orderReqVO);
|
|
|
- List<IotMainWorkOrderDO> filteredOrders = associateOrders.stream()
|
|
|
- .filter(order -> !order.getId().equals(updateObj.getId()))
|
|
|
- .collect(Collectors.toList());
|
|
|
- if (CollUtil.isNotEmpty(filteredOrders)) {
|
|
|
- // 将关联工单设置为 已执行 直接删除
|
|
|
- filteredOrders.forEach(order -> {order.setResult(2); order.setDeleted(true);});
|
|
|
- iotMainWorkOrderMapper.updateBatch(filteredOrders);
|
|
|
- List<Long> workOrderIds = filteredOrders.stream()
|
|
|
- .map(IotMainWorkOrderDO::getId)
|
|
|
+ // 如果当前工单已经关闭,需要同时将当前工单的关联工单 一并关闭 是否需要将当前工单选择的物料及费用也复制到 关联工单?
|
|
|
+ if (2 == updateObj.getResult()) {
|
|
|
+ IotMainWorkOrderPageReqVO orderReqVO = new IotMainWorkOrderPageReqVO();
|
|
|
+ orderReqVO.setOrderGroupId(updateObj.getOrderGroupId());
|
|
|
+ List<IotMainWorkOrderDO> associateOrders = iotMainWorkOrderMapper.selectList(orderReqVO);
|
|
|
+ List<IotMainWorkOrderDO> filteredOrders = associateOrders.stream()
|
|
|
+ .filter(order -> !order.getId().equals(updateObj.getId()))
|
|
|
.collect(Collectors.toList());
|
|
|
- // 将关联工单的明细 status 设置为 1
|
|
|
- IotMainWorkOrderBomPageReqVO reqVO = new IotMainWorkOrderBomPageReqVO();
|
|
|
- reqVO.setWorkOrderIds(workOrderIds);
|
|
|
- List<IotMainWorkOrderBomDO> associateOrderBomS = iotMainWorkOrderBomMapper.selectList(reqVO);
|
|
|
- associateOrderBomS.forEach(order -> order.setStatus(1));
|
|
|
- iotMainWorkOrderBomMapper.updateBatch(associateOrderBomS);
|
|
|
+ if (CollUtil.isNotEmpty(filteredOrders)) {
|
|
|
+ // 将关联工单设置为 已执行 直接删除
|
|
|
+ filteredOrders.forEach(order -> {order.setResult(2); order.setDeleted(true);});
|
|
|
+ iotMainWorkOrderMapper.updateBatch(filteredOrders);
|
|
|
+ List<Long> workOrderIds = filteredOrders.stream()
|
|
|
+ .map(IotMainWorkOrderDO::getId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ // 将关联工单的明细 status 设置为 1
|
|
|
+ IotMainWorkOrderBomPageReqVO reqVO = new IotMainWorkOrderBomPageReqVO();
|
|
|
+ reqVO.setWorkOrderIds(workOrderIds);
|
|
|
+ List<IotMainWorkOrderBomDO> associateOrderBomS = iotMainWorkOrderBomMapper.selectList(reqVO);
|
|
|
+ associateOrderBomS.forEach(order -> order.setStatus(1));
|
|
|
+ iotMainWorkOrderBomMapper.updateBatch(associateOrderBomS);
|
|
|
+ }
|
|
|
}
|
|
|
// 只扣减本地库存 不处理SAP库存
|
|
|
if (CollUtil.isNotEmpty(factoryIds) && CollUtil.isNotEmpty(costCenterIds) && CollUtil.isNotEmpty(materialCodes)) {
|
|
@@ -859,4 +881,27 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
|
|
|
return workOrderResp;
|
|
|
}
|
|
|
|
|
|
+ private static class Triple<A, B, C> {
|
|
|
+ private final A first;
|
|
|
+ private final B second;
|
|
|
+ private final C third;
|
|
|
+
|
|
|
+ public Triple(A first, B second, C third) {
|
|
|
+ this.first = first;
|
|
|
+ this.second = second;
|
|
|
+ this.third = third;
|
|
|
+ }
|
|
|
+
|
|
|
+ public A getFirst() {
|
|
|
+ return first;
|
|
|
+ }
|
|
|
+
|
|
|
+ public B getSecond() {
|
|
|
+ return second;
|
|
|
+ }
|
|
|
+
|
|
|
+ public C getThird() {
|
|
|
+ return third;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|