云
4 天以前 f02d0df2f1dfc7a8b775cf50d45375e57628a5ef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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)));
    }
}