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.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; @ExtendWith(MockitoExtension.class) class WcsApiServiceImplTest { @Mock private WrkMastService wrkMastService; @Mock private WorkService workService; @Mock private WrkDetlService wrkDetlService; @Mock private LocMastService locMastService; @Mock private BasDevpService basDevpService; @Mock private CommonService commonService; private WcsApiServiceImpl service; @BeforeEach void setUp() { 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 void receviceTaskFromWcs_marksOutboundStationCompleteWhenDevpCallbackArrives() { WrkMast mast = outboundMast(25L); when(wrkMastService.selectOne(any())).thenReturn(mast); when(wrkMastService.updateById(mast)).thenReturn(true); service.receviceTaskFromWcs(new ReceviceTaskParams() .setNotifyType("Devp") .setMsgType("station_out_task_run_complete") .setSuperTaskNo("7597")); assertEquals(Long.valueOf(26L), mast.getWrkSts()); verify(wrkMastService).updateById(mast); } @Test void receviceTaskFromWcs_allowsTaskCompleteAfterStationOutComplete() { WrkMast mast = outboundMast(26L); when(wrkMastService.selectOne(any())).thenReturn(mast); when(wrkMastService.updateById(mast)).thenReturn(true); service.receviceTaskFromWcs(new ReceviceTaskParams() .setNotifyType("task") .setMsgType("task_complete") .setSuperTaskNo("7597")); assertEquals(Long.valueOf(14L), mast.getWrkSts()); 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 @SuppressWarnings("unchecked") void buildReassignCrnSearchOrder_currentThree_shouldSearchSmallerThenWrapDescending() { List 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 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 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 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 result = ReflectionTestUtils.invokeMethod( service, "buildReassignCrnSearchOrder", Collections.singletonList(3), 3); assertEquals(Collections.emptyList(), result); } @Test @SuppressWarnings("unchecked") void buildReassignCrnSearchOrder_currentNotInPool_shouldStartFromLargestSmallerCrane() { List 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 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 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 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 captor = ArgumentCaptor.forClass(List.class); ArgumentCaptor 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); mast.setIoType(101); 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); } }