Browse Source

✨ feat(mes): 新增采购入库单及相关明细表结构和单元测试

YunaiV 7 months ago
parent
commit
d1d43ca47b

+ 0 - 2
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;
     }
 
-
-
     /**
      * 生成或获取批次
      *

+ 160 - 0
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);
+    }
+
+}

+ 3 - 0
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";

+ 68 - 0
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")
+);