package cn.iocoder.yudao.module.mes.service.qc.ncr;
|
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.module.mes.controller.admin.qc.ncr.vo.MesQcNcrDisposeReqVO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ncr.MesQcNcrDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceLineMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceMapper;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc.MesQcRqcMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesLineMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.scrap.MesWmScrapReceiptMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.transaction.MesWmTransactionMapper;
|
import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
|
import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
|
import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
|
import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
|
import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
|
import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;
|
import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService;
|
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.BeforeAll;
|
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.mockito.InjectMocks;
|
import org.mockito.Mock;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
import java.math.BigDecimal;
|
import java.util.List;
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import static org.junit.jupiter.api.Assertions.*;
|
import static org.mockito.ArgumentMatchers.*;
|
import static org.mockito.Mockito.*;
|
|
@ExtendWith(MockitoExtension.class)
|
class MesQcNcrScrapServiceTest {
|
@BeforeAll static void initializeTableInfo() {
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), "test"),
|
MesWmProductProduceLineDO.class);
|
}
|
@InjectMocks MesQcNcrScrapService service;
|
@Mock MesQcRqcMapper rqc;
|
@Mock MesQcIpqcMapper ipqc;
|
@Mock MesProWorkOrderMapper orders;
|
@Mock MesWmProductProduceLineMapper outputs;
|
@Mock MesWmProductProduceMapper produces;
|
@Mock MesWmReturnSalesLineMapper lines;
|
@Mock MesWmScrapReceiptMapper receipts;
|
@Mock MesWmTransactionMapper transactions;
|
@Mock MesWmTransactionService transactionService;
|
@Mock MesWmWarehouseService warehouse;
|
@Mock MesWmWarehouseAreaService area;
|
|
private MesQcNcrDO ncr() { return new MesQcNcrDO().setId(1L).setCode("NCR1").setQcType(MesQcTypeEnum.RQC.getType())
|
.setQcId(2L).setItemId(3L).setUnqualifiedQuantity(BigDecimal.TEN); }
|
private MesQcRqcDO qc(int source) { return new MesQcRqcDO().setId(2L).setItemId(3L).setSourceDocType(source)
|
.setSourceDocId(4L).setSourceLineId(5L).setBatchCode("B1").setStatus(MesQcStatusEnum.FINISHED.getStatus())
|
.setUnqualifiedQuantity(BigDecimal.TEN); }
|
private MesQcNcrDisposeReqVO request() { var req = new MesQcNcrDisposeReqVO(); req.setWarehouseId(8L); req.setLocationId(9L); req.setAreaId(10L); return req; }
|
|
@Test void rejectsProductionReturn() {
|
when(rqc.selectById(2L)).thenReturn(qc(MesBizTypeConstants.WM_RETURN_ISSUE));
|
assertThrows(ServiceException.class, () -> service.receive(ncr(), request()));
|
verifyNoInteractions(receipts, transactionService);
|
}
|
|
@Test void validatesUnstockedIpqcOutputAndKeepsItsOriginalBatch() {
|
var item = ncr().setQcType(MesQcTypeEnum.IPQC.getType());
|
var qc = new MesQcIpqcDO().setId(2L).setItemId(3L).setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK)
|
.setSourceDocId(11L).setSourceLineId(12L).setWorkOrderId(15L)
|
.setStatus(MesQcStatusEnum.FINISHED.getStatus()).setUnqualifiedQuantity(BigDecimal.TEN);
|
var original = new MesWmProductProduceLineDO().setId(12L).setFeedbackId(11L).setProduceId(13L)
|
.setBatchId(7L).setBatchCode("B1");
|
var failed = new MesWmProductProduceLineDO().setId(14L).setFeedbackId(11L).setProduceId(13L)
|
.setItemId(3L).setQuantity(BigDecimal.TEN).setBatchId(7L).setBatchCode("B1")
|
.setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus());
|
when(ipqc.selectById(2L)).thenReturn(qc);
|
when(outputs.selectById(12L)).thenReturn(original);
|
when(produces.selectById(13L)).thenReturn(new MesWmProductProduceDO().setId(13L).setFeedbackId(11L).setWorkOrderId(15L));
|
when(outputs.selectListByFeedbackId(11L)).thenReturn(List.of(failed));
|
when(orders.selectById(15L)).thenReturn(new MesProWorkOrderDO().setId(15L).setCode("WO1"));
|
var source = service.validateIpqcSource(item);
|
assertEquals(14L, source.sourceLineId());
|
assertEquals(7L, source.batchId());
|
assertEquals("B1", source.batchCode());
|
when(transactions.selectCount(any())).thenReturn(1L);
|
assertThrows(ServiceException.class, () -> service.validateIpqcSource(item));
|
failed.setBatchCode("other");
|
assertThrows(ServiceException.class, () -> service.validateIpqcSource(item));
|
}
|
|
@Test void onlyOneNcrCanClaimTheFailedOutput() {
|
var item = ncr().setQcType(MesQcTypeEnum.IPQC.getType());
|
var source = new MesQcNcrScrapService.IpqcSource(15L, "WO1", 14L, 7L, "B1");
|
when(outputs.update(isNull(), any(Wrapper.class))).thenReturn(1, 0);
|
assertDoesNotThrow(() -> service.claimIpqcSource(item, source));
|
assertThrows(ServiceException.class, () -> service.claimIpqcSource(item.setId(99L), source));
|
verify(outputs, times(2)).update(isNull(), any(Wrapper.class));
|
}
|
|
@Test void recordsCustomerReturnInScrapWarehouseWithOriginalBatch() {
|
when(rqc.selectById(2L)).thenReturn(qc(MesBizTypeConstants.WM_RETURN_SALES));
|
var line = new MesWmReturnSalesLineDO().setId(6L).setReturnId(4L).setRqcId(2L).setItemId(3L)
|
.setQuantity(BigDecimal.TEN).setBatchId(7L).setBatchCode("B1").setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus());
|
when(lines.selectListByReturnId(4L)).thenReturn(List.of(line));
|
when(warehouse.validateWarehouseExists(8L)).thenReturn(new MesWmWarehouseDO().setWarehouseType("废料仓"));
|
var response = service.receive(ncr(), request());
|
assertEquals("SCRAP_RECEIPT", response.getDocType());
|
assertEquals("SCR-N" + MesQcTypeEnum.RQC.getType() + "-6", response.getDocCode());
|
verify(transactionService).createTransaction(argThat(tx -> tx.getItemId().equals(3L) && tx.getBatchId().equals(7L)
|
&& tx.getQuantity().compareTo(BigDecimal.TEN) == 0 && tx.getWarehouseId().equals(8L)));
|
}
|
}
|