package cn.iocoder.yudao.module.mes.service.pro.feedback; import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi; import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsRespDTO; import cn.iocoder.yudao.module.mes.api.event.ProductionFinishedEvent; import cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO; import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderProcessService; import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationEventPublisher; import org.springframework.test.util.ReflectionTestUtils; import org.mockito.ArgumentCaptor; import java.math.BigDecimal; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import static org.mockito.Mockito.*; import static org.mockito.ArgumentMatchers.*; import static org.junit.jupiter.api.Assertions.assertEquals; class MesProFeedbackMpsAllocationTest { @Test void mergedWorkOrderKeepsSurplusOutOfSaleOrders() { MesProMpsApi mpsApi = mock(MesProMpsApi.class); MesProFeedbackServiceImpl service = new MesProFeedbackServiceImpl(); ReflectionTestUtils.setField(service, "mpsApi", mpsApi); when(mpsApi.getMpsListByWorkOrderId(28L)).thenReturn(List.of( mps(1716L, 38, 0, MesProMpsStatusEnum.ISSUED), mps(1737L, 1, 0, MesProMpsStatusEnum.ISSUED))); service.allocateMpsProducedQuantity(28L, new BigDecimal("40")); verify(mpsApi).updateMpsProducedQuantity(1716L, new BigDecimal("38")); verify(mpsApi).updateMpsProducedQuantity(1737L, BigDecimal.ONE); verify(mpsApi, times(2)).updateMpsProducedQuantity(anyLong(), any(BigDecimal.class)); } @Test void onlyRemainingDemandIsAssignedAndCanceledMpsIsSkipped() { MesProMpsApi mpsApi = mock(MesProMpsApi.class); MesProFeedbackServiceImpl service = new MesProFeedbackServiceImpl(); ReflectionTestUtils.setField(service, "mpsApi", mpsApi); when(mpsApi.getMpsListByWorkOrderId(29L)).thenReturn(List.of( mps(1L, 5, 0, MesProMpsStatusEnum.CANCELED), mps(2L, 3, 2, MesProMpsStatusEnum.ISSUED))); service.allocateMpsProducedQuantity(29L, new BigDecimal("4")); verify(mpsApi).updateMpsProducedQuantity(2L, BigDecimal.ONE); verify(mpsApi, never()).updateMpsProducedQuantity(eq(1L), any(BigDecimal.class)); verify(mpsApi, times(1)).updateMpsProducedQuantity(anyLong(), any(BigDecimal.class)); } @Test void mergedWorkOrderChecksBothSaleOrdersExactlyOnce() { MesProMpsApi mpsApi = mock(MesProMpsApi.class); ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class); MesProFeedbackServiceImpl service = new MesProFeedbackServiceImpl(); ReflectionTestUtils.setField(service, "mpsApi", mpsApi); ReflectionTestUtils.setField(service, "eventPublisher", publisher); MesProMpsRespDTO first = mps(1716L, 38, 38, MesProMpsStatusEnum.ISSUED); first.setSaleOrderId(512L); MesProMpsRespDTO second = mps(1737L, 1, 1, MesProMpsStatusEnum.ISSUED); second.setSaleOrderId(513L); when(mpsApi.getMpsListByWorkOrderId(28L)).thenReturn(List.of(first, second)); when(mpsApi.checkAndFinishMps(1716L)).thenReturn(true); when(mpsApi.checkAndFinishMps(1737L)).thenReturn(true); when(mpsApi.checkSaleOrderProductionFinished(512L)).thenReturn(true); when(mpsApi.checkSaleOrderProductionFinished(513L)).thenReturn(true); service.checkAndPublishProductionFinished(28L); verify(mpsApi).checkAndFinishMps(1716L); verify(mpsApi).checkAndFinishMps(1737L); ArgumentCaptor events = ArgumentCaptor.forClass(ProductionFinishedEvent.class); verify(publisher, times(2)).publishEvent(events.capture()); assertEquals(Set.of(512L, 513L), events.getAllValues().stream() .map(ProductionFinishedEvent::getSaleOrderId).collect(Collectors.toSet())); } @Test void lastProcessUpdatesWorkOrderEvenWhenItIsNotKeyProcess() { MesProMpsApi mpsApi = mock(MesProMpsApi.class); MesProTaskService taskService = mock(MesProTaskService.class); MesProWorkOrderService workOrderService = mock(MesProWorkOrderService.class); MesProWorkOrderProcessService processService = mock(MesProWorkOrderProcessService.class); MesProFeedbackServiceImpl service = new MesProFeedbackServiceImpl(); ReflectionTestUtils.setField(service, "mpsApi", mpsApi); ReflectionTestUtils.setField(service, "taskService", taskService); ReflectionTestUtils.setField(service, "workOrderService", workOrderService); ReflectionTestUtils.setField(service, "workOrderProcessService", processService); when(processService.getLastWorkOrderProcessByWorkOrderId(28L)) .thenReturn(new MesProWorkOrderProcessDO().setProcessId(13L).setKeyFlag(false)); when(mpsApi.getMpsListByWorkOrderId(28L)).thenReturn(List.of( mps(1716L, 38, 0, MesProMpsStatusEnum.ISSUED), mps(1737L, 1, 0, MesProMpsStatusEnum.ISSUED))); MesProFeedbackDO feedback = new MesProFeedbackDO().setWorkOrderId(28L) .setTaskId(362L).setProcessId(13L).setFeedbackQuantity(new BigDecimal("40")); service.updateTaskAndWorkOrderByFeedback(feedback); verify(taskService).updateProducedQuantity(362L, new BigDecimal("40"), BigDecimal.ZERO, BigDecimal.ZERO); verify(workOrderService).updateProducedQuantity(28L, new BigDecimal("40")); verify(mpsApi).updateMpsProducedQuantity(1716L, new BigDecimal("38")); verify(mpsApi).updateMpsProducedQuantity(1737L, BigDecimal.ONE); } @Test void keyProcessBeforeLastOnlyUpdatesItsTask() { MesProMpsApi mpsApi = mock(MesProMpsApi.class); MesProTaskService taskService = mock(MesProTaskService.class); MesProWorkOrderService workOrderService = mock(MesProWorkOrderService.class); MesProWorkOrderProcessService processService = mock(MesProWorkOrderProcessService.class); MesProFeedbackServiceImpl service = new MesProFeedbackServiceImpl(); ReflectionTestUtils.setField(service, "mpsApi", mpsApi); ReflectionTestUtils.setField(service, "taskService", taskService); ReflectionTestUtils.setField(service, "workOrderService", workOrderService); ReflectionTestUtils.setField(service, "workOrderProcessService", processService); when(processService.getLastWorkOrderProcessByWorkOrderId(28L)) .thenReturn(new MesProWorkOrderProcessDO().setProcessId(13L).setKeyFlag(false)); when(mpsApi.getMpsListByWorkOrderId(28L)).thenReturn(List.of()); MesProFeedbackDO feedback = new MesProFeedbackDO().setWorkOrderId(28L) .setTaskId(360L).setProcessId(11L).setFeedbackQuantity(new BigDecimal("40")); service.updateTaskAndWorkOrderByFeedback(feedback); verify(taskService).updateProducedQuantity(360L, new BigDecimal("40"), BigDecimal.ZERO, BigDecimal.ZERO); verify(workOrderService, never()).updateProducedQuantity(anyLong(), any(BigDecimal.class)); verify(mpsApi, never()).updateMpsProducedQuantity(anyLong(), any(BigDecimal.class)); } @Test void lastQcAutoFinishesOnlyAfterAllLastProcessFeedbacksAreFinished() { MesProFeedbackMapper feedbackMapper = mock(MesProFeedbackMapper.class); MesProWorkOrderService workOrderService = mock(MesProWorkOrderService.class); MesProWorkOrderProcessService processService = mock(MesProWorkOrderProcessService.class); MesProFeedbackServiceImpl service = new MesProFeedbackServiceImpl(); ReflectionTestUtils.setField(service, "feedbackMapper", feedbackMapper); ReflectionTestUtils.setField(service, "workOrderService", workOrderService); ReflectionTestUtils.setField(service, "workOrderProcessService", processService); when(processService.getLastWorkOrderProcessByWorkOrderId(28L)) .thenReturn(new MesProWorkOrderProcessDO().setProcessId(13L)); MesProFeedbackDO lastFeedback = new MesProFeedbackDO().setWorkOrderId(28L).setProcessId(13L); when(feedbackMapper.selectCount(any(com.baomidou.mybatisplus.core.conditions.Wrapper.class))) .thenReturn(1L, 0L); service.checkAndAutoFinishAfterLastQc(lastFeedback); verify(workOrderService, never()).checkAndAutoFinishWorkOrder(28L); service.checkAndAutoFinishAfterLastQc(lastFeedback); verify(workOrderService).checkAndAutoFinishWorkOrder(28L); } @Test void nonLastQcDoesNotAutoFinishWorkOrder() { MesProWorkOrderService workOrderService = mock(MesProWorkOrderService.class); MesProWorkOrderProcessService processService = mock(MesProWorkOrderProcessService.class); MesProFeedbackServiceImpl service = new MesProFeedbackServiceImpl(); ReflectionTestUtils.setField(service, "workOrderService", workOrderService); ReflectionTestUtils.setField(service, "workOrderProcessService", processService); when(processService.getLastWorkOrderProcessByWorkOrderId(28L)) .thenReturn(new MesProWorkOrderProcessDO().setProcessId(13L)); service.checkAndAutoFinishAfterLastQc(new MesProFeedbackDO().setWorkOrderId(28L).setProcessId(11L)); verifyNoInteractions(workOrderService); } private static MesProMpsRespDTO mps(Long id, int planned, int produced, MesProMpsStatusEnum status) { MesProMpsRespDTO mps = new MesProMpsRespDTO(); mps.setId(id); mps.setQuantity(BigDecimal.valueOf(planned)); mps.setQuantityProduced(BigDecimal.valueOf(produced)); mps.setStatus(status.getStatus()); return mps; } }