Commit 627bbba382db3c4dd53bc4475d16212eff38f27a

Authored by YunaiV
1 parent cc29c141

✨ feat(mes): 新增库存记录和批次编码字段,优化退料单功能

在退料单相关的多个类中新增库存记录 ID 和批次编码字段,以支持更精确的库存管理和数据校验。同时,更新了相关的表单和服务逻辑,确保新字段的正确使用和验证。
Showing 15 changed files with 85 additions and 7 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueLineController.java
@@ -41,7 +41,6 @@ public class MesWmReturnIssueLineController { @@ -41,7 +41,6 @@ public class MesWmReturnIssueLineController {
41 41
42 @Resource 42 @Resource
43 private MesMdItemService itemService; 43 private MesMdItemService itemService;
44 -  
45 @Resource 44 @Resource
46 private MesMdUnitMeasureService unitMeasureService; 45 private MesMdUnitMeasureService unitMeasureService;
47 46
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLineRespVO.java
@@ -31,12 +31,18 @@ public class MesWmReturnIssueLineRespVO { @@ -31,12 +31,18 @@ public class MesWmReturnIssueLineRespVO {
31 @Schema(description = "计量单位名称", example = "千克") 31 @Schema(description = "计量单位名称", example = "千克")
32 private String unitMeasureName; 32 private String unitMeasureName;
33 33
  34 + @Schema(description = "库存记录 ID", example = "1")
  35 + private Long materialStockId;
  36 +
34 @Schema(description = "退料数量", example = "100.00") 37 @Schema(description = "退料数量", example = "100.00")
35 private BigDecimal quantity; 38 private BigDecimal quantity;
36 39
37 @Schema(description = "批次 ID", example = "1") 40 @Schema(description = "批次 ID", example = "1")
38 private Long batchId; 41 private Long batchId;
39 42
  43 + @Schema(description = "批次编码", example = "BAT202601001")
  44 + private String batchCode;
  45 +
40 @Schema(description = "是否需要质检", example = "false") 46 @Schema(description = "是否需要质检", example = "false")
41 private Boolean rqcCheckFlag; 47 private Boolean rqcCheckFlag;
42 48
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLineSaveReqVO.java
@@ -27,9 +27,15 @@ public class MesWmReturnIssueLineSaveReqVO { @@ -27,9 +27,15 @@ public class MesWmReturnIssueLineSaveReqVO {
27 @DecimalMin(value = "0", inclusive = false, message = "退料数量必须大于 0") 27 @DecimalMin(value = "0", inclusive = false, message = "退料数量必须大于 0")
28 private BigDecimal quantity; 28 private BigDecimal quantity;
29 29
  30 + @Schema(description = "库存记录 ID", example = "1")
  31 + private Long materialStockId;
  32 +
30 @Schema(description = "批次 ID", example = "1") 33 @Schema(description = "批次 ID", example = "1")
31 private Long batchId; 34 private Long batchId;
32 35
  36 + @Schema(description = "批次编码", example = "BCH20260330001")
  37 + private String batchCode;
  38 +
33 @Schema(description = "是否需要质检", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") 39 @Schema(description = "是否需要质检", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
34 @NotNull(message = "是否需要质检不能为空") 40 @NotNull(message = "是否需要质检不能为空")
35 private Boolean rqcCheckFlag; 41 private Boolean rqcCheckFlag;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDO.java
@@ -43,7 +43,6 @@ public class MesWmReturnIssueDO extends BaseDO { @@ -43,7 +43,6 @@ public class MesWmReturnIssueDO extends BaseDO {
43 * 关联 {@link MesProWorkOrderDO#getId()} 43 * 关联 {@link MesProWorkOrderDO#getId()}
44 */ 44 */
45 private Long workOrderId; 45 private Long workOrderId;
46 - // TODO @芋艿:可能不需要这个字段。界面上没有;  
47 /** 46 /**
48 * 工作站 ID 47 * 工作站 ID
49 * 48 *
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueLineDO.java
@@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue; @@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; 4 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO;
5 import com.baomidou.mybatisplus.annotation.KeySequence; 8 import com.baomidou.mybatisplus.annotation.KeySequence;
6 import com.baomidou.mybatisplus.annotation.TableId; 9 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 10 import com.baomidou.mybatisplus.annotation.TableName;
@@ -35,6 +38,8 @@ public class MesWmReturnIssueLineDO extends BaseDO { @@ -35,6 +38,8 @@ public class MesWmReturnIssueLineDO extends BaseDO {
35 private Long issueId; 38 private Long issueId;
36 /** 39 /**
37 * 库存记录 ID 40 * 库存记录 ID
  41 + *
  42 + * 关联 {@link MesWmMaterialStockDO#getId()}
38 */ 43 */
39 private Long materialStockId; 44 private Long materialStockId;
40 /** 45 /**
@@ -49,10 +54,20 @@ public class MesWmReturnIssueLineDO extends BaseDO { @@ -49,10 +54,20 @@ public class MesWmReturnIssueLineDO extends BaseDO {
49 private BigDecimal quantity; 54 private BigDecimal quantity;
50 /** 55 /**
51 * 批次 ID 56 * 批次 ID
  57 + *
  58 + * 关联 {@link MesWmBatchDO#getId()}
52 */ 59 */
53 private Long batchId; 60 private Long batchId;
54 /** 61 /**
  62 + * 批次编码
  63 + *
  64 + * 关联 {@link MesWmBatchDO#getCode()}
  65 + */
  66 + private String batchCode;
  67 + /**
55 * 退货检验单 ID 68 * 退货检验单 ID
  69 + *
  70 + * 关联 {@link MesQcRqcDO#getId()}
56 */ 71 */
57 private Long rqcId; 72 private Long rqcId;
58 /** 73 /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueDetailMapper.java
@@ -24,4 +24,8 @@ public interface MesWmReturnIssueDetailMapper extends BaseMapperX<MesWmReturnIss @@ -24,4 +24,8 @@ public interface MesWmReturnIssueDetailMapper extends BaseMapperX<MesWmReturnIss
24 delete(MesWmReturnIssueDetailDO::getIssueId, issueId); 24 delete(MesWmReturnIssueDetailDO::getIssueId, issueId);
25 } 25 }
26 26
  27 + default void deleteByLineId(Long lineId) {
  28 + delete(MesWmReturnIssueDetailDO::getLineId, lineId);
  29 + }
  30 +
27 } 31 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueMapper.java
@@ -23,4 +23,8 @@ public interface MesWmReturnIssueMapper extends BaseMapperX<MesWmReturnIssueDO> @@ -23,4 +23,8 @@ public interface MesWmReturnIssueMapper extends BaseMapperX<MesWmReturnIssueDO>
23 .orderByDesc(MesWmReturnIssueDO::getId)); 23 .orderByDesc(MesWmReturnIssueDO::getId));
24 } 24 }
25 25
  26 + default MesWmReturnIssueDO selectByCode(String code) {
  27 + return selectOne(MesWmReturnIssueDO::getCode, code);
  28 + }
  29 +
26 } 30 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -468,6 +468,7 @@ public interface ErrorCodeConstants { @@ -468,6 +468,7 @@ public interface ErrorCodeConstants {
468 ErrorCode WM_RETURN_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_710_200, "生产退料单明细不存在"); 468 ErrorCode WM_RETURN_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_710_200, "生产退料单明细不存在");
469 ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_710_201, "退料明细数量必须大于0"); 469 ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_710_201, "退料明细数量必须大于0");
470 ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_710_202, "退料明细总数量不能超过退料单行数量"); 470 ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_710_202, "退料明细总数量不能超过退料单行数量");
  471 + ErrorCode WM_RETURN_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_710_203, "退料单编码已存在");
471 472
472 // ========== MES 仓库管理-供应商退货单(1-040-711-000) ========== 473 // ========== MES 仓库管理-供应商退货单(1-040-711-000) ==========
473 ErrorCode WM_RETURN_VENDOR_NOT_EXISTS = new ErrorCode(1_040_711_000, "供应商退货单不存在"); 474 ErrorCode WM_RETURN_VENDOR_NOT_EXISTS = new ErrorCode(1_040_711_000, "供应商退货单不存在");
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java
@@ -20,6 +20,7 @@ public enum MesMdAutoCodeRuleCodeEnum { @@ -20,6 +20,7 @@ public enum MesMdAutoCodeRuleCodeEnum {
20 WM_ARRIVAL_NOTICE_CODE("WM_ARRIVAL_NOTICE_CODE", "到货通知单编码"), 20 WM_ARRIVAL_NOTICE_CODE("WM_ARRIVAL_NOTICE_CODE", "到货通知单编码"),
21 WM_ITEM_RECEIPT_CODE("WM_ITEM_RECEIPT_CODE", "采购入库单编码"), 21 WM_ITEM_RECEIPT_CODE("WM_ITEM_RECEIPT_CODE", "采购入库单编码"),
22 WM_RETURN_VENDOR_CODE("WM_RETURN_VENDOR_CODE", "采购退货单编码"), 22 WM_RETURN_VENDOR_CODE("WM_RETURN_VENDOR_CODE", "采购退货单编码"),
  23 + WM_RETURN_ISSUE_CODE("WM_RETURN_ISSUE_CODE", "生产退料单编码"),
23 WM_SN_CODE("WM_SN_CODE", "SN 码"), 24 WM_SN_CODE("WM_SN_CODE", "SN 码"),
24 WM_PACKAGE_CODE("WM_PACKAGE_CODE", "装箱单编码"), 25 WM_PACKAGE_CODE("WM_PACKAGE_CODE", "装箱单编码"),
25 WM_BATCH_CODE("WM_BATCH_CODE", "批次编码"), 26 WM_BATCH_CODE("WM_BATCH_CODE", "批次编码"),
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailService.java
@@ -64,4 +64,11 @@ public interface MesWmReturnIssueDetailService { @@ -64,4 +64,11 @@ public interface MesWmReturnIssueDetailService {
64 */ 64 */
65 void deleteReturnIssueDetailByIssueId(Long issueId); 65 void deleteReturnIssueDetailByIssueId(Long issueId);
66 66
  67 + /**
  68 + * 根据行 ID 删除明细
  69 + *
  70 + * @param lineId 行 ID
  71 + */
  72 + void deleteReturnIssueDetailByLineId(Long lineId);
  73 +
67 } 74 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java
@@ -87,6 +87,11 @@ public class MesWmReturnIssueDetailServiceImpl implements MesWmReturnIssueDetail @@ -87,6 +87,11 @@ public class MesWmReturnIssueDetailServiceImpl implements MesWmReturnIssueDetail
87 issueDetailMapper.deleteByIssueId(issueId); 87 issueDetailMapper.deleteByIssueId(issueId);
88 } 88 }
89 89
  90 + @Override
  91 + public void deleteReturnIssueDetailByLineId(Long lineId) {
  92 + issueDetailMapper.deleteByLineId(lineId);
  93 + }
  94 +
90 private void validateReturnIssueDetailExists(Long id) { 95 private void validateReturnIssueDetailExists(Long id) {
91 if (issueDetailMapper.selectById(id) == null) { 96 if (issueDetailMapper.selectById(id) == null) {
92 throw exception(WM_RETURN_ISSUE_DETAIL_NOT_EXISTS); 97 throw exception(WM_RETURN_ISSUE_DETAIL_NOT_EXISTS);
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImpl.java
@@ -40,6 +40,9 @@ public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineServ @@ -40,6 +40,9 @@ public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineServ
40 private MesWmReturnIssueService issueService; 40 private MesWmReturnIssueService issueService;
41 @Resource 41 @Resource
42 private MesMdItemService itemService; 42 private MesMdItemService itemService;
  43 + @Resource
  44 + @Lazy
  45 + private MesWmReturnIssueDetailService issueDetailService;
43 46
44 @Override 47 @Override
45 public Long createReturnIssueLine(MesWmReturnIssueLineSaveReqVO createReqVO) { 48 public Long createReturnIssueLine(MesWmReturnIssueLineSaveReqVO createReqVO) {
@@ -69,8 +72,12 @@ public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineServ @@ -69,8 +72,12 @@ public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineServ
69 @Override 72 @Override
70 public void deleteReturnIssueLine(Long id) { 73 public void deleteReturnIssueLine(Long id) {
71 // 校验存在 74 // 校验存在
72 - validateReturnIssueLineExists(id);  
73 - // 删除 75 + MesWmReturnIssueLineDO line = validateReturnIssueLineExists(id);
  76 + // 校验主单为草稿状态才允许删除行
  77 + issueService.validateReturnIssueExistsAndPrepare(line.getIssueId());
  78 + // 级联删除该行的明细
  79 + issueDetailService.deleteReturnIssueDetailByLineId(id);
  80 + // 删除行
74 issueLineMapper.deleteById(id); 81 issueLineMapper.deleteById(id);
75 } 82 }
76 83
@@ -107,8 +114,8 @@ public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineServ @@ -107,8 +114,8 @@ public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineServ
107 * 校验保存时的关联数据 114 * 校验保存时的关联数据
108 */ 115 */
109 private MesWmReturnIssueDO validateReturnIssueLineSaveData(MesWmReturnIssueLineSaveReqVO reqVO) { 116 private MesWmReturnIssueDO validateReturnIssueLineSaveData(MesWmReturnIssueLineSaveReqVO reqVO) {
110 - // 校验父数据存在  
111 - MesWmReturnIssueDO issue = issueService.validateReturnIssueExists(reqVO.getIssueId()); 117 + // 校验父数据存在 + 草稿状态
  118 + MesWmReturnIssueDO issue = issueService.validateReturnIssueExistsAndPrepare(reqVO.getIssueId());
112 // 校验物料存在 119 // 校验物料存在
113 itemService.validateItemExists(reqVO.getItemId()); 120 itemService.validateItemExists(reqVO.getItemId());
114 return issue; 121 return issue;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueService.java
@@ -58,6 +58,14 @@ public interface MesWmReturnIssueService { @@ -58,6 +58,14 @@ public interface MesWmReturnIssueService {
58 MesWmReturnIssueDO validateReturnIssueExists(Long id); 58 MesWmReturnIssueDO validateReturnIssueExists(Long id);
59 59
60 /** 60 /**
  61 + * 校验生产退料单存在且为准备中状态
  62 + *
  63 + * @param id 编号
  64 + * @return 生产退料单
  65 + */
  66 + MesWmReturnIssueDO validateReturnIssueExistsAndPrepare(Long id);
  67 +
  68 + /**
61 * 提交生产退料单(草稿 → 待检验/待上架) 69 * 提交生产退料单(草稿 → 待检验/待上架)
62 * 70 *
63 * @param id 编号 71 * @param id 编号
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java
@@ -254,7 +254,8 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService { @@ -254,7 +254,8 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService {
254 /** 254 /**
255 * 校验生产退料单存在且为准备中状态 255 * 校验生产退料单存在且为准备中状态
256 */ 256 */
257 - private MesWmReturnIssueDO validateReturnIssueExistsAndPrepare(Long id) { 257 + @Override
  258 + public MesWmReturnIssueDO validateReturnIssueExistsAndPrepare(Long id) {
258 MesWmReturnIssueDO issue = validateReturnIssueExists(id); 259 MesWmReturnIssueDO issue = validateReturnIssueExists(id);
259 if (ObjUtil.notEqual(MesWmReturnIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) { 260 if (ObjUtil.notEqual(MesWmReturnIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) {
260 throw exception(WM_RETURN_ISSUE_NOT_PREPARE); 261 throw exception(WM_RETURN_ISSUE_NOT_PREPARE);
@@ -269,9 +270,23 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService { @@ -269,9 +270,23 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService {
269 } 270 }
270 271
271 /** 272 /**
  273 + * 校验编码唯一性
  274 + */
  275 + private void validateCodeUnique(Long id, String code) {
  276 + MesWmReturnIssueDO issue = issueMapper.selectByCode(code);
  277 + if (issue == null) {
  278 + return;
  279 + }
  280 + if (ObjUtil.notEqual(id, issue.getId())) {
  281 + throw exception(WM_RETURN_ISSUE_CODE_DUPLICATE);
  282 + }
  283 + }
  284 +
  285 + /**
272 * 校验保存时的关联数据 286 * 校验保存时的关联数据
273 */ 287 */
274 private void validateReturnIssueSaveData(MesWmReturnIssueSaveReqVO reqVO) { 288 private void validateReturnIssueSaveData(MesWmReturnIssueSaveReqVO reqVO) {
  289 + validateCodeUnique(reqVO.getId(), reqVO.getCode());
275 workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); 290 workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId());
276 if (reqVO.getWorkstationId() != null) { 291 if (reqVO.getWorkstationId() != null) {
277 workstationService.validateWorkstationExists(reqVO.getWorkstationId()); 292 workstationService.validateWorkstationExists(reqVO.getWorkstationId());
yudao-module-mes/src/test/resources/sql/create_tables.sql
@@ -414,6 +414,7 @@ CREATE TABLE IF NOT EXISTS "mes_wm_return_issue_line" ( @@ -414,6 +414,7 @@ CREATE TABLE IF NOT EXISTS "mes_wm_return_issue_line" (
414 "item_id" bigint NOT NULL, 414 "item_id" bigint NOT NULL,
415 "quantity" decimal(12,2) NOT NULL DEFAULT 0.00, 415 "quantity" decimal(12,2) NOT NULL DEFAULT 0.00,
416 "batch_id" bigint DEFAULT NULL, 416 "batch_id" bigint DEFAULT NULL,
  417 + "batch_code" varchar(255) DEFAULT NULL,
417 "rqc_id" bigint DEFAULT NULL, 418 "rqc_id" bigint DEFAULT NULL,
418 "rqc_check_flag" bit NOT NULL DEFAULT FALSE, 419 "rqc_check_flag" bit NOT NULL DEFAULT FALSE,
419 "quality_status" int DEFAULT NULL, 420 "quality_status" int DEFAULT NULL,