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());
|
}
|
}
|