package cn.iocoder.yudao.module.mes.service.wm.itemreceipt;
|
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
|
import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi;
|
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
|
import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptSaveReqVO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptMapper;
|
import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum;
|
import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService;
|
import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeLineService;
|
import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService;
|
import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
|
import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.context.annotation.Import;
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
|
import jakarta.annotation.Resource;
|
|
import java.math.BigDecimal;
|
import java.time.LocalDateTime;
|
import java.util.Arrays;
|
import java.util.Collections;
|
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
import static org.mockito.ArgumentMatchers.anyList;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.Mockito.*;
|
|
/**
|
* {@link MesWmItemReceiptServiceImpl} 的单元测试
|
*
|
* @author 超级管理员
|
*/
|
@Import(MesWmItemReceiptServiceImpl.class)
|
public class MesWmItemReceiptServiceImplTest extends BaseDbUnitTest {
|
|
@Resource
|
private MesWmItemReceiptServiceImpl itemReceiptService;
|
|
@Resource
|
private MesWmItemReceiptMapper itemReceiptMapper;
|
|
@MockitoBean
|
private MesWmItemReceiptLineService itemReceiptLineService;
|
@MockitoBean
|
private MesWmItemReceiptDetailService itemReceiptDetailService;
|
@MockitoBean
|
private MesWmArrivalNoticeService arrivalNoticeService;
|
@MockitoBean
|
private MesQcIqcService iqcService;
|
@MockitoBean
|
private MesWmTransactionService wmTransactionService;
|
@MockitoBean
|
private MesWmArrivalNoticeLineService arrivalNoticeLineService;
|
@MockitoBean
|
private SrmSupplierApi srmSupplierApi;
|
@MockitoBean
|
private BpmProcessInstanceApi processInstanceApi;
|
@MockitoBean
|
private ErpPurchaseOrderApi purchaseOrderApi;
|
@MockitoBean
|
private MdmItemApi mdmItemApi;
|
|
// ========== createItemReceipt:供应商 / 到货通知单支持手工填写 ==========
|
|
@Test
|
public void testCreateItemReceipt_success_withManualVendorNameAndNoticeCode() {
|
// 准备参数:只手工填写供应商名称与到货通知单号,不选供应商主数据、不选到货通知单
|
MesWmItemReceiptSaveReqVO reqVO = new MesWmItemReceiptSaveReqVO();
|
reqVO.setCode("IR-MANUAL-" + randomLongId());
|
reqVO.setName("手工供应商入库单");
|
reqVO.setVendorId(null);
|
reqVO.setVendorName("某某贸易有限公司");
|
reqVO.setNoticeId(null);
|
reqVO.setNoticeCode("AN2026020001");
|
reqVO.setReceiptDate(LocalDateTime.now());
|
|
// 调用
|
Long id = itemReceiptService.createItemReceipt(reqVO);
|
|
// 断言 1:保存成功,手工填写的内容落库
|
MesWmItemReceiptDO saved = itemReceiptMapper.selectById(id);
|
assertNotNull(saved);
|
assertNull(saved.getVendorId());
|
assertEquals("某某贸易有限公司", saved.getVendorName());
|
assertNull(saved.getNoticeId());
|
assertEquals("AN2026020001", saved.getNoticeCode());
|
// 断言 2:未选择供应商主数据时不校验供应商
|
verify(srmSupplierApi, never()).getSupplier(anyLong());
|
}
|
|
@Test
|
public void testCreateItemReceipt_success_withNoticeIdButManualVendor() {
|
// 准备参数:关联了到货通知单(兼容历史单据),但供应商是手工填写
|
Long noticeId = randomLongId();
|
when(arrivalNoticeService.validateArrivalNoticeReadyForReceipt(eq(noticeId)))
|
.thenReturn(randomPojo(MesWmArrivalNoticeDO.class, o -> o.setVendorId(randomLongId())));
|
|
MesWmItemReceiptSaveReqVO reqVO = new MesWmItemReceiptSaveReqVO();
|
reqVO.setCode("IR-MANUAL-" + randomLongId());
|
reqVO.setName("手工供应商入库单");
|
reqVO.setNoticeId(noticeId);
|
reqVO.setVendorId(null);
|
reqVO.setVendorName("某某贸易有限公司");
|
reqVO.setReceiptDate(LocalDateTime.now());
|
|
// 调用:不应因「供应商与到货通知单不一致」而报错
|
Long id = itemReceiptService.createItemReceipt(reqVO);
|
|
// 断言:保存成功
|
assertNotNull(itemReceiptMapper.selectById(id));
|
}
|
|
@Test
|
public void testCreateItemReceipt_success_withVendorId() {
|
// 准备参数:仍可选择供应商主数据
|
Long vendorId = randomLongId();
|
MesWmItemReceiptSaveReqVO reqVO = new MesWmItemReceiptSaveReqVO();
|
reqVO.setCode("IR-MANUAL-" + randomLongId());
|
reqVO.setName("选择供应商入库单");
|
reqVO.setVendorId(vendorId);
|
reqVO.setReceiptDate(LocalDateTime.now());
|
|
// 调用
|
Long id = itemReceiptService.createItemReceipt(reqVO);
|
|
// 断言 1:保存成功
|
assertNotNull(itemReceiptMapper.selectById(id));
|
// 断言 2:选择了供应商主数据时仍会校验供应商存在
|
verify(srmSupplierApi).getSupplier(eq(vendorId));
|
}
|
|
// ========== finishItemReceipt ==========
|
|
@Test
|
public void testFinishItemReceipt_success_withNoticeId() {
|
// mock 数据:插入一条待入库状态的入库单(有关联到货通知单)
|
Long noticeId = randomLongId();
|
MesWmItemReceiptDO receipt = randomPojo(MesWmItemReceiptDO.class, o -> {
|
o.setStatus(MesWmItemReceiptStatusEnum.APPROVED.getStatus());
|
o.setNoticeId(noticeId);
|
});
|
itemReceiptMapper.insert(receipt);
|
Long receiptId = receipt.getId();
|
|
// mock 明细列表
|
MesWmItemReceiptDetailDO detail1 = randomPojo(MesWmItemReceiptDetailDO.class, o -> {
|
o.setReceiptId(receiptId);
|
o.setQuantity(BigDecimal.valueOf(100));
|
});
|
MesWmItemReceiptDetailDO detail2 = randomPojo(MesWmItemReceiptDetailDO.class, o -> {
|
o.setReceiptId(receiptId);
|
o.setQuantity(BigDecimal.valueOf(50));
|
});
|
when(itemReceiptDetailService.getItemReceiptDetailListByReceiptId(eq(receiptId)))
|
.thenReturn(Arrays.asList(detail1, detail2));
|
|
// 调用
|
itemReceiptService.finishItemReceipt(receiptId);
|
|
// 断言 1:状态更新为已完成
|
MesWmItemReceiptDO updated = itemReceiptMapper.selectById(receiptId);
|
assertEquals(MesWmItemReceiptStatusEnum.FINISHED.getStatus(), updated.getStatus());
|
// 断言 2:库存事务被创建(2 条明细)
|
verify(wmTransactionService).createTransactionList(anyList());
|
// 断言 3:到货通知单被完成
|
verify(arrivalNoticeService).finishArrivalNotice(eq(noticeId));
|
}
|
|
@Test
|
public void testFinishItemReceipt_success_withoutNoticeId() {
|
// mock 数据:插入一条待入库状态的入库单(无关联到货通知单)
|
MesWmItemReceiptDO receipt = randomPojo(MesWmItemReceiptDO.class, o -> {
|
o.setStatus(MesWmItemReceiptStatusEnum.APPROVED.getStatus());
|
o.setNoticeId(null); // 无到货通知单
|
});
|
itemReceiptMapper.insert(receipt);
|
Long receiptId = receipt.getId();
|
|
// mock 空明细
|
when(itemReceiptDetailService.getItemReceiptDetailListByReceiptId(eq(receiptId)))
|
.thenReturn(Collections.emptyList());
|
|
// 调用
|
itemReceiptService.finishItemReceipt(receiptId);
|
|
// 断言 1:状态更新为已完成
|
MesWmItemReceiptDO updated = itemReceiptMapper.selectById(receiptId);
|
assertEquals(MesWmItemReceiptStatusEnum.FINISHED.getStatus(), updated.getStatus());
|
// 断言 2:库存事务仍被调用(空列表)
|
verify(wmTransactionService).createTransactionList(anyList());
|
// 断言 3:到货通知单完成方法不被调用
|
verify(arrivalNoticeService, never()).finishArrivalNotice(any());
|
}
|
|
@Test
|
public void testFinishItemReceipt_notExists() {
|
// 准备参数
|
Long receiptId = randomLongId();
|
|
// 调用,并断言异常
|
assertServiceException(
|
() -> itemReceiptService.finishItemReceipt(receiptId),
|
WM_ITEM_RECEIPT_NOT_EXISTS);
|
}
|
|
@Test
|
public void testFinishItemReceipt_statusNotApproved() {
|
// mock 数据:插入一条草稿状态
|
MesWmItemReceiptDO receipt = randomPojo(MesWmItemReceiptDO.class, o -> {
|
o.setStatus(MesWmItemReceiptStatusEnum.PREPARE.getStatus());
|
});
|
itemReceiptMapper.insert(receipt);
|
|
// 调用,并断言异常
|
assertServiceException(
|
() -> itemReceiptService.finishItemReceipt(receipt.getId()),
|
WM_ITEM_RECEIPT_STATUS_ERROR);
|
}
|
|
@Test
|
public void testFinishItemReceipt_statusAlreadyFinished() {
|
// mock 数据:插入一条已完成状态
|
MesWmItemReceiptDO receipt = randomPojo(MesWmItemReceiptDO.class, o -> {
|
o.setStatus(MesWmItemReceiptStatusEnum.FINISHED.getStatus());
|
});
|
itemReceiptMapper.insert(receipt);
|
|
// 调用,并断言异常
|
assertServiceException(
|
() -> itemReceiptService.finishItemReceipt(receipt.getId()),
|
WM_ITEM_RECEIPT_STATUS_ERROR);
|
}
|
|
}
|