feat: add manual WCS dispatch action
This commit is contained in:
@@ -74,7 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="priority != null "> and priority = #{priority}</if>
|
||||
<if test="height != null "> and height = #{height}</if>
|
||||
<if test="weight != null "> and weight = #{weight}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and mydo_job.create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="entranceId != null and entranceId != ''"> and entrance_id = #{entranceId}</if>
|
||||
<if test="exitId != null and exitId != ''"> and exit_id = #{exitId}</if>
|
||||
<if test="deptName != null and deptName != ''"> and dept_name like concat('%', #{deptName}, '%')</if>
|
||||
@@ -430,7 +430,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="priority != null "> and priority = #{priority}</if>
|
||||
<if test="height != null "> and height = #{height}</if>
|
||||
<if test="weight != null "> and weight = #{weight}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and mydo_job.create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="entranceId != null and entranceId != ''"> and entrance_id = #{entranceId}</if>
|
||||
<if test="exitId != null and exitId != ''"> and exit_id = #{exitId}</if>
|
||||
<if test="deptName != null and deptName != ''"> and dept_name like concat('%', #{deptName}, '%')</if>
|
||||
@@ -484,7 +484,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="priority != null "> and priority = #{priority}</if>
|
||||
<if test="height != null "> and height = #{height}</if>
|
||||
<if test="weight != null "> and weight = #{weight}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and mydo_job.create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="entranceId != null and entranceId != ''"> and entrance_id = #{entranceId}</if>
|
||||
<if test="exitId != null and exitId != ''"> and exit_id = #{exitId}</if>
|
||||
<if test="deptName != null and deptName != ''"> and dept_name like concat('%', #{deptName}, '%')</if>
|
||||
@@ -594,7 +594,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="priority != null "> and priority = #{priority}</if>
|
||||
<if test="height != null "> and height = #{height}</if>
|
||||
<if test="weight != null "> and weight = #{weight}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and mydo_job.create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="entranceId != null and entranceId != ''"> and entrance_id = #{entranceId}</if>
|
||||
<if test="exitId != null and exitId != ''"> and exit_id = #{exitId}</if>
|
||||
<if test="deptName != null and deptName != ''"> and dept_name like concat('%', #{deptName}, '%')</if>
|
||||
@@ -622,7 +622,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="priority != null "> and priority = #{priority}</if>
|
||||
<if test="height != null "> and height = #{height}</if>
|
||||
<if test="weight != null "> and weight = #{weight}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and mydo_job.create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
<if test="entranceId != null and entranceId != ''"> and entrance_id = #{entranceId}</if>
|
||||
<if test="exitId != null and exitId != ''"> and exit_id = #{exitId}</if>
|
||||
<if test="deptName != null and deptName != ''"> and dept_name like concat('%', #{deptName}, '%')</if>
|
||||
|
||||
@@ -88,6 +88,19 @@ class MydoJobMapperSqlTest {
|
||||
.contains("<if test=\"warehouseId != null and warehouseId != ''\"> and warehouse_id = #{warehouseId}</if>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void outboundListQualifiesCreateTimeAfterJoiningDispatchOutbox() throws Exception {
|
||||
String xml = Files.readString(resolveMapperXml());
|
||||
for (String selectId : new String[] {"selectMydoJobList", "selectInMydoJobList",
|
||||
"selectInventoryInMydoJobList", "selectOutMydoJobList", "selectInventoryOutMydoJobList"}) {
|
||||
String activeList = section(xml, "<select id=\"" + selectId + "\"", "</select>");
|
||||
assertThat(activeList)
|
||||
.as(selectId)
|
||||
.contains("mydo_job.create_time between #{params.beginCreateTime} and #{params.endCreateTime}")
|
||||
.doesNotContain("> and create_time between #{params.beginCreateTime}");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void denseInboundJobClaimIsAtomicAndLimitedToPendingWarehouse03Jobs() throws Exception {
|
||||
String xml = Files.readString(resolveMapperXml());
|
||||
|
||||
@@ -180,6 +180,21 @@ class OutboundDispatchServiceImplTest
|
||||
verify(wcsClient, never()).sendRetrieveTask(any(MydoJob.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void completedJobCannotBeManuallyDispatched()
|
||||
{
|
||||
MydoJob job = jobOfType("CK-COMPLETED", 21L);
|
||||
job.setStatus("4");
|
||||
when(jobMapper.selectMydoJobByJobId("CK-COMPLETED")).thenReturn(job);
|
||||
|
||||
AjaxResult result = service.dispatch("CK-COMPLETED", DispatchTrigger.MANUAL);
|
||||
|
||||
assertThat(result.isSuccess()).isFalse();
|
||||
assertThat(result.get("msg")).asString().contains("状态不允许");
|
||||
verify(dispatchMapper, never()).insertIfAbsent(any(String.class));
|
||||
verify(wcsClient, never()).sendRetrieveTask(any(MydoJob.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void blockedDenseJobDoesNotConsumeRetryOrCallWcs()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.ruoyi.out.job.controller;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.Stream;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.out.dispatch.domain.DispatchTrigger;
|
||||
import com.ruoyi.out.dispatch.service.IOutboundDispatchService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class OutMydoJobDispatchControllerTest
|
||||
{
|
||||
@Test
|
||||
void manualEndpointUsesDedicatedPermissionAndManualTrigger() throws Exception
|
||||
{
|
||||
Method endpoint = OutMydoJobController.class.getMethod("pushWcs", String.class);
|
||||
assertThat(endpoint.getAnnotation(PreAuthorize.class).value())
|
||||
.isEqualTo("@ss.hasPermi('out:job:pushWcs')");
|
||||
|
||||
IOutboundDispatchService dispatchService = mock(IOutboundDispatchService.class);
|
||||
when(dispatchService.dispatch("CK-1", DispatchTrigger.MANUAL))
|
||||
.thenReturn(AjaxResult.success("已下发"));
|
||||
OutMydoJobController controller = new OutMydoJobController();
|
||||
ReflectionTestUtils.setField(controller, "outboundDispatchService", dispatchService);
|
||||
|
||||
assertThat(controller.pushWcs("CK-1").isSuccess()).isTrue();
|
||||
verify(dispatchService).dispatch("CK-1", DispatchTrigger.MANUAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void jobPageShowsDispatchStateAndRestrictsManualAction() throws Exception
|
||||
{
|
||||
String vue = Files.readString(resolve("ruoyi-ui/src/views/out/job/index.vue"));
|
||||
String api = Files.readString(resolve("ruoyi-ui/src/api/out/job.js"));
|
||||
|
||||
assertThat(vue)
|
||||
.contains("prop=\"dispatchStatus\"")
|
||||
.contains("prop=\"autoRetryCount\"")
|
||||
.contains("lastDispatchError")
|
||||
.contains("out:job:pushWcs")
|
||||
.contains("canPushWcs")
|
||||
.contains("手动下发 WCS")
|
||||
.doesNotContain("v-hasPermi=\"['out:job:edit']\"");
|
||||
assertThat(api).contains("/out/job/pushWcs/");
|
||||
}
|
||||
|
||||
private Path resolve(String path)
|
||||
{
|
||||
return Stream.of(Path.of(path), Path.of("..", path))
|
||||
.filter(Files::exists)
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user