package cn.iocoder.yudao.module.erp.service.sale; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderMapper; import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderItemMapper; import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi; import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsCreateReqDTO; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import java.math.BigDecimal; import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; class ErpSaleOrderAutoApproveTest extends BaseMockitoUnitTest { @InjectMocks private ErpSaleOrderServiceImpl service; @Mock private ErpSaleOrderMapper saleOrderMapper; @Mock private ErpSaleOrderItemMapper saleOrderItemMapper; @Mock private BpmProcessInstanceApi processInstanceApi; @Mock private MesProMpsApi mpsApi; private ErpSaleOrderDO prepareOrder(int status, boolean withItems) { ErpSaleOrderDO order = new ErpSaleOrderDO().setId(1L).setNo("SO-1").setStatus(status); when(saleOrderMapper.selectById(1L)).thenReturn(order); if (withItems) { when(saleOrderItemMapper.selectListByOrderId(1L)).thenReturn(List.of( new ErpSaleOrderItemDO().setId(10L).setProductId(20L) .setCount(BigDecimal.TEN).setNeedProduction(1))); } return order; } @Test void globalAutoApproveWithoutModelApprovesAndCreatesProductionPlan() { ErpSaleOrderDO order = prepareOrder(ErpAuditStatus.DRAFT.getStatus(), true); when(processInstanceApi.isGlobalAutoApprove()).thenReturn(true); when(mpsApi.createMps(any())).thenReturn(100L); doAnswer(invocation -> { ErpSaleOrderDO update = invocation.getArgument(0); order.setStatus(update.getStatus()); return 1; }).when(saleOrderMapper).updateById(any(ErpSaleOrderDO.class)); service.submitSaleOrder(1L, "no_model", 2L); assertEquals(ErpAuditStatus.APPROVE.getStatus(), order.getStatus()); verify(processInstanceApi, never()).createProcessInstance(any(), any()); verify(mpsApi).createMps(argThat((MesProMpsCreateReqDTO request) -> request.getSaleOrderId().equals(1L) && request.getSaleOrderItemId().equals(10L))); verify(saleOrderItemMapper).updateById(argThat((ErpSaleOrderItemDO item) -> item.getId().equals(10L) && item.getMpsId().equals(100L))); } @Test void switchOffStillStartsNormalApproval() { prepareOrder(ErpAuditStatus.DRAFT.getStatus(), true); when(processInstanceApi.createProcessInstance(eq(2L), any())).thenReturn("process-1"); service.submitSaleOrder(1L, "sale_order_approve", 2L); verify(saleOrderMapper).updateById(argThat((ErpSaleOrderDO update) -> ErpAuditStatus.APPROVING.getStatus().equals(update.getStatus()) && "process-1".equals(update.getProcessInstanceId()))); verifyNoInteractions(mpsApi); } @Test void switchOffWithoutModelStillFails() { prepareOrder(ErpAuditStatus.DRAFT.getStatus(), true); when(processInstanceApi.createProcessInstance(eq(2L), any())) .thenThrow(new IllegalStateException("流程定义不存在")); assertThrows(IllegalStateException.class, () -> service.submitSaleOrder(1L, "no_model", 2L)); verify(saleOrderMapper, never()).updateById(any(ErpSaleOrderDO.class)); verifyNoInteractions(mpsApi); } @Test void cannotSubmitAlreadyApprovedOrder() { prepareOrder(ErpAuditStatus.APPROVE.getStatus(), false); assertThrows(ServiceException.class, () -> service.submitSaleOrder(1L, "no_model", 2L)); verifyNoInteractions(processInstanceApi, mpsApi); } @Test void cannotSubmitOrderWithoutItems() { prepareOrder(ErpAuditStatus.DRAFT.getStatus(), false); when(saleOrderItemMapper.selectListByOrderId(1L)).thenReturn(List.of()); assertThrows(ServiceException.class, () -> service.submitSaleOrder(1L, "no_model", 2L)); verifyNoInteractions(processInstanceApi, mpsApi); } }