fix: 修复自动插单排程异常

parent 74589725
......@@ -388,6 +388,13 @@ public class IdGroupingWithDualSerial {
* @return 包含新分组的结果列表
*/
public static List<GroupResult> addNewDataWithIsolatedGroup(List<GroupResult> existingResults, List<String> newIdList, List<String> newChildIdList) {
return addNewDataWithIsolatedGroup(existingResults, newIdList, newChildIdList, 1);
}
public static List<GroupResult> addNewDataWithIsolatedGroup(List<GroupResult> existingResults,
List<String> newIdList,
List<String> newChildIdList,
int minimumGlobalSerial) {
// 空值安全检查
if (newIdList == null || newIdList.isEmpty()) {
return existingResults;
......@@ -428,6 +435,7 @@ public class IdGroupingWithDualSerial {
.mapToInt(NodeInfo::getGlobalSerial)
.max()
.orElse(0);
maxGlobalSerial = Math.max(maxGlobalSerial, Math.max(1, minimumGlobalSerial) - 1);
int[] globalCounter = {maxGlobalSerial + 1};
// 4. 为每个连通分量创建独立分组
......
......@@ -1240,6 +1240,7 @@ if(targetOp.getSequence()>1) {
ProdLaunchOrder newLaunchOrder, List<ProdProcessExec> newProcessExecs,
List<ProdEquipment> newProdEquipments,
LocalDateTime anchorTime, GlobalParam globalParam) {
pinFrozenResults(chromosome, anchorTime);
List<Order> orders = chromosome.getOrders();
List<GroupResult> OperatRels = chromosome.getOperatRel();
......@@ -1257,12 +1258,11 @@ if(targetOp.getSequence()>1) {
newOrder.setRoutingCode(newLaunchOrder.getRoutingCode());
newOrder.setSerie(newLaunchOrder.getSerie());
int maxOrderId = orders.stream().mapToInt(Order::getId).max().orElse(0) + 1;
newOrder.setId(maxOrderId);
int newGroupId = resolveNextAutoInsertGroupId(chromosome);
newOrder.setId(newGroupId);
orders.add(newOrder);
int maxGroupId = OperatRels.size();
int newGroupId = maxGroupId + 1;
padOperationRelations(OperatRels, newGroupId);
List<Entry> newEntrys = new ArrayList<>();
List<String> newIdList = new ArrayList<>();
......@@ -1357,7 +1357,12 @@ if(targetOp.getSequence()>1) {
}
}
OperatRels = IdGroupingWithDualSerial.addNewDataWithIsolatedGroup(OperatRels, newIdList, newChildIdList);
int nextOperationId = chromosome.getAllOperations().stream()
.mapToInt(Entry::getId)
.max()
.orElse(0) + 1;
OperatRels = IdGroupingWithDualSerial.addNewDataWithIsolatedGroup(
OperatRels, newIdList, newChildIdList, nextOperationId);
chromosome.setOperatRel(new CopyOnWriteArrayList<>(OperatRels));
int globalOpId = chromosome.getGlobalOpList().stream()
......@@ -1531,6 +1536,56 @@ if(targetOp.getSequence()>1) {
globalParam.setIsCheckSf(originalIsCheckSf);
}
private void pinFrozenResults(Chromosome chromosome, LocalDateTime anchorTime) {
if (chromosome == null || chromosome.getBaseTime() == null || anchorTime == null
|| chromosome.getResult() == null || chromosome.getResult().isEmpty()) {
return;
}
int anchorSeconds = (int) java.time.temporal.ChronoUnit.SECONDS.between(
chromosome.getBaseTime(), anchorTime);
Map<Integer, Entry> entriesById = chromosome.getAllOperations() == null
? Collections.emptyMap()
: chromosome.getAllOperations().stream()
.collect(Collectors.toMap(Entry::getId, entry -> entry, (left, right) -> left));
int pinnedCount = 0;
for (GAScheduleResult result : chromosome.getResult()) {
if (result == null || result.getStartTime() >= anchorSeconds) {
continue;
}
result.setLockStartTime(1);
result.setDesignatedStartTime(result.getStartTime());
result.setForcedMachineId(result.getMachineId());
Entry entry = entriesById.get(result.getOperationId());
if (entry != null) {
entry.setDesignatedStartTime(chromosome.getBaseTime().plusSeconds(result.getStartTime()));
}
pinnedCount++;
}
}
private int resolveNextAutoInsertGroupId(Chromosome chromosome) {
int maxOrderId = chromosome.getOrders() == null
? 0
: chromosome.getOrders().stream().mapToInt(Order::getId).max().orElse(0);
int maxEntryGroupId = chromosome.getAllOperations() == null
? 0
: chromosome.getAllOperations().stream().mapToInt(Entry::getGroupId).max().orElse(0);
int maxResultGroupId = chromosome.getResult() == null
? 0
: chromosome.getResult().stream().mapToInt(GAScheduleResult::getGroupId).max().orElse(0);
int relationCount = chromosome.getOperatRel() == null ? 0 : chromosome.getOperatRel().size();
return Math.max(Math.max(maxOrderId, maxEntryGroupId), Math.max(maxResultGroupId, relationCount)) + 1;
}
private void padOperationRelations(List<GroupResult> operationRelations, int newGroupId) {
while (operationRelations.size() < newGroupId - 1) {
operationRelations.add(new GroupResult(new ArrayList<>(), new HashMap<>()));
}
}
private int calcBestMachineSeq(Entry entry, Chromosome chromosome, LocalDateTime anchorTime) {
List<MachineOption> rawOptions = entry.getMachineOptions();
if (rawOptions == null || rawOptions.isEmpty()) {
......
......@@ -2066,12 +2066,11 @@ public class LanuchServiceImpl implements LanuchService {
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Optional<RoutingHeader> sceneRouting = candidates.stream()
.filter(header -> sceneRoutingIds.contains(header.getId()))
.filter(this::hasResolvableProcessResources)
.findFirst();
if (sceneRouting.isPresent()) {
return sceneRouting.get();
RoutingHeader sceneRouting = selectExistingSceneRouting(candidates, sceneRoutingIds);
if (sceneRouting != null) {
log.info("Auto insert reuses existing routing: sceneId={}, materialId={}, routingId={}, routingCode={}",
sceneId, materialId, sceneRouting.getId(), sceneRouting.getCode());
return sceneRouting;
}
Optional<RoutingHeader> namedValidRouting = candidates.stream()
......@@ -2088,6 +2087,17 @@ public class LanuchServiceImpl implements LanuchService {
return anyValidRouting.orElse(candidates.get(0));
}
static RoutingHeader selectExistingSceneRouting(List<RoutingHeader> candidates, Set<Integer> sceneRoutingIds) {
if (CollectionUtils.isEmpty(candidates) || CollectionUtils.isEmpty(sceneRoutingIds)) {
return null;
}
return candidates.stream()
.filter(Objects::nonNull)
.filter(header -> sceneRoutingIds.contains(header.getId()))
.findFirst()
.orElse(null);
}
private boolean hasResolvableProcessResources(RoutingHeader routingHeader) {
if (routingHeader == null || routingHeader.getId() == null) {
return false;
......
......@@ -344,7 +344,7 @@ public class LockedOrderProcessorService {
// 深拷贝工单并转换时间
GAScheduleResult lockedResult = copyGAScheduleResult(result);
lockedResult.setIsLocked(false); // 重要:标记为锁定工单,确保重新解码时不被清除
lockedResult.setIsLocked(false); // 仍参与解码,通过固定开始时间保持原排程
// 转换时间:从旧baseTime转换到新baseTime
LocalDateTime prevStartTime = oldBaseTime.plusSeconds(result.getStartTime());
......@@ -1464,4 +1464,4 @@ public class LockedOrderProcessorService {
Map<String, Entry> entries = new HashMap<>();
Set<Long> machineIds = new HashSet<>();
}
}
\ No newline at end of file
}
......@@ -1362,7 +1362,7 @@ public class PlanResultService {
ScheduleOperation.dragOperation(chromosome,opId,targetopId,isfront,newMachineId, globalParam);
// WriteScheduleSummary(chromosome);
_sceneService.saveChromosomeToFile(chromosome, SceneId);
saveChromosomeOrThrow(chromosome, SceneId, "drag operation");
return chromosome;
}
/**
......@@ -1492,9 +1492,12 @@ public class PlanResultService {
throw new RuntimeException("quantity 不能为空");
}
Double quantity = Double.valueOf(String.valueOf(qtyObj));
LocalDateTime startDate = parseOrderDateTime(newOrderData.get("startDate"));
LocalDateTime endDate = parseOrderDateTime(newOrderData.get("endDate"));
Integer priority = parseOrderPriority(newOrderData.get("priority"));
LocalDateTime startDate = parseOrderDateTime(
getFirstStringValue(newOrderData, "startDate", "begintime", "beginTime"));
LocalDateTime endDate = parseOrderDateTime(
getFirstStringValue(newOrderData, "endDate", "deliverytime", "deliveryTime"));
Integer priority = parseOrderPriority(
getFirstStringValue(newOrderData, "priority", "prioritry"));
// 1. 创建新订单(沿用现有创建逻辑)
R<String> insertResp = lanuchService.insertOrder(sceneId, orderCode, materialId,
......@@ -1552,7 +1555,6 @@ public class PlanResultService {
if (newProdEquipments == null || newProdEquipments.isEmpty()) {
throw new RuntimeException("自动插单失败:新工单未生成可选设备,请检查PROD_EQUIPMENT");
}
// 4. 计算锚点时间:基准时间 + 冻结期
LocalDateTime baseTime = chromosome.getBaseTime();
LambdaQueryWrapper<ApsTimeConfig> queryWrapper = new LambdaQueryWrapper<>();
......@@ -1587,7 +1589,7 @@ public class PlanResultService {
// 6. 保存
WriteScheduleSummary(chromosome);
_sceneService.saveChromosomeToFile(chromosome, sceneId);
saveChromosomeOrThrow(chromosome, sceneId, "auto insert order");
return chromosome;
}
......@@ -1659,7 +1661,7 @@ public class PlanResultService {
ScheduleOperation.moveOperation(chromosome,opId, (int)ChronoUnit.SECONDS.between(chromosome.getBaseTime(), newStartTime),newMachineId, globalParam, lockStartTime);
// WriteScheduleSummary(chromosome);
_sceneService.saveChromosomeToFile(chromosome, SceneId);
saveChromosomeOrThrow(chromosome, SceneId, "move operation");
return chromosome;
}
......@@ -1870,10 +1872,16 @@ public class PlanResultService {
scheduleOperation.InsertOrder(chromosome, afterOrderId, newOrderId, newLaunchOrder, newProcessExecs, globalParam);
WriteScheduleSummary(chromosome);
_sceneService.saveChromosomeToFile(chromosome, SceneId);
saveChromosomeOrThrow(chromosome, SceneId, "insert order");
return chromosome;
}
private void saveChromosomeOrThrow(Chromosome chromosome, String sceneId, String operationName) {
if (!_sceneService.saveChromosomeToFile(chromosome, sceneId)) {
throw new RuntimeException(operationName + " failed: unable to save schedule version");
}
}
public Chromosome MergeOrder(String SceneId,String sourceorderId,String targetorderId) {
Chromosome chromosome= _sceneService.loadChromosomeFromFile(SceneId);
......
......@@ -16,7 +16,10 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
......@@ -42,6 +45,7 @@ public class SceneService {
private RedisUtils redisUtils;
private final ObjectMapper objectMapper = createObjectMapper();
private final Map<String, Object> sceneLocks = new ConcurrentHashMap<>();
private ObjectMapper createObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
......@@ -154,38 +158,38 @@ public class SceneService {
return false;
}
try {
Object sceneLock = sceneLocks.computeIfAbsent(sceneId, key -> new Object());
synchronized (sceneLock) {
try {
ObjectMapper objectMapper = createObjectMapper();
SceneChromsome sceneChromsome = (SceneChromsome) redisUtils.get("SceneId." + sceneId);
Integer nextVersion;
List<SceneDetail> retainedDetails = new ArrayList<>();
if (sceneChromsome == null) {
sceneChromsome = new SceneChromsome();
sceneChromsome.setSceneID(sceneId);
sceneChromsome.setVersion(1);
nextVersion = 1;
} else {
Integer currentVersion = sceneChromsome.getVersion();
List<SceneDetail> nextVersions = sceneChromsome.getSceneDetails().stream()
.filter(detail -> detail.getVersion() > currentVersion)
.collect(Collectors.toList());
if (!nextVersions.isEmpty()) {
for (SceneDetail detail : nextVersions) {
File nextFile = getChromosomeFile(sceneId, detail.getVersion().toString());
Files.deleteIfExists(nextFile.toPath());
}
if (currentVersion == null) {
currentVersion = 0;
}
nextVersion = currentVersion + 1;
if (sceneChromsome.getSceneDetails() != null) {
Integer finalCurrentVersion = currentVersion;
retainedDetails.addAll(sceneChromsome.getSceneDetails().stream()
.filter(detail -> detail != null
&& detail.getVersion() != null
&& detail.getVersion() <= finalCurrentVersion)
.collect(Collectors.toList()));
}
sceneChromsome.getSceneDetails().removeIf(detail -> detail.getVersion() > currentVersion);
sceneChromsome.setVersion(sceneChromsome.getVersion() + 1);
}
SceneDetail sceneDetail = new SceneDetail();
sceneDetail.setVersion(sceneChromsome.getVersion());
sceneChromsome.getSceneDetails().add(sceneDetail);
redisUtils.set("SceneId." + sceneId, sceneChromsome);
File file = getChromosomeFile(sceneId, sceneChromsome.getVersion().toString());
File file = getChromosomeFile(sceneId, nextVersion.toString());
File tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
chromosome.setVersion(sceneChromsome.getVersion());
chromosome.setVersion(nextVersion);
if (useCompression) {
try (FileOutputStream fos = new FileOutputStream(tempFile);
GZIPOutputStream gzos = new GZIPOutputStream(fos)) {
......@@ -227,11 +231,28 @@ public class SceneService {
}
Files.move(tempFile.toPath(), file.toPath());
if (sceneChromsome.getSceneDetails() != null) {
for (SceneDetail detail : sceneChromsome.getSceneDetails()) {
if (detail != null && detail.getVersion() != null && detail.getVersion() > nextVersion) {
File futureFile = getChromosomeFile(sceneId, detail.getVersion().toString());
Files.deleteIfExists(futureFile.toPath());
}
}
}
SceneDetail sceneDetail = new SceneDetail();
sceneDetail.setVersion(nextVersion);
retainedDetails.add(sceneDetail);
sceneChromsome.setVersion(nextVersion);
sceneChromsome.setSceneDetails(retainedDetails);
redisUtils.set("SceneId." + sceneId, sceneChromsome);
logger.info("染色体保存成功,场景ID: {}, 文件: {}", sceneId, file.getAbsolutePath());
return true;
} catch (Exception e) {
logger.error("保存染色体文件失败,场景ID: " + sceneId, e);
return false;
} catch (Exception e) {
logger.error("保存染色体文件失败,场景ID: " + sceneId, e);
return false;
}
}
}
......
package com.aps.demo;
import com.aps.service.plan.PlanResultService;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
class AutoInsertPayloadTest {
@Test
void autoInsertPayloadSupportsFrontendDateAndPriorityAliases() {
PlanResultService service = new PlanResultService();
Map<String, Object> payload = new HashMap<>();
payload.put("begintime", "2026-07-01T00:00:00.000Z");
payload.put("deliverytime", "2026-07-31T00:00:00.000Z");
payload.put("prioritry", "3");
String startText = ReflectionTestUtils.invokeMethod(
service, "getFirstStringValue", payload, new String[]{"startDate", "begintime", "beginTime"});
String endText = ReflectionTestUtils.invokeMethod(
service, "getFirstStringValue", payload, new String[]{"endDate", "deliverytime", "deliveryTime"});
String priorityText = ReflectionTestUtils.invokeMethod(
service, "getFirstStringValue", payload, new String[]{"priority", "prioritry"});
LocalDateTime start = ReflectionTestUtils.invokeMethod(service, "parseOrderDateTime", startText);
LocalDateTime end = ReflectionTestUtils.invokeMethod(service, "parseOrderDateTime", endText);
Integer priority = ReflectionTestUtils.invokeMethod(service, "parseOrderPriority", priorityText);
assertEquals(LocalDateTime.of(2026, 7, 1, 0, 0), start);
assertEquals(LocalDateTime.of(2026, 7, 31, 0, 0), end);
assertEquals(Integer.valueOf(3), priority);
}
}
package com.aps.demo;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GAScheduleResult;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.Algorithm.IDAndChildID.NodeInfo;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.Order;
import com.aps.service.Algorithm.IdGroupingWithDualSerial;
import com.aps.service.Algorithm.ScheduleOperationService;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import static org.junit.jupiter.api.Assertions.assertEquals;
class AutoInsertProtectionTest {
@Test
void frozenResultIsPinnedBeforeAutoInsertRedecode() {
LocalDateTime baseTime = LocalDateTime.of(2026, 5, 1, 0, 0);
Chromosome chromosome = new Chromosome();
chromosome.setBaseTime(baseTime);
Entry frozenEntry = new Entry();
frozenEntry.setId(10);
chromosome.setAllOperations(new CopyOnWriteArrayList<>(Arrays.asList(frozenEntry)));
GAScheduleResult frozenResult = new GAScheduleResult();
frozenResult.setOperationId(10);
frozenResult.setMachineId(31L);
frozenResult.setStartTime(3600);
GAScheduleResult futureResult = new GAScheduleResult();
futureResult.setOperationId(11);
futureResult.setMachineId(32L);
futureResult.setStartTime(20000);
chromosome.setResult(new CopyOnWriteArrayList<>(Arrays.asList(frozenResult, futureResult)));
ScheduleOperationService service = new ScheduleOperationService(null, null);
ReflectionTestUtils.invokeMethod(service, "pinFrozenResults", chromosome, baseTime.plusSeconds(10000));
assertEquals(1, frozenResult.getLockStartTime());
assertEquals(3600, frozenResult.getDesignatedStartTime());
assertEquals(Long.valueOf(31L), frozenResult.getForcedMachineId());
assertEquals(baseTime.plusSeconds(3600), frozenEntry.getDesignatedStartTime());
assertEquals(0, futureResult.getLockStartTime());
}
@Test
void autoInsertOperationIdsStartAfterExistingChromosomeOperations() {
NodeInfo existingNode = new NodeInfo("old", 3, 1, new ArrayList<>(), new ArrayList<>());
List<GroupResult> relations = new ArrayList<>(Collections.singletonList(
new GroupResult(new ArrayList<>(Collections.singletonList(existingNode)), new HashMap<>())));
List<GroupResult> updated = IdGroupingWithDualSerial.addNewDataWithIsolatedGroup(
relations,
Collections.singletonList("new"),
Collections.singletonList(""),
12);
GroupResult insertedGroup = updated.get(updated.size() - 1);
assertEquals(Integer.valueOf(12), insertedGroup.getNodeInfoList().get(0).getGlobalSerial());
}
@Test
void autoInsertGroupIdStartsAfterExistingOrderEntryAndResultGroups() {
Chromosome chromosome = new Chromosome();
Order order = new Order();
order.setId(3);
chromosome.setOrders(new CopyOnWriteArrayList<>(Collections.singletonList(order)));
Entry entry = new Entry();
entry.setGroupId(4);
chromosome.setAllOperations(new CopyOnWriteArrayList<>(Collections.singletonList(entry)));
GAScheduleResult result = new GAScheduleResult();
result.setGroupId(4);
chromosome.setResult(new CopyOnWriteArrayList<>(Collections.singletonList(result)));
chromosome.setOperatRel(new CopyOnWriteArrayList<>(Collections.singletonList(
new GroupResult(new ArrayList<>(), new HashMap<>()))));
ScheduleOperationService service = new ScheduleOperationService(null, null);
Integer nextGroupId = ReflectionTestUtils.invokeMethod(service, "resolveNextAutoInsertGroupId", chromosome);
ReflectionTestUtils.invokeMethod(service, "padOperationRelations", chromosome.getOperatRel(), nextGroupId);
assertEquals(Integer.valueOf(5), nextGroupId);
assertEquals(4, chromosome.getOperatRel().size());
}
}
package com.aps.demo;
import com.aps.common.util.redis.RedisUtils;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Schedule.SceneChromsome;
import com.aps.service.plan.SceneService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.io.File;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class SceneServiceVersionTest {
private final String sceneId = "VERSION_TEST_" + System.nanoTime();
@AfterEach
void cleanVersionFiles() {
File resultDir = new File("result");
File[] files = resultDir.listFiles((dir, name) -> name.startsWith("chromosome_result_" + sceneId + "_"));
if (files == null) {
return;
}
for (File file : files) {
file.delete();
}
}
@Test
void undoAndRedoKeepInsertAndMoveAsSeparateVersions() {
AtomicReference<SceneChromsome> sceneState = new AtomicReference<>();
RedisUtils redisUtils = mock(RedisUtils.class);
when(redisUtils.get(anyString())).thenAnswer(invocation -> sceneState.get());
doAnswer(invocation -> {
sceneState.set(invocation.getArgument(1));
return null;
}).when(redisUtils).set(anyString(), any());
SceneService sceneService = new SceneService();
ReflectionTestUtils.setField(sceneService, "redisUtils", redisUtils);
Chromosome inserted = new Chromosome();
inserted.setGenerateType("inserted");
assertTrue(sceneService.saveChromosomeToFile(inserted, sceneId));
Chromosome moved = sceneService.loadChromosomeFromFile(sceneId);
moved.setGenerateType("moved");
assertTrue(sceneService.saveChromosomeToFile(moved, sceneId));
Chromosome undone = sceneService.moveChromosome(sceneId, 0);
assertNotNull(undone);
assertEquals(1, undone.getVersion());
assertEquals("inserted", undone.getGenerateType());
Chromosome redone = sceneService.revertVersion(sceneId, 2);
assertNotNull(redone);
assertEquals(2, redone.getVersion());
assertEquals("moved", redone.getGenerateType());
}
}
package com.aps.service.impl;
import com.aps.entity.RoutingHeader;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
class LanuchServiceImplTest {
@Test
void autoInsertPrefersNewestRoutingAlreadyUsedBySameMaterialInScene() {
RoutingHeader newestOtherRouting = routing(300, LocalDate.of(2026, 7, 20));
RoutingHeader newestExistingRouting = routing(200, LocalDate.of(2026, 7, 19));
RoutingHeader olderExistingRouting = routing(100, LocalDate.of(2026, 7, 18));
RoutingHeader selected = LanuchServiceImpl.selectExistingSceneRouting(
Arrays.asList(newestOtherRouting, newestExistingRouting, olderExistingRouting),
new HashSet<>(Arrays.asList(100, 200)));
assertEquals(Integer.valueOf(200), selected.getId());
}
@Test
void autoInsertFallsBackWhenSceneHasNoRoutingForMaterial() {
RoutingHeader selected = LanuchServiceImpl.selectExistingSceneRouting(
Collections.singletonList(routing(300, LocalDate.of(2026, 7, 20))),
Collections.singleton(100));
assertNull(selected);
}
private RoutingHeader routing(int id, LocalDate creationTime) {
RoutingHeader routingHeader = new RoutingHeader();
routingHeader.setId(id);
routingHeader.setCreationTime(creationTime);
return routingHeader;
}
}
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