From d1d43ca47bda866e9152b737420b20fc69b0c67f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 29 Mar 2026 11:02:34 +0800 Subject: [PATCH] ✨ feat(mes): 新增采购入库单及相关明细表结构和单元测试 --- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java | 2 -- yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImplTest.java | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/test/resources/sql/clean.sql | 3 +++ yudao-module-mes/src/test/resources/sql/create_tables.sql | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImplTest.java diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java index 8580f12..a32dabe 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java @@ -167,8 +167,6 @@ public class MesWmItemReceiptLineServiceImpl implements MesWmItemReceiptLineServ return line; } - - /** * 生成或获取批次 * diff --git a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImplTest.java b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImplTest.java new file mode 100644 index 0000000..fe59cc8 --- /dev/null +++ b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImplTest.java @@ -0,0 +1,160 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemreceipt; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +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.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +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.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.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 MesMdVendorService vendorService; + @MockitoBean + private MesQcIqcService iqcService; + @MockitoBean + private MesWmTransactionService wmTransactionService; + + // ========== 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); + } + +} diff --git a/yudao-module-mes/src/test/resources/sql/clean.sql b/yudao-module-mes/src/test/resources/sql/clean.sql index b458b3c..814d4f3 100644 --- a/yudao-module-mes/src/test/resources/sql/clean.sql +++ b/yudao-module-mes/src/test/resources/sql/clean.sql @@ -9,3 +9,6 @@ DELETE FROM "mes_pro_feedback"; DELETE FROM "mes_wm_product_produce"; DELETE FROM "mes_wm_product_produce_line"; DELETE FROM "mes_wm_product_produce_detail"; +DELETE FROM "mes_wm_item_receipt"; +DELETE FROM "mes_wm_item_receipt_line"; +DELETE FROM "mes_wm_item_receipt_detail"; diff --git a/yudao-module-mes/src/test/resources/sql/create_tables.sql b/yudao-module-mes/src/test/resources/sql/create_tables.sql index 5074186..8e2dfa3 100644 --- a/yudao-module-mes/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mes/src/test/resources/sql/create_tables.sql @@ -449,3 +449,71 @@ CREATE TABLE IF NOT EXISTS "mes_wm_return_sales_line" ( PRIMARY KEY ("id") ); +-- ---------------------------- +-- MES 采购入库单 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_item_receipt" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) NOT NULL, + "name" varchar(255) DEFAULT NULL, + "iqc_id" bigint DEFAULT NULL, + "notice_id" bigint DEFAULT NULL, + "vendor_id" bigint DEFAULT NULL, + "receipt_date" timestamp DEFAULT NULL, + "status" tinyint NOT NULL DEFAULT 0, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 采购入库单行 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_item_receipt_line" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "receipt_id" bigint NOT NULL, + "arrival_notice_line_id" bigint DEFAULT NULL, + "item_id" bigint NOT NULL, + "received_quantity" decimal(14,2) DEFAULT NULL, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(255) DEFAULT NULL, + "production_date" timestamp DEFAULT NULL, + "expire_date" timestamp DEFAULT NULL, + "lot_number" varchar(128) DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 采购入库明细 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_item_receipt_detail" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "line_id" bigint NOT NULL, + "receipt_id" bigint NOT NULL, + "item_id" bigint NOT NULL, + "quantity" decimal(14,2) DEFAULT NULL, + "batch_id" bigint DEFAULT NULL, + "warehouse_id" bigint DEFAULT NULL, + "location_id" bigint DEFAULT NULL, + "area_id" bigint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); -- libgit2 0.21.4