云
20 小时以前 704265308b1227dbada5a36b2027b588c062ded2
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
package cn.iocoder.yudao.module.mes.service.pro.bagcode;
 
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.mes.controller.admin.pro.pallet.vo.*;
import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchPreGenerateReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.pallet.MesProPalletDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.pallet.MesProPalletMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.batch.MesProBatchMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode.MesProBagCodeMapper;
import cn.iocoder.yudao.module.mes.dal.redis.MesCodeRedisDAO;
import cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletServiceImpl;
import cn.iocoder.yudao.module.mes.service.pro.batch.MesProBatchServiceImpl;
import cn.iocoder.yudao.module.mes.framework.qrcode.MesProQrLabelBuilder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.List;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
 
class PalletBatchBusinessCodeTest {
    private final MesProPalletServiceImpl palletService = new MesProPalletServiceImpl();
    private final MesProBatchServiceImpl batchService = new MesProBatchServiceImpl();
    private final MesProPalletMapper pallets = mock(MesProPalletMapper.class);
    private final MesProBatchMapper batches = mock(MesProBatchMapper.class);
    private final MesProBagCodeMapper bags = mock(MesProBagCodeMapper.class);
    private final MesCodeRedisDAO codes = mock(MesCodeRedisDAO.class);
 
    @BeforeEach void setup() {
        ReflectionTestUtils.setField(palletService, "palletMapper", pallets);
        ReflectionTestUtils.setField(palletService, "batchMapper", batches);
        ReflectionTestUtils.setField(palletService, "bagCodeMapper", bags);
        ReflectionTestUtils.setField(palletService, "codeRedisDao", codes);
        ReflectionTestUtils.setField(palletService,"integrityService",mock(cn.iocoder.yudao.module.mes.service.trace.integrity.MesTraceIntegrityService.class));
        ReflectionTestUtils.setField(batchService, "batchMapper", batches);
        ReflectionTestUtils.setField(batchService, "codeRedisDao", codes);
        AtomicLong sequence = new AtomicLong(1000000000000000L);
        when(codes.generate()).thenAnswer(invocation -> String.valueOf(sequence.incrementAndGet()));
    }
 
    @Test void preGeneratedPalletsAndBatchesAlreadyHaveIndependentBusinessCodes() {
        var palletReq = new MesProPalletPreGenerateReqVO(); palletReq.setCount(2);
        var batchReq = new MesProBatchPreGenerateReqVO(); batchReq.setCount(2);
        var values = new java.util.HashSet<String>();
        palletService.preGeneratePallet(palletReq).forEach(record -> {
            assertTrue(values.add(record.getTempCode())); assertTrue(values.add(record.getBusinessCode()));
        });
        batchService.preGenerateBatch(batchReq).forEach(record -> {
            assertTrue(values.add(record.getTempCode())); assertTrue(values.add(record.getBusinessCode()));
        });
        assertEquals(8, values.size());
        assertTrue(values.stream().allMatch(code -> code.matches("[0-9]{16}")));
        verify(pallets).insertBatch(anyCollection());
        verify(batches, times(2)).insert(any(MesProBatchDO.class));
        // 预生成只能写入新记录,不应读取或截取数据库中的旧临时码。
        verifyNoMoreInteractions(pallets, batches);
    }
 
    @Test @SuppressWarnings({"unchecked", "rawtypes"})
    void directPalletCreationCreatesBothCodes() {
        when(batches.selectById(2L)).thenReturn(new MesProBatchDO().setId(2L).setCode("batch").setStatus(20));
        var req = new MesProPalletBatchCreateReqVO(); req.setBatchId(2L); req.setCount(1);
        palletService.batchCreatePallet(req);
        ArgumentCaptor<Collection<MesProPalletDO>> saved = ArgumentCaptor.forClass((Class) Collection.class);
        verify(pallets).insertBatch(saved.capture());
        var pallet = saved.getValue().iterator().next();
        assertNotNull(pallet.getBusinessCode()); assertNotEquals(pallet.getCode(), pallet.getBusinessCode());
    }
 
    @Test void batchBindingKeepsBusinessCodeAndCopiesActualFormalCodeToBags() {
        var pallet = new MesProPalletDO().setId(1L).setItemId(3L).setTempCode("1111111111111111").setBusinessCode("2222222222222222").setStatus(10);
        when(pallets.selectByIdForUpdate(1L)).thenReturn(pallet);
        when(batches.selectByIdForUpdate(2L)).thenReturn(new MesProBatchDO().setId(2L).setCode("BATCH").setStatus(20));
        var req = new MesProPalletBindBatchReqVO(); req.setBatchId(2L); req.setIds(List.of(1L));
        palletService.bindBatch(req);
        var update = ArgumentCaptor.forClass(MesProPalletDO.class);
        verify(pallets).updateById(update.capture());
        assertNull(update.getValue().getBusinessCode()); // MyBatis ignores null fields, so stable business code is retained.
        assertEquals("2222222222222222", pallet.getBusinessCode());
        verify(bags).updatePalletCodeByPalletId(1L, update.getValue().getCode());
    }
 
    @Test void supplementationNeverChangesPreviouslyIssuedPalletOrBatchCode() {
        when(pallets.selectByIdForUpdate(1L)).thenReturn(new MesProPalletDO().setId(1L).setStatus(10).setBusinessCode("1111111111111111"));
        when(batches.selectByIdForUpdate(2L)).thenReturn(new MesProBatchDO().setId(2L).setStatus(20).setBusinessCode("2222222222222222"));
        assertEquals(0, palletService.generateBusinessCodes(List.of(1L, 1L)));
        assertEquals(0, batchService.generateBusinessCodes(List.of(2L)));
        verifyNoInteractions(codes);
        verify(pallets, never()).updateById(any(MesProPalletDO.class));
        verify(batches, never()).updateById(any(MesProBatchDO.class));
    }
 
    @Test void supplementationRejectsCanceledAndMissingBeforeWritingAnyCode() {
        when(pallets.selectByIdForUpdate(1L)).thenReturn(new MesProPalletDO().setId(1L).setStatus(10));
        when(pallets.selectByIdForUpdate(2L)).thenReturn(new MesProPalletDO().setId(2L).setStatus(20));
        when(batches.selectByIdForUpdate(1L)).thenReturn(new MesProBatchDO().setId(1L).setStatus(40));
        assertThrows(ServiceException.class, () -> palletService.generateBusinessCodes(List.of(1L, 2L)));
        assertThrows(ServiceException.class, () -> batchService.generateBusinessCodes(List.of(1L)));
        assertThrows(ServiceException.class, () -> batchService.generateBusinessCodes(List.of(3L)));
        verifyNoInteractions(codes);
        verify(pallets, never()).updateById(any(MesProPalletDO.class));
    }
 
    @Test void publicQueryRemainsSeparateFromInternalBusinessQuery() {
        palletService.getPalletByCode("old"); batchService.getBatchByCode("old");
        verify(pallets).selectByCode("old"); verify(pallets).selectByTempCode("old");
        verify(batches).selectByCode("old"); verify(batches).selectByTempCode("old");
        palletService.getPalletByScanCode("business"); batchService.getBatchByScanCode("business");
        verify(pallets).selectByScanCode("business"); verify(batches).selectByScanCode("business");
        assertEquals("1111111111111111", MesProQrLabelBuilder.buildPalletBusinessCodeLabel(
                new MesProPalletDO().setBusinessCode("1111111111111111")).getCode());
        assertEquals("2222222222222222", MesProQrLabelBuilder.buildBatchBusinessCodeLabel(
                new MesProBatchDO().setBusinessCode("2222222222222222")).getCode());
    }
}