From 2cc61346cc0a3e5338aa8957f79f4c99c204f339 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期一, 27 四月 2026 14:02:58 +0800
Subject: [PATCH] fix: preserve unlimited station limits in auto tune apply
---
src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 101 insertions(+), 0 deletions(-)
diff --git a/src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java b/src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java
index 29a4323..864c535 100644
--- a/src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java
+++ b/src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java
@@ -11,10 +11,12 @@
import com.zy.asrs.entity.BasDualCrnp;
import com.zy.asrs.entity.BasStation;
import com.zy.asrs.entity.StationFlowCapacity;
+import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.BasDualCrnpService;
import com.zy.asrs.service.BasStationService;
import com.zy.asrs.service.StationFlowCapacityService;
+import com.zy.asrs.service.WrkMastService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
import com.zy.system.entity.Config;
@@ -79,6 +81,8 @@
@Mock
private StationFlowCapacityService stationFlowCapacityService;
@Mock
+ private WrkMastService wrkMastService;
+ @Mock
private RedisUtil redisUtil;
private RecordingTransactionManager transactionManager;
@@ -93,6 +97,7 @@
ReflectionTestUtils.setField(service, "basCrnpService", basCrnpService);
ReflectionTestUtils.setField(service, "basDualCrnpService", basDualCrnpService);
ReflectionTestUtils.setField(service, "stationFlowCapacityService", stationFlowCapacityService);
+ ReflectionTestUtils.setField(service, "wrkMastService", wrkMastService);
ReflectionTestUtils.setField(service, "transactionManager", transactionManager);
ReflectionTestUtils.setField(service, "redisUtil", redisUtil);
@@ -109,6 +114,7 @@
});
when(aiAutoTuneChangeService.saveBatch(any(Collection.class))).thenReturn(true);
when(aiAutoTuneChangeService.list(any(Wrapper.class))).thenReturn(Collections.emptyList());
+ when(wrkMastService.count(any(Wrapper.class))).thenReturn(0L);
when(configService.getConfigValue(eq("aiAutoTuneIntervalMinutes"), any())).thenReturn("10");
when(configService.saveConfigValue(any(), any())).thenReturn(true);
when(basStationService.update(any(Wrapper.class))).thenReturn(true);
@@ -206,6 +212,44 @@
}
@Test
+ void rejectStationOutTaskLimitNullUnlimitedCurrentValue() {
+ when(basStationService.getById(101)).thenReturn(station(101, null));
+
+ service.apply(request(true, command("station", "101", "outTaskLimit", "1")));
+
+ List<AiAutoTuneChange> changes = savedChanges();
+ assertEquals("rejected", changes.get(0).getResultStatus());
+ assertTrue(changes.get(0).getRejectReason().contains("闇�瑕佷汉宸ュ厛鍒濆鍖栦负鏈夐檺鍊�"));
+ verify(stationFlowCapacityService, never()).getOne(any(Wrapper.class));
+ }
+
+ @Test
+ void rejectStationOutTaskLimitNegativeUnlimitedCurrentValue() {
+ when(basStationService.getById(101)).thenReturn(station(101, -1));
+
+ service.apply(request(true, command("station", "101", "outTaskLimit", "1")));
+
+ List<AiAutoTuneChange> changes = savedChanges();
+ assertEquals("rejected", changes.get(0).getResultStatus());
+ assertTrue(changes.get(0).getRejectReason().contains("闇�瑕佷汉宸ュ厛鍒濆鍖栦负鏈夐檺鍊�"));
+ verify(stationFlowCapacityService, never()).getOne(any(Wrapper.class));
+ }
+
+ @Test
+ void allowStationOutTaskLimitZeroToOneAsFiniteStep() {
+ when(basStationService.getById(101)).thenReturn(station(101, 0));
+ when(stationFlowCapacityService.getOne(any(Wrapper.class))).thenReturn(capacity(101, "OUT", 1));
+
+ AutoTuneApplyResult result = service.apply(request(true, command("station", "101", "outTaskLimit", "1")));
+
+ List<AiAutoTuneChange> changes = savedChanges();
+ assertTrue(result.getSuccess());
+ assertEquals("dry_run", changes.get(0).getResultStatus());
+ assertEquals("0", changes.get(0).getOldValue());
+ assertEquals("1", changes.get(0).getRequestedValue());
+ }
+
+ @Test
void rejectCooldownHit() {
when(configService.getOne(any(Wrapper.class))).thenReturn(config("conveyorStationTaskLimit", "10"));
AiAutoTuneChange cooldownChange = new AiAutoTuneChange();
@@ -252,6 +296,46 @@
verify(basStationService, never()).update(any(Wrapper.class));
verify(basCrnpService, never()).update(any(Wrapper.class));
verify(basDualCrnpService, never()).update(any(Wrapper.class));
+ }
+
+ @Test
+ void applyJobRecordsActiveTasksWhenCountIsPositive() {
+ when(configService.getOne(any(Wrapper.class))).thenReturn(config("conveyorStationTaskLimit", "10"));
+ when(wrkMastService.count(any(Wrapper.class))).thenReturn(1L);
+
+ service.apply(request(true, command("sys_config", null, "conveyorStationTaskLimit", "15")));
+
+ AiAutoTuneJob updatedJob = updatedJob();
+ assertEquals(1, updatedJob.getHasActiveTasks());
+
+ ArgumentCaptor<Wrapper<WrkMast>> captor = ArgumentCaptor.forClass(Wrapper.class);
+ verify(wrkMastService).count(captor.capture());
+ String sqlSegment = captor.getValue().getSqlSegment();
+ assertTrue(sqlSegment.contains("NOT IN"));
+ assertTrue(sqlSegment.contains("OR"));
+ assertTrue(sqlSegment.contains("wrk_sts IS NULL"));
+ }
+
+ @Test
+ void applyJobRecordsNoActiveTasksWhenCountIsZero() {
+ when(configService.getOne(any(Wrapper.class))).thenReturn(config("conveyorStationTaskLimit", "10"));
+ when(wrkMastService.count(any(Wrapper.class))).thenReturn(0L);
+
+ service.apply(request(true, command("sys_config", null, "conveyorStationTaskLimit", "15")));
+
+ AiAutoTuneJob updatedJob = updatedJob();
+ assertEquals(0, updatedJob.getHasActiveTasks());
+ }
+
+ @Test
+ void applyJobFallsBackToNoActiveTasksWhenCountFails() {
+ when(configService.getOne(any(Wrapper.class))).thenReturn(config("conveyorStationTaskLimit", "10"));
+ when(wrkMastService.count(any(Wrapper.class))).thenThrow(new IllegalStateException("count failed"));
+
+ service.apply(request(true, command("sys_config", null, "conveyorStationTaskLimit", "15")));
+
+ AiAutoTuneJob updatedJob = updatedJob();
+ assertEquals(0, updatedJob.getHasActiveTasks());
}
@Test
@@ -493,6 +577,23 @@
}
@Test
+ void rollbackJobRecordsActiveTasksWhenCountIsPositive() {
+ AiAutoTuneJob latestRealJob = job(10L, "manual", "success");
+ AiAutoTuneChange configChange = successChange(10L, "sys_config", "", "conveyorStationTaskLimit", "10", "15");
+ when(wrkMastService.count(any(Wrapper.class))).thenReturn(1L);
+ when(aiAutoTuneChangeService.list(any(Wrapper.class)))
+ .thenReturn(List.of(configChange))
+ .thenReturn(List.of(configChange));
+ when(aiAutoTuneJobService.getById(10L)).thenReturn(latestRealJob);
+ when(configService.getOne(any(Wrapper.class))).thenReturn(config("conveyorStationTaskLimit", "15"));
+
+ service.rollbackLastSuccessfulJob("manual rollback");
+
+ AiAutoTuneJob updatedJob = updatedJob();
+ assertEquals(1, updatedJob.getHasActiveTasks());
+ }
+
+ @Test
void rollbackCacheRefreshFailureDoesNotAppendFailedAuditOrJob() {
AiAutoTuneJob latestRealJob = job(10L, "manual", "success");
AiAutoTuneChange configChange = successChange(10L, "sys_config", "", "conveyorStationTaskLimit", "10", "15");
--
Gitblit v1.9.1