Commit d6d6887bdffe1be5be08f00e27f7bedd41e77478

Authored by YunaiV
1 parent fa473f7d

✨ feat(mes): 将质量状态字段类型更新为整型,优化数据一致性

Showing 46 changed files with 970 additions and 127 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java
@@ -33,8 +33,8 @@ public class MesQcOqcRespVO { @@ -33,8 +33,8 @@ public class MesQcOqcRespVO {
33 @Schema(description = "来源单据 ID", example = "200") 33 @Schema(description = "来源单据 ID", example = "200")
34 private Long sourceDocId; 34 private Long sourceDocId;
35 35
36 - @Schema(description = "来源单据类型", example = "SALES")  
37 - private String sourceDocType; 36 + @Schema(description = "来源单据类型", example = "118")
  37 + private Integer sourceDocType;
38 38
39 @Schema(description = "来源单据编号", example = "SO20250101001") 39 @Schema(description = "来源单据编号", example = "SO20250101001")
40 private String sourceDocCode; 40 private String sourceDocCode;
@@ -88,15 +88,15 @@ public class MesQcOqcRespVO { @@ -88,15 +88,15 @@ public class MesQcOqcRespVO {
88 88
89 @Schema(description = "本次检测数量", example = "10") 89 @Schema(description = "本次检测数量", example = "10")
90 @ExcelProperty("检测数量") 90 @ExcelProperty("检测数量")
91 - private Integer checkQuantity; 91 + private BigDecimal checkQuantity;
92 92
93 @Schema(description = "合格品数量", example = "9") 93 @Schema(description = "合格品数量", example = "9")
94 @ExcelProperty("合格品数量") 94 @ExcelProperty("合格品数量")
95 - private Integer qualifiedQuantity; 95 + private BigDecimal qualifiedQuantity;
96 96
97 @Schema(description = "不合格品数量", example = "1") 97 @Schema(description = "不合格品数量", example = "1")
98 @ExcelProperty("不合格品数量") 98 @ExcelProperty("不合格品数量")
99 - private Integer unqualifiedQuantity; 99 + private BigDecimal unqualifiedQuantity;
100 100
101 // ========== 缺陷统计 ========== 101 // ========== 缺陷统计 ==========
102 102
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java
@@ -29,8 +29,8 @@ public class MesQcOqcSaveReqVO { @@ -29,8 +29,8 @@ public class MesQcOqcSaveReqVO {
29 @Schema(description = "来源单据 ID", example = "200") 29 @Schema(description = "来源单据 ID", example = "200")
30 private Long sourceDocId; 30 private Long sourceDocId;
31 31
32 - @Schema(description = "来源单据类型", example = "SALES")  
33 - private String sourceDocType; 32 + @Schema(description = "来源单据类型", example = "118")
  33 + private Integer sourceDocType;
34 34
35 @Schema(description = "来源单据编号", example = "SO20250101001") 35 @Schema(description = "来源单据编号", example = "SO20250101001")
36 private String sourceDocCode; 36 private String sourceDocCode;
@@ -62,18 +62,18 @@ public class MesQcOqcSaveReqVO { @@ -62,18 +62,18 @@ public class MesQcOqcSaveReqVO {
62 62
63 @Schema(description = "本次检测数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 63 @Schema(description = "本次检测数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
64 @NotNull(message = "本次检测数量不能为空") 64 @NotNull(message = "本次检测数量不能为空")
65 - @Min(value = 1, message = "本次检测数量必须大于 0")  
66 - private Integer checkQuantity; 65 + @DecimalMin(value = "0", message = "本次检测数量不能小于 0")
  66 + private BigDecimal checkQuantity;
67 67
68 @Schema(description = "合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "9") 68 @Schema(description = "合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "9")
69 @NotNull(message = "合格品数量不能为空") 69 @NotNull(message = "合格品数量不能为空")
70 - @Min(value = 0, message = "合格品数量不能小于 0")  
71 - private Integer qualifiedQuantity; 70 + @DecimalMin(value = "0", message = "合格品数量不能小于 0")
  71 + private BigDecimal qualifiedQuantity;
72 72
73 @Schema(description = "不合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 73 @Schema(description = "不合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
74 @NotNull(message = "不合格品数量不能为空") 74 @NotNull(message = "不合格品数量不能为空")
75 - @Min(value = 0, message = "不合格品数量不能小于 0")  
76 - private Integer unqualifiedQuantity; 75 + @DecimalMin(value = "0", message = "不合格品数量不能小于 0")
  76 + private BigDecimal unqualifiedQuantity;
77 77
78 // ========== 检验 ========== 78 // ========== 检验 ==========
79 79
@@ -101,7 +101,7 @@ public class MesQcOqcSaveReqVO { @@ -101,7 +101,7 @@ public class MesQcOqcSaveReqVO {
101 if (ObjUtil.hasNull(checkQuantity, qualifiedQuantity, unqualifiedQuantity)) { 101 if (ObjUtil.hasNull(checkQuantity, qualifiedQuantity, unqualifiedQuantity)) {
102 return true; // @NotNull 会处理 null 102 return true; // @NotNull 会处理 null
103 } 103 }
104 - return checkQuantity.equals(qualifiedQuantity + unqualifiedQuantity); 104 + return checkQuantity.compareTo(qualifiedQuantity.add(unqualifiedQuantity)) == 0;
105 } 105 }
106 106
107 } 107 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java
@@ -33,8 +33,8 @@ public class MesQcRqcRespVO { @@ -33,8 +33,8 @@ public class MesQcRqcRespVO {
33 @Schema(description = "来源单据 ID", example = "200") 33 @Schema(description = "来源单据 ID", example = "200")
34 private Long sourceDocId; 34 private Long sourceDocId;
35 35
36 - @Schema(description = "来源单据类型", example = "RTISSUE")  
37 - private String sourceDocType; 36 + @Schema(description = "来源单据类型", example = "116")
  37 + private Integer sourceDocType;
38 38
39 @Schema(description = "来源单据行 ID", example = "300") 39 @Schema(description = "来源单据行 ID", example = "300")
40 private Long sourceLineId; 40 private Long sourceLineId;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcSaveReqVO.java
@@ -35,8 +35,8 @@ public class MesQcRqcSaveReqVO { @@ -35,8 +35,8 @@ public class MesQcRqcSaveReqVO {
35 @Schema(description = "来源单据 ID", example = "200") 35 @Schema(description = "来源单据 ID", example = "200")
36 private Long sourceDocId; 36 private Long sourceDocId;
37 37
38 - @Schema(description = "来源单据类型", example = "RTISSUE")  
39 - private String sourceDocType; 38 + @Schema(description = "来源单据类型", example = "116")
  39 + private Integer sourceDocType;
40 40
41 @Schema(description = "来源单据行 ID", example = "300") 41 @Schema(description = "来源单据行 ID", example = "300")
42 private Long sourceLineId; 42 private Long sourceLineId;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchGenerateReqVO.java
@@ -78,6 +78,6 @@ public class MesWmBatchGenerateReqVO { @@ -78,6 +78,6 @@ public class MesWmBatchGenerateReqVO {
78 /** 78 /**
79 * 质量状态 79 * 质量状态
80 */ 80 */
81 - private String qualityStatus; 81 + private Integer qualityStatus;
82 82
83 } 83 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchRespVO.java
@@ -88,7 +88,7 @@ public class MesWmBatchRespVO { @@ -88,7 +88,7 @@ public class MesWmBatchRespVO {
88 private String lotNumber; 88 private String lotNumber;
89 89
90 @Schema(description = "质量状态", example = "1") 90 @Schema(description = "质量状态", example = "1")
91 - private String qualityStatus; 91 + private Integer qualityStatus;
92 92
93 @Schema(description = "备注", example = "备注") 93 @Schema(description = "备注", example = "备注")
94 private String remark; 94 private String remark;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineRespVO.java
@@ -46,7 +46,7 @@ public class MesWmReturnSalesLineRespVO { @@ -46,7 +46,7 @@ public class MesWmReturnSalesLineRespVO {
46 private String batchCode; 46 private String batchCode;
47 47
48 @Schema(description = "质量状态", example = "合格") 48 @Schema(description = "质量状态", example = "合格")
49 - private String qualityStatus; 49 + private Integer qualityStatus;
50 50
51 @Schema(description = "备注", example = "备注") 51 @Schema(description = "备注", example = "备注")
52 private String remark; 52 private String remark;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineSaveReqVO.java
@@ -36,7 +36,7 @@ public class MesWmReturnSalesLineSaveReqVO { @@ -36,7 +36,7 @@ public class MesWmReturnSalesLineSaveReqVO {
36 private Long batchId; 36 private Long batchId;
37 37
38 @Schema(description = "质量状态", example = "合格") 38 @Schema(description = "质量状态", example = "合格")
39 - private String qualityStatus; 39 + private Integer qualityStatus;
40 40
41 @Schema(description = "备注", example = "备注") 41 @Schema(description = "备注", example = "备注")
42 private String remark; 42 private String remark;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java
@@ -47,7 +47,7 @@ public class MesQcOqcDO extends BaseDO { @@ -47,7 +47,7 @@ public class MesQcOqcDO extends BaseDO {
47 */ 47 */
48 private Long templateId; 48 private Long templateId;
49 49
50 - // ========== 来源单据(TODO @芋艿:WM 模块迁移后接入) ========== 50 + // ========== 来源单据 ==========
51 51
52 /** 52 /**
53 * 来源单据 ID 53 * 来源单据 ID
@@ -55,8 +55,10 @@ public class MesQcOqcDO extends BaseDO { @@ -55,8 +55,10 @@ public class MesQcOqcDO extends BaseDO {
55 private Long sourceDocId; 55 private Long sourceDocId;
56 /** 56 /**
57 * 来源单据类型 57 * 来源单据类型
  58 + *
  59 + * 关联 {@link cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants}
58 */ 60 */
59 - private String sourceDocType; 61 + private Integer sourceDocType;
60 /** 62 /**
61 * 来源单据编号 63 * 来源单据编号
62 */ 64 */
@@ -97,15 +99,15 @@ public class MesQcOqcDO extends BaseDO { @@ -97,15 +99,15 @@ public class MesQcOqcDO extends BaseDO {
97 /** 99 /**
98 * 本次检测数量 100 * 本次检测数量
99 */ 101 */
100 - private Integer checkQuantity; 102 + private BigDecimal checkQuantity;
101 /** 103 /**
102 * 合格品数量 104 * 合格品数量
103 */ 105 */
104 - private Integer qualifiedQuantity; 106 + private BigDecimal qualifiedQuantity;
105 /** 107 /**
106 * 不合格品数量 108 * 不合格品数量
107 */ 109 */
108 - private Integer unqualifiedQuantity; 110 + private BigDecimal unqualifiedQuantity;
109 111
110 // ========== 缺陷统计 ========== 112 // ========== 缺陷统计 ==========
111 113
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcDO.java
@@ -47,7 +47,7 @@ public class MesQcRqcDO extends BaseDO { @@ -47,7 +47,7 @@ public class MesQcRqcDO extends BaseDO {
47 */ 47 */
48 private Long templateId; 48 private Long templateId;
49 49
50 - // ========== 来源单据(TODO @芋艿:WM 模块迁移后接入) ========== 50 + // ========== 来源单据 ==========
51 51
52 /** 52 /**
53 * 来源单据 ID 53 * 来源单据 ID
@@ -55,8 +55,10 @@ public class MesQcRqcDO extends BaseDO { @@ -55,8 +55,10 @@ public class MesQcRqcDO extends BaseDO {
55 private Long sourceDocId; 55 private Long sourceDocId;
56 /** 56 /**
57 * 来源单据类型 57 * 来源单据类型
  58 + *
  59 + * 关联 {@link cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants}
58 */ 60 */
59 - private String sourceDocType; 61 + private Integer sourceDocType;
60 /** 62 /**
61 * 来源单据行 ID 63 * 来源单据行 ID
62 */ 64 */
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/batch/MesWmBatchDO.java
@@ -113,7 +113,7 @@ public class MesWmBatchDO extends BaseDO { @@ -113,7 +113,7 @@ public class MesWmBatchDO extends BaseDO {
113 /** 113 /**
114 * 质量状态 114 * 质量状态
115 */ 115 */
116 - private String qualityStatus; 116 + private Integer qualityStatus;
117 /** 117 /**
118 * 备注 118 * 备注
119 */ 119 */
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java
@@ -68,7 +68,7 @@ public class MesWmProductSalesLineDO extends BaseDO { @@ -68,7 +68,7 @@ public class MesWmProductSalesLineDO extends BaseDO {
68 * 68 *
69 * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} 69 * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum}
70 */ 70 */
71 - private String qualityStatus; 71 + private Integer qualityStatus;
72 /** 72 /**
73 * 备注 73 * 备注
74 */ 74 */
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO.java
@@ -54,7 +54,7 @@ public class MesWmReturnSalesLineDO extends BaseDO { @@ -54,7 +54,7 @@ public class MesWmReturnSalesLineDO extends BaseDO {
54 * 54 *
55 * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} 55 * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum}
56 */ 56 */
57 - private String qualityStatus; 57 + private Integer qualityStatus;
58 /** 58 /**
59 * 备注 59 * 备注
60 */ 60 */
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -312,6 +312,7 @@ public interface ErrorCodeConstants { @@ -312,6 +312,7 @@ public interface ErrorCodeConstants {
312 ErrorCode QC_OQC_NOT_PREPARE = new ErrorCode(1_040_607_002, "只有草稿状态的检验单才可操作"); 312 ErrorCode QC_OQC_NOT_PREPARE = new ErrorCode(1_040_607_002, "只有草稿状态的检验单才可操作");
313 ErrorCode QC_OQC_QUANTITY_MISMATCH = new ErrorCode(1_040_607_004, "合格品与不合格品数量之和须等于检测数量"); 313 ErrorCode QC_OQC_QUANTITY_MISMATCH = new ErrorCode(1_040_607_004, "合格品与不合格品数量之和须等于检测数量");
314 ErrorCode QC_OQC_NO_TEMPLATE = new ErrorCode(1_040_607_005, "当前产品未配置 OQC 检测模板"); 314 ErrorCode QC_OQC_NO_TEMPLATE = new ErrorCode(1_040_607_005, "当前产品未配置 OQC 检测模板");
  315 + ErrorCode QC_OQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_607_006, "完成检验单前,检测结果必须填写");
315 // ========== MES 质量管理-出货检验行(1-040-607-100) ========== 316 // ========== MES 质量管理-出货检验行(1-040-607-100) ==========
316 ErrorCode QC_OQC_LINE_NOT_EXISTS = new ErrorCode(1_040_607_100, "出货检验行不存在"); 317 ErrorCode QC_OQC_LINE_NOT_EXISTS = new ErrorCode(1_040_607_100, "出货检验行不存在");
317 318
@@ -321,6 +322,7 @@ public interface ErrorCodeConstants { @@ -321,6 +322,7 @@ public interface ErrorCodeConstants {
321 ErrorCode QC_RQC_NOT_PREPARE = new ErrorCode(1_040_608_002, "只有草稿状态的检验单才可操作"); 322 ErrorCode QC_RQC_NOT_PREPARE = new ErrorCode(1_040_608_002, "只有草稿状态的检验单才可操作");
322 ErrorCode QC_RQC_QUANTITY_MISMATCH = new ErrorCode(1_040_608_004, "合格品与不合格品数量之和须等于检测数量"); 323 ErrorCode QC_RQC_QUANTITY_MISMATCH = new ErrorCode(1_040_608_004, "合格品与不合格品数量之和须等于检测数量");
323 ErrorCode QC_RQC_NO_TEMPLATE = new ErrorCode(1_040_608_005, "当前产品未配置 RQC 检测模板"); 324 ErrorCode QC_RQC_NO_TEMPLATE = new ErrorCode(1_040_608_005, "当前产品未配置 RQC 检测模板");
  325 + ErrorCode QC_RQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_608_006, "完成检验单前,检测结果必须填写");
324 // ========== MES 质量管理-退货检验行(1-040-608-100) ========== 326 // ========== MES 质量管理-退货检验行(1-040-608-100) ==========
325 ErrorCode QC_RQC_LINE_NOT_EXISTS = new ErrorCode(1_040_608_100, "退货检验行不存在"); 327 ErrorCode QC_RQC_LINE_NOT_EXISTS = new ErrorCode(1_040_608_100, "退货检验行不存在");
326 328
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmArrivalNoticeStatusEnum.java
@@ -36,7 +36,7 @@ public enum MesWmArrivalNoticeStatusEnum implements ArrayValuable<Integer> { @@ -36,7 +36,7 @@ public enum MesWmArrivalNoticeStatusEnum implements ArrayValuable<Integer> {
36 * 36 *
37 * 对应方法: 37 * 对应方法:
38 * 1. 不需要检验时:{@link MesWmArrivalNoticeService#submitArrivalNotice(Long)} 38 * 1. 不需要检验时:{@link MesWmArrivalNoticeService#submitArrivalNotice(Long)}
39 - * 2. 或检验完成时:{@link MesWmArrivalNoticeService#approveArrivalNoticeWhenIqcComplete(Long, Long, Long, BigDecimal)} 39 + * 2. 或检验完成时:{@link MesWmArrivalNoticeService#updateArrivalNoticeWhenIqcFinish(Long, Long, Long, BigDecimal)}
40 */ 40 */
41 PENDING_RECEIPT(MesOrderStatusConstants.APPROVED, "待入库"), 41 PENDING_RECEIPT(MesOrderStatusConstants.APPROVED, "待入库"),
42 /** 42 /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java
@@ -102,8 +102,8 @@ public interface MesProFeedbackService { @@ -102,8 +102,8 @@ public interface MesProFeedbackService {
102 * @param materialScrapQty 料废数量 102 * @param materialScrapQty 料废数量
103 * @param otherScrapQty 其他废品数量 103 * @param otherScrapQty 其他废品数量
104 */ 104 */
105 - void completeFeedbackFromIpqc(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty,  
106 - BigDecimal laborScrapQty, BigDecimal materialScrapQty, BigDecimal otherScrapQty); 105 + void updateProFeedbackWhenIpqcFinish(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty,
  106 + BigDecimal laborScrapQty, BigDecimal materialScrapQty, BigDecimal otherScrapQty);
107 107
108 } 108 }
109 109
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
@@ -285,8 +285,8 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { @@ -285,8 +285,8 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService {
285 285
286 @Override 286 @Override
287 @Transactional(rollbackFor = Exception.class) 287 @Transactional(rollbackFor = Exception.class)
288 - public void completeFeedbackFromIpqc(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty,  
289 - BigDecimal laborScrapQty, BigDecimal materialScrapQty, BigDecimal otherScrapQty) { 288 + public void updateProFeedbackWhenIpqcFinish(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty,
  289 + BigDecimal laborScrapQty, BigDecimal materialScrapQty, BigDecimal otherScrapQty) {
290 // 1. 校验报工单存在且为待检验状态 290 // 1. 校验报工单存在且为待检验状态
291 MesProFeedbackDO feedback = validateFeedbackExists(feedbackId); 291 MesProFeedbackDO feedback = validateFeedbackExists(feedbackId);
292 if (ObjUtil.notEqual(feedback.getStatus(), MesProFeedbackStatusEnum.UNCHECK.getStatus())) { 292 if (ObjUtil.notEqual(feedback.getStatus(), MesProFeedbackStatusEnum.UNCHECK.getStatus())) {
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
@@ -155,7 +155,7 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @@ -155,7 +155,7 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService {
155 } 155 }
156 156
157 if (Objects.equals(ipqc.getSourceDocType(), MesBizTypeConstants.PRO_FEEDBACK)) { 157 if (Objects.equals(ipqc.getSourceDocType(), MesBizTypeConstants.PRO_FEEDBACK)) {
158 - feedbackService.completeFeedbackFromIpqc(ipqc.getSourceDocId(), 158 + feedbackService.updateProFeedbackWhenIpqcFinish(ipqc.getSourceDocId(),
159 ObjectUtil.defaultIfNull(ipqc.getQualifiedQuantity(), BigDecimal.ZERO), 159 ObjectUtil.defaultIfNull(ipqc.getQualifiedQuantity(), BigDecimal.ZERO),
160 ObjectUtil.defaultIfNull(ipqc.getUnqualifiedQuantity(), BigDecimal.ZERO), 160 ObjectUtil.defaultIfNull(ipqc.getUnqualifiedQuantity(), BigDecimal.ZERO),
161 ObjectUtil.defaultIfNull(ipqc.getLaborScrapQuantity(), BigDecimal.ZERO), 161 ObjectUtil.defaultIfNull(ipqc.getLaborScrapQuantity(), BigDecimal.ZERO),
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java
@@ -148,10 +148,10 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -148,10 +148,10 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
148 148
149 // 根据不同的来源单据类型,回写不同的单据 149 // 根据不同的来源单据类型,回写不同的单据
150 if (Objects.equals(iqc.getSourceDocType(), MesBizTypeConstants.WM_ARRIVAL_NOTICE)) { 150 if (Objects.equals(iqc.getSourceDocType(), MesBizTypeConstants.WM_ARRIVAL_NOTICE)) {
151 - arrivalNoticeService.approveArrivalNoticeWhenIqcComplete(iqc.getSourceDocId(), iqc.getSourceLineId(), 151 + arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(iqc.getSourceDocId(), iqc.getSourceLineId(),
152 iqc.getId(), iqc.getQualifiedQuantity()); 152 iqc.getId(), iqc.getQualifiedQuantity());
153 } else if (Objects.equals(iqc.getSourceDocType(), MesBizTypeConstants.WM_OUTSOURCE_RECPT)) { 153 } else if (Objects.equals(iqc.getSourceDocType(), MesBizTypeConstants.WM_OUTSOURCE_RECPT)) {
154 - outsourceReceiptService.approveOutsourceReceiptWhenIqcComplete(iqc.getSourceDocId(), iqc.getSourceLineId(), 154 + outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish(iqc.getSourceDocId(), iqc.getSourceLineId(),
155 iqc.getId(), iqc.getQualifiedQuantity(), iqc.getUnqualifiedQuantity()); 155 iqc.getId(), iqc.getQualifiedQuantity(), iqc.getUnqualifiedQuantity());
156 } else { 156 } else {
157 throw new IllegalArgumentException( 157 throw new IllegalArgumentException(
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java
@@ -12,10 +12,12 @@ import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcMapper; @@ -12,10 +12,12 @@ import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcMapper;
12 import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; 12 import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum;
13 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; 13 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
14 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; 14 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
  15 +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
15 import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; 16 import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
16 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 17 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
17 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; 18 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
18 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateDetailService; 19 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateDetailService;
  20 +import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService;
19 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 21 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
20 import jakarta.annotation.Resource; 22 import jakarta.annotation.Resource;
21 import org.springframework.context.annotation.Lazy; 23 import org.springframework.context.annotation.Lazy;
@@ -56,6 +58,10 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @@ -56,6 +58,10 @@ public class MesQcOqcServiceImpl implements MesQcOqcService {
56 @Lazy 58 @Lazy
57 private MesMdItemService itemService; 59 private MesMdItemService itemService;
58 @Resource 60 @Resource
  61 + @Lazy
  62 + private MesWmProductSalesLineService productSalesLineService;
  63 +
  64 + @Resource
59 private AdminUserApi adminUserApi; 65 private AdminUserApi adminUserApi;
60 66
61 @Override 67 @Override
@@ -100,16 +106,47 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @@ -100,16 +106,47 @@ public class MesQcOqcServiceImpl implements MesQcOqcService {
100 } 106 }
101 107
102 @Override 108 @Override
  109 + @Transactional(rollbackFor = Exception.class)
103 public void finishOqc(Long id) { 110 public void finishOqc(Long id) {
104 - // 1. 校验存在 + 草稿状态  
105 - validateOqcStatusPrepare(id); 111 + // 1.1 校验存在 + 草稿状态
  112 + MesQcOqcDO oqc = validateOqcStatusPrepare(id);
  113 + // 1.2 校验检测结论必填
  114 + if (oqc.getCheckResult() == null) {
  115 + throw exception(QC_OQC_CHECK_RESULT_EMPTY);
  116 + }
106 117
107 // 2. 更新状态为已完成 118 // 2. 更新状态为已完成
108 MesQcOqcDO updateObj = new MesQcOqcDO() 119 MesQcOqcDO updateObj = new MesQcOqcDO()
109 .setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus()); 120 .setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus());
110 oqcMapper.updateById(updateObj); 121 oqcMapper.updateById(updateObj);
111 122
112 - // TODO @芋艿:WM 模块迁移后,更新销售出库单行的检验结果 123 + // 3. 回写来源单据
  124 + writeBackSourceDoc(oqc);
  125 + }
  126 +
  127 + /**
  128 + * 回写来源单据(OQC 完成后)
  129 + *
  130 + * <p>当来源为销售出库单时,回写行的 oqcId 和 qualityStatus
  131 + *
  132 + * @param oqc 出货检验单
  133 + */
  134 + private void writeBackSourceDoc(MesQcOqcDO oqc) {
  135 + if (oqc.getSourceDocType() == null) {
  136 + return;
  137 + }
  138 + if (oqc.getSourceLineId() == null) {
  139 + throw new IllegalArgumentException(
  140 + "OQC 单[" + oqc.getId() + "] sourceDocType 非空但 sourceLineId 为空");
  141 + }
  142 +
  143 + if (Objects.equals(oqc.getSourceDocType(), MesBizTypeConstants.WM_PRODUCT_SALES)) {
  144 + // 回写销售出库单行的 oqcId + qualityStatus
  145 + productSalesLineService.updateProductSalesLineWhenOqcFinish(oqc.getSourceLineId(), oqc.getId(), oqc.getCheckResult());
  146 + } else {
  147 + throw new IllegalArgumentException(
  148 + "OQC 单[" + oqc.getId() + "] sourceDocType=" + oqc.getSourceDocType() + " 无法识别,无法回写来源单据");
  149 + }
113 } 150 }
114 151
115 @Override 152 @Override
@@ -190,8 +227,8 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @@ -190,8 +227,8 @@ public class MesQcOqcServiceImpl implements MesQcOqcService {
190 BigDecimal criticalRate = BigDecimal.ZERO; 227 BigDecimal criticalRate = BigDecimal.ZERO;
191 BigDecimal majorRate = BigDecimal.ZERO; 228 BigDecimal majorRate = BigDecimal.ZERO;
192 BigDecimal minorRate = BigDecimal.ZERO; 229 BigDecimal minorRate = BigDecimal.ZERO;
193 - if (oqc.getCheckQuantity() != null && oqc.getCheckQuantity() > 0) {  
194 - BigDecimal checkQty = BigDecimal.valueOf(oqc.getCheckQuantity()); 230 + if (oqc.getCheckQuantity() != null && oqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) {
  231 + BigDecimal checkQty = oqc.getCheckQuantity();
195 criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100)) 232 criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100))
196 .divide(checkQty, 2, RoundingMode.HALF_UP); 233 .divide(checkQty, 2, RoundingMode.HALF_UP);
197 majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100)) 234 majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100))
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java
@@ -12,9 +12,12 @@ import cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc.MesQcRqcMapper; @@ -12,9 +12,12 @@ import cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc.MesQcRqcMapper;
12 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; 12 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
13 import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; 13 import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum;
14 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; 14 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
  15 +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
15 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 16 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
16 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; 17 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
17 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateDetailService; 18 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateDetailService;
  19 +import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueLineService;
  20 +import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesLineService;
18 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 21 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
19 import jakarta.annotation.Resource; 22 import jakarta.annotation.Resource;
20 import org.springframework.context.annotation.Lazy; 23 import org.springframework.context.annotation.Lazy;
@@ -51,6 +54,12 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @@ -51,6 +54,12 @@ public class MesQcRqcServiceImpl implements MesQcRqcService {
51 @Resource 54 @Resource
52 @Lazy 55 @Lazy
53 private MesQcDefectRecordService defectRecordService; 56 private MesQcDefectRecordService defectRecordService;
  57 + @Resource
  58 + @Lazy
  59 + private MesWmReturnIssueLineService returnIssueLineService;
  60 + @Resource
  61 + @Lazy
  62 + private MesWmReturnSalesLineService returnSalesLineService;
54 63
55 @Resource 64 @Resource
56 private AdminUserApi adminUserApi; 65 private AdminUserApi adminUserApi;
@@ -95,10 +104,15 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @@ -95,10 +104,15 @@ public class MesQcRqcServiceImpl implements MesQcRqcService {
95 } 104 }
96 105
97 @Override 106 @Override
  107 + @Transactional(rollbackFor = Exception.class)
98 public void finishRqc(Long id) { 108 public void finishRqc(Long id) {
99 // 1.1 校验存在 + 草稿状态 109 // 1.1 校验存在 + 草稿状态
100 MesQcRqcDO rqc = validateRqcStatusPrepare(id); 110 MesQcRqcDO rqc = validateRqcStatusPrepare(id);
101 - // 1.2 校验合格品 + 不合格品 = 检测数量 111 + // 1.2 校验检测结论必填
  112 + if (rqc.getCheckResult() == null) {
  113 + throw exception(QC_RQC_CHECK_RESULT_EMPTY);
  114 + }
  115 + // 1.3 校验合格品 + 不合格品 = 检测数量
102 if (rqc.getCheckQuantity() != null && rqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { 116 if (rqc.getCheckQuantity() != null && rqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) {
103 BigDecimal qualified = rqc.getQualifiedQuantity() != null ? rqc.getQualifiedQuantity() : BigDecimal.ZERO; 117 BigDecimal qualified = rqc.getQualifiedQuantity() != null ? rqc.getQualifiedQuantity() : BigDecimal.ZERO;
104 BigDecimal unqualified = rqc.getUnqualifiedQuantity() != null ? rqc.getUnqualifiedQuantity() : BigDecimal.ZERO; 118 BigDecimal unqualified = rqc.getUnqualifiedQuantity() != null ? rqc.getUnqualifiedQuantity() : BigDecimal.ZERO;
@@ -111,7 +125,40 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @@ -111,7 +125,40 @@ public class MesQcRqcServiceImpl implements MesQcRqcService {
111 MesQcRqcDO updateObj = new MesQcRqcDO().setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus()); 125 MesQcRqcDO updateObj = new MesQcRqcDO().setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus());
112 rqcMapper.updateById(updateObj); 126 rqcMapper.updateById(updateObj);
113 127
114 - // TODO @芋艿:WM 模块迁移后,更新来源退料/退货单行的质量状态 128 + // 3. 回写来源单据
  129 + writeBackSourceDoc(rqc);
  130 + }
  131 +
  132 + /**
  133 + * 回写来源单据(RQC 完成后)
  134 + *
  135 + * <p>根据 sourceDocType 分发:
  136 + * <ul>
  137 + * <li>WM_RETURN_ISSUE(生产退料单)→ 回写行的 qualityStatus</li>
  138 + * <li>WM_RETURN_SALES(销售退货单)→ 回写行的 qualityStatus</li>
  139 + * </ul>
  140 + *
  141 + * @param rqc 退货检验单
  142 + */
  143 + private void writeBackSourceDoc(MesQcRqcDO rqc) {
  144 + if (rqc.getSourceDocType() == null) {
  145 + return;
  146 + }
  147 + if (rqc.getSourceLineId() == null) {
  148 + throw new IllegalArgumentException(
  149 + "RQC 单[" + rqc.getId() + "] sourceDocType 非空但 sourceLineId 为空");
  150 + }
  151 +
  152 + if (Objects.equals(rqc.getSourceDocType(), MesBizTypeConstants.WM_RETURN_ISSUE)) {
  153 + // 回写生产退料单行的 qualityStatus
  154 + returnIssueLineService.updateReturnIssueLineWhenRqcFinish(rqc.getSourceLineId(), rqc.getCheckResult());
  155 + } else if (Objects.equals(rqc.getSourceDocType(), MesBizTypeConstants.WM_RETURN_SALES)) {
  156 + // 回写销售退货单行的 qualityStatus
  157 + returnSalesLineService.updateReturnSalesLineWhenRqcFinish(rqc.getSourceLineId(), rqc.getCheckResult());
  158 + } else {
  159 + throw new IllegalArgumentException(
  160 + "RQC 单[" + rqc.getId() + "] sourceDocType=" + rqc.getSourceDocType() + " 无法识别,无法回写来源单据");
  161 + }
115 } 162 }
116 163
117 @Override 164 @Override
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java
@@ -74,7 +74,7 @@ public interface MesWmArrivalNoticeLineService { @@ -74,7 +74,7 @@ public interface MesWmArrivalNoticeLineService {
74 * @param iqcId IQC 检验单编号 74 * @param iqcId IQC 检验单编号
75 * @param qualifiedQuantity 合格数量 75 * @param qualifiedQuantity 合格数量
76 */ 76 */
77 - void updateByIqcComplete(Long lineId, Long iqcId, BigDecimal qualifiedQuantity); 77 + void updateArrivalNoticeLineWhenIqcFinish(Long lineId, Long iqcId, BigDecimal qualifiedQuantity);
78 78
79 /** 79 /**
80 * 校验到货通知单行存在 80 * 校验到货通知单行存在
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java
@@ -63,7 +63,7 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine @@ -63,7 +63,7 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine
63 /** 63 /**
64 * 初始化合格品数量: 64 * 初始化合格品数量:
65 * 1. 如果不需要 IQC 检验,则合格品数量直接 = 接收数量; 65 * 1. 如果不需要 IQC 检验,则合格品数量直接 = 接收数量;
66 - * 2. 否则,合格品数量由对应的 IQC 检验单负责更新(见 {@link #updateByIqcComplete}) 66 + * 2. 否则,合格品数量由对应的 IQC 检验单负责更新(见 {@link #updateArrivalNoticeLineWhenIqcFinish})
67 */ 67 */
68 private void initQualifiedQuantityIfNoIqc(MesWmArrivalNoticeLineDO line) { 68 private void initQualifiedQuantityIfNoIqc(MesWmArrivalNoticeLineDO line) {
69 if (BooleanUtil.isFalse(line.getIqcCheckFlag())) { 69 if (BooleanUtil.isFalse(line.getIqcCheckFlag())) {
@@ -100,7 +100,7 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine @@ -100,7 +100,7 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine
100 } 100 }
101 101
102 @Override 102 @Override
103 - public void updateByIqcComplete(Long lineId, Long iqcId, BigDecimal qualifiedQuantity) { 103 + public void updateArrivalNoticeLineWhenIqcFinish(Long lineId, Long iqcId, BigDecimal qualifiedQuantity) {
104 // 校验行存在 104 // 校验行存在
105 validateArrivalNoticeLineExists(lineId); 105 validateArrivalNoticeLineExists(lineId);
106 // 更新 106 // 更新
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java
@@ -71,7 +71,7 @@ public interface MesWmArrivalNoticeService { @@ -71,7 +71,7 @@ public interface MesWmArrivalNoticeService {
71 * @param iqcId IQC 检验单编号 71 * @param iqcId IQC 检验单编号
72 * @param qualifiedQuantity 合格数量 72 * @param qualifiedQuantity 合格数量
73 */ 73 */
74 - void approveArrivalNoticeWhenIqcComplete(Long id, Long lineId, Long iqcId, BigDecimal qualifiedQuantity); 74 + void updateArrivalNoticeWhenIqcFinish(Long id, Long lineId, Long iqcId, BigDecimal qualifiedQuantity);
75 75
76 /** 76 /**
77 * 完成到货通知单(待入库 → 已完成),内部调用 77 * 完成到货通知单(待入库 → 已完成),内部调用
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java
@@ -96,24 +96,23 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService @@ -96,24 +96,23 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
96 throw exception(WM_ARRIVAL_NOTICE_NO_LINE); 96 throw exception(WM_ARRIVAL_NOTICE_NO_LINE);
97 } 97 }
98 98
99 - // 2. 检查所有行的 iqcCheckFlag:如果没有需要检验的行,则直接审批通过 99 + // 2. 检查所有行的 iqcCheckFlag:如果有需要检验的行,进入待质检状态
100 boolean needCheck = CollectionUtils.anyMatch(lines, 100 boolean needCheck = CollectionUtils.anyMatch(lines,
101 line -> Boolean.TRUE.equals(line.getIqcCheckFlag())); 101 line -> Boolean.TRUE.equals(line.getIqcCheckFlag()));
102 - // TODO @AI:if return;并且不要取反;  
103 - if (!needCheck) {  
104 - // 不需要检验,直接进入待入库  
105 - arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()  
106 - .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus()));  
107 - } else { 102 + if (needCheck) {
108 // 需要检验,进入待质检 103 // 需要检验,进入待质检
109 arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO() 104 arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()
110 .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus())); 105 .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus()));
  106 + return;
111 } 107 }
  108 + // 不需要检验,直接进入待入库
  109 + arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()
  110 + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus()));
112 } 111 }
113 112
114 @Override 113 @Override
115 @Transactional(rollbackFor = Exception.class) 114 @Transactional(rollbackFor = Exception.class)
116 - public void approveArrivalNoticeWhenIqcComplete(Long id, Long lineId, Long iqcId, BigDecimal qualifiedQuantity) { 115 + public void updateArrivalNoticeWhenIqcFinish(Long id, Long lineId, Long iqcId, BigDecimal qualifiedQuantity) {
117 // 1.1 校验到货通知单存在 116 // 1.1 校验到货通知单存在
118 MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id); 117 MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id);
119 // 1.2 校验状态为待质检 118 // 1.2 校验状态为待质检
@@ -122,14 +121,14 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService @@ -122,14 +121,14 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
122 } 121 }
123 122
124 // 2. 更新到货通知单行:绑定 iqcId + 合格数量 123 // 2. 更新到货通知单行:绑定 iqcId + 合格数量
125 - arrivalNoticeLineService.updateByIqcComplete(lineId, iqcId, qualifiedQuantity); 124 + arrivalNoticeLineService.updateArrivalNoticeLineWhenIqcFinish(lineId, iqcId, qualifiedQuantity);
126 125
127 // 3.1 判断是否所有需检行都已完成 126 // 3.1 判断是否所有需检行都已完成
128 List<MesWmArrivalNoticeLineDO> lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id); 127 List<MesWmArrivalNoticeLineDO> lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id);
129 boolean hasUnchecked = CollectionUtils.anyMatch(lines, 128 boolean hasUnchecked = CollectionUtils.anyMatch(lines,
130 line -> Boolean.TRUE.equals(line.getIqcCheckFlag()) && line.getIqcId() == null); 129 line -> Boolean.TRUE.equals(line.getIqcCheckFlag()) && line.getIqcId() == null);
131 if (hasUnchecked) { 130 if (hasUnchecked) {
132 - log.info("[updateWhenIqcComplete][到货通知单({}) 还有未完成检验的行,暂不更新状态]", id); 131 + log.info("[updateArrivalNoticeWhenIqcFinish][到货通知单({}) 还有未完成检验的行,暂不更新状态]", id);
133 return; 132 return;
134 } 133 }
135 // 3.2 所有行检验完成,更新主表状态 PENDING_QC → PENDING_RECEIPT 134 // 3.2 所有行检验完成,更新主表状态 PENDING_QC → PENDING_RECEIPT
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java
@@ -88,8 +88,8 @@ public interface MesWmOutsourceReceiptService { @@ -88,8 +88,8 @@ public interface MesWmOutsourceReceiptService {
88 * @param qualifiedQuantity 合格品数量 88 * @param qualifiedQuantity 合格品数量
89 * @param unqualifiedQuantity 不合格品数量 89 * @param unqualifiedQuantity 不合格品数量
90 */ 90 */
91 - void approveOutsourceReceiptWhenIqcComplete(Long receiptId, Long lineId, Long iqcId,  
92 - BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity); 91 + void updateOutsourceReceiptWhenIqcFinish(Long receiptId, Long lineId, Long iqcId,
  92 + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity);
93 93
94 /** 94 /**
95 * 校验外协入库单和行存在 95 * 校验外协入库单和行存在
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java
@@ -209,8 +209,8 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe @@ -209,8 +209,8 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe
209 209
210 @Override 210 @Override
211 @Transactional(rollbackFor = Exception.class) 211 @Transactional(rollbackFor = Exception.class)
212 - public void approveOutsourceReceiptWhenIqcComplete(Long receiptId, Long lineId, Long iqcId,  
213 - BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity) { 212 + public void updateOutsourceReceiptWhenIqcFinish(Long receiptId, Long lineId, Long iqcId,
  213 + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity) {
214 // 1.1 校验入库单存在 214 // 1.1 校验入库单存在
215 MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(receiptId); 215 MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(receiptId);
216 // 1.2 校验状态为待检验 216 // 1.2 校验状态为待检验
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineService.java
1 package cn.iocoder.yudao.module.mes.service.wm.productsales; 1 package cn.iocoder.yudao.module.mes.service.wm.productsales;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
3 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLinePageReqVO; 4 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLinePageReqVO;
4 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineSaveReqVO; 5 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineSaveReqVO;
5 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; 6 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO;
@@ -65,7 +66,15 @@ public interface MesWmProductSalesLineService { @@ -65,7 +66,15 @@ public interface MesWmProductSalesLineService {
65 * @param pageReqVO 分页查询 66 * @param pageReqVO 分页查询
66 * @return 销售出库单行分页 67 * @return 销售出库单行分页
67 */ 68 */
68 - cn.iocoder.yudao.framework.common.pojo.PageResult<MesWmProductSalesLineDO> getProductSalesLinePage(  
69 - MesWmProductSalesLinePageReqVO pageReqVO); 69 + PageResult<MesWmProductSalesLineDO> getProductSalesLinePage(MesWmProductSalesLinePageReqVO pageReqVO);
  70 +
  71 + /**
  72 + * OQC 检验完成后,更新销售出库单行的 OQC 质检状态
  73 + *
  74 + * @param id 行 ID
  75 + * @param oqcId 质检单 ID
  76 + * @param checkResult 检验结果
  77 + */
  78 + void updateProductSalesLineWhenOqcFinish(Long id, Long oqcId, Integer checkResult);
70 79
71 } 80 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java
@@ -5,15 +5,16 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesW @@ -5,15 +5,16 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesW
5 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineSaveReqVO; 5 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineSaveReqVO;
6 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; 6 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO;
7 import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesLineMapper; 7 import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesLineMapper;
  8 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum;
  9 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
8 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 10 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
9 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
10 -import org.springframework.context.annotation.Lazy;  
11 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
12 import org.springframework.transaction.annotation.Transactional; 13 import org.springframework.transaction.annotation.Transactional;
13 import org.springframework.validation.annotation.Validated; 14 import org.springframework.validation.annotation.Validated;
14 15
15 -import java.math.BigDecimal;  
16 import java.util.List; 16 import java.util.List;
  17 +import java.util.Objects;
17 18
18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PRODUCT_SALES_LINE_NOT_EXISTS; 20 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PRODUCT_SALES_LINE_NOT_EXISTS;
@@ -29,14 +30,8 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe @@ -29,14 +30,8 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe
29 30
30 @Resource 31 @Resource
31 private MesWmProductSalesLineMapper productSalesLineMapper; 32 private MesWmProductSalesLineMapper productSalesLineMapper;
32 -  
33 - @Resource  
34 - @Lazy  
35 - private MesWmProductSalesService productSalesService;  
36 -  
37 @Resource 33 @Resource
38 private MesWmProductSalesDetailService productSalesDetailService; 34 private MesWmProductSalesDetailService productSalesDetailService;
39 -  
40 @Resource 35 @Resource
41 private MesMdItemService itemService; 36 private MesMdItemService itemService;
42 37
@@ -104,4 +99,12 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe @@ -104,4 +99,12 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe
104 return line; 99 return line;
105 } 100 }
106 101
  102 + @Override
  103 + public void updateProductSalesLineWhenOqcFinish(Long id, Long oqcId, Integer checkResult) {
  104 + Integer qualityStatus = Objects.equals(checkResult, MesQcCheckResultEnum.PASS.getType())
  105 + ? MesWmQualityStatusEnum.PASS.getStatus() : MesWmQualityStatusEnum.FAIL.getStatus();
  106 + productSalesLineMapper.updateById(new MesWmProductSalesLineDO()
  107 + .setId(id).setOqcId(oqcId).setQualityStatus(qualityStatus));
  108 + }
  109 +
107 } 110 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineService.java
@@ -82,4 +82,12 @@ public interface MesWmReturnIssueLineService { @@ -82,4 +82,12 @@ public interface MesWmReturnIssueLineService {
82 */ 82 */
83 void updateReturnIssueQualityStatusByIssueId(Long issueId, Integer issueType); 83 void updateReturnIssueQualityStatusByIssueId(Long issueId, Integer issueType);
84 84
  85 + /**
  86 + * RQC 检验完成后,更新生产退料单行的质量状态
  87 + *
  88 + * @param id 行 ID
  89 + * @param checkResult 检验结果
  90 + */
  91 + void updateReturnIssueLineWhenRqcFinish(Long id, Integer checkResult);
  92 +
85 } 93 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImpl.java
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWm @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWm
8 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDO; 8 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDO;
9 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueLineDO; 9 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueLineDO;
10 import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue.MesWmReturnIssueLineMapper; 10 import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue.MesWmReturnIssueLineMapper;
  11 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum;
11 import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; 12 import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
12 import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnIssueTypeEnum; 13 import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnIssueTypeEnum;
13 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 14 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
@@ -17,6 +18,7 @@ import org.springframework.stereotype.Service; @@ -17,6 +18,7 @@ import org.springframework.stereotype.Service;
17 import org.springframework.validation.annotation.Validated; 18 import org.springframework.validation.annotation.Validated;
18 19
19 import java.util.List; 20 import java.util.List;
  21 +import java.util.Objects;
20 22
21 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
22 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_ISSUE_LINE_NOT_EXISTS; 24 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_ISSUE_LINE_NOT_EXISTS;
@@ -134,4 +136,11 @@ public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineServ @@ -134,4 +136,11 @@ public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineServ
134 return MesWmQualityStatusEnum.FAIL.getStatus(); // 不合格 136 return MesWmQualityStatusEnum.FAIL.getStatus(); // 不合格
135 } 137 }
136 138
  139 + @Override
  140 + public void updateReturnIssueLineWhenRqcFinish(Long id, Integer checkResult) {
  141 + Integer qualityStatus = Objects.equals(checkResult, MesQcCheckResultEnum.PASS.getType())
  142 + ? MesWmQualityStatusEnum.PASS.getStatus() : MesWmQualityStatusEnum.FAIL.getStatus();
  143 + issueLineMapper.updateById(new MesWmReturnIssueLineDO().setId(id).setQualityStatus(qualityStatus));
  144 + }
  145 +
137 } 146 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineService.java
@@ -82,6 +82,14 @@ public interface MesWmReturnSalesLineService { @@ -82,6 +82,14 @@ public interface MesWmReturnSalesLineService {
82 * @param returnId 退货单ID 82 * @param returnId 退货单ID
83 * @param qualityStatus 质量状态 83 * @param qualityStatus 质量状态
84 */ 84 */
85 - void updateQualityStatusByReturnId(Long returnId, String qualityStatus); 85 + void updateQualityStatusByReturnId(Long returnId, Integer qualityStatus);
  86 +
  87 + /**
  88 + * RQC 检验完成后,更新销售退货单行的质量状态
  89 + *
  90 + * @param id 行 ID
  91 + * @param checkResult 检验结果
  92 + */
  93 + void updateReturnSalesLineWhenRqcFinish(Long id, Integer checkResult);
86 94
87 } 95 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java
@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWm @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWm
7 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; 7 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
8 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; 8 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO;
9 import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesLineMapper; 9 import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesLineMapper;
  10 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum;
  11 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
10 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 12 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
11 import jakarta.annotation.Resource; 13 import jakarta.annotation.Resource;
12 import org.springframework.context.annotation.Lazy; 14 import org.springframework.context.annotation.Lazy;
@@ -14,6 +16,7 @@ import org.springframework.stereotype.Service; @@ -14,6 +16,7 @@ import org.springframework.stereotype.Service;
14 import org.springframework.validation.annotation.Validated; 16 import org.springframework.validation.annotation.Validated;
15 17
16 import java.util.List; 18 import java.util.List;
  19 +import java.util.Objects;
17 20
18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 21 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_BATCH_REQUIRED; 22 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_BATCH_REQUIRED;
@@ -102,7 +105,7 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ @@ -102,7 +105,7 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ
102 } 105 }
103 106
104 @Override 107 @Override
105 - public void updateQualityStatusByReturnId(Long returnId, String qualityStatus) { 108 + public void updateQualityStatusByReturnId(Long returnId, Integer qualityStatus) {
106 List<MesWmReturnSalesLineDO> lines = returnSalesLineMapper.selectListByReturnId(returnId); 109 List<MesWmReturnSalesLineDO> lines = returnSalesLineMapper.selectListByReturnId(returnId);
107 for (MesWmReturnSalesLineDO line : lines) { 110 for (MesWmReturnSalesLineDO line : lines) {
108 returnSalesLineMapper.updateById(new MesWmReturnSalesLineDO() 111 returnSalesLineMapper.updateById(new MesWmReturnSalesLineDO()
@@ -125,4 +128,12 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ @@ -125,4 +128,12 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ
125 } 128 }
126 } 129 }
127 130
  131 + @Override
  132 + public void updateReturnSalesLineWhenRqcFinish(Long id, Integer checkResult) {
  133 + Integer qualityStatus = Objects.equals(checkResult, MesQcCheckResultEnum.PASS.getType())
  134 + ? MesWmQualityStatusEnum.PASS.getStatus()
  135 + : MesWmQualityStatusEnum.FAIL.getStatus();
  136 + returnSalesLineMapper.updateById(new MesWmReturnSalesLineDO().setId(id).setQualityStatus(qualityStatus));
  137 + }
  138 +
128 } 139 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java
@@ -124,7 +124,7 @@ public class MesWmReturnSalesServiceImpl implements MesWmReturnSalesService { @@ -124,7 +124,7 @@ public class MesWmReturnSalesServiceImpl implements MesWmReturnSalesService {
124 124
125 // DONE @AI:全部的行设置为待检验状态 125 // DONE @AI:全部的行设置为待检验状态
126 returnSalesLineService.updateQualityStatusByReturnId(id, 126 returnSalesLineService.updateQualityStatusByReturnId(id,
127 - String.valueOf(MesWmQualityStatusEnum.PENDING.getStatus())); 127 + MesWmQualityStatusEnum.PENDING.getStatus());
128 } 128 }
129 129
130 @Override 130 @Override
yudao-module-mes/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml
@@ -3,11 +3,12 @@ @@ -3,11 +3,12 @@
3 <mapper namespace="cn.iocoder.yudao.module.mes.dal.mysql.qc.pendinginspect.MesQcPendingInspectMapper"> 3 <mapper namespace="cn.iocoder.yudao.module.mes.dal.mysql.qc.pendinginspect.MesQcPendingInspectMapper">
4 4
5 <!-- 5 <!--
6 - 待检任务查询(UNION ALL 多来源),目前已实现的来源: 6 + 待检任务查询(UNION ALL 多来源),已实现的来源:
7 1. 到货通知单(IQC):状态=待质检(2),行的 iqc_check_flag=1 且 iqc_id IS NULL 7 1. 到货通知单(IQC):状态=待质检(2),行的 iqc_check_flag=1 且 iqc_id IS NULL
8 2. 外协入库单(IQC/OIQC):状态=待检验(1),行的 iqc_check=1 且 iqc_id IS NULL 8 2. 外协入库单(IQC/OIQC):状态=待检验(1),行的 iqc_check=1 且 iqc_id IS NULL
9 -  
10 - TODO IPQC/OQC/RQC 来源待对应模块就绪后补充 9 + 3. 生产报工(IPQC):状态=待检验(3)
  10 + 4. 销售出库单(OQC):行的 oqc_check=1 且 oqc_id IS NULL
  11 + 5. 生产退料单(RQC):状态=待检验(5),行的 qc_flag=1 且 quality_status=0(待检)
11 --> 12 -->
12 <select id="selectQcPendingPage" resultType="cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectRespVO"> 13 <select id="selectQcPendingPage" resultType="cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectRespVO">
13 SELECT * FROM ( 14 SELECT * FROM (
@@ -50,6 +51,64 @@ @@ -50,6 +51,64 @@
50 AND rl.iqc_id IS NULL 51 AND rl.iqc_id IS NULL
51 AND r.deleted = 0 52 AND r.deleted = 0
52 AND rl.deleted = 0 53 AND rl.deleted = 0
  54 +
  55 + UNION ALL
  56 +
  57 + <!-- 3. IPQC 来源:生产报工(状态=待检验) -->
  58 + SELECT
  59 + f.id AS sourceDocId,
  60 + ${@cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants@PRO_FEEDBACK} AS sourceDocType,
  61 + f.code AS sourceDocCode,
  62 + NULL AS sourceLineId,
  63 + f.feedback_time AS recordTime,
  64 + ${@cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum@IPQC.type} AS qcType,
  65 + f.item_id AS itemId,
  66 + f.uncheck_quantity AS quantity,
  67 + NULL AS vendorId
  68 + FROM mes_pro_feedback f
  69 + WHERE f.status = ${@cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum@UNCHECK.status}
  70 + AND f.deleted = 0
  71 +
  72 + UNION ALL
  73 +
  74 + <!-- 4. OQC 来源:销售出库单行(oqc_check=1 且 oqc_id IS NULL) -->
  75 + SELECT
  76 + s.id AS sourceDocId,
  77 + ${@cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants@WM_PRODUCT_SALES} AS sourceDocType,
  78 + s.code AS sourceDocCode,
  79 + sl.id AS sourceLineId,
  80 + s.sales_date AS recordTime,
  81 + ${@cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum@OQC.type} AS qcType,
  82 + sl.item_id AS itemId,
  83 + sl.quantity AS quantity,
  84 + NULL AS vendorId
  85 + FROM mes_wm_product_sales s
  86 + JOIN mes_wm_product_sales_line sl ON s.id = sl.sales_id
  87 + WHERE sl.oqc_check = 1
  88 + AND sl.oqc_id IS NULL
  89 + AND s.deleted = 0
  90 + AND sl.deleted = 0
  91 +
  92 + UNION ALL
  93 +
  94 + <!-- 5. RQC 来源:生产退料单行(状态=待检验,行的 qc_flag=1 且 quality_status=0) -->
  95 + SELECT
  96 + ri.id AS sourceDocId,
  97 + ${@cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants@WM_RETURN_ISSUE} AS sourceDocType,
  98 + ri.code AS sourceDocCode,
  99 + ril.id AS sourceLineId,
  100 + ri.return_date AS recordTime,
  101 + ${@cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum@RQC.type} AS qcType,
  102 + ril.item_id AS itemId,
  103 + ril.quantity AS quantity,
  104 + NULL AS vendorId
  105 + FROM mes_wm_return_issue ri
  106 + JOIN mes_wm_return_issue_line ril ON ri.id = ril.issue_id
  107 + WHERE ri.status = ${@cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnIssueStatusEnum@CONFIRMED.status}
  108 + AND ril.qc_flag = 1
  109 + AND ril.quality_status = ${@cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum@PENDING.status}
  110 + AND ri.deleted = 0
  111 + AND ril.deleted = 0
53 ) t 112 ) t
54 <where> 113 <where>
55 <if test="sourceDocCode != null and sourceDocCode != ''"> 114 <if test="sourceDocCode != null and sourceDocCode != ''">
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImplTest.java
@@ -56,7 +56,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { @@ -56,7 +56,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest {
56 private MesWmProductProduceLineService produceLineService; 56 private MesWmProductProduceLineService produceLineService;
57 57
58 @Test 58 @Test
59 - public void testCompleteFeedbackFromIpqc_success_withUnqualified() { 59 + public void testUpdateProFeedbackWhenIpqcFinish_success_withUnqualified() {
60 // 准备数据:插入一条待检验状态的报工单 60 // 准备数据:插入一条待检验状态的报工单
61 Long taskId = randomLongId(); 61 Long taskId = randomLongId();
62 Long workOrderId = randomLongId(); 62 Long workOrderId = randomLongId();
@@ -87,7 +87,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { @@ -87,7 +87,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest {
87 BigDecimal materialScrapQty = BigDecimal.valueOf(10); 87 BigDecimal materialScrapQty = BigDecimal.valueOf(10);
88 BigDecimal otherScrapQty = BigDecimal.valueOf(5); 88 BigDecimal otherScrapQty = BigDecimal.valueOf(5);
89 89
90 - feedbackService.completeFeedbackFromIpqc(feedback.getId(), 90 + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(),
91 qualifiedQty, unqualifiedQty, laborScrapQty, materialScrapQty, otherScrapQty); 91 qualifiedQty, unqualifiedQty, laborScrapQty, materialScrapQty, otherScrapQty);
92 92
93 // 断言 1:调用了 splitPendingAndFinishProduce 93 // 断言 1:调用了 splitPendingAndFinishProduce
@@ -115,7 +115,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { @@ -115,7 +115,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest {
115 } 115 }
116 116
117 @Test 117 @Test
118 - public void testCompleteFeedbackFromIpqc_success_allQualified() { 118 + public void testUpdateProFeedbackWhenIpqcFinish_success_allQualified() {
119 // 准备数据:全部合格 119 // 准备数据:全部合格
120 Long taskId = randomLongId(); 120 Long taskId = randomLongId();
121 Long workOrderId = randomLongId(); 121 Long workOrderId = randomLongId();
@@ -136,7 +136,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { @@ -136,7 +136,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest {
136 .thenReturn(List.of(qualifiedLine)); 136 .thenReturn(List.of(qualifiedLine));
137 137
138 // 调用 138 // 调用
139 - feedbackService.completeFeedbackFromIpqc(feedback.getId(), 139 + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(),
140 BigDecimal.valueOf(50), BigDecimal.ZERO, 140 BigDecimal.valueOf(50), BigDecimal.ZERO,
141 BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO); 141 BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO);
142 142
@@ -151,17 +151,17 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { @@ -151,17 +151,17 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest {
151 } 151 }
152 152
153 @Test 153 @Test
154 - public void testCompleteFeedbackFromIpqc_feedbackNotExists() { 154 + public void testUpdateProFeedbackWhenIpqcFinish_feedbackNotExists() {
155 // 调用不存在的 feedbackId,应该抛异常 155 // 调用不存在的 feedbackId,应该抛异常
156 Long feedbackId = randomLongId(); 156 Long feedbackId = randomLongId();
157 assertThrows(Exception.class, () -> 157 assertThrows(Exception.class, () ->
158 - feedbackService.completeFeedbackFromIpqc(feedbackId, 158 + feedbackService.updateProFeedbackWhenIpqcFinish(feedbackId,
159 BigDecimal.TEN, BigDecimal.ZERO, 159 BigDecimal.TEN, BigDecimal.ZERO,
160 BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)); 160 BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO));
161 } 161 }
162 162
163 @Test 163 @Test
164 - public void testCompleteFeedbackFromIpqc_feedbackNotUncheck() { 164 + public void testUpdateProFeedbackWhenIpqcFinish_feedbackNotUncheck() {
165 // 准备数据:草稿状态(不是 UNCHECK),应该报错 165 // 准备数据:草稿状态(不是 UNCHECK),应该报错
166 MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { 166 MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> {
167 o.setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus()); 167 o.setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus());
@@ -170,7 +170,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { @@ -170,7 +170,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest {
170 170
171 // 调用,应该抛异常 171 // 调用,应该抛异常
172 assertThrows(Exception.class, () -> 172 assertThrows(Exception.class, () ->
173 - feedbackService.completeFeedbackFromIpqc(feedback.getId(), 173 + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(),
174 BigDecimal.TEN, BigDecimal.ZERO, 174 BigDecimal.TEN, BigDecimal.ZERO,
175 BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)); 175 BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO));
176 176
@@ -179,7 +179,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { @@ -179,7 +179,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest {
179 } 179 }
180 180
181 @Test 181 @Test
182 - public void testCompleteFeedbackFromIpqc_feedbackAlreadyFinished() { 182 + public void testUpdateProFeedbackWhenIpqcFinish_feedbackAlreadyFinished() {
183 // 准备数据:已完成状态,不能再次完成 183 // 准备数据:已完成状态,不能再次完成
184 MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { 184 MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> {
185 o.setStatus(MesProFeedbackStatusEnum.FINISHED.getStatus()); 185 o.setStatus(MesProFeedbackStatusEnum.FINISHED.getStatus());
@@ -188,7 +188,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { @@ -188,7 +188,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest {
188 188
189 // 调用,应该抛异常 189 // 调用,应该抛异常
190 assertThrows(Exception.class, () -> 190 assertThrows(Exception.class, () ->
191 - feedbackService.completeFeedbackFromIpqc(feedback.getId(), 191 + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(),
192 BigDecimal.TEN, BigDecimal.ZERO, 192 BigDecimal.TEN, BigDecimal.ZERO,
193 BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)); 193 BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO));
194 } 194 }
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java
@@ -88,7 +88,7 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { @@ -88,7 +88,7 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest {
88 88
89 // 断言 2:调用了 feedbackService.completeFeedbackFromIpqc,传递正确参数 89 // 断言 2:调用了 feedbackService.completeFeedbackFromIpqc,传递正确参数
90 // 注意:数量经过 DB 存取后 scale 可能变化(例如 80 → 80.00),所以用 any() 匹配 90 // 注意:数量经过 DB 存取后 scale 可能变化(例如 80 → 80.00),所以用 any() 匹配
91 - verify(feedbackService).completeFeedbackFromIpqc( 91 + verify(feedbackService).updateProFeedbackWhenIpqcFinish(
92 eq(sourceDocId), 92 eq(sourceDocId),
93 any(BigDecimal.class), 93 any(BigDecimal.class),
94 any(BigDecimal.class), 94 any(BigDecimal.class),
@@ -119,7 +119,7 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { @@ -119,7 +119,7 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest {
119 ipqcService.finishIpqc(ipqc.getId()); 119 ipqcService.finishIpqc(ipqc.getId());
120 120
121 // 断言:所有数量参数都是 BigDecimal.ZERO(defaultIfNull 处理) 121 // 断言:所有数量参数都是 BigDecimal.ZERO(defaultIfNull 处理)
122 - verify(feedbackService).completeFeedbackFromIpqc( 122 + verify(feedbackService).updateProFeedbackWhenIpqcFinish(
123 eq(sourceDocId), 123 eq(sourceDocId),
124 eq(BigDecimal.ZERO), 124 eq(BigDecimal.ZERO),
125 eq(BigDecimal.ZERO), 125 eq(BigDecimal.ZERO),
@@ -148,7 +148,7 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { @@ -148,7 +148,7 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest {
148 assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIpqc.getStatus()); 148 assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIpqc.getStatus());
149 149
150 // 断言 2:不应该调用 feedbackService 150 // 断言 2:不应该调用 feedbackService
151 - verify(feedbackService, never()).completeFeedbackFromIpqc( 151 + verify(feedbackService, never()).updateProFeedbackWhenIpqcFinish(
152 anyLong(), any(), any(), any(), any(), any()); 152 anyLong(), any(), any(), any(), any(), any());
153 } 153 }
154 154
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImplTest.java
@@ -58,7 +58,7 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest { @@ -58,7 +58,7 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest {
58 58
59 @Test 59 @Test
60 public void testFinishIqc_writeBack_arrivalNotice() { 60 public void testFinishIqc_writeBack_arrivalNotice() {
61 - // mock 数据:插入一条草稿状态的 IQC 单,来源为到货通知单 61 + // 准备数据:插入一条草稿状态的 IQC 单,来源为到货通知单
62 Long sourceDocId = randomLongId(); 62 Long sourceDocId = randomLongId();
63 Long sourceLineId = randomLongId(); 63 Long sourceLineId = randomLongId();
64 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { 64 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> {
@@ -79,16 +79,16 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest { @@ -79,16 +79,16 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest {
79 MesQcIqcDO updatedIqc = iqcMapper.selectById(iqc.getId()); 79 MesQcIqcDO updatedIqc = iqcMapper.selectById(iqc.getId());
80 assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIqc.getStatus()); 80 assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIqc.getStatus());
81 // 断言:验证回写到货通知单(参数使用 any 避免 BigDecimal 精度问题) 81 // 断言:验证回写到货通知单(参数使用 any 避免 BigDecimal 精度问题)
82 - verify(arrivalNoticeService).approveArrivalNoticeWhenIqcComplete( 82 + verify(arrivalNoticeService).updateArrivalNoticeWhenIqcFinish(
83 eq(sourceDocId), eq(sourceLineId), eq(iqc.getId()), any(BigDecimal.class)); 83 eq(sourceDocId), eq(sourceLineId), eq(iqc.getId()), any(BigDecimal.class));
84 // 断言:不应该调用外协入库单的回写 84 // 断言:不应该调用外协入库单的回写
85 - verify(outsourceReceiptService, never()).approveOutsourceReceiptWhenIqcComplete( 85 + verify(outsourceReceiptService, never()).updateOutsourceReceiptWhenIqcFinish(
86 anyLong(), anyLong(), anyLong(), any(), any()); 86 anyLong(), anyLong(), anyLong(), any(), any());
87 } 87 }
88 88
89 @Test 89 @Test
90 public void testFinishIqc_writeBack_outsourceReceipt() { 90 public void testFinishIqc_writeBack_outsourceReceipt() {
91 - // mock 数据:插入一条草稿状态的 IQC 单,来源为外协入库单 91 + // 准备数据:插入一条草稿状态的 IQC 单,来源为外协入库单
92 Long sourceDocId = randomLongId(); 92 Long sourceDocId = randomLongId();
93 Long sourceLineId = randomLongId(); 93 Long sourceLineId = randomLongId();
94 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { 94 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> {
@@ -109,16 +109,16 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest { @@ -109,16 +109,16 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest {
109 MesQcIqcDO updatedIqc = iqcMapper.selectById(iqc.getId()); 109 MesQcIqcDO updatedIqc = iqcMapper.selectById(iqc.getId());
110 assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIqc.getStatus()); 110 assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIqc.getStatus());
111 // 断言:验证回写外协入库单(参数使用 any 避免 BigDecimal 精度问题) 111 // 断言:验证回写外协入库单(参数使用 any 避免 BigDecimal 精度问题)
112 - verify(outsourceReceiptService).approveOutsourceReceiptWhenIqcComplete( 112 + verify(outsourceReceiptService).updateOutsourceReceiptWhenIqcFinish(
113 eq(sourceDocId), eq(sourceLineId), eq(iqc.getId()), any(BigDecimal.class), any(BigDecimal.class)); 113 eq(sourceDocId), eq(sourceLineId), eq(iqc.getId()), any(BigDecimal.class), any(BigDecimal.class));
114 // 断言:不应该调用到货通知单的回写 114 // 断言:不应该调用到货通知单的回写
115 - verify(arrivalNoticeService, never()).approveArrivalNoticeWhenIqcComplete( 115 + verify(arrivalNoticeService, never()).updateArrivalNoticeWhenIqcFinish(
116 anyLong(), anyLong(), anyLong(), any()); 116 anyLong(), anyLong(), anyLong(), any());
117 } 117 }
118 118
119 @Test 119 @Test
120 public void testFinishIqc_writeBack_noSourceDoc() { 120 public void testFinishIqc_writeBack_noSourceDoc() {
121 - // mock 数据:sourceDocType 为空,不需要回写 121 + // 准备数据:sourceDocType 为空,不需要回写
122 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { 122 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> {
123 o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); 123 o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
124 o.setCheckResult(1); 124 o.setCheckResult(1);
@@ -135,15 +135,15 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest { @@ -135,15 +135,15 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest {
135 MesQcIqcDO updatedIqc = iqcMapper.selectById(iqc.getId()); 135 MesQcIqcDO updatedIqc = iqcMapper.selectById(iqc.getId());
136 assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIqc.getStatus()); 136 assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIqc.getStatus());
137 // 断言:不应该调用任何回写 137 // 断言:不应该调用任何回写
138 - verify(arrivalNoticeService, never()).approveArrivalNoticeWhenIqcComplete( 138 + verify(arrivalNoticeService, never()).updateArrivalNoticeWhenIqcFinish(
139 anyLong(), anyLong(), anyLong(), any()); 139 anyLong(), anyLong(), anyLong(), any());
140 - verify(outsourceReceiptService, never()).approveOutsourceReceiptWhenIqcComplete( 140 + verify(outsourceReceiptService, never()).updateOutsourceReceiptWhenIqcFinish(
141 anyLong(), anyLong(), anyLong(), any(), any()); 141 anyLong(), anyLong(), anyLong(), any(), any());
142 } 142 }
143 143
144 @Test 144 @Test
145 public void testFinishIqc_writeBack_sourceDocTypeDirtyData() { 145 public void testFinishIqc_writeBack_sourceDocTypeDirtyData() {
146 - // mock 数据:sourceDocType 非空但 sourceLineId 为空,应该抛异常 146 + // 准备数据:sourceDocType 非空但 sourceLineId 为空,应该抛异常
147 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { 147 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> {
148 o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); 148 o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
149 o.setCheckResult(1); 149 o.setCheckResult(1);
@@ -159,7 +159,7 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest { @@ -159,7 +159,7 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest {
159 159
160 @Test 160 @Test
161 public void testFinishIqc_writeBack_unknownSourceDocType() { 161 public void testFinishIqc_writeBack_unknownSourceDocType() {
162 - // mock 数据:sourceDocType 无法识别 162 + // 准备数据:sourceDocType 无法识别
163 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { 163 MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> {
164 o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); 164 o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
165 o.setCheckResult(1); 165 o.setCheckResult(1);
@@ -173,4 +173,31 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest { @@ -173,4 +173,31 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest {
173 assertThrows(IllegalArgumentException.class, () -> iqcService.finishIqc(iqc.getId())); 173 assertThrows(IllegalArgumentException.class, () -> iqcService.finishIqc(iqc.getId()));
174 } 174 }
175 175
  176 + @Test
  177 + public void testFinishIqc_checkResultEmpty() {
  178 + // 准备数据:checkResult 为空,应该报错
  179 + MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> {
  180 + o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
  181 + o.setCheckResult(null); // 检测结论为空
  182 + o.setSourceDocType(null);
  183 + });
  184 + iqcMapper.insert(iqc);
  185 +
  186 + // 调用,应该抛异常(检测结论必填)
  187 + assertThrows(Exception.class, () -> iqcService.finishIqc(iqc.getId()));
  188 + }
  189 +
  190 + @Test
  191 + public void testFinishIqc_notDraftStatus() {
  192 + // 准备数据:已完成状态,不能再次完成
  193 + MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> {
  194 + o.setStatus(MesQcStatusEnum.FINISHED.getStatus());
  195 + o.setCheckResult(1);
  196 + });
  197 + iqcMapper.insert(iqc);
  198 +
  199 + // 调用,应该抛异常(不是草稿状态)
  200 + assertThrows(Exception.class, () -> iqcService.finishIqc(iqc.getId()));
  201 + }
  202 +
176 } 203 }
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.qc.oqc;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO;
  5 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcMapper;
  6 +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
  7 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
  8 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  9 +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
  10 +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateDetailService;
  11 +import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService;
  12 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  13 +import jakarta.annotation.Resource;
  14 +import org.junit.jupiter.api.Test;
  15 +import org.springframework.context.annotation.Import;
  16 +import org.springframework.test.context.bean.override.mockito.MockitoBean;
  17 +
  18 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  19 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  20 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  21 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.QC_OQC_NOT_EXISTS;
  22 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.QC_OQC_NOT_PREPARE;
  23 +import static org.junit.jupiter.api.Assertions.assertEquals;
  24 +import static org.mockito.ArgumentMatchers.eq;
  25 +import static org.mockito.Mockito.verify;
  26 +
  27 +/**
  28 + * {@link MesQcOqcServiceImpl} 的单元测试类
  29 + *
  30 + * @author 芋道源码
  31 + */
  32 +@Import(MesQcOqcServiceImpl.class)
  33 +public class MesQcOqcServiceImplTest extends BaseDbUnitTest {
  34 +
  35 + @Resource
  36 + private MesQcOqcServiceImpl oqcService;
  37 +
  38 + @Resource
  39 + private MesQcOqcMapper oqcMapper;
  40 +
  41 + @MockitoBean
  42 + private MesWmProductSalesLineService productSalesLineService;
  43 + @MockitoBean
  44 + private MesQcOqcLineService oqcLineService;
  45 + @MockitoBean
  46 + private MesMdItemService itemService;
  47 + @MockitoBean
  48 + private MesQcTemplateDetailService templateDetailService;
  49 + @MockitoBean
  50 + private MesQcDefectRecordService defectRecordService;
  51 + @MockitoBean
  52 + private AdminUserApi adminUserApi;
  53 +
  54 + @Test
  55 + public void testFinishOqc_success() {
  56 + // 准备参数
  57 + Long sourceLineId = randomLongId();
  58 + Integer checkResult = 1;
  59 +
  60 + // mock 数据
  61 + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> {
  62 + o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
  63 + o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES);
  64 + o.setSourceLineId(sourceLineId);
  65 + o.setCheckResult(checkResult);
  66 + });
  67 + oqcMapper.insert(oqc);
  68 +
  69 + // 调用
  70 + oqcService.finishOqc(oqc.getId());
  71 +
  72 + // 断言:验证状态更新
  73 + MesQcOqcDO updatedOqc = oqcMapper.selectById(oqc.getId());
  74 + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedOqc.getStatus());
  75 +
  76 + // 断言:验证回写调用
  77 + verify(productSalesLineService).updateProductSalesLineWhenOqcFinish(eq(sourceLineId), eq(oqc.getId()), eq(checkResult));
  78 + }
  79 +
  80 + @Test
  81 + public void testFinishOqc_notExists() {
  82 + // 准备参数
  83 + Long oqcId = randomLongId();
  84 +
  85 + // 调用,并断言异常
  86 + assertServiceException(() -> oqcService.finishOqc(oqcId), QC_OQC_NOT_EXISTS);
  87 + }
  88 +
  89 + @Test
  90 + public void testFinishOqc_statusNotDraft() {
  91 + // 准备参数
  92 + // mock 数据:状态为已完成
  93 + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> {
  94 + o.setStatus(MesQcStatusEnum.FINISHED.getStatus());
  95 + });
  96 + oqcMapper.insert(oqc);
  97 +
  98 + // 调用,并断言异常
  99 + assertServiceException(() -> oqcService.finishOqc(oqc.getId()), QC_OQC_NOT_PREPARE);
  100 + }
  101 +
  102 +}
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.qc.rqc;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO;
  5 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc.MesQcRqcMapper;
  6 +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
  7 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
  8 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  9 +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
  10 +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateDetailService;
  11 +import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueLineService;
  12 +import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesLineService;
  13 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  14 +import jakarta.annotation.Resource;
  15 +import org.junit.jupiter.api.Test;
  16 +import org.springframework.context.annotation.Import;
  17 +import org.springframework.test.context.bean.override.mockito.MockitoBean;
  18 +
  19 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  20 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  21 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  22 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.QC_RQC_NOT_EXISTS;
  23 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.QC_RQC_NOT_PREPARE;
  24 +import static org.junit.jupiter.api.Assertions.assertEquals;
  25 +import static org.mockito.ArgumentMatchers.anyInt;
  26 +import static org.mockito.ArgumentMatchers.anyLong;
  27 +import static org.mockito.ArgumentMatchers.eq;
  28 +import static org.mockito.Mockito.never;
  29 +import static org.mockito.Mockito.verify;
  30 +
  31 +/**
  32 + * {@link MesQcRqcServiceImpl} 的单元测试类
  33 + *
  34 + * @author 芋道源码
  35 + */
  36 +@Import(MesQcRqcServiceImpl.class)
  37 +public class MesQcRqcServiceImplTest extends BaseDbUnitTest {
  38 +
  39 + @Resource
  40 + private MesQcRqcServiceImpl rqcService;
  41 +
  42 + @Resource
  43 + private MesQcRqcMapper rqcMapper;
  44 +
  45 + @MockitoBean
  46 + private MesWmReturnIssueLineService returnIssueLineService;
  47 + @MockitoBean
  48 + private MesWmReturnSalesLineService returnSalesLineService;
  49 + @MockitoBean
  50 + private MesQcRqcLineService rqcLineService;
  51 + @MockitoBean
  52 + private MesMdItemService itemService;
  53 + @MockitoBean
  54 + private MesQcTemplateDetailService templateDetailService;
  55 + @MockitoBean
  56 + private MesQcDefectRecordService defectRecordService;
  57 + @MockitoBean
  58 + private AdminUserApi adminUserApi;
  59 +
  60 + @Test
  61 + public void testFinishRqc_successWithReturnIssue() {
  62 + // 准备参数
  63 + Long sourceLineId = randomLongId();
  64 + Integer checkResult = 1;
  65 +
  66 + // mock 数据
  67 + MesQcRqcDO rqc = randomPojo(MesQcRqcDO.class, o -> {
  68 + o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
  69 + o.setSourceDocType(MesBizTypeConstants.WM_RETURN_ISSUE);
  70 + o.setSourceLineId(sourceLineId);
  71 + o.setCheckResult(checkResult);
  72 + // 设置数量通过 finishRqc 的数量校验:合格 + 不合格 = 检测数量
  73 + o.setCheckQuantity(new java.math.BigDecimal("100"));
  74 + o.setQualifiedQuantity(new java.math.BigDecimal("80"));
  75 + o.setUnqualifiedQuantity(new java.math.BigDecimal("20"));
  76 + });
  77 + rqcMapper.insert(rqc);
  78 +
  79 + // 调用
  80 + rqcService.finishRqc(rqc.getId());
  81 +
  82 + // 断言:验证状态更新
  83 + MesQcRqcDO updatedRqc = rqcMapper.selectById(rqc.getId());
  84 + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedRqc.getStatus());
  85 +
  86 + // 断言:验证回写调用生产退料
  87 + verify(returnIssueLineService).updateReturnIssueLineWhenRqcFinish(eq(sourceLineId), eq(checkResult));
  88 + // 断言:未调用销售退货
  89 + verify(returnSalesLineService, never()).updateReturnSalesLineWhenRqcFinish(anyLong(), anyInt());
  90 + }
  91 +
  92 + @Test
  93 + public void testFinishRqc_successWithReturnSales() {
  94 + // 准备参数
  95 + Long sourceLineId = randomLongId();
  96 + Integer checkResult = 1;
  97 +
  98 + // mock 数据
  99 + MesQcRqcDO rqc = randomPojo(MesQcRqcDO.class, o -> {
  100 + o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
  101 + o.setSourceDocType(MesBizTypeConstants.WM_RETURN_SALES);
  102 + o.setSourceLineId(sourceLineId);
  103 + o.setCheckResult(checkResult);
  104 + // 设置数量通过 finishRqc 的数量校验:合格 + 不合格 = 检测数量
  105 + o.setCheckQuantity(new java.math.BigDecimal("100"));
  106 + o.setQualifiedQuantity(new java.math.BigDecimal("90"));
  107 + o.setUnqualifiedQuantity(new java.math.BigDecimal("10"));
  108 + });
  109 + rqcMapper.insert(rqc);
  110 +
  111 + // 调用
  112 + rqcService.finishRqc(rqc.getId());
  113 +
  114 + // 断言:验证状态更新
  115 + MesQcRqcDO updatedRqc = rqcMapper.selectById(rqc.getId());
  116 + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedRqc.getStatus());
  117 +
  118 + // 断言:验证回写调用销售退货
  119 + verify(returnSalesLineService).updateReturnSalesLineWhenRqcFinish(eq(sourceLineId), eq(checkResult));
  120 + // 断言:未调用生产退料
  121 + verify(returnIssueLineService, never()).updateReturnIssueLineWhenRqcFinish(anyLong(), anyInt());
  122 + }
  123 +
  124 + @Test
  125 + public void testFinishRqc_notExists() {
  126 + // 准备参数
  127 + Long rqcId = randomLongId();
  128 +
  129 + // 调用,并断言异常
  130 + assertServiceException(() -> rqcService.finishRqc(rqcId), QC_RQC_NOT_EXISTS);
  131 + }
  132 +
  133 + @Test
  134 + public void testFinishRqc_statusNotDraft() {
  135 + // 准备参数
  136 + // mock 数据:状态为已完成
  137 + MesQcRqcDO rqc = randomPojo(MesQcRqcDO.class, o -> {
  138 + o.setStatus(MesQcStatusEnum.FINISHED.getStatus());
  139 + });
  140 + rqcMapper.insert(rqc);
  141 +
  142 + // 调用,并断言异常
  143 + assertServiceException(() -> rqcService.finishRqc(rqc.getId()), QC_RQC_NOT_PREPARE);
  144 + }
  145 +
  146 +}
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImplTest.java
@@ -23,7 +23,7 @@ import static org.mockito.ArgumentMatchers.eq; @@ -23,7 +23,7 @@ import static org.mockito.ArgumentMatchers.eq;
23 import static org.mockito.Mockito.*; 23 import static org.mockito.Mockito.*;
24 24
25 /** 25 /**
26 - * {@link MesWmArrivalNoticeServiceImpl#approveArrivalNoticeWhenIqcComplete} 的单元测试 26 + * {@link MesWmArrivalNoticeServiceImpl} 的单元测试
27 * 27 *
28 * @author 芋道源码 28 * @author 芋道源码
29 */ 29 */
@@ -40,7 +40,7 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest { @@ -40,7 +40,7 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest {
40 private MesWmArrivalNoticeLineService arrivalNoticeLineService; 40 private MesWmArrivalNoticeLineService arrivalNoticeLineService;
41 41
42 @Test 42 @Test
43 - public void testApproveArrivalNoticeWhenIqcComplete_success_allLinesChecked() { 43 + public void testUpdateArrivalNoticeWhenIqcFinish_success_allLinesChecked() {
44 // mock 数据:插入一条待质检的到货通知单 44 // mock 数据:插入一条待质检的到货通知单
45 MesWmArrivalNoticeDO notice = randomPojo(MesWmArrivalNoticeDO.class, o -> { 45 MesWmArrivalNoticeDO notice = randomPojo(MesWmArrivalNoticeDO.class, o -> {
46 o.setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus()); 46 o.setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus());
@@ -67,17 +67,17 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest { @@ -67,17 +67,17 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest {
67 .thenReturn(Arrays.asList(line1, line2)); 67 .thenReturn(Arrays.asList(line1, line2));
68 68
69 // 调用 69 // 调用
70 - arrivalNoticeService.approveArrivalNoticeWhenIqcComplete(noticeId, lineId, iqcId, qualifiedQuantity); 70 + arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(noticeId, lineId, iqcId, qualifiedQuantity);
71 71
72 // 断言:行回写被调用 72 // 断言:行回写被调用
73 - verify(arrivalNoticeLineService).updateByIqcComplete(eq(lineId), eq(iqcId), eq(qualifiedQuantity)); 73 + verify(arrivalNoticeLineService).updateArrivalNoticeLineWhenIqcFinish(eq(lineId), eq(iqcId), eq(qualifiedQuantity));
74 // 断言:主表状态更新为待入库 74 // 断言:主表状态更新为待入库
75 MesWmArrivalNoticeDO updatedNotice = arrivalNoticeMapper.selectById(noticeId); 75 MesWmArrivalNoticeDO updatedNotice = arrivalNoticeMapper.selectById(noticeId);
76 assertEquals(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus(), updatedNotice.getStatus()); 76 assertEquals(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus(), updatedNotice.getStatus());
77 } 77 }
78 78
79 @Test 79 @Test
80 - public void testApproveArrivalNoticeWhenIqcComplete_success_hasUncheckedLines() { 80 + public void testUpdateArrivalNoticeWhenIqcFinish_success_hasUncheckedLines() {
81 // mock 数据:插入一条待质检的到货通知单 81 // mock 数据:插入一条待质检的到货通知单
82 MesWmArrivalNoticeDO notice = randomPojo(MesWmArrivalNoticeDO.class, o -> { 82 MesWmArrivalNoticeDO notice = randomPojo(MesWmArrivalNoticeDO.class, o -> {
83 o.setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus()); 83 o.setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus());
@@ -104,17 +104,17 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest { @@ -104,17 +104,17 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest {
104 .thenReturn(Arrays.asList(line1, line2)); 104 .thenReturn(Arrays.asList(line1, line2));
105 105
106 // 调用 106 // 调用
107 - arrivalNoticeService.approveArrivalNoticeWhenIqcComplete(noticeId, lineId, iqcId, qualifiedQuantity); 107 + arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(noticeId, lineId, iqcId, qualifiedQuantity);
108 108
109 // 断言:行回写被调用 109 // 断言:行回写被调用
110 - verify(arrivalNoticeLineService).updateByIqcComplete(eq(lineId), eq(iqcId), eq(qualifiedQuantity)); 110 + verify(arrivalNoticeLineService).updateArrivalNoticeLineWhenIqcFinish(eq(lineId), eq(iqcId), eq(qualifiedQuantity));
111 // 断言:主表状态不变,仍然是待质检 111 // 断言:主表状态不变,仍然是待质检
112 MesWmArrivalNoticeDO updatedNotice = arrivalNoticeMapper.selectById(noticeId); 112 MesWmArrivalNoticeDO updatedNotice = arrivalNoticeMapper.selectById(noticeId);
113 assertEquals(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus(), updatedNotice.getStatus()); 113 assertEquals(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus(), updatedNotice.getStatus());
114 } 114 }
115 115
116 @Test 116 @Test
117 - public void testApproveArrivalNoticeWhenIqcComplete_noticeNotExists() { 117 + public void testUpdateArrivalNoticeWhenIqcFinish_noticeNotExists() {
118 // 准备参数 118 // 准备参数
119 Long noticeId = randomLongId(); 119 Long noticeId = randomLongId();
120 Long lineId = randomLongId(); 120 Long lineId = randomLongId();
@@ -123,12 +123,12 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest { @@ -123,12 +123,12 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest {
123 123
124 // 调用,并断言异常 124 // 调用,并断言异常
125 assertServiceException( 125 assertServiceException(
126 - () -> arrivalNoticeService.approveArrivalNoticeWhenIqcComplete(noticeId, lineId, iqcId, qualifiedQuantity), 126 + () -> arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(noticeId, lineId, iqcId, qualifiedQuantity),
127 WM_ARRIVAL_NOTICE_NOT_EXISTS); 127 WM_ARRIVAL_NOTICE_NOT_EXISTS);
128 } 128 }
129 129
130 @Test 130 @Test
131 - public void testApproveArrivalNoticeWhenIqcComplete_statusNotPendingQc() { 131 + public void testUpdateArrivalNoticeWhenIqcFinish_statusNotPendingQc() {
132 // mock 数据:插入一条草稿状态的到货通知单(非待质检) 132 // mock 数据:插入一条草稿状态的到货通知单(非待质检)
133 MesWmArrivalNoticeDO notice = randomPojo(MesWmArrivalNoticeDO.class, o -> { 133 MesWmArrivalNoticeDO notice = randomPojo(MesWmArrivalNoticeDO.class, o -> {
134 o.setStatus(MesWmArrivalNoticeStatusEnum.PREPARE.getStatus()); 134 o.setStatus(MesWmArrivalNoticeStatusEnum.PREPARE.getStatus());
@@ -142,7 +142,7 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest { @@ -142,7 +142,7 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest {
142 142
143 // 调用,并断言异常 143 // 调用,并断言异常
144 assertServiceException( 144 assertServiceException(
145 - () -> arrivalNoticeService.approveArrivalNoticeWhenIqcComplete(noticeId, lineId, iqcId, qualifiedQuantity), 145 + () -> arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(noticeId, lineId, iqcId, qualifiedQuantity),
146 WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_QC); 146 WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_QC);
147 } 147 }
148 148
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImplTest.java
@@ -26,7 +26,7 @@ import static org.mockito.ArgumentMatchers.*; @@ -26,7 +26,7 @@ import static org.mockito.ArgumentMatchers.*;
26 import static org.mockito.Mockito.*; 26 import static org.mockito.Mockito.*;
27 27
28 /** 28 /**
29 - * {@link MesWmOutsourceReceiptServiceImpl#approveOutsourceReceiptWhenIqcComplete} 的单元测试 29 + * {@link MesWmOutsourceReceiptServiceImpl} 的单元测试
30 * 30 *
31 * @author 芋道源码 31 * @author 芋道源码
32 */ 32 */
@@ -51,7 +51,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest { @@ -51,7 +51,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest {
51 private MesMdItemService itemService; 51 private MesMdItemService itemService;
52 52
53 @Test 53 @Test
54 - public void testApproveOutsourceReceiptWhenIqcComplete_success_bothQualifiedAndUnqualified() { 54 + public void testUpdateOutsourceReceiptWhenIqcFinish_success_bothQualifiedAndUnqualified() {
55 // mock 数据:插入一条待检验状态的外协入库单 55 // mock 数据:插入一条待检验状态的外协入库单
56 MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> { 56 MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> {
57 o.setStatus(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus()); 57 o.setStatus(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus());
@@ -73,7 +73,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest { @@ -73,7 +73,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest {
73 when(outsourceReceiptLineService.getOutsourceReceiptLine(eq(lineId))).thenReturn(line); 73 when(outsourceReceiptLineService.getOutsourceReceiptLine(eq(lineId))).thenReturn(line);
74 74
75 // 调用 75 // 调用
76 - outsourceReceiptService.approveOutsourceReceiptWhenIqcComplete( 76 + outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish(
77 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity); 77 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity);
78 78
79 // 断言:合格品行更新 79 // 断言:合格品行更新
@@ -94,7 +94,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest { @@ -94,7 +94,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest {
94 } 94 }
95 95
96 @Test 96 @Test
97 - public void testApproveOutsourceReceiptWhenIqcComplete_success_onlyQualified() { 97 + public void testUpdateOutsourceReceiptWhenIqcFinish_success_onlyQualified() {
98 // mock 数据:插入一条待检验状态的外协入库单 98 // mock 数据:插入一条待检验状态的外协入库单
99 MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> { 99 MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> {
100 o.setStatus(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus()); 100 o.setStatus(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus());
@@ -115,7 +115,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest { @@ -115,7 +115,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest {
115 when(outsourceReceiptLineService.getOutsourceReceiptLine(eq(lineId))).thenReturn(line); 115 when(outsourceReceiptLineService.getOutsourceReceiptLine(eq(lineId))).thenReturn(line);
116 116
117 // 调用 117 // 调用
118 - outsourceReceiptService.approveOutsourceReceiptWhenIqcComplete( 118 + outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish(
119 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity); 119 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity);
120 120
121 // 断言:合格品行更新 121 // 断言:合格品行更新
@@ -129,7 +129,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest { @@ -129,7 +129,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest {
129 } 129 }
130 130
131 @Test 131 @Test
132 - public void testApproveOutsourceReceiptWhenIqcComplete_receiptNotExists() { 132 + public void testUpdateOutsourceReceiptWhenIqcFinish_receiptNotExists() {
133 // 准备参数 133 // 准备参数
134 Long receiptId = randomLongId(); 134 Long receiptId = randomLongId();
135 Long lineId = randomLongId(); 135 Long lineId = randomLongId();
@@ -139,13 +139,13 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest { @@ -139,13 +139,13 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest {
139 139
140 // 调用,并断言异常 140 // 调用,并断言异常
141 assertServiceException( 141 assertServiceException(
142 - () -> outsourceReceiptService.approveOutsourceReceiptWhenIqcComplete( 142 + () -> outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish(
143 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity), 143 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity),
144 WM_OUTSOURCE_RECEIPT_NOT_EXISTS); 144 WM_OUTSOURCE_RECEIPT_NOT_EXISTS);
145 } 145 }
146 146
147 @Test 147 @Test
148 - public void testApproveOutsourceReceiptWhenIqcComplete_statusNotConfirmed() { 148 + public void testUpdateOutsourceReceiptWhenIqcFinish_statusNotConfirmed() {
149 // mock 数据:插入一条草稿状态的外协入库单(非待检验状态) 149 // mock 数据:插入一条草稿状态的外协入库单(非待检验状态)
150 MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> { 150 MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> {
151 o.setStatus(MesWmOutsourceReceiptStatusEnum.PREPARE.getStatus()); 151 o.setStatus(MesWmOutsourceReceiptStatusEnum.PREPARE.getStatus());
@@ -160,13 +160,13 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest { @@ -160,13 +160,13 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest {
160 160
161 // 调用,并断言异常 161 // 调用,并断言异常
162 assertServiceException( 162 assertServiceException(
163 - () -> outsourceReceiptService.approveOutsourceReceiptWhenIqcComplete( 163 + () -> outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish(
164 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity), 164 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity),
165 WM_OUTSOURCE_RECEIPT_STATUS_ERROR); 165 WM_OUTSOURCE_RECEIPT_STATUS_ERROR);
166 } 166 }
167 167
168 @Test 168 @Test
169 - public void testApproveOutsourceReceiptWhenIqcComplete_lineNotExists() { 169 + public void testUpdateOutsourceReceiptWhenIqcFinish_lineNotExists() {
170 // mock 数据:插入一条待检验状态的外协入库单 170 // mock 数据:插入一条待检验状态的外协入库单
171 MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> { 171 MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> {
172 o.setStatus(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus()); 172 o.setStatus(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus());
@@ -184,7 +184,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest { @@ -184,7 +184,7 @@ public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest {
184 184
185 // 调用,并断言异常 185 // 调用,并断言异常
186 assertServiceException( 186 assertServiceException(
187 - () -> outsourceReceiptService.approveOutsourceReceiptWhenIqcComplete( 187 + () -> outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish(
188 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity), 188 receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity),
189 WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS); 189 WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS);
190 } 190 }
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.productsales;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO;
  5 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesLineMapper;
  6 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum;
  7 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
  8 +import jakarta.annotation.Resource;
  9 +import org.junit.jupiter.api.Test;
  10 +import org.springframework.context.annotation.Import;
  11 +import org.springframework.test.context.bean.override.mockito.MockitoBean;
  12 +
  13 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  14 +
  15 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  16 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  17 +import static org.junit.jupiter.api.Assertions.assertEquals;
  18 +
  19 +/**
  20 + * {@link MesWmProductSalesLineServiceImpl} 的单元测试类
  21 + *
  22 + * @author 芋道源码
  23 + */
  24 +@Import(MesWmProductSalesLineServiceImpl.class)
  25 +public class MesWmProductSalesLineServiceImplTest extends BaseDbUnitTest {
  26 +
  27 + @Resource
  28 + private MesWmProductSalesLineServiceImpl productSalesLineService;
  29 +
  30 + @Resource
  31 + private MesWmProductSalesLineMapper productSalesLineMapper;
  32 +
  33 + @MockitoBean
  34 + private MesWmProductSalesService productSalesService;
  35 +
  36 + @MockitoBean
  37 + private MesWmProductSalesDetailService productSalesDetailService;
  38 +
  39 + @MockitoBean
  40 + private MesMdItemService itemService;
  41 +
  42 + @Test
  43 + public void testUpdateProductSalesLineWhenOqcFinish_pass() {
  44 + // 准备参数
  45 + Long oqcId = randomLongId();
  46 + Integer checkResult = MesQcCheckResultEnum.PASS.getType();
  47 +
  48 + // mock 数据
  49 + MesWmProductSalesLineDO lineDO = randomPojo(MesWmProductSalesLineDO.class);
  50 + productSalesLineMapper.insert(lineDO);
  51 +
  52 + // 调用
  53 + productSalesLineService.updateProductSalesLineWhenOqcFinish(lineDO.getId(), oqcId, checkResult);
  54 +
  55 + // 断言:验证 mapper 更新参数正确
  56 + MesWmProductSalesLineDO updateLine = productSalesLineMapper.selectById(lineDO.getId());
  57 + assertEquals(oqcId, updateLine.getOqcId());
  58 + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), updateLine.getQualityStatus());
  59 + }
  60 +
  61 + @Test
  62 + public void testUpdateProductSalesLineWhenOqcFinish_fail() {
  63 + // 准备参数
  64 + Long oqcId = randomLongId();
  65 + Integer checkResult = MesQcCheckResultEnum.FAIL.getType();
  66 +
  67 + // mock 数据
  68 + MesWmProductSalesLineDO lineDO = randomPojo(MesWmProductSalesLineDO.class);
  69 + productSalesLineMapper.insert(lineDO);
  70 +
  71 + // 调用
  72 + productSalesLineService.updateProductSalesLineWhenOqcFinish(lineDO.getId(), oqcId, checkResult);
  73 +
  74 + // 断言:验证 mapper 更新参数正确
  75 + MesWmProductSalesLineDO updateLine = productSalesLineMapper.selectById(lineDO.getId());
  76 + assertEquals(oqcId, updateLine.getOqcId());
  77 + assertEquals(MesWmQualityStatusEnum.FAIL.getStatus(), updateLine.getQualityStatus());
  78 + }
  79 +
  80 +}
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.returnissue;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueLineDO;
  5 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue.MesWmReturnIssueLineMapper;
  6 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum;
  7 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
  8 +import jakarta.annotation.Resource;
  9 +import org.junit.jupiter.api.Test;
  10 +import org.springframework.context.annotation.Import;
  11 +import org.springframework.test.context.bean.override.mockito.MockitoBean;
  12 +
  13 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  14 +
  15 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  16 +import static org.junit.jupiter.api.Assertions.assertEquals;
  17 +
  18 +/**
  19 + * {@link MesWmReturnIssueLineServiceImpl} 的单元测试类
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +@Import(MesWmReturnIssueLineServiceImpl.class)
  24 +public class MesWmReturnIssueLineServiceImplTest extends BaseDbUnitTest {
  25 +
  26 + @Resource
  27 + private MesWmReturnIssueLineServiceImpl returnIssueLineService;
  28 +
  29 + @Resource
  30 + private MesWmReturnIssueLineMapper returnIssueLineMapper;
  31 +
  32 + @MockitoBean
  33 + private MesWmReturnIssueService issueService;
  34 +
  35 + @MockitoBean
  36 + private MesMdItemService itemService;
  37 +
  38 + @Test
  39 + public void testUpdateReturnIssueLineWhenRqcFinish_pass() {
  40 + // 准备参数
  41 + Integer checkResult = MesQcCheckResultEnum.PASS.getType();
  42 +
  43 + // mock 数据
  44 + MesWmReturnIssueLineDO lineDO = randomPojo(MesWmReturnIssueLineDO.class);
  45 + returnIssueLineMapper.insert(lineDO);
  46 +
  47 + // 调用
  48 + returnIssueLineService.updateReturnIssueLineWhenRqcFinish(lineDO.getId(), checkResult);
  49 +
  50 + // 断言:验证 mapper 更新参数正确
  51 + MesWmReturnIssueLineDO updateLine = returnIssueLineMapper.selectById(lineDO.getId());
  52 + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), updateLine.getQualityStatus());
  53 + }
  54 +
  55 + @Test
  56 + public void testUpdateReturnIssueLineWhenRqcFinish_fail() {
  57 + // 准备参数
  58 + Integer checkResult = MesQcCheckResultEnum.FAIL.getType();
  59 +
  60 + // mock 数据
  61 + MesWmReturnIssueLineDO lineDO = randomPojo(MesWmReturnIssueLineDO.class);
  62 + returnIssueLineMapper.insert(lineDO);
  63 +
  64 + // 调用
  65 + returnIssueLineService.updateReturnIssueLineWhenRqcFinish(lineDO.getId(), checkResult);
  66 +
  67 + // 断言:验证 mapper 更新参数正确
  68 + MesWmReturnIssueLineDO updateLine = returnIssueLineMapper.selectById(lineDO.getId());
  69 + assertEquals(MesWmQualityStatusEnum.FAIL.getStatus(), updateLine.getQualityStatus());
  70 + }
  71 +
  72 +}
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.returnsales;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO;
  5 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesLineMapper;
  6 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum;
  7 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
  8 +import jakarta.annotation.Resource;
  9 +import org.junit.jupiter.api.Test;
  10 +import org.springframework.context.annotation.Import;
  11 +import org.springframework.test.context.bean.override.mockito.MockitoBean;
  12 +
  13 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  14 +
  15 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  16 +import static org.junit.jupiter.api.Assertions.assertEquals;
  17 +
  18 +/**
  19 + * {@link MesWmReturnSalesLineServiceImpl} 的单元测试类
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +@Import(MesWmReturnSalesLineServiceImpl.class)
  24 +public class MesWmReturnSalesLineServiceImplTest extends BaseDbUnitTest {
  25 +
  26 + @Resource
  27 + private MesWmReturnSalesLineServiceImpl returnSalesLineService;
  28 +
  29 + @Resource
  30 + private MesWmReturnSalesLineMapper returnSalesLineMapper;
  31 +
  32 + @MockitoBean
  33 + private MesWmReturnSalesService returnSalesService;
  34 +
  35 + @MockitoBean
  36 + private MesMdItemService itemService;
  37 +
  38 + @Test
  39 + public void testUpdateReturnSalesLineWhenRqcFinish_pass() {
  40 + // 准备参数
  41 + Integer checkResult = MesQcCheckResultEnum.PASS.getType();
  42 +
  43 + // mock 数据
  44 + MesWmReturnSalesLineDO lineDO = randomPojo(MesWmReturnSalesLineDO.class);
  45 + returnSalesLineMapper.insert(lineDO);
  46 +
  47 + // 调用
  48 + returnSalesLineService.updateReturnSalesLineWhenRqcFinish(lineDO.getId(), checkResult);
  49 +
  50 + // 断言:验证 mapper 更新参数正确
  51 + MesWmReturnSalesLineDO updateLine = returnSalesLineMapper.selectById(lineDO.getId());
  52 + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), updateLine.getQualityStatus());
  53 + }
  54 +
  55 + @Test
  56 + public void testUpdateReturnSalesLineWhenRqcFinish_fail() {
  57 + // 准备参数
  58 + Integer checkResult = MesQcCheckResultEnum.FAIL.getType();
  59 +
  60 + // mock 数据
  61 + MesWmReturnSalesLineDO lineDO = randomPojo(MesWmReturnSalesLineDO.class);
  62 + returnSalesLineMapper.insert(lineDO);
  63 +
  64 + // 调用
  65 + returnSalesLineService.updateReturnSalesLineWhenRqcFinish(lineDO.getId(), checkResult);
  66 +
  67 + // 断言:验证 mapper 更新参数正确
  68 + MesWmReturnSalesLineDO updateLine = returnSalesLineMapper.selectById(lineDO.getId());
  69 + assertEquals(MesWmQualityStatusEnum.FAIL.getStatus(), updateLine.getQualityStatus());
  70 + }
  71 +
  72 +}
yudao-module-mes/src/test/resources/sql/create_tables.sql
@@ -297,3 +297,151 @@ CREATE TABLE IF NOT EXISTS &quot;mes_wm_product_produce_detail&quot; ( @@ -297,3 +297,151 @@ CREATE TABLE IF NOT EXISTS &quot;mes_wm_product_produce_detail&quot; (
297 "tenant_id" bigint NOT NULL DEFAULT 0, 297 "tenant_id" bigint NOT NULL DEFAULT 0,
298 PRIMARY KEY ("id") 298 PRIMARY KEY ("id")
299 ); 299 );
  300 +
  301 +
  302 +-- ----------------------------
  303 +-- MES 出货检验单(OQC)
  304 +-- ----------------------------
  305 +CREATE TABLE IF NOT EXISTS "mes_qc_oqc" (
  306 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  307 + "code" varchar(64) NOT NULL,
  308 + "name" varchar(500) NOT NULL,
  309 + "template_id" bigint NOT NULL,
  310 + "source_doc_id" bigint DEFAULT NULL,
  311 + "source_doc_type" int DEFAULT NULL,
  312 + "source_doc_code" varchar(64) DEFAULT NULL,
  313 + "source_line_id" bigint DEFAULT NULL,
  314 + "client_id" bigint NOT NULL,
  315 + "batch_code" varchar(64) DEFAULT NULL,
  316 + "item_id" bigint NOT NULL,
  317 + "min_check_quantity" int DEFAULT 1,
  318 + "max_unqualified_quantity" int DEFAULT 0,
  319 + "out_quantity" decimal(14,2) NOT NULL,
  320 + "check_quantity" decimal(14,2) DEFAULT NULL,
  321 + "qualified_quantity" decimal(14,2) DEFAULT 0.00,
  322 + "unqualified_quantity" decimal(14,2) DEFAULT 0.00,
  323 + "critical_rate" decimal(14,2) DEFAULT 0.00,
  324 + "major_rate" decimal(14,2) DEFAULT 0.00,
  325 + "minor_rate" decimal(14,2) DEFAULT 0.00,
  326 + "critical_quantity" int DEFAULT 0,
  327 + "major_quantity" int DEFAULT 0,
  328 + "minor_quantity" int DEFAULT 0,
  329 + "check_result" tinyint DEFAULT NULL,
  330 + "out_date" timestamp DEFAULT NULL,
  331 + "inspect_date" timestamp DEFAULT NULL,
  332 + "inspector_user_id" bigint DEFAULT NULL,
  333 + "status" tinyint NOT NULL DEFAULT 0,
  334 + "remark" varchar(500) DEFAULT '',
  335 + "creator" varchar(64) DEFAULT '',
  336 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  337 + "updater" varchar(64) DEFAULT '',
  338 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  339 + "deleted" bit NOT NULL DEFAULT FALSE,
  340 + "tenant_id" bigint NOT NULL DEFAULT 0,
  341 + PRIMARY KEY ("id")
  342 +);
  343 +
  344 +-- ----------------------------
  345 +-- MES 退货检验单(RQC)
  346 +-- ----------------------------
  347 +CREATE TABLE IF NOT EXISTS "mes_qc_rqc" (
  348 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  349 + "code" varchar(64) NOT NULL,
  350 + "name" varchar(500) NOT NULL,
  351 + "template_id" bigint NOT NULL,
  352 + "source_doc_id" bigint DEFAULT NULL,
  353 + "source_doc_type" int DEFAULT NULL,
  354 + "source_doc_code" varchar(64) DEFAULT NULL,
  355 + "source_line_id" bigint DEFAULT NULL,
  356 + "type" int DEFAULT NULL,
  357 + "item_id" bigint NOT NULL,
  358 + "batch_code" varchar(128) DEFAULT NULL,
  359 + "check_quantity" decimal(14,2) DEFAULT NULL,
  360 + "qualified_quantity" decimal(14,2) DEFAULT 0.00,
  361 + "unqualified_quantity" decimal(14,2) DEFAULT 0.00,
  362 + "check_result" tinyint DEFAULT NULL,
  363 + "inspect_date" timestamp DEFAULT NULL,
  364 + "inspector_user_id" bigint DEFAULT NULL,
  365 + "status" tinyint NOT NULL DEFAULT 0,
  366 + "remark" varchar(500) DEFAULT '',
  367 + "critical_quantity" int DEFAULT 0,
  368 + "major_quantity" int DEFAULT 0,
  369 + "minor_quantity" int DEFAULT 0,
  370 + "critical_rate" decimal(5,2) DEFAULT 0.00,
  371 + "major_rate" decimal(5,2) DEFAULT 0.00,
  372 + "minor_rate" decimal(5,2) DEFAULT 0.00,
  373 + "creator" varchar(64) DEFAULT '',
  374 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  375 + "updater" varchar(64) DEFAULT '',
  376 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  377 + "deleted" bit NOT NULL DEFAULT FALSE,
  378 + "tenant_id" bigint NOT NULL DEFAULT 0,
  379 + PRIMARY KEY ("id")
  380 +);
  381 +
  382 +-- ----------------------------
  383 +-- MES 销售出库单行
  384 +-- ----------------------------
  385 +CREATE TABLE IF NOT EXISTS "mes_wm_product_sales_line" (
  386 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  387 + "sales_id" bigint NOT NULL,
  388 + "item_id" bigint NOT NULL,
  389 + "quantity" decimal(20,6) NOT NULL,
  390 + "batch_id" bigint DEFAULT NULL,
  391 + "material_stock_id" bigint DEFAULT NULL,
  392 + "oqc_check" tinyint DEFAULT NULL,
  393 + "oqc_id" bigint DEFAULT NULL,
  394 + "quality_status" int DEFAULT NULL,
  395 + "remark" varchar(500) DEFAULT NULL,
  396 + "creator" varchar(64) DEFAULT '',
  397 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  398 + "updater" varchar(64) DEFAULT '',
  399 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  400 + "deleted" bit NOT NULL DEFAULT FALSE,
  401 + "tenant_id" bigint NOT NULL DEFAULT 0,
  402 + PRIMARY KEY ("id")
  403 +);
  404 +
  405 +-- ----------------------------
  406 +-- MES 生产退料单行
  407 +-- ----------------------------
  408 +CREATE TABLE IF NOT EXISTS "mes_wm_return_issue_line" (
  409 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  410 + "issue_id" bigint NOT NULL,
  411 + "material_stock_id" bigint DEFAULT NULL,
  412 + "item_id" bigint NOT NULL,
  413 + "quantity" decimal(12,2) NOT NULL DEFAULT 0.00,
  414 + "batch_id" bigint DEFAULT NULL,
  415 + "ipqc_id" bigint DEFAULT NULL,
  416 + "qc_flag" bit NOT NULL DEFAULT FALSE,
  417 + "quality_status" int DEFAULT NULL,
  418 + "remark" varchar(500) DEFAULT '',
  419 + "creator" varchar(64) DEFAULT '',
  420 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  421 + "updater" varchar(64) DEFAULT '',
  422 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  423 + "deleted" bit NOT NULL DEFAULT FALSE,
  424 + "tenant_id" bigint NOT NULL DEFAULT 0,
  425 + PRIMARY KEY ("id")
  426 +);
  427 +
  428 +-- ----------------------------
  429 +-- MES 销售退货单行
  430 +-- ----------------------------
  431 +CREATE TABLE IF NOT EXISTS "mes_wm_return_sales_line" (
  432 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  433 + "return_id" bigint NOT NULL,
  434 + "item_id" bigint NOT NULL,
  435 + "quantity" decimal(12,2) NOT NULL DEFAULT 0.00,
  436 + "batch_id" bigint DEFAULT NULL,
  437 + "quality_status" int DEFAULT NULL,
  438 + "remark" varchar(500) DEFAULT '',
  439 + "creator" varchar(64) DEFAULT '',
  440 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  441 + "updater" varchar(64) DEFAULT '',
  442 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  443 + "deleted" bit NOT NULL DEFAULT FALSE,
  444 + "tenant_id" bigint NOT NULL DEFAULT 0,
  445 + PRIMARY KEY ("id")
  446 +);
  447 +