Commit 37313f35b00f6eefbebfed3fad516adbe903a9b2

Authored by YunaiV
1 parent c1c9c8ba

✨ feat(mes): 添加来源单据编号字段,优化数据结构

Showing 16 changed files with 138 additions and 14 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java
@@ -43,6 +43,9 @@ public class MesQcIpqcRespVO { @@ -43,6 +43,9 @@ public class MesQcIpqcRespVO {
43 @Schema(description = "来源单据行 ID", example = "300") 43 @Schema(description = "来源单据行 ID", example = "300")
44 private Long sourceLineId; 44 private Long sourceLineId;
45 45
  46 + @Schema(description = "来源单据编号", example = "FB20250101001")
  47 + private String sourceDocCode;
  48 +
46 // ========== 生产关联 ========== 49 // ========== 生产关联 ==========
47 50
48 @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 51 @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java
@@ -39,6 +39,9 @@ public class MesQcIqcRespVO { @@ -39,6 +39,9 @@ public class MesQcIqcRespVO {
39 @Schema(description = "来源单据行 ID", example = "300") 39 @Schema(description = "来源单据行 ID", example = "300")
40 private Long sourceLineId; 40 private Long sourceLineId;
41 41
  42 + @Schema(description = "来源单据编号", example = "DOC20250101001")
  43 + private String sourceDocCode;
  44 +
42 // ========== 供应商 ========== 45 // ========== 供应商 ==========
43 46
44 @Schema(description = "供应商 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 47 @Schema(description = "供应商 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java
@@ -39,6 +39,9 @@ public class MesQcOqcRespVO { @@ -39,6 +39,9 @@ public class MesQcOqcRespVO {
39 @Schema(description = "来源单据行 ID", example = "300") 39 @Schema(description = "来源单据行 ID", example = "300")
40 private Long sourceLineId; 40 private Long sourceLineId;
41 41
  42 + @Schema(description = "来源单据编号", example = "DOC20250101001")
  43 + private String sourceDocCode;
  44 +
42 // ========== 客户 ========== 45 // ========== 客户 ==========
43 46
44 @Schema(description = "客户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 47 @Schema(description = "客户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcPageReqVO.java
@@ -23,6 +23,9 @@ public class MesQcRqcPageReqVO extends PageParam { @@ -23,6 +23,9 @@ public class MesQcRqcPageReqVO extends PageParam {
23 @Schema(description = "来源单据类型", example = "1") 23 @Schema(description = "来源单据类型", example = "1")
24 private Integer sourceDocType; 24 private Integer sourceDocType;
25 25
  26 + @Schema(description = "来源单据编码", example = "RT2025")
  27 + private String sourceDocCode;
  28 +
26 @Schema(description = "产品物料 ID", example = "20") 29 @Schema(description = "产品物料 ID", example = "20")
27 private Long itemId; 30 private Long itemId;
28 31
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java
@@ -39,6 +39,9 @@ public class MesQcRqcRespVO { @@ -39,6 +39,9 @@ public class MesQcRqcRespVO {
39 @Schema(description = "来源单据行 ID", example = "300") 39 @Schema(description = "来源单据行 ID", example = "300")
40 private Long sourceLineId; 40 private Long sourceLineId;
41 41
  42 + @Schema(description = "来源单据编码", example = "RT20250101001")
  43 + private String sourceDocCode;
  44 +
42 // ========== 检验类型 ========== 45 // ========== 检验类型 ==========
43 46
44 @Schema(description = "检验类型", example = "1") 47 @Schema(description = "检验类型", example = "1")
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java
@@ -69,16 +69,20 @@ public class MesQcIpqcDO extends BaseDO { @@ -69,16 +69,20 @@ public class MesQcIpqcDO extends BaseDO {
69 * 来源单据 ID 69 * 来源单据 ID
70 * 70 *
71 * 关联:根据 {@link #sourceDocType} 不同: 71 * 关联:根据 {@link #sourceDocType} 不同:
72 - * 1. {@link MesQcSourceDocTypeEnum#FEEDBACK} 时,关联 {@link MesProFeedbackDO#getId()} 72 + * 1. {@link MesQcSourceDocTypeEnum#PRO_FEEDBACK} 时,关联 {@link MesProFeedbackDO#getId()}
73 */ 73 */
74 private Long sourceDocId; 74 private Long sourceDocId;
75 /** 75 /**
76 * 来源单据行 ID 76 * 来源单据行 ID
77 * 77 *
78 * 关联:根据 {@link #sourceDocType} 不同: 78 * 关联:根据 {@link #sourceDocType} 不同:
79 - * 1. {@link MesQcSourceDocTypeEnum#FEEDBACK} 时,暂不使用(预留) 79 + * 1. {@link MesQcSourceDocTypeEnum#PRO_FEEDBACK} 时,暂不使用(预留)
80 */ 80 */
81 private Long sourceLineId; 81 private Long sourceLineId;
  82 + /**
  83 + * 来源单据编号(冗余)
  84 + */
  85 + private String sourceDocCode;
82 86
83 // ========== 生产关联 ========== 87 // ========== 生产关联 ==========
84 88
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java
@@ -74,6 +74,10 @@ public class MesQcIqcDO extends BaseDO { @@ -74,6 +74,10 @@ public class MesQcIqcDO extends BaseDO {
74 * 1. {@link MesQcSourceDocTypeEnum#ARRIVAL_NOTICE} 时,关联 {@link MesWmArrivalNoticeLineDO#getId()} 74 * 1. {@link MesQcSourceDocTypeEnum#ARRIVAL_NOTICE} 时,关联 {@link MesWmArrivalNoticeLineDO#getId()}
75 */ 75 */
76 private Long sourceLineId; 76 private Long sourceLineId;
  77 + /**
  78 + * 来源单据编号(冗余)
  79 + */
  80 + private String sourceDocCode;
77 81
78 // ========== 供应商 ========== 82 // ========== 供应商 ==========
79 83
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java
@@ -51,18 +51,28 @@ public class MesQcOqcDO extends BaseDO { @@ -51,18 +51,28 @@ public class MesQcOqcDO extends BaseDO {
51 51
52 /** 52 /**
53 * 来源单据 ID 53 * 来源单据 ID
  54 + *
  55 + * 关联:根据 {@link #sourceDocType} 不同:
  56 + * 1. {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum#PRODUCT_SALES} 时,关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO#getId()}
54 */ 57 */
55 private Long sourceDocId; 58 private Long sourceDocId;
56 /** 59 /**
57 * 来源单据类型 60 * 来源单据类型
58 * 61 *
59 - * 关联 {@link cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants} 62 + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum}
60 */ 63 */
61 private Integer sourceDocType; 64 private Integer sourceDocType;
62 /** 65 /**
63 * 来源单据行 ID 66 * 来源单据行 ID
  67 + *
  68 + * 关联:根据 {@link #sourceDocType} 不同:
  69 + * 1. {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum#PRODUCT_SALES} 时,关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO#getId()}
64 */ 70 */
65 private Long sourceLineId; 71 private Long sourceLineId;
  72 + /**
  73 + * 来源单据编号(冗余)
  74 + */
  75 + private String sourceDocCode;
66 76
67 // ========== 客户 ========== 77 // ========== 客户 ==========
68 78
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcDO.java
@@ -63,6 +63,10 @@ public class MesQcRqcDO extends BaseDO { @@ -63,6 +63,10 @@ public class MesQcRqcDO extends BaseDO {
63 * 来源单据行 ID 63 * 来源单据行 ID
64 */ 64 */
65 private Long sourceLineId; 65 private Long sourceLineId;
  66 + /**
  67 + * 来源单据编码(冗余)
  68 + */
  69 + private String sourceDocCode;
66 70
67 // ========== 检验类型 ========== 71 // ========== 检验类型 ==========
68 72
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcMapper.java
@@ -19,6 +19,7 @@ public interface MesQcRqcMapper extends BaseMapperX<MesQcRqcDO> { @@ -19,6 +19,7 @@ public interface MesQcRqcMapper extends BaseMapperX<MesQcRqcDO> {
19 return selectPage(reqVO, new LambdaQueryWrapperX<MesQcRqcDO>() 19 return selectPage(reqVO, new LambdaQueryWrapperX<MesQcRqcDO>()
20 .likeIfPresent(MesQcRqcDO::getCode, reqVO.getCode()) 20 .likeIfPresent(MesQcRqcDO::getCode, reqVO.getCode())
21 .eqIfPresent(MesQcRqcDO::getSourceDocType, reqVO.getSourceDocType()) 21 .eqIfPresent(MesQcRqcDO::getSourceDocType, reqVO.getSourceDocType())
  22 + .likeIfPresent(MesQcRqcDO::getSourceDocCode, reqVO.getSourceDocCode())
22 .eqIfPresent(MesQcRqcDO::getItemId, reqVO.getItemId()) 23 .eqIfPresent(MesQcRqcDO::getItemId, reqVO.getItemId())
23 .likeIfPresent(MesQcRqcDO::getBatchCode, reqVO.getBatchCode()) 24 .likeIfPresent(MesQcRqcDO::getBatchCode, reqVO.getBatchCode())
24 .eqIfPresent(MesQcRqcDO::getCheckResult, reqVO.getCheckResult()) 25 .eqIfPresent(MesQcRqcDO::getCheckResult, reqVO.getCheckResult())
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcSourceDocTypeEnum.java
@@ -16,9 +16,19 @@ import java.util.Arrays; @@ -16,9 +16,19 @@ import java.util.Arrays;
16 @AllArgsConstructor 16 @AllArgsConstructor
17 public enum MesQcSourceDocTypeEnum implements ArrayValuable<Integer> { 17 public enum MesQcSourceDocTypeEnum implements ArrayValuable<Integer> {
18 18
  19 + // === IQC 来源单据 ===
19 ARRIVAL_NOTICE(MesBizTypeConstants.WM_ARRIVAL_NOTICE, "到货通知单"), 20 ARRIVAL_NOTICE(MesBizTypeConstants.WM_ARRIVAL_NOTICE, "到货通知单"),
20 OUTSOURCE_RECPT(MesBizTypeConstants.WM_OUTSOURCE_RECPT, "外协入库单"), 21 OUTSOURCE_RECPT(MesBizTypeConstants.WM_OUTSOURCE_RECPT, "外协入库单"),
21 - FEEDBACK(MesBizTypeConstants.PRO_FEEDBACK, "生产报工"), 22 +
  23 + // === IPQC 来源单据 ===
  24 + PRO_FEEDBACK(MesBizTypeConstants.PRO_FEEDBACK, "生产报工"),
  25 +
  26 + // === OQC 来源单据 ===
  27 + PRODUCT_SALES(MesBizTypeConstants.WM_PRODUCT_SALES, "销售出库单"),
  28 +
  29 + // === RQC 来源单据 ===
  30 + RETURN_ISSUE(MesBizTypeConstants.WM_RETURN_ISSUE, "生产退料单"),
  31 + RETURN_SALES(MesBizTypeConstants.WM_RETURN_SALES, "销售退货单"),
22 ; 32 ;
23 33
24 public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcSourceDocTypeEnum::getType).toArray(Integer[]::new); 34 public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcSourceDocTypeEnum::getType).toArray(Integer[]::new);
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqV @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqV
9 import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; 9 import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
10 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; 10 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO;
11 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; 11 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
  12 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
12 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; 13 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO;
13 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; 14 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO;
14 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; 15 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO;
@@ -95,12 +96,16 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @@ -95,12 +96,16 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService {
95 MesQcTemplateItemDO templateItem = templateDetailService.getRequiredTemplateByItemIdAndType( 96 MesQcTemplateItemDO templateItem = templateDetailService.getRequiredTemplateByItemIdAndType(
96 workOrder.getProductId(), MesQcTypeEnum.IPQC.getType()); 97 workOrder.getProductId(), MesQcTypeEnum.IPQC.getType());
97 Long templateId = templateItem.getTemplateId(); 98 Long templateId = templateItem.getTemplateId();
  99 + // 1.4 获取来源单据编号
  100 + String sourceDocCode = validateAndGetSourceDocCode(
  101 + createReqVO.getSourceDocType(), createReqVO.getSourceDocId());
98 102
99 // 2. 插入主表 103 // 2. 插入主表
100 MesQcIpqcDO ipqc = BeanUtils.toBean(createReqVO, MesQcIpqcDO.class) 104 MesQcIpqcDO ipqc = BeanUtils.toBean(createReqVO, MesQcIpqcDO.class)
101 .setItemId(workOrder.getProductId()) 105 .setItemId(workOrder.getProductId())
102 .setProcessId(getProcessId(workOrder.getProductId(), workstation.getProcessId())) 106 .setProcessId(getProcessId(workOrder.getProductId(), workstation.getProcessId()))
103 .setTemplateId(templateId) 107 .setTemplateId(templateId)
  108 + .setSourceDocCode(sourceDocCode)
104 .setStatus(MesQcStatusEnum.DRAFT.getStatus()); 109 .setStatus(MesQcStatusEnum.DRAFT.getStatus());
105 ipqcMapper.insert(ipqc); 110 ipqcMapper.insert(ipqc);
106 111
@@ -224,6 +229,17 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @@ -224,6 +229,17 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService {
224 } 229 }
225 } 230 }
226 231
  232 + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId) {
  233 + if (sourceDocType == null || sourceDocId == null) {
  234 + return null;
  235 + }
  236 + if (Objects.equals(sourceDocType, MesBizTypeConstants.PRO_FEEDBACK)) {
  237 + MesProFeedbackDO feedback = feedbackService.getFeedback(sourceDocId);
  238 + return feedback != null ? feedback.getCode() : null;
  239 + }
  240 + return null;
  241 + }
  242 +
227 /** 243 /**
228 * 推导工序 ID:对齐 KTG getProcessInfo() 逻辑 244 * 推导工序 ID:对齐 KTG getProcessInfo() 逻辑
229 * 245 *
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java
@@ -76,17 +76,19 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -76,17 +76,19 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
76 itemService.validateItemExists(createReqVO.getItemId()); 76 itemService.validateItemExists(createReqVO.getItemId());
77 adminUserApi.validateUser(createReqVO.getInspectorUserId()); 77 adminUserApi.validateUser(createReqVO.getInspectorUserId());
78 // 1.3 校验来源单据参数,并验证数据存在 78 // 1.3 校验来源单据参数,并验证数据存在
79 - validateSourceDoc(createReqVO.getSourceDocType(), createReqVO.getSourceDocId(), createReqVO.getSourceLineId()); 79 + String sourceDocCode = validateAndGetSourceDocCode(
  80 + createReqVO.getSourceDocType(), createReqVO.getSourceDocId(), createReqVO.getSourceLineId());
80 // 1.4 通过 itemId + IQC 类型自动查找模板 81 // 1.4 通过 itemId + IQC 类型自动查找模板
81 MesQcTemplateItemDO templateItem = templateDetailService.getRequiredTemplateByItemIdAndType( 82 MesQcTemplateItemDO templateItem = templateDetailService.getRequiredTemplateByItemIdAndType(
82 createReqVO.getItemId(), MesQcTypeEnum.IQC.getType()); 83 createReqVO.getItemId(), MesQcTypeEnum.IQC.getType());
83 Long templateId = templateItem.getTemplateId(); 84 Long templateId = templateItem.getTemplateId();
84 85
85 // 2. 插入主表 86 // 2. 插入主表
86 - MesQcIqcDO iqc = BeanUtils.toBean(createReqVO, MesQcIqcDO.class);  
87 - iqc.setTemplateId(templateId);  
88 - iqc.setCheckQuantity(createReqVO.getQualifiedQuantity().add(createReqVO.getUnqualifiedQuantity()));  
89 - iqc.setStatus(MesQcStatusEnum.DRAFT.getStatus()); 87 + MesQcIqcDO iqc = BeanUtils.toBean(createReqVO, MesQcIqcDO.class)
  88 + .setTemplateId(templateId)
  89 + .setCheckQuantity(createReqVO.getQualifiedQuantity().add(createReqVO.getUnqualifiedQuantity()))
  90 + .setSourceDocCode(sourceDocCode)
  91 + .setStatus(MesQcStatusEnum.DRAFT.getStatus());
90 iqcMapper.insert(iqc); 92 iqcMapper.insert(iqc);
91 93
92 // 3. 从模板指标自动生成检验行 94 // 3. 从模板指标自动生成检验行
@@ -213,9 +215,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -213,9 +215,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
213 * @param sourceDocId 来源单据 ID 215 * @param sourceDocId 来源单据 ID
214 * @param sourceLineId 来源单据行 ID 216 * @param sourceLineId 来源单据行 ID
215 */ 217 */
216 - private void validateSourceDoc(Integer sourceDocType, Long sourceDocId, Long sourceLineId) { 218 + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId, Long sourceLineId) {
217 if (sourceDocType == null) { 219 if (sourceDocType == null) {
218 - return; 220 + return null;
219 } 221 }
220 if (ObjUtil.hasNull(sourceDocId, sourceLineId)) { 222 if (ObjUtil.hasNull(sourceDocId, sourceLineId)) {
221 throw exception(QC_IQC_SOURCE_DOC_PARAMS_MISSING); 223 throw exception(QC_IQC_SOURCE_DOC_PARAMS_MISSING);
@@ -223,9 +225,12 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -223,9 +225,12 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
223 // 根据来源单据类型,校验数据存在且匹配 225 // 根据来源单据类型,校验数据存在且匹配
224 if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_ARRIVAL_NOTICE)) { 226 if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_ARRIVAL_NOTICE)) {
225 arrivalNoticeService.validateArrivalNoticeAndLineExists(sourceDocId, sourceLineId); 227 arrivalNoticeService.validateArrivalNoticeAndLineExists(sourceDocId, sourceLineId);
  228 + return arrivalNoticeService.getArrivalNotice(sourceDocId).getCode();
226 } else if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_OUTSOURCE_RECPT)) { 229 } else if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_OUTSOURCE_RECPT)) {
227 outsourceReceiptService.validateOutsourceReceiptAndLineExists(sourceDocId, sourceLineId); 230 outsourceReceiptService.validateOutsourceReceiptAndLineExists(sourceDocId, sourceLineId);
  231 + return outsourceReceiptService.getOutsourceReceipt(sourceDocId).getCode();
228 } 232 }
  233 + return null;
229 } 234 }
230 235
231 @Override 236 @Override
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java
@@ -18,6 +18,9 @@ import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; @@ -18,6 +18,9 @@ import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
18 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; 18 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
19 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; 20 import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService;
  21 +import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService;
  22 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO;
  23 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO;
21 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 24 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
22 import jakarta.annotation.Resource; 25 import jakarta.annotation.Resource;
23 import org.springframework.context.annotation.Lazy; 26 import org.springframework.context.annotation.Lazy;
@@ -60,6 +63,9 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @@ -60,6 +63,9 @@ public class MesQcOqcServiceImpl implements MesQcOqcService {
60 @Resource 63 @Resource
61 @Lazy 64 @Lazy
62 private MesWmProductSalesLineService productSalesLineService; 65 private MesWmProductSalesLineService productSalesLineService;
  66 + @Resource
  67 + @Lazy
  68 + private MesWmProductSalesService productSalesService;
63 69
64 @Resource 70 @Resource
65 private AdminUserApi adminUserApi; 71 private AdminUserApi adminUserApi;
@@ -77,11 +83,15 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @@ -77,11 +83,15 @@ public class MesQcOqcServiceImpl implements MesQcOqcService {
77 MesQcTemplateItemDO templateItem = templateDetailService.getRequiredTemplateByItemIdAndType( 83 MesQcTemplateItemDO templateItem = templateDetailService.getRequiredTemplateByItemIdAndType(
78 createReqVO.getItemId(), MesQcTypeEnum.OQC.getType()); 84 createReqVO.getItemId(), MesQcTypeEnum.OQC.getType());
79 Long templateId = templateItem.getTemplateId(); 85 Long templateId = templateItem.getTemplateId();
  86 + // 1.4 获取来源单据编号
  87 + String sourceDocCode = validateAndGetSourceDocCode(
  88 + createReqVO.getSourceDocType(), createReqVO.getSourceLineId());
80 89
81 // 2. 插入主表 90 // 2. 插入主表
82 - MesQcOqcDO oqc = BeanUtils.toBean(createReqVO, MesQcOqcDO.class);  
83 - oqc.setTemplateId(templateId);  
84 - oqc.setStatus(MesQcStatusEnum.DRAFT.getStatus()); 91 + MesQcOqcDO oqc = BeanUtils.toBean(createReqVO, MesQcOqcDO.class)
  92 + .setTemplateId(templateId)
  93 + .setSourceDocCode(sourceDocCode)
  94 + .setStatus(MesQcStatusEnum.DRAFT.getStatus());
85 oqcMapper.insert(oqc); 95 oqcMapper.insert(oqc);
86 96
87 // 3. 从模板指标自动生成检验行 97 // 3. 从模板指标自动生成检验行
@@ -193,6 +203,20 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @@ -193,6 +203,20 @@ public class MesQcOqcServiceImpl implements MesQcOqcService {
193 } 203 }
194 } 204 }
195 205
  206 + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceLineId) {
  207 + if (sourceDocType == null || sourceLineId == null) {
  208 + return null;
  209 + }
  210 + if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_PRODUCT_SALES)) {
  211 + MesWmProductSalesLineDO salesLine = productSalesLineService.getProductSalesLine(sourceLineId);
  212 + if (salesLine != null && salesLine.getSalesId() != null) {
  213 + MesWmProductSalesDO sales = productSalesService.getProductSales(salesLine.getSalesId());
  214 + return sales != null ? sales.getCode() : null;
  215 + }
  216 + }
  217 + return null;
  218 + }
  219 +
196 @Override 220 @Override
197 public MesQcOqcDO getOqc(Long id) { 221 public MesQcOqcDO getOqc(Long id) {
198 return oqcMapper.selectById(id); 222 return oqcMapper.selectById(id);
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java
@@ -15,6 +15,8 @@ import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; @@ -15,6 +15,8 @@ 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.enums.MesBizTypeConstants;
16 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 16 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
17 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; 17 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
  18 +import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueService;
  19 +import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesService;
18 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateDetailService; 20 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateDetailService;
19 import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueLineService; 21 import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueLineService;
20 import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesLineService; 22 import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesLineService;
@@ -60,6 +62,12 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @@ -60,6 +62,12 @@ public class MesQcRqcServiceImpl implements MesQcRqcService {
60 @Resource 62 @Resource
61 @Lazy 63 @Lazy
62 private MesWmReturnSalesLineService returnSalesLineService; 64 private MesWmReturnSalesLineService returnSalesLineService;
  65 + @Resource
  66 + @Lazy
  67 + private MesWmReturnIssueService returnIssueService;
  68 + @Resource
  69 + @Lazy
  70 + private MesWmReturnSalesService returnSalesService;
63 71
64 @Resource 72 @Resource
65 private AdminUserApi adminUserApi; 73 private AdminUserApi adminUserApi;
@@ -76,10 +84,14 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @@ -76,10 +84,14 @@ public class MesQcRqcServiceImpl implements MesQcRqcService {
76 MesQcTemplateItemDO templateItem = templateDetailService.getRequiredTemplateByItemIdAndType( 84 MesQcTemplateItemDO templateItem = templateDetailService.getRequiredTemplateByItemIdAndType(
77 createReqVO.getItemId(), createReqVO.getType()); 85 createReqVO.getItemId(), createReqVO.getType());
78 Long templateId = templateItem.getTemplateId(); 86 Long templateId = templateItem.getTemplateId();
  87 + // 1.4 获取来源单据编号
  88 + String sourceDocCode = validateAndGetSourceDocCode(
  89 + createReqVO.getSourceDocType(), createReqVO.getSourceDocId());
79 90
80 // 2. 插入主表 91 // 2. 插入主表
81 MesQcRqcDO rqc = BeanUtils.toBean(createReqVO, MesQcRqcDO.class) 92 MesQcRqcDO rqc = BeanUtils.toBean(createReqVO, MesQcRqcDO.class)
82 .setTemplateId(templateId) 93 .setTemplateId(templateId)
  94 + .setSourceDocCode(sourceDocCode)
83 .setStatus(MesQcStatusEnum.DRAFT.getStatus()); 95 .setStatus(MesQcStatusEnum.DRAFT.getStatus());
84 rqcMapper.insert(rqc); 96 rqcMapper.insert(rqc);
85 97
@@ -217,6 +229,21 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @@ -217,6 +229,21 @@ public class MesQcRqcServiceImpl implements MesQcRqcService {
217 return rqcMapper.selectById(id); 229 return rqcMapper.selectById(id);
218 } 230 }
219 231
  232 + /**
  233 + * 根据来源单据类型 + 来源单据 ID,推导来源单据编码
  234 + */
  235 + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId) {
  236 + if (sourceDocType == null || sourceDocId == null) {
  237 + return null;
  238 + }
  239 + if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_RETURN_ISSUE)) {
  240 + return returnIssueService.getReturnIssue(sourceDocId).getCode();
  241 + } else if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_RETURN_SALES)) {
  242 + return returnSalesService.getReturnSales(sourceDocId).getCode();
  243 + }
  244 + return null;
  245 + }
  246 +
220 @Override 247 @Override
221 public PageResult<MesQcRqcDO> getRqcPage(MesQcRqcPageReqVO pageReqVO) { 248 public PageResult<MesQcRqcDO> getRqcPage(MesQcRqcPageReqVO pageReqVO) {
222 return rqcMapper.selectPage(pageReqVO); 249 return rqcMapper.selectPage(pageReqVO);
yudao-module-mes/src/test/resources/sql/create_tables.sql
@@ -119,6 +119,7 @@ CREATE TABLE IF NOT EXISTS &quot;mes_qc_iqc&quot; ( @@ -119,6 +119,7 @@ CREATE TABLE IF NOT EXISTS &quot;mes_qc_iqc&quot; (
119 "source_doc_type" int DEFAULT NULL, 119 "source_doc_type" int DEFAULT NULL,
120 "source_doc_id" bigint DEFAULT NULL, 120 "source_doc_id" bigint DEFAULT NULL,
121 "source_line_id" bigint DEFAULT NULL, 121 "source_line_id" bigint DEFAULT NULL,
  122 + "source_doc_code" varchar(64) DEFAULT NULL,
122 "vendor_id" bigint DEFAULT NULL, 123 "vendor_id" bigint DEFAULT NULL,
123 "vendor_batch" varchar(64) DEFAULT NULL, 124 "vendor_batch" varchar(64) DEFAULT NULL,
124 "item_id" bigint DEFAULT NULL, 125 "item_id" bigint DEFAULT NULL,
@@ -159,6 +160,7 @@ CREATE TABLE IF NOT EXISTS &quot;mes_qc_ipqc&quot; ( @@ -159,6 +160,7 @@ CREATE TABLE IF NOT EXISTS &quot;mes_qc_ipqc&quot; (
159 "source_doc_type" int DEFAULT NULL, 160 "source_doc_type" int DEFAULT NULL,
160 "source_doc_id" bigint DEFAULT NULL, 161 "source_doc_id" bigint DEFAULT NULL,
161 "source_line_id" bigint DEFAULT NULL, 162 "source_line_id" bigint DEFAULT NULL,
  163 + "source_doc_code" varchar(64) DEFAULT NULL,
162 "work_order_id" bigint DEFAULT NULL, 164 "work_order_id" bigint DEFAULT NULL,
163 "task_id" bigint DEFAULT NULL, 165 "task_id" bigint DEFAULT NULL,
164 "workstation_id" bigint DEFAULT NULL, 166 "workstation_id" bigint DEFAULT NULL,
@@ -310,6 +312,7 @@ CREATE TABLE IF NOT EXISTS &quot;mes_qc_oqc&quot; ( @@ -310,6 +312,7 @@ CREATE TABLE IF NOT EXISTS &quot;mes_qc_oqc&quot; (
310 "source_doc_id" bigint DEFAULT NULL, 312 "source_doc_id" bigint DEFAULT NULL,
311 "source_doc_type" int DEFAULT NULL, 313 "source_doc_type" int DEFAULT NULL,
312 "source_line_id" bigint DEFAULT NULL, 314 "source_line_id" bigint DEFAULT NULL,
  315 + "source_doc_code" varchar(64) DEFAULT NULL,
313 "client_id" bigint NOT NULL, 316 "client_id" bigint NOT NULL,
314 "batch_code" varchar(64) DEFAULT NULL, 317 "batch_code" varchar(64) DEFAULT NULL,
315 "item_id" bigint NOT NULL, 318 "item_id" bigint NOT NULL,
@@ -351,6 +354,7 @@ CREATE TABLE IF NOT EXISTS &quot;mes_qc_rqc&quot; ( @@ -351,6 +354,7 @@ CREATE TABLE IF NOT EXISTS &quot;mes_qc_rqc&quot; (
351 "source_doc_id" bigint DEFAULT NULL, 354 "source_doc_id" bigint DEFAULT NULL,
352 "source_doc_type" int DEFAULT NULL, 355 "source_doc_type" int DEFAULT NULL,
353 "source_line_id" bigint DEFAULT NULL, 356 "source_line_id" bigint DEFAULT NULL,
  357 + "source_doc_code" varchar(64) DEFAULT NULL,
354 "type" int DEFAULT NULL, 358 "type" int DEFAULT NULL,
355 "item_id" bigint NOT NULL, 359 "item_id" bigint NOT NULL,
356 "batch_code" varchar(128) DEFAULT NULL, 360 "batch_code" varchar(128) DEFAULT NULL,