diff --git a/ruoyi-api/hwmom-api-pda/src/main/java/org/dromara/pda/api/model/bo/GenerateInspectionTaskBo.java b/ruoyi-api/hwmom-api-pda/src/main/java/org/dromara/pda/api/model/bo/GenerateInspectionTaskBo.java
index 239b4e3e..db9f1e15 100644
--- a/ruoyi-api/hwmom-api-pda/src/main/java/org/dromara/pda/api/model/bo/GenerateInspectionTaskBo.java
+++ b/ruoyi-api/hwmom-api-pda/src/main/java/org/dromara/pda/api/model/bo/GenerateInspectionTaskBo.java
@@ -24,7 +24,7 @@ public class GenerateInspectionTaskBo implements Serializable {
/**
* qc_inspection_type表的qc_inspection_type
- * 0首检 1专检 2自检 3互检 4原材料检 5抽检 6成品检 7入库检
+ * 首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8
*/
private String qcInspectionType;
diff --git a/ruoyi-api/hwmom-api-qms/src/main/java/org/dromara/qms/api/dto/WmsInspectionTaskRequest.java b/ruoyi-api/hwmom-api-qms/src/main/java/org/dromara/qms/api/dto/WmsInspectionTaskRequest.java
new file mode 100644
index 00000000..86cc16c6
--- /dev/null
+++ b/ruoyi-api/hwmom-api-qms/src/main/java/org/dromara/qms/api/dto/WmsInspectionTaskRequest.java
@@ -0,0 +1,99 @@
+package org.dromara.qms.api.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * WMS 入库质检任务请求 DTO
+ *
+ * 用于 WMS 调用 QMS 创建质检任务时传递参数
+ *
+ * @author zch
+ * @date 2026-1-14
+ */
+@Data
+@NoArgsConstructor
+public class WmsInspectionTaskRequest implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 入库单号
+ *
+ * 用于关联质检单与入库单,质检完成后回写入库状态
+ */
+ private String instockCode;
+
+ /**
+ * 物料编码
+ *
+ * 必填,用于质检模板匹配(8级降级策略中物料=200分)
+ */
+ private String materialCode;
+
+ /**
+ * 物料名称
+ */
+ private String materialName;
+
+ /**
+ * 质检数量
+ *
+ * 必填,从入库单物料数量获取
+ */
+ private BigDecimal inspectionQty;
+
+ /**
+ * 批次号
+ */
+ private String batchCode;
+
+ /**
+ * 工位名称/编码
+ *
+ * 可选,用于质检模板精确匹配(工位=20分)
+ */
+ private String stationName;
+
+ /**
+ * 工序编码
+ *
+ * 可选,用于质检模板精确匹配(工序=2分)
+ */
+ private String processCode;
+
+ /**
+ * 检验类型
+ *
+ * 必填,WMS 入库固定传 "7"(入库检)
+ * 检验类型字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8
+ */
+ private String inspectionType;
+
+ /**
+ * 供应商名称
+ *
+ * 可选,用于记录来源
+ */
+ private String supplierName;
+
+ /**
+ * 生产订单号
+ *
+ * 可选,用于追溯
+ */
+ private String productionOrder;
+
+ /**
+ * 车间
+ *
+ * 可选,用于数据权限过滤
+ */
+ private String workshop;
+
+}
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionItemCategory.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionItemCategory.java
index b03ed86c..6aee2c64 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionItemCategory.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionItemCategory.java
@@ -70,7 +70,7 @@ public class QcInspectionItemCategory extends TenantEntity {
private String typeName;//join
/**
- * 检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)
+ * 检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
*/
@TableField(exist = false)
private String qcInspectionType;//join
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionResult.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionResult.java
index 2a20a9be..02c7cf6e 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionResult.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionResult.java
@@ -134,5 +134,9 @@ public class QcInspectionResult extends TenantEntity {
@TableLogic
private String delFlag;
+ @TableField(exist = false)
+ private String method;
+ @TableField(exist = false)
+ private String methodName;
}
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionTemplate.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionTemplate.java
index c5a7fac8..4c645450 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionTemplate.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionTemplate.java
@@ -87,6 +87,12 @@ public class QcInspectionTemplate extends TenantEntity {
*/
private String description;
+ /**
+ * 是否通用模板(0否/1是)
+ * 通用模板不绑定具体物料/工序/工位,仅按检测类型适用
+ */
+ private String isDefault;
+
/**
* 是否删除(0表示存在,2表示删除)
*/
@@ -106,7 +112,7 @@ public class QcInspectionTemplate extends TenantEntity {
private String typeName;//JOIN
/**
- * 检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)
+ * 检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
*/
@TableField(exist = false)
private String qcInspectionType;//JOIN
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionType.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionType.java
index 3157d11b..9a470426 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionType.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/QcInspectionType.java
@@ -38,7 +38,7 @@ public class QcInspectionType extends TenantEntity {
private String typeName;
/**
- * 检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)
+ * 检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
*/
private String qcInspectionType;
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionItemCategoryBo.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionItemCategoryBo.java
index 05c68d5a..ad349f98 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionItemCategoryBo.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionItemCategoryBo.java
@@ -63,7 +63,7 @@ public class QcInspectionItemCategoryBo extends BaseEntity {
private String typeName;//join
/**
- * 检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)
+ * 检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
*/
private String qcInspectionType;//join
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionMainBo.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionMainBo.java
index dea57ee5..92de85ad 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionMainBo.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionMainBo.java
@@ -158,10 +158,15 @@ public class QcInspectionMainBo extends BaseEntity {
private String templateName;//join
/**
- * 检测类型字典
+ * 检测类型字典(单值查询)
*/
private String qcInspectionType;
+ /**
+ * 检测类型字典列表(多值查询,用于产品检等需要查询多个类型的场景)
+ */
+ private List qcInspectionTypes;
+
/**
* 检测类型名称
*/
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionTemplateBo.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionTemplateBo.java
index 8e89b755..3bebcd24 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionTemplateBo.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionTemplateBo.java
@@ -88,6 +88,10 @@ public class QcInspectionTemplateBo extends BaseEntity {
*/
private String description;
+ /**
+ * 是否通用模板(0否/1是)
+ */
+ private String isDefault;
/**
* 检测类型编码
@@ -100,7 +104,7 @@ public class QcInspectionTemplateBo extends BaseEntity {
private String typeName;//JOIN
/**
- * 检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)
+ * 检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
*/
private String qcInspectionType;//JOIN
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionTypeBo.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionTypeBo.java
index c31e2f5b..4c20de29 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionTypeBo.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/bo/QcInspectionTypeBo.java
@@ -39,9 +39,9 @@ public class QcInspectionTypeBo extends BaseEntity {
private String typeName;
/**
- * 检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)
+ * 检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
*/
- // @NotNull(message = "检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)不能为空", groups = { AddGroup.class, EditGroup.class })
+ // @NotNull(message = "检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)不能为空", groups = { AddGroup.class, EditGroup.class })
private String qcInspectionType;
/**
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/dto/QcInspectionMainTask.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/dto/QcInspectionMainTask.java
index 9ae96bb7..033b8a04 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/dto/QcInspectionMainTask.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/dto/QcInspectionMainTask.java
@@ -33,7 +33,7 @@ public class QcInspectionMainTask {
private String inspectionQty;
/**
- * 检验类型(0首检 1专检 2自检 3互检 4原材料检 5抽检 6成品检 7入库检)
+ * 检验类型(首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
* 必填,上位机写死传7入库检
*/
@JsonProperty("InspectionType")
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionItemCategoryVo.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionItemCategoryVo.java
index fd35bae5..21a4fa07 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionItemCategoryVo.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionItemCategoryVo.java
@@ -78,7 +78,7 @@ public class QcInspectionItemCategoryVo implements Serializable {
private String typeName;//join
/**
- * 检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)
+ * 检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
*/
private String qcInspectionType;//join
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionResultVo.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionResultVo.java
index 02778e60..ec2d49a3 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionResultVo.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionResultVo.java
@@ -1,5 +1,7 @@
package org.dromara.qms.domain.vo;
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
import java.math.BigDecimal;
import org.dromara.qms.domain.QcInspectionResult;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
@@ -107,6 +109,20 @@ public class QcInspectionResultVo implements Serializable {
@ExcelDictFormat(readConverterExp = "快=照")
private Long typeId;
+ /**
+ * 检测方法(0目视,1千分尺)
+ */
+ @ExcelProperty(value = "检测方法", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "qc_methond")
+ @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "qc_methond")
+ private String methodName;
+
+// /**
+// * 检测方法名称
+// */
+// @ExcelProperty(value = "检测方法名称")
+// private String methodName;
+
/**
* 检测方式(0定性,1定量)(快照)
*/
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionTemplateVo.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionTemplateVo.java
index cd6036db..d968a483 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionTemplateVo.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionTemplateVo.java
@@ -106,6 +106,12 @@ public class QcInspectionTemplateVo implements Serializable {
@ExcelProperty(value = "模板说明")
private String description;
+ /**
+ * 是否通用模板(0否/1是)
+ */
+ @ExcelProperty(value = "是否通用模板")
+ private String isDefault;
+
/**
* 检测类型编码
*/
@@ -117,7 +123,7 @@ public class QcInspectionTemplateVo implements Serializable {
private String typeName;//JOIN
/**
- * 检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)
+ * 检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
*/
private String qcInspectionType;//JOIN
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionTypeVo.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionTypeVo.java
index 67fea006..ee0c2409 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionTypeVo.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/vo/QcInspectionTypeVo.java
@@ -47,9 +47,9 @@ public class QcInspectionTypeVo implements Serializable {
private String typeName;
/**
- * 检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)
+ * 检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
*/
- @ExcelProperty(value = "检测类型(字典:首检 专检 自检 互检 原材料检 抽检 成品检)", converter = ExcelDictConvert.class)
+ @ExcelProperty(value = "检测类型(字典:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "qc_inspection_type")
private String qcInspectionType;
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcInspectionTemplateService.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcInspectionTemplateService.java
index 200a7ea2..6fcb3e23 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcInspectionTemplateService.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcInspectionTemplateService.java
@@ -58,6 +58,19 @@ public interface IQcInspectionTemplateService {
*/
Boolean updateByBo(QcInspectionTemplateBo bo);
+ /**
+ * 多级降级匹配策略获取质检模板
+ * 匹配优先级:物料相关(精确优先) > 工位相关(精确优先) > 通用模板
+ *
+ * @param materialCode 物料编码
+ * @param stationCode 工位编码
+ * @param processCode 工序编码
+ * @param qcInspectionType 检测类型(首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
+ * @return 匹配的质检模板
+ */
+ QcInspectionTemplateVo getMatchedTemplate(String materialCode, String stationCode,
+ String processCode, String qcInspectionType);
+
/**
* 校验并批量删除检测模板主信息
*
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcInspectionMainServiceImpl.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcInspectionMainServiceImpl.java
index 9867f449..55e714bf 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcInspectionMainServiceImpl.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcInspectionMainServiceImpl.java
@@ -1,31 +1,41 @@
package org.dromara.qms.service.impl;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.github.yulichang.toolkit.JoinWrappers;
-import com.github.yulichang.wrapper.MPJLambdaWrapper;
-import lombok.RequiredArgsConstructor;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.system.api.RemoteCodeRuleService;
import org.dromara.qms.domain.QcInspectionMain;
import org.dromara.qms.domain.QcInspectionResult;
import org.dromara.qms.domain.QcInspectionTemplate;
import org.dromara.qms.domain.QcInspectionType;
import org.dromara.qms.domain.bo.QcInspectionMainBo;
+import org.dromara.qms.domain.bo.QcInspectionResultBo;
+import org.dromara.qms.domain.bo.QcTemplateItemBo;
import org.dromara.qms.domain.vo.QcInspectionMainVo;
+import org.dromara.qms.domain.vo.QcTemplateItemVo;
+import org.dromara.qms.domain.vo.QcInspectionTemplateVo;
import org.dromara.qms.mapper.QcInspectionMainMapper;
import org.dromara.qms.mapper.QcInspectionResultMapper;
import org.dromara.qms.service.IQcInspectionMainService;
import org.dromara.qms.service.IQcInspectionResultService;
+import org.dromara.qms.service.IQcInspectionTemplateService;
+import org.dromara.qms.service.IQcTemplateItemService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.yulichang.toolkit.JoinWrappers;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import lombok.RequiredArgsConstructor;
/**
* 质检任务Service业务层处理
@@ -38,9 +48,10 @@ import java.util.Map;
public class QcInspectionMainServiceImpl implements IQcInspectionMainService {
private final QcInspectionMainMapper baseMapper;
-
private final IQcInspectionResultService qcInspectionResultService;
private final QcInspectionResultMapper qcInspectionResultMapper;
+ private final IQcInspectionTemplateService qcInspectionTemplateService;
+ private final IQcTemplateItemService qcTemplateItemService;
/**
@@ -107,7 +118,9 @@ public class QcInspectionMainServiceImpl implements IQcInspectionMainService {
.eq(bo.getInspectionType() != null, QcInspectionMain::getInspectionType, bo.getInspectionType())
// .eq(bo.getStatus() != null, QcInspectionMain::getStatus, bo.getStatus())
- .eq(StringUtils.isNotBlank(bo.getQcInspectionType()), QcInspectionType::getQcInspectionType, bo.getQcInspectionType())
+ // 支持单值和多值查询检测类型字典
+ .eq(StringUtils.isNotBlank(bo.getQcInspectionType()) && (bo.getQcInspectionTypes() == null || bo.getQcInspectionTypes().isEmpty()), QcInspectionType::getQcInspectionType, bo.getQcInspectionType())
+ .in(bo.getQcInspectionTypes() != null && !bo.getQcInspectionTypes().isEmpty(), QcInspectionType::getQcInspectionType, bo.getQcInspectionTypes())
.eq(StringUtils.isNotBlank(bo.getStatus()), QcInspectionMain::getStatus, bo.getStatus())
.eq(StringUtils.isNotBlank(bo.getInspector()), QcInspectionMain::getInspector, bo.getInspector())
.eq(StringUtils.isNotBlank(bo.getShift()), QcInspectionMain::getShift, bo.getShift())
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcInspectionTemplateServiceImpl.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcInspectionTemplateServiceImpl.java
index d2ac13bd..019587d5 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcInspectionTemplateServiceImpl.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcInspectionTemplateServiceImpl.java
@@ -1,5 +1,8 @@
package org.dromara.qms.service.impl;
+import jakarta.annotation.PostConstruct;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -20,6 +23,7 @@ import org.dromara.qms.service.IQcInspectionTemplateService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
+import java.util.stream.Collectors;
/**
* 检测模板主Service业务层处理
@@ -27,12 +31,20 @@ import java.util.Collection;
* @author zch
* @date 2025-07-14
*/
+@Slf4j
@RequiredArgsConstructor
@Service
public class QcInspectionTemplateServiceImpl implements IQcInspectionTemplateService {
private final QcInspectionTemplateMapper baseMapper;
+ // ========== 应用级缓存:所有质检模板 ==========
+ // 应用启动时一次性加载,避免运行时频繁查询数据库
+ private volatile List templateCache;
+
+ // 按检测类型分组的缓存(加速查找)
+ private volatile Map> templatesByTypeCache;
+
/**
* 查询检测模板主
*
@@ -93,6 +105,7 @@ public class QcInspectionTemplateServiceImpl implements IQcInspectionTemplateSer
.like(StringUtils.isNotBlank(bo.getSupplierName()), QcInspectionTemplate::getSupplierName, bo.getSupplierName())
.eq(StringUtils.isNotBlank(bo.getDescription()), QcInspectionTemplate::getDescription, bo.getDescription())
.eq(StringUtils.isNotBlank(bo.getQcInspectionType()), QcInspectionType::getQcInspectionType, bo.getQcInspectionType())
+ .eq(StringUtils.isNotBlank(bo.getIsDefault()), QcInspectionTemplate::getIsDefault, bo.getIsDefault())
.orderByDesc(QcInspectionTemplate::getCreateTime);
return lqw;
}
@@ -110,6 +123,7 @@ public class QcInspectionTemplateServiceImpl implements IQcInspectionTemplateSer
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setTemplateId(add.getTemplateId());
+ refreshCache(); // 刷新应用级缓存
}
return flag;
}
@@ -124,14 +138,178 @@ public class QcInspectionTemplateServiceImpl implements IQcInspectionTemplateSer
public Boolean updateByBo(QcInspectionTemplateBo bo) {
QcInspectionTemplate update = MapstructUtils.convert(bo, QcInspectionTemplate.class);
validEntityBeforeSave(update);
- return baseMapper.updateById(update) > 0;
+ boolean flag = baseMapper.updateById(update) > 0;
+ if (flag) {
+ refreshCache(); // 刷新应用级缓存
+ }
+ return flag;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(QcInspectionTemplate entity){
- //TODO 做一些数据校验,如唯一约束
+ // 校验1:通用模板不能绑定物料/工序/工位
+ if ("1".equals(entity.getIsDefault())) {
+ boolean hasBinding = StringUtils.isNotBlank(entity.getMaterialCode())
+ || StringUtils.isNotBlank(entity.getStationCode())
+ || StringUtils.isNotBlank(entity.getProcessCode());
+ if (hasBinding) {
+ throw new ServiceException("通用模板不能绑定具体物料、工序或工位!");
+ }
+ }
+
+ // 校验2:每种检测类型只能有一个通用模板
+ if ("1".equals(entity.getIsDefault()) && entity.getTypeId() != null) {
+ QcInspectionTemplateBo checkBo = new QcInspectionTemplateBo();
+ checkBo.setTypeId(entity.getTypeId());
+ checkBo.setIsDefault("1");
+ List existingDefaults = queryList(checkBo);
+ boolean hasOtherDefault = existingDefaults.stream()
+ .anyMatch(vo -> !vo.getTemplateId().equals(entity.getTemplateId()));
+ if (hasOtherDefault) {
+ throw new ServiceException("该检测类型已存在通用模板!");
+ }
+ }
+ }
+
+ /**
+ * 多级降级匹配策略获取质检模板(应用层缓存版,零数据库查询)
+ * 匹配优先级:物料+工位+工序 > 物料+工位 > 物料+工序 > 物料 > 工位+工序 > 工位 > 工序 > 通用模板
+ * 赋分规则:物料=200, 工位=20, 工序=2, 通用模板=0(兜底)
+ *
+ * @param materialCode 物料编码
+ * @param stationCode 工位编码
+ * @param processCode 工序编码
+ * @param qcInspectionType 检测类型(首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8)
+ * @return 匹配的质检模板
+ */
+ @Override
+ public QcInspectionTemplateVo getMatchedTemplate(String materialCode, String stationCode,
+ String processCode, String qcInspectionType) {
+ if (StringUtils.isBlank(qcInspectionType)) {
+ throw new ServiceException("检测类型不能为空!");
+ }
+
+ // 确保缓存已初始化
+ if (templatesByTypeCache == null) {
+ synchronized (this) {
+ if (templatesByTypeCache == null) {
+ refreshCache();
+ }
+ }
+ }
+
+ // 从缓存获取该检测类型的所有模板
+ List typeTemplates = templatesByTypeCache.get(qcInspectionType);
+ if (typeTemplates == null || typeTemplates.isEmpty()) {
+ throw new ServiceException("检测类型[" + qcInspectionType + "]无可用检测模板!");
+ }
+
+ // 【修复】阶段1:在非通用模板中找最佳匹配(分数>0)
+ QcInspectionTemplateVo bestMatch = typeTemplates.stream()
+ .filter(t -> !"1".equals(t.getIsDefault())) // 排除通用模板
+ .max((t1, t2) -> {
+ int score1 = calculateMatchScore(t1, materialCode, stationCode, processCode);
+ int score2 = calculateMatchScore(t2, materialCode, stationCode, processCode);
+ return Integer.compare(score1, score2);
+ })
+ .filter(t -> calculateMatchScore(t, materialCode, stationCode, processCode) > 0)
+ .orElse(null);
+
+ // 【修复】阶段2:如果没有非通用模板匹配,使用通用模板兜底
+ if (bestMatch == null) {
+ bestMatch = typeTemplates.stream()
+ .filter(t -> "1".equals(t.getIsDefault())) // 只查找通用模板
+ .findFirst()
+ .orElse(null);
+
+ if (bestMatch != null) {
+ log.info("使用通用模板兜底:{},检测类型:{}", bestMatch.getTemplateName(), qcInspectionType);
+ }
+ }
+
+ if (bestMatch == null) {
+ throw new ServiceException("[" +
+ (StringUtils.isNotBlank(materialCode) ? "物料=" + materialCode + " " : "") +
+ (StringUtils.isNotBlank(stationCode) ? "工位=" + stationCode + " " : "") +
+ (StringUtils.isNotBlank(processCode) ? "工序=" + processCode + " " : "") +
+ "检测类型=" + qcInspectionType + "]无匹配模板!");
+ }
+
+ int score = calculateMatchScore(bestMatch, materialCode, stationCode, processCode);
+ log.info("匹配到模板:{},分数:{}", bestMatch.getTemplateName(), score);
+ return bestMatch;
+ }
+
+ /**
+ * 计算非通用模板的匹配分数
+ * 赋分规则:物料=200, 工位=20, 工序=2, 通用模板=0(不参与分数计算,单独处理)
+ *
+ * 分数计算示例:
+ * - 物料+工位+工序 = 200+20+2 = 222分(最高优先级)
+ * - 物料+工位 = 200+20 = 220分
+ * - 物料+工序 = 200+2 = 202分
+ * - 物料 = 200 = 200分
+ * - 工位+工序 = 20+2 = 22分
+ * - 工位 = 20 = 20分
+ * - 工序 = 2 = 2分
+ * - 通用模板 = 0 = 0分(兜底,不参与分数比较)
+ */
+ private int calculateMatchScore(QcInspectionTemplateVo template,
+ String materialCode, String stationCode, String processCode) {
+ // 通用模板返回0分,不参与分数计算,单独作为兜底策略
+ if ("1".equals(template.getIsDefault())) {
+ return 0;
+ }
+
+ int score = 0;
+
+ // 物料匹配(最高权重:200分)
+ if (StringUtils.isNotBlank(materialCode) && materialCode.equals(template.getMaterialCode())) {
+ score += 200;
+ }
+
+ // 工位匹配(中等权重:20分)
+ if (StringUtils.isNotBlank(stationCode) && stationCode.equals(template.getStationCode())) {
+ score += 20;
+ }
+
+ // 工序匹配(较低权重:2分)
+ if (StringUtils.isNotBlank(processCode) && processCode.equals(template.getProcessCode())) {
+ score += 2;
+ }
+
+ return score;
+ }
+
+ /**
+ * 初始化缓存(应用启动时自动调用)
+ */
+ @PostConstruct
+ public synchronized void initCache() {
+ refreshCache();
+ }
+
+ /**
+ * 刷新缓存(模板增删改时调用)
+ */
+ public synchronized void refreshCache() {
+ log.info("开始加载质检模板缓存...");
+
+ // 一次性查询所有模板
+ QcInspectionTemplateBo bo = new QcInspectionTemplateBo();
+ templateCache = queryList(bo);
+
+ // 按检测类型分组,加速后续查找
+ templatesByTypeCache = templateCache.stream()
+ .collect(Collectors.groupingBy(t -> {
+ String type = t.getQcInspectionType();
+ return StringUtils.isNotBlank(type) ? type : "";
+ }));
+
+ log.info("质检模板缓存加载完成,共{}条,检测类型数:{}",
+ templateCache.size(), templatesByTypeCache.size());
}
/**
@@ -146,6 +324,10 @@ public class QcInspectionTemplateServiceImpl implements IQcInspectionTemplateSer
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
- return baseMapper.deleteByIds(ids) > 0;
+ boolean flag = baseMapper.deleteByIds(ids) > 0;
+ if (flag) {
+ refreshCache(); // 刷新应用级缓存
+ }
+ return flag;
}
}
diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcPDAServiceImpl.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcPDAServiceImpl.java
index 363ecc46..31d94cb5 100644
--- a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcPDAServiceImpl.java
+++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcPDAServiceImpl.java
@@ -60,17 +60,58 @@ public class QcPDAServiceImpl implements IQcPDAService {
private final IQcInspectionMainFileRelationService qcInspectionMainFileRelationService;
- @DubboReference
+ @DubboReference(timeout = 300000)
private final RemotePdaMesApiService remotePdaMesApiService;
- @DubboReference
+ @DubboReference(timeout = 300000)
private final RemoteCodeRuleService remoteCodeRuleService;
//WARM-FLOW工作流
- @DubboReference(timeout = 30000)
+ @DubboReference(timeout = 300000)
private final RemoteWorkflowService remoteWorkflowService;
+
+ // 工位信息和工序信息服务(用于通过名称查询编码)
+ private final IProdBaseStationInfoService prodBaseStationInfoService;
+ private final IProdBaseProcessInfoService prodBaseProcessInfoService;
+
private static final String UNQUALIFIED_REVIEW_FLOW_CODE = "unqualified_review";
+ /**
+ * 根据工位名称(机台名称)查询工位编码
+ * FIXME: 后期需要优化缓存策略,避免每次查询都访问数据库
+ * TODO: 考虑在应用启动时缓存工位名称→编码的映射关系
+ *
+ * @param stationName 工位名称(来自 ProdQmsPlanDetail.releaseName,对应机台名称)
+ * @return 工位编码,如果查询不到返回 null
+ */
+ private String getStationCodeByName(String stationName) {
+ if (StringUtils.isBlank(stationName)) {
+ return null;
+ }
+ ProdBaseStationInfoBo bo = new ProdBaseStationInfoBo();
+ bo.setStationName(stationName);
+ List list = prodBaseStationInfoService.queryList(bo);
+ return (list != null && !list.isEmpty()) ? list.get(0).getStationCode() : null;
+ }
+
+ /**
+ * 根据工序名称查询工序编码
+ * FIXME: 后期需要优化缓存策略,避免每次查询都访问数据库
+ * TODO: 考虑在应用启动时缓存工序名称→编码的映射关系
+ *
+ * @param processName 工序名称(来自 ProdQmsPlanDetail.processName)
+ * @return 工序编码,如果查询不到返回 null
+ */
+ private String getProcessCodeByName(String processName) {
+ if (StringUtils.isBlank(processName)) {
+ return null;
+ }
+ ProdBaseProcessInfoBo bo = new ProdBaseProcessInfoBo();
+ bo.setProcessName(processName);
+ List list = prodBaseProcessInfoService.queryList(bo);
+ return (list != null && !list.isEmpty()) ? list.get(0).getProcessCode() : null;
+ }
+
/**
* 通过planDetailId和processId生成质检任务
@@ -88,20 +129,28 @@ public class QcPDAServiceImpl implements IQcPDAService {
}
QcInspectionMainBo selectMain = new QcInspectionMainBo();
selectMain.setPlanDetailId(planDetail.getPlanDetailId());
+ selectMain.setQcInspectionType(bo.getQcInspectionType()); // 按质检类型筛选
selectMain.setStatus("0");//单据状态(0未处理/1完成)
List mainVoList = qcInspectionMainService.queryList(selectMain);
if (!mainVoList.isEmpty()){
- throw new ServiceException("此生产计划已生成质检任务且未处理!");
+ // 获取已存在的未处理质检任务信息
+ QcInspectionMainVo existingTask = mainVoList.get(0);
+ String existingInspectionNo = existingTask.getInspectionNo();
+ String typeName = StringUtils.isNotBlank(existingTask.getTypeName())
+ ? existingTask.getTypeName()
+ : getInspectionTypeName(bo.getQcInspectionType());
+ throw new ServiceException("【" + existingInspectionNo + "】" + typeName + "任务未质检,当前状态为未判定,请先完成该质检任务!");
}
+ // 使用多级降级匹配策略:物料相关 > 工位相关 > 通用模板
+ // FIXME: ProdQmsPlanDetail.releaseName 是机台名称(对应工位名称),需要查询工位编码
+ // FIXME: ProdQmsPlanDetail.processName 是工序名称,需要查询工序编码
+ // TODO: 后期建议 PDA API 直接返回编码,避免跨模块查询
String materialCode = planDetail.getMaterialCode();
- QcInspectionTemplateBo templateBo = new QcInspectionTemplateBo();
- templateBo.setMaterialCode(materialCode);
- templateBo.setQcInspectionType(bo.getQcInspectionType());
- List templateVos = qcInspectionTemplateService.queryList(templateBo);
- if (templateVos.size() != 1) {
- throw new ServiceException("此物料无可用检测模板!");
- }
- QcInspectionTemplateVo templateVo = templateVos.get(0);
+ String stationCode = getStationCodeByName(planDetail.getReleaseName()); // 根据机台名称查询工位编码
+ String processCode = getProcessCodeByName(planDetail.getProcessName()); // 根据工序名称查询工序编码
+ QcInspectionTemplateVo templateVo = qcInspectionTemplateService.getMatchedTemplate(
+ materialCode, stationCode, processCode, bo.getQcInspectionType()
+ );
QcInspectionMainBo inspectionBo = new QcInspectionMainBo();
inspectionBo.setInspectionNo(inspectionNo);
inspectionBo.setPlanDetailId(planDetail.getPlanDetailId());
@@ -436,5 +485,37 @@ public class QcPDAServiceImpl implements IQcPDAService {
return true;
}
+ /**
+ * 根据质检类型代码获取质检类型名称
+ * @param qcInspectionType 质检类型代码:首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8
+ * @return 质检类型名称
+ */
+ private String getInspectionTypeName(String qcInspectionType) {
+ if (StringUtils.isBlank(qcInspectionType)) {
+ return "质检";
+ }
+ switch (qcInspectionType) {
+ case "0":
+ return "首检";
+ case "1":
+ return "专检";
+ case "2":
+ return "自检";
+ case "3":
+ return "互检";
+ case "4":
+ return "原材料检";
+ case "5":
+ return "抽检";
+ case "6":
+ return "成品检";
+ case "7":
+ return "入库检";
+ case "8":
+ return "出库检";
+ default:
+ return "质检";
+ }
+ }
}
diff --git a/ruoyi-modules/hwmom-qms/src/main/resources/mapper/qms/QcInspectionMainFileRelationMapper.xml b/ruoyi-modules/hwmom-qms/src/main/resources/mapper/qms/QcInspectionMainFileRelationMapper.xml
index 897c56bc..93caf65f 100644
--- a/ruoyi-modules/hwmom-qms/src/main/resources/mapper/qms/QcInspectionMainFileRelationMapper.xml
+++ b/ruoyi-modules/hwmom-qms/src/main/resources/mapper/qms/QcInspectionMainFileRelationMapper.xml
@@ -4,4 +4,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+
+
+
+
+
+
+ select relation_id, tenant_id, inspection_id, tenant_id, oss_id, create_dept, create_by, create_time, update_by, update_time, del_flag
+ from qc_inspection_main_file_relation
+
+
+
+
+