自动化立体仓库 - WMS系统
src/test/java/com/zy/api/service/impl/WcsApiServiceImplTest.java
@@ -1,18 +1,39 @@
package com.zy.api.service.impl;
import com.zy.api.controller.params.ReassignLocParams;
import com.zy.api.controller.params.ReceviceTaskParams;
import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.entity.WrkDetl;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.WorkService;
import com.zy.asrs.service.WrkDetlService;
import com.zy.asrs.service.WrkMastService;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -25,6 +46,18 @@
    @Mock
    private WorkService workService;
    @Mock
    private WrkDetlService wrkDetlService;
    @Mock
    private LocMastService locMastService;
    @Mock
    private BasDevpService basDevpService;
    @Mock
    private CommonService commonService;
    private WcsApiServiceImpl service;
    @BeforeEach
@@ -32,6 +65,10 @@
        service = new WcsApiServiceImpl();
        ReflectionTestUtils.setField(service, "wrkMastService", wrkMastService);
        ReflectionTestUtils.setField(service, "workService", workService);
        ReflectionTestUtils.setField(service, "wrkDetlService", wrkDetlService);
        ReflectionTestUtils.setField(service, "locMastService", locMastService);
        ReflectionTestUtils.setField(service, "basDevpService", basDevpService);
        ReflectionTestUtils.setField(service, "commonService", commonService);
    }
    @Test
@@ -64,6 +101,261 @@
        verify(wrkMastService).updateById(mast);
    }
    @Test
    void receviceTaskFromWcs_marksMoveCompleteWhenTaskCompleteUsesCrnNotifyType() {
        WrkMast mast = moveMast(11);
        when(wrkMastService.selectOne(any())).thenReturn(mast);
        when(wrkMastService.updateById(mast)).thenReturn(true);
        service.receviceTaskFromWcs(new ReceviceTaskParams()
                .setNotifyType("Crn")
                .setMsgType("task_complete")
                .setSuperTaskNo("7597"));
        assertEquals(Long.valueOf(4L), mast.getWrkSts());
        verify(wrkMastService).updateById(mast);
    }
    @Test
    void receviceTaskFromWcs_marksChangeLocCompleteWhenTaskCompleteUsesCrnNotifyType() {
        WrkMast mast = moveMast(5);
        when(wrkMastService.selectOne(any())).thenReturn(mast);
        when(wrkMastService.updateById(mast)).thenReturn(true);
        service.receviceTaskFromWcs(new ReceviceTaskParams()
                .setNotifyType("Crn")
                .setMsgType("task_complete")
                .setSuperTaskNo("7597"));
        assertEquals(Long.valueOf(4L), mast.getWrkSts());
        verify(wrkMastService).updateById(mast);
    }
    @Test
    void receviceTaskFromWcs_marksEmptyPalletInboundCompleteWhenTaskCompleteUsesCrnNotifyType() {
        WrkMast mast = moveMast(10);
        when(wrkMastService.selectOne(any())).thenReturn(mast);
        when(wrkMastService.updateById(mast)).thenReturn(true);
        service.receviceTaskFromWcs(new ReceviceTaskParams()
                .setNotifyType("Crn")
                .setMsgType("task_complete")
                .setSuperTaskNo("7597"));
        assertEquals(Long.valueOf(4L), mast.getWrkSts());
        verify(wrkMastService).updateById(mast);
    }
    @Test
    void receviceTaskFromWcs_recordsTaskCompleteWeightOnMast() {
        WrkMast mast = moveMast(1);
        when(wrkMastService.selectOne(any())).thenReturn(mast);
        when(wrkMastService.updateById(mast)).thenReturn(true);
        service.receviceTaskFromWcs(new ReceviceTaskParams()
                .setNotifyType("Crn")
                .setMsgType("task_complete")
                .setSuperTaskNo("7597")
                .setWeight(32.5D));
        assertEquals(new BigDecimal("32.5"), mast.getScWeight());
        assertEquals(Long.valueOf(4L), mast.getWrkSts());
        verify(wrkMastService).updateById(mast);
    }
    @Test
    void receviceTaskFromWcs_doesNotAutoCompleteUnsupportedIoTypeTwo() {
        WrkMast mast = moveMast(2);
        when(wrkMastService.selectOne(any())).thenReturn(mast);
        service.receviceTaskFromWcs(new ReceviceTaskParams()
                .setNotifyType("Crn")
                .setMsgType("task_complete")
                .setSuperTaskNo("7597"));
        assertEquals(Long.valueOf(2L), mast.getWrkSts());
        verify(wrkMastService, never()).updateById(mast);
    }
    @Test
    void updateWrkMastAfterPublish_marksEmptyPalletInboundRunning() {
        WrkMast mast = moveMast(10);
        mast.setWrkSts(1L);
        ReflectionTestUtils.invokeMethod(service, "updateWrkMastAfterPublish", mast);
        assertEquals(Long.valueOf(2L), mast.getWrkSts());
        verify(wrkMastService).updateById(mast);
    }
    @Test
    @SuppressWarnings("unchecked")
    void buildReassignCrnSearchOrder_currentThree_shouldSearchSmallerThenWrapDescending() {
        List<Integer> result = ReflectionTestUtils.invokeMethod(
                service, "buildReassignCrnSearchOrder", Arrays.asList(1, 2, 3, 4, 5, 6), 3);
        assertEquals(Arrays.asList(2, 1, 6, 5, 4), result);
    }
    @Test
    @SuppressWarnings("unchecked")
    void buildReassignCrnSearchOrder_currentOne_shouldWrapFromMax() {
        List<Integer> result = ReflectionTestUtils.invokeMethod(
                service, "buildReassignCrnSearchOrder", Arrays.asList(1, 2, 3, 4, 5, 6), 1);
        assertEquals(Arrays.asList(6, 5, 4, 3, 2), result);
    }
    @Test
    @SuppressWarnings("unchecked")
    void buildReassignCrnSearchOrder_currentSix_shouldSearchDescending() {
        List<Integer> result = ReflectionTestUtils.invokeMethod(
                service, "buildReassignCrnSearchOrder", Arrays.asList(1, 2, 3, 4, 5, 6), 6);
        assertEquals(Arrays.asList(5, 4, 3, 2, 1), result);
    }
    @Test
    @SuppressWarnings("unchecked")
    void buildReassignCrnSearchOrder_nonContinuousPool_shouldKeepDescendingCircularOrder() {
        List<Integer> result = ReflectionTestUtils.invokeMethod(
                service, "buildReassignCrnSearchOrder", Arrays.asList(1, 3, 6), 3);
        assertEquals(Arrays.asList(1, 6), result);
    }
    @Test
    @SuppressWarnings("unchecked")
    void buildReassignCrnSearchOrder_singleCurrentCrane_shouldReturnEmpty() {
        List<Integer> result = ReflectionTestUtils.invokeMethod(
                service, "buildReassignCrnSearchOrder", Collections.singletonList(3), 3);
        assertEquals(Collections.emptyList(), result);
    }
    @Test
    @SuppressWarnings("unchecked")
    void buildReassignCrnSearchOrder_currentNotInPool_shouldStartFromLargestSmallerCrane() {
        List<Integer> result = ReflectionTestUtils.invokeMethod(
                service, "buildReassignCrnSearchOrder", Arrays.asList(1, 4, 6), 3);
        assertEquals(Arrays.asList(1, 6, 4), result);
    }
    @Test
    void reassignInboundLoc_currentCraneInFirstPool_shouldUseFirstPoolDescendingOrder() {
        WrkMast mast = inboundMast(3, "0100101");
        LocMast currentLoc = loc("0100101", 3, "S");
        LocMast targetLoc = loc("0200101", 2, "O");
        StartupDto startupDto = startup("0200101", 2);
        prepareSuccessfulReassign(mast, currentLoc, targetLoc, station("1,2,3,4,5,6", "7,8"));
        when(commonService.findRun2InboundLocByCandidateCrnNos(eq(1001), eq(1), anyList(), any(LocTypeDto.class), isNull()))
                .thenReturn(startupDto);
        service.reassignInboundLoc(reassignParams());
        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
        verify(commonService).findRun2InboundLocByCandidateCrnNos(eq(1001), eq(1), captor.capture(), any(LocTypeDto.class), isNull());
        assertEquals(Arrays.asList(2, 1, 6, 5, 4), captor.getValue());
    }
    @Test
    void reassignInboundLoc_currentCraneInSecondPool_shouldUseSecondPoolBeforeFirstPool() {
        WrkMast mast = inboundMast(5, "0100101");
        LocMast currentLoc = loc("0100101", 5, "S");
        LocMast targetLoc = loc("0200101", 4, "O");
        StartupDto startupDto = startup("0200101", 4);
        prepareSuccessfulReassign(mast, currentLoc, targetLoc, station("1,2,3", "4,5,6"));
        when(commonService.findRun2InboundLocByCandidateCrnNos(eq(1001), eq(1), anyList(), any(LocTypeDto.class), isNull()))
                .thenReturn(startupDto);
        service.reassignInboundLoc(reassignParams());
        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
        verify(commonService).findRun2InboundLocByCandidateCrnNos(eq(1001), eq(1), captor.capture(), any(LocTypeDto.class), isNull());
        assertEquals(Arrays.asList(4, 6), captor.getValue());
    }
    @Test
    void reassignInboundLoc_firstPoolNoLocation_shouldFallbackToSecondPool() {
        WrkMast mast = inboundMast(3, "0100101");
        LocMast currentLoc = loc("0100101", 3, "S");
        LocMast targetLoc = loc("0200101", 6, "O");
        StartupDto startupDto = startup("0200101", 6);
        prepareSuccessfulReassign(mast, currentLoc, targetLoc, station("1,2,3", "4,5,6"));
        when(commonService.findRun2InboundLocByCandidateCrnNos(eq(1001), eq(1), anyList(), any(LocTypeDto.class), isNull()))
                .thenReturn(null)
                .thenReturn(startupDto);
        service.reassignInboundLoc(reassignParams());
        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
        verify(commonService, org.mockito.Mockito.times(2))
                .findRun2InboundLocByCandidateCrnNos(eq(1001), eq(1), captor.capture(), any(LocTypeDto.class), isNull());
        assertEquals(Arrays.asList(2, 1), captor.getAllValues().get(0));
        assertEquals(Arrays.asList(6, 5, 4), captor.getAllValues().get(1));
    }
    @Test
    void reassignInboundLoc_emptyPalletDetail_shouldSearchOnlyLevelEight() {
        WrkMast mast = inboundMast(3, "0100101");
        LocMast currentLoc = loc("0100101", 3, "S");
        currentLoc.setLocType1((short) 2);
        currentLoc.setLocType2((short) 0);
        currentLoc.setLocType3(null);
        LocMast targetLoc = loc("0200108", 2, "O");
        targetLoc.setLev1(8);
        targetLoc.setLocType1((short) 3);
        targetLoc.setLocType2((short) 0);
        StartupDto startupDto = startup("0200108", 2);
        prepareSuccessfulReassign(mast, currentLoc, targetLoc, station("1,2,3,4,5,6", ""));
        when(wrkDetlService.selectByWrkNo(7597)).thenReturn(Collections.singletonList(wrkDetl("emptyPallet")));
        when(commonService.findRun2InboundLocByCandidateCrnNos(eq(1001), eq(1), anyList(), any(LocTypeDto.class), eq(8)))
                .thenReturn(startupDto);
        service.reassignInboundLoc(reassignParams());
        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
        ArgumentCaptor<LocTypeDto> locTypeCaptor = ArgumentCaptor.forClass(LocTypeDto.class);
        verify(commonService).findRun2InboundLocByCandidateCrnNos(eq(1001), eq(1), captor.capture(), locTypeCaptor.capture(), eq(8));
        assertEquals(Arrays.asList(2, 1, 6, 5, 4), captor.getValue());
        assertEquals(Short.valueOf((short) 3), locTypeCaptor.getValue().getLocType1());
        assertEquals(Short.valueOf((short) 0), locTypeCaptor.getValue().getLocType2());
    }
    @Test
    void reassignInboundLoc_emptyMasterFlagWithoutEmptyPalletDetail_shouldNotForceLevelEight() {
        WrkMast mast = inboundMast(3, "0100101");
        mast.setIoType(10);
        mast.setEmptyMk("Y");
        LocMast currentLoc = loc("0100101", 3, "S");
        LocMast targetLoc = loc("0200101", 2, "O");
        StartupDto startupDto = startup("0200101", 2);
        prepareSuccessfulReassign(mast, currentLoc, targetLoc, station("1,2,3,4,5,6", ""));
        when(wrkDetlService.selectByWrkNo(7597)).thenReturn(Collections.singletonList(wrkDetl("MAT-001")));
        when(commonService.findRun2InboundLocByCandidateCrnNos(eq(1001), eq(10), anyList(), any(LocTypeDto.class), isNull()))
                .thenReturn(startupDto);
        service.reassignInboundLoc(reassignParams());
        verify(commonService).findRun2InboundLocByCandidateCrnNos(eq(1001), eq(10), anyList(), any(LocTypeDto.class), isNull());
    }
    @Test
    void reassignInboundLoc_currentCraneNotInAnyPool_shouldNotSearchLocation() {
        WrkMast mast = inboundMast(3, "0100101");
        LocMast currentLoc = loc("0100101", 3, "S");
        when(wrkMastService.selectOne(any())).thenReturn(mast);
        when(locMastService.selectById("0100101")).thenReturn(currentLoc);
        when(basDevpService.selectById(1001)).thenReturn(station("1,2", "4,5"));
        Object result = service.reassignInboundLoc(reassignParams());
        assertNotNull(result);
        verify(commonService, never())
                .findRun2InboundLocByCandidateCrnNos(any(), any(), anyList(), any(LocTypeDto.class), any());
    }
    private static WrkMast outboundMast(Long wrkSts) {
        WrkMast mast = new WrkMast();
        mast.setWrkNo(7597);
@@ -71,4 +363,73 @@
        mast.setWrkSts(wrkSts);
        return mast;
    }
    private static WrkMast moveMast(Integer ioType) {
        WrkMast mast = new WrkMast();
        mast.setWrkNo(7597);
        mast.setIoType(ioType);
        mast.setWrkSts(2L);
        return mast;
    }
    private static WrkMast inboundMast(Integer crnNo, String locNo) {
        WrkMast mast = new WrkMast();
        mast.setWrkNo(7597);
        mast.setIoType(1);
        mast.setWrkSts(2L);
        mast.setCrnNo(crnNo);
        mast.setLocNo(locNo);
        mast.setSourceStaNo(1001);
        mast.setBarcode("BC-001");
        return mast;
    }
    private static LocMast loc(String locNo, Integer crnNo, String locSts) {
        LocMast locMast = new LocMast();
        locMast.setLocNo(locNo);
        locMast.setCrnNo(crnNo);
        locMast.setLocSts(locSts);
        locMast.setLocType1((short) 1);
        locMast.setLocType2((short) 2);
        locMast.setLocType3((short) 1);
        return locMast;
    }
    private static BasDevp station(String firstCrnCsv, String secondCrnCsv) {
        BasDevp station = new BasDevp();
        station.setDevNo(1001);
        station.setInFirstCrnCsv(firstCrnCsv);
        station.setInSecondCrnCsv(secondCrnCsv);
        return station;
    }
    private static StartupDto startup(String locNo, Integer crnNo) {
        StartupDto startupDto = new StartupDto();
        startupDto.setLocNo(locNo);
        startupDto.setCrnNo(crnNo);
        startupDto.setStaNo(2001);
        return startupDto;
    }
    private static WrkDetl wrkDetl(String matnr) {
        WrkDetl wrkDetl = new WrkDetl();
        wrkDetl.setWrkNo(7597);
        wrkDetl.setMatnr(matnr);
        return wrkDetl;
    }
    private static ReassignLocParams reassignParams() {
        ReassignLocParams params = new ReassignLocParams();
        params.setTaskNo("7597");
        return params;
    }
    private void prepareSuccessfulReassign(WrkMast mast, LocMast currentLoc, LocMast targetLoc, BasDevp station) {
        when(wrkMastService.selectOne(any())).thenReturn(mast);
        when(locMastService.selectById(currentLoc.getLocNo())).thenReturn(currentLoc);
        when(locMastService.selectById(targetLoc.getLocNo())).thenReturn(targetLoc);
        when(locMastService.updateById(any(LocMast.class))).thenReturn(true);
        when(wrkMastService.updateById(mast)).thenReturn(true);
        when(basDevpService.selectById(mast.getSourceStaNo())).thenReturn(station);
    }
}