From a1598d7a1a9fd8c34b34242d8d47e62e0ff5b3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B8=B8=E7=86=9F=E5=90=B4=E5=BD=A6=E7=A5=96?= Date: Wed, 5 Aug 2026 13:24:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=93=81=E6=B5=81=E7=A8=8Bok?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/qms/controller/QcController.java | 48 ++++ .../data/QcPartAttributeTemplateCopyData.java | 95 +++++++ .../xujie/modules/qms/mapper/QcMapper.java | 39 +++ .../xujie/modules/qms/service/QcService.java | 15 ++ .../qms/service/impl/QcServiceImpl.java | 253 +++++++++++++++++- src/main/resources/application-dev.yml | 4 +- src/main/resources/mapper/qms/QcMapper.xml | 184 +++++++++++++ 7 files changed, 633 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/xujie/modules/qms/data/QcPartAttributeTemplateCopyData.java diff --git a/src/main/java/com/xujie/modules/qms/controller/QcController.java b/src/main/java/com/xujie/modules/qms/controller/QcController.java index 9bfe893..8fc9b32 100644 --- a/src/main/java/com/xujie/modules/qms/controller/QcController.java +++ b/src/main/java/com/xujie/modules/qms/controller/QcController.java @@ -803,6 +803,54 @@ public class QcController { return R.ok(); } + /** + * @description: 查询检验模板复制候选物料(只查在用物料,并排除源物料自身) + * @author: system + * @date: 2026/8/5 + * @param: [data] + * @return: com.xujie.common.utils.R + * + * 业务说明: + * 1) 用于“复制检验模板”弹窗内的目标物料清单; + * 2) 支持基准料号/物料名称/SKU/item/物料分类1~3名称筛选; + * 3) 不按供应商过滤,范围为当前 site 下 status='Y' 的全部物料。 + */ + @PostMapping("/listPartAttributeTemplateCopyTargetParts") + public R listPartAttributeTemplateCopyTargetParts(@RequestBody QcPartAttributeTemplateCopyData data){ + List list = qcService.listPartAttributeTemplateCopyTargetParts(data); + return R.ok().put("rows", list).put("total", list.size()); + } + + /** + * @description: 校验复制目标中已存在检验模板的物料(前端用于提示“是否覆盖”) + * @author: system + * @date: 2026/8/5 + * @param: [data] + * @return: com.xujie.common.utils.R + */ + @PostMapping("/checkPartAttributeTemplateCopyConflicts") + public R checkPartAttributeTemplateCopyConflicts(@RequestBody QcPartAttributeTemplateCopyData data){ + List list = qcService.checkPartAttributeTemplateCopyConflicts(data); + return R.ok().put("rows", list).put("total", list.size()); + } + + /** + * @description: 复制检验模板主从记录到目标物料(可覆盖) + * @author: system + * @date: 2026/8/5 + * @param: [data] + * @return: com.xujie.common.utils.R + * + * 关键行为: + * 1) 覆盖模式:先删目标物料既有模板主从记录,再复制源物料配置; + * 2) 非覆盖模式:若目标已存在模板,后端直接拦截,避免脏写入。 + */ + @PostMapping("/copyPartAttributeTemplateToParts") + public R copyPartAttributeTemplateToParts(@RequestBody QcPartAttributeTemplateCopyData data){ + qcService.copyPartAttributeTemplateToParts(data); + return R.ok(); + } + /** * @description: 物料属性导入 * @author: fengyuan_yang diff --git a/src/main/java/com/xujie/modules/qms/data/QcPartAttributeTemplateCopyData.java b/src/main/java/com/xujie/modules/qms/data/QcPartAttributeTemplateCopyData.java new file mode 100644 index 0000000..8fba054 --- /dev/null +++ b/src/main/java/com/xujie/modules/qms/data/QcPartAttributeTemplateCopyData.java @@ -0,0 +1,95 @@ +package com.xujie.modules.qms.data; + +import com.xujie.common.utils.QueryPage; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * 物料检验模板复制请求/响应模型。 + * + * 业务语义说明: + * 1) 本模型服务于「/qc-qcPartAttribute」页面的“模板复制”能力; + * 2) 复制对象包含: + * - 主记录:qc_attribute_template(检验模板清单); + * - 子记录:qc_attribute_template_item(检验标准明细); + * 3) 复制目标物料来源于 part 表,且仅允许 status = 'Y' 的在用物料; + * 4) 覆盖模式下会先删除目标物料既有模板主从记录,再复制源物料配置。 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class QcPartAttributeTemplateCopyData extends QueryPage { + + /** + * 站点(唯一业务来源:前端 user.site)。 + */ + private String site; + + /** + * BU编码(模板主从表分区字段)。 + */ + private String buNo; + + /** + * 源物料编码(被复制模板的来源物料)。 + */ + private String sourcePartNo; + + /** + * 目标物料编码列表(复制到哪些物料)。 + */ + private List targetPartNos; + + /** + * 是否覆盖已存在模板: + * - false:若目标已存在模板则拦截; + * - true :先删目标模板主从记录,再复制。 + */ + private Boolean overwriteExisting; + + /** + * 操作人(用于复制后子表创建/更新人字段回填)。 + */ + private String submitBy; + + /** + * 基准料号筛选(part.bast_part_no,支持模糊匹配)。 + */ + private String basePartNo; + + /** + * 物料编码筛选(part.part_no,支持模糊匹配)。 + */ + private String partNo; + + /** + * 物料名称筛选(part.part_desc,支持模糊匹配)。 + */ + private String partDesc; + + /** + * Item筛选(part.item,支持模糊匹配)。 + */ + private String item; + + /** + * SKU筛选(part.sku,支持模糊匹配)。 + */ + private String sku; + + /** + * 物料分类1名称筛选(part.category -> part_family.family_name)。 + */ + private String categoryName; + + /** + * 物料分类2名称筛选(part.category_level2 -> part_family.family_name)。 + */ + private String categoryLevel2Name; + + /** + * 物料分类3名称筛选(part.category_level3 -> part_family.family_name)。 + */ + private String categoryLevel3Name; +} diff --git a/src/main/java/com/xujie/modules/qms/mapper/QcMapper.java b/src/main/java/com/xujie/modules/qms/mapper/QcMapper.java index eb275fa..14aa00b 100644 --- a/src/main/java/com/xujie/modules/qms/mapper/QcMapper.java +++ b/src/main/java/com/xujie/modules/qms/mapper/QcMapper.java @@ -206,6 +206,45 @@ public interface QcMapper { int copyQcTemplateDetailedToAttributeTemplateItem(QcTemplateData data); + /** + * 查询“检验模板复制”候选物料(status='Y',排除源物料)。 + */ + List listPartAttributeTemplateCopyTargetParts(QcPartAttributeTemplateCopyData data); + + /** + * 按物料编码集合查询“在用物料”明细(用于后端二次校验目标合法性)。 + */ + List listEnabledPartRowsByPartNos(QcPartAttributeTemplateCopyData data); + + /** + * 查询目标物料中已存在检验模板的记录。 + */ + List listPartAttributeTemplateCopyConflicts(QcPartAttributeTemplateCopyData data); + + /** + * 查询源物料已绑定的模板主记录。 + */ + List listPartAttributeTemplateMainByPartNo(@Param("site") String site, + @Param("buNo") String buNo, + @Param("sourcePartNo") String sourcePartNo); + + /** + * 复制源物料模板主记录到目标物料。 + */ + int copyPartAttributeTemplateMainToTarget(@Param("site") String site, + @Param("buNo") String buNo, + @Param("sourcePartNo") String sourcePartNo, + @Param("targetPartNo") String targetPartNo); + + /** + * 复制源物料模板检验标准明细到目标物料。 + */ + int copyPartAttributeTemplateItemToTarget(@Param("site") String site, + @Param("buNo") String buNo, + @Param("sourcePartNo") String sourcePartNo, + @Param("targetPartNo") String targetPartNo, + @Param("submitBy") String submitBy); + QcTemplateData selectTemplateData(QcTemplateData data); void qcPartAttributeDelete(QcPartAttributeData data); diff --git a/src/main/java/com/xujie/modules/qms/service/QcService.java b/src/main/java/com/xujie/modules/qms/service/QcService.java index 00e0cc2..c8d2d34 100644 --- a/src/main/java/com/xujie/modules/qms/service/QcService.java +++ b/src/main/java/com/xujie/modules/qms/service/QcService.java @@ -135,6 +135,21 @@ public interface QcService { void qcAttributeTemplateItemSave(QcTemplateData data); + /** + * 查询“检验模板复制”候选物料(仅在用物料,且排除源物料)。 + */ + List listPartAttributeTemplateCopyTargetParts(QcPartAttributeTemplateCopyData data); + + /** + * 校验目标物料中哪些已存在检验模板(用于前端“是否覆盖”确认)。 + */ + List checkPartAttributeTemplateCopyConflicts(QcPartAttributeTemplateCopyData data); + + /** + * 复制源物料检验模板主从记录到目标物料(支持覆盖模式)。 + */ + void copyPartAttributeTemplateToParts(QcPartAttributeTemplateCopyData data); + void qcPartAttributeDelete(QcPartAttributeData data); PageUtils qcFamilyAttributeSearch(QcPartAttributeData data); diff --git a/src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java b/src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java index b43a60f..0af3b5d 100644 --- a/src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java +++ b/src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java @@ -70,6 +70,7 @@ import java.util.stream.Collectors; @Slf4j public class QcServiceImpl implements QcService { private static final String TEMPLATE_SUPPLIER_WILDCARD = "*"; + private static final String PART_ATTRIBUTE_TYPE_MATERIAL = "A"; //记录日志使用 private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class); @@ -1102,6 +1103,117 @@ public class QcServiceImpl implements QcService { return list; } + /** + * 查询“检验模板复制”候选物料。 + * + * 关键约束: + * 1) 只返回 status='Y' 的在用物料; + * 2) 排除源物料自身,避免出现“复制到自己”; + * 3) 不按供应商过滤,按用户要求支持“全在用物料”范围; + * 4) 支持基准料号/物料名称/SKU/item/物料分类1~3名称筛选。 + */ + @Override + public List listPartAttributeTemplateCopyTargetParts(QcPartAttributeTemplateCopyData data) { + normalizeAndValidateCopyContext(data, true); + trimCopyQueryFields(data); + return qcMapper.listPartAttributeTemplateCopyTargetParts(data); + } + + /** + * 校验目标物料中已存在模板的冲突数据。 + * + * 返回值用途: + * - 前端据此展示“以下物料已经有检验模板,是否覆盖”的确认提示。 + */ + @Override + public List checkPartAttributeTemplateCopyConflicts(QcPartAttributeTemplateCopyData data) { + normalizeAndValidateCopyContext(data, true); + List targetPartNos = normalizeCopyTargetPartNos(data.getTargetPartNos(), data.getSourcePartNo()); + if (targetPartNos.isEmpty()) { + throw new RuntimeException("请至少选择一个目标物料"); + } + data.setTargetPartNos(targetPartNos); + validateAllTargetPartsEnabled(data, targetPartNos); + return qcMapper.listPartAttributeTemplateCopyConflicts(data); + } + + /** + * 执行“模板复制”。 + * + * 业务流程: + * 1) 校验源物料是否存在模板主记录; + * 2) 校验目标物料均为在用物料,且不包含源物料; + * 3) 非覆盖模式:若任一目标已有模板则直接拦截; + * 4) 覆盖模式:先删目标模板主从记录,再复制源模板主从记录; + * 5) 若目标物料尚未建立 qc_part_attribute 主记录,则自动补建,保证后续页面可见。 + */ + @Override + @Transactional + public void copyPartAttributeTemplateToParts(QcPartAttributeTemplateCopyData data) { + normalizeAndValidateCopyContext(data, true); + String submitBy = StringUtils.trimToEmpty(data.getSubmitBy()); + if (StringUtils.isBlank(submitBy)) { + throw new RuntimeException("操作人不能为空"); + } + + List targetPartNos = normalizeCopyTargetPartNos(data.getTargetPartNos(), data.getSourcePartNo()); + if (targetPartNos.isEmpty()) { + throw new RuntimeException("请至少选择一个目标物料"); + } + data.setTargetPartNos(targetPartNos); + + // 防止前端绕过筛选条件手工构造请求:后端再次校验目标物料必须真实存在且为在用。 + validateAllTargetPartsEnabled(data, targetPartNos); + + // 源模板必须存在,否则复制没有业务意义。 + List sourceTemplateRows = qcMapper.listPartAttributeTemplateMainByPartNo( + data.getSite(), data.getBuNo(), data.getSourcePartNo()); + if (sourceTemplateRows == null || sourceTemplateRows.isEmpty()) { + throw new RuntimeException("源物料未维护检验模板,无法复制"); + } + + List conflictRows = qcMapper.listPartAttributeTemplateCopyConflicts(data); + boolean overwriteExisting = Boolean.TRUE.equals(data.getOverwriteExisting()); + if (!overwriteExisting && conflictRows != null && !conflictRows.isEmpty()) { + throw new RuntimeException("以下物料已经有检验模板,请确认覆盖后重试:" + joinPartNos(conflictRows)); + } + + // 逐个目标复制,保证每个目标物料的主从记录完整迁移。 + for (String targetPartNo : targetPartNos) { + QcPartAttributeData targetPartAttribute = buildTargetPartAttributeForCopy(data, targetPartNo, submitBy); + QcPartAttributeData existsPartAttribute = qcMapper.selectPartAttributeByNo(targetPartAttribute); + if (existsPartAttribute == null) { + // 补建物料属性主记录,避免“复制后在物料属性列表不可见”。 + qcMapper.qcPartAttributeSave(targetPartAttribute); + } + + if (overwriteExisting) { + // 覆盖模式必须先删旧记录,避免历史模板残留导致重复/脏数据。 + qcMapper.deletePartAttributeTemplate(targetPartAttribute); + qcMapper.deleteQcAttributeTemplateItemByAttribute(targetPartAttribute); + } + + int copiedMainCount = qcMapper.copyPartAttributeTemplateMainToTarget( + data.getSite(), data.getBuNo(), data.getSourcePartNo(), targetPartNo); + if (copiedMainCount <= 0) { + throw new RuntimeException("复制失败:目标物料[" + targetPartNo + "]未生成模板主记录"); + } + + // 子表(检验标准)按源物料覆盖表复制;若源物料未维护覆盖表,系统会回退到模板默认明细读取。 + qcMapper.copyPartAttributeTemplateItemToTarget( + data.getSite(), data.getBuNo(), data.getSourcePartNo(), targetPartNo, submitBy); + + // 统一刷新目标物料属性的更新时间,便于前端列表和审计追踪。 + QcTemplateData updateTimeData = new QcTemplateData(); + updateTimeData.setSite(data.getSite()); + updateTimeData.setBuNo(data.getBuNo()); + updateTimeData.setAttributeNo(targetPartNo); + updateTimeData.setAttributeType(PART_ATTRIBUTE_TYPE_MATERIAL); + updateTimeData.setUpdateBy(submitBy); + qcMapper.updatePartAttributeTime(updateTimeData); + } + } + /** * 新增物料属性模板 **/ @@ -1295,7 +1407,7 @@ public class QcServiceImpl implements QcService { * 3) 校验放在 Service 层且与保存同事务,避免前端并发或绕过页面导致脏数据入库。 */ private void validateSingleTemplatePerPartAndInspectionType(QcTemplateData partData) { - if (!"A".equals(partData.getAttributeType())) { + if (!PART_ATTRIBUTE_TYPE_MATERIAL.equals(partData.getAttributeType())) { return; } if (StringUtils.isBlank(partData.getInspectionTypeNo())) { @@ -1311,7 +1423,7 @@ public class QcServiceImpl implements QcService { * 首次绑定模板时,将模板默认明细复制到物料模板明细覆盖表。 */ private void copyPartAttributeTemplateItemsIfNeed(QcTemplateData partData, QcTemplateData requestData) { - if (!"A".equals(partData.getAttributeType())) { + if (!PART_ATTRIBUTE_TYPE_MATERIAL.equals(partData.getAttributeType())) { return; } QcTemplateData query = new QcTemplateData(); @@ -1340,7 +1452,7 @@ public class QcServiceImpl implements QcService { return; } if (StringUtils.isBlank(data.getAttributeType())) { - data.setAttributeType("A"); + data.setAttributeType(PART_ATTRIBUTE_TYPE_MATERIAL); } Integer bindCount = qcMapper.countPartAttributeTemplateByTemplateKey(data); if (bindCount == null || bindCount == 0) { @@ -1353,6 +1465,141 @@ public class QcServiceImpl implements QcService { } } + /** + * 标准化并校验复制上下文的基础参数。 + * + * @param requireSourcePart 是否强制要求传 sourcePartNo(列表查询/校验/复制场景均建议为 true) + */ + private void normalizeAndValidateCopyContext(QcPartAttributeTemplateCopyData data, boolean requireSourcePart) { + if (data == null) { + throw new RuntimeException("复制参数不能为空"); + } + data.setSite(StringUtils.trimToEmpty(data.getSite())); + data.setBuNo(StringUtils.trimToEmpty(data.getBuNo())); + data.setSourcePartNo(StringUtils.trimToEmpty(data.getSourcePartNo())); + if (StringUtils.isBlank(data.getSite())) { + throw new RuntimeException("site不能为空"); + } + if (StringUtils.isBlank(data.getBuNo())) { + throw new RuntimeException("buNo不能为空"); + } + if (requireSourcePart && StringUtils.isBlank(data.getSourcePartNo())) { + throw new RuntimeException("源物料编码不能为空"); + } + } + + /** + * 统一去除查询字符串两端空格,避免“看起来相同但实际有空格”导致筛选偏差。 + */ + private void trimCopyQueryFields(QcPartAttributeTemplateCopyData data) { + data.setBasePartNo(StringUtils.trimToEmpty(data.getBasePartNo())); + data.setPartNo(StringUtils.trimToEmpty(data.getPartNo())); + data.setPartDesc(StringUtils.trimToEmpty(data.getPartDesc())); + data.setItem(StringUtils.trimToEmpty(data.getItem())); + data.setSku(StringUtils.trimToEmpty(data.getSku())); + data.setCategoryName(StringUtils.trimToEmpty(data.getCategoryName())); + data.setCategoryLevel2Name(StringUtils.trimToEmpty(data.getCategoryLevel2Name())); + data.setCategoryLevel3Name(StringUtils.trimToEmpty(data.getCategoryLevel3Name())); + } + + /** + * 规范化目标物料编码列表: + * 1) 去空值; + * 2) 去重(按不区分大小写); + * 3) 排除源物料自身。 + */ + private List normalizeCopyTargetPartNos(List rawTargetPartNos, String sourcePartNo) { + if (rawTargetPartNos == null || rawTargetPartNos.isEmpty()) { + return Collections.emptyList(); + } + String sourceKey = StringUtils.trimToEmpty(sourcePartNo).toUpperCase(Locale.ROOT); + LinkedHashMap normalizedMap = new LinkedHashMap<>(); + for (String partNo : rawTargetPartNos) { + String normalizedPartNo = StringUtils.trimToEmpty(partNo); + if (StringUtils.isBlank(normalizedPartNo)) { + continue; + } + String key = normalizedPartNo.toUpperCase(Locale.ROOT); + if (StringUtils.isNotBlank(sourceKey) && sourceKey.equals(key)) { + continue; + } + normalizedMap.putIfAbsent(key, normalizedPartNo); + } + return new ArrayList<>(normalizedMap.values()); + } + + /** + * 校验目标物料是否全部为“在用物料”。 + * + * 失败场景: + * - 目标编码不存在; + * - 目标编码存在但 status != 'Y'; + * - 前端绕过页面限制,手工提交非法编码。 + */ + private void validateAllTargetPartsEnabled(QcPartAttributeTemplateCopyData data, List targetPartNos) { + if (targetPartNos == null || targetPartNos.isEmpty()) { + throw new RuntimeException("请至少选择一个目标物料"); + } + List enabledRows = qcMapper.listEnabledPartRowsByPartNos(data); + Set enabledPartNoSet = new HashSet<>(); + if (enabledRows != null) { + for (QcPartAttributeTemplateCopyData row : enabledRows) { + if (row != null && StringUtils.isNotBlank(row.getPartNo())) { + enabledPartNoSet.add(row.getPartNo().trim().toUpperCase(Locale.ROOT)); + } + } + } + List invalidPartNos = new ArrayList<>(); + for (String targetPartNo : targetPartNos) { + String key = StringUtils.trimToEmpty(targetPartNo).toUpperCase(Locale.ROOT); + if (!enabledPartNoSet.contains(key)) { + invalidPartNos.add(targetPartNo); + } + } + if (!invalidPartNos.isEmpty()) { + throw new RuntimeException("以下物料不存在或非在用状态,不允许复制:" + String.join("、", invalidPartNos)); + } + } + + /** + * 组装目标物料的 qc_part_attribute 主记录。 + * + * 注意: + * - 仅当目标尚未维护主记录时才会插入; + * - 插入时不覆盖业务备注,默认空字符串,避免误带源物料备注语义。 + */ + private QcPartAttributeData buildTargetPartAttributeForCopy(QcPartAttributeTemplateCopyData data, + String targetPartNo, + String submitBy) { + QcPartAttributeData targetPartAttribute = new QcPartAttributeData(); + targetPartAttribute.setSite(data.getSite()); + targetPartAttribute.setBuNo(data.getBuNo()); + targetPartAttribute.setPartNo(targetPartNo); + targetPartAttribute.setAttributeType(PART_ATTRIBUTE_TYPE_MATERIAL); + targetPartAttribute.setAttributeRemark(""); + targetPartAttribute.setExemptInspection(""); + targetPartAttribute.setCreateBy(submitBy); + targetPartAttribute.setUpdateBy(submitBy); + return targetPartAttribute; + } + + /** + * 冲突列表转文本,便于异常提示和日志定位。 + */ + private String joinPartNos(List rows) { + if (rows == null || rows.isEmpty()) { + return ""; + } + List partNos = rows.stream() + .filter(Objects::nonNull) + .map(QcPartAttributeTemplateCopyData::getPartNo) + .filter(StringUtils::isNotBlank) + .map(String::trim) + .distinct() + .collect(Collectors.toList()); + return String.join("、", partNos); + } + /** * 物料属性导入 **/ diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 33340a2..776814f 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -4,8 +4,8 @@ spring: druid: driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver type: com.alibaba.druid.pool.DruidDataSource - url: jdbc:sqlserver://192.168.1.90:1433;databaseName=krd_srm -# url: jdbc:sqlserver://xujiesoft.vicp.net:11515;databaseName=krd_srm +# url: jdbc:sqlserver://192.168.1.90:1433;databaseName=krd_srm + url: jdbc:sqlserver://xujiesoft.vicp.net:11515;databaseName=krd_srm username: sa password: XJsoft123 initial-size: 10 diff --git a/src/main/resources/mapper/qms/QcMapper.xml b/src/main/resources/mapper/qms/QcMapper.xml index ea0844c..5d45af2 100644 --- a/src/main/resources/mapper/qms/QcMapper.xml +++ b/src/main/resources/mapper/qms/QcMapper.xml @@ -1464,6 +1464,190 @@ ) + + + + + + + + + + + + + + + INSERT INTO qc_attribute_template + (attribute_no, template_id, sampling_level_no, inspection_cycle, sampling_programme_no, AQL, AC, RE, + attribute_type, operation, manufacturer_id, resource_id, site, bu_no, inspection_type_no) + SELECT + #{targetPartNo}, + template_id, + sampling_level_no, + inspection_cycle, + sampling_programme_no, + AQL, + AC, + RE, + attribute_type, + operation, + manufacturer_id, + resource_id, + site, + bu_no, + inspection_type_no + FROM qc_attribute_template + WHERE site = #{site} + AND bu_no = #{buNo} + AND attribute_no = #{sourcePartNo} + AND attribute_type = 'A' + + + + + INSERT INTO qc_attribute_template_item + (site, bu_no, attribute_no, template_id, item_no, default_value, max_value, min_value, order_id, create_by, create_time, update_by, update_date) + SELECT + site, + bu_no, + #{targetPartNo}, + template_id, + item_no, + default_value, + max_value, + min_value, + order_id, + #{submitBy}, + getDate(), + #{submitBy}, + getDate() + FROM qc_attribute_template_item + WHERE site = #{site} + AND bu_no = #{buNo} + AND attribute_no = #{sourcePartNo} + +