Browse Source

高级复制

master
常熟吴彦祖 1 week ago
parent
commit
e380559e0a
  1. 26
      src/main/java/com/xujie/modules/part/controller/PartAdvancedCopyController.java
  2. 29
      src/main/java/com/xujie/modules/part/dao/PartAdvancedCopyMapper.java
  3. 249
      src/main/java/com/xujie/modules/part/service/Impl/PartAdvancedCopyService.java
  4. 11
      src/main/java/com/xujie/modules/part/service/Impl/PartServiceImpl.java
  5. 15
      src/main/java/com/xujie/modules/part/vo/PartAdvancedCopyContext.java
  6. 27
      src/main/java/com/xujie/modules/part/vo/PartAdvancedCopyRequest.java
  7. 10
      src/main/java/com/xujie/modules/part/vo/PartAdvancedCopyResult.java
  8. 59
      src/main/resources/mapper/part/mapperXml/PartAdvancedCopyMapper.xml
  9. 9
      src/main/resources/mapper/qms/QcMapper.xml

26
src/main/java/com/xujie/modules/part/controller/PartAdvancedCopyController.java

@ -0,0 +1,26 @@
package com.xujie.modules.part.controller;
import com.xujie.common.utils.R;
import com.xujie.modules.part.service.Impl.PartAdvancedCopyService;
import com.xujie.modules.part.vo.PartAdvancedCopyRequest;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/** 物料高级复制独立入口,沿用项目统一返回和异常处理 - rqrq */
@RestController
@RequestMapping("/part")
public class PartAdvancedCopyController {
@Autowired
private PartAdvancedCopyService advancedCopyService;
/** 未确认覆盖时仅返回确认标志;确认后由服务层事务执行复制 - rqrq */
@PostMapping("/advancedCopy")
@ApiOperation("物料高级复制")
public R advancedCopy(@RequestBody PartAdvancedCopyRequest request) {
return R.ok().put("row", advancedCopyService.copy(request));
}
}

29
src/main/java/com/xujie/modules/part/dao/PartAdvancedCopyMapper.java

@ -0,0 +1,29 @@
package com.xujie.modules.part.dao;
import com.xujie.modules.part.entity.Part;
import com.xujie.modules.part.vo.PartAdvancedCopyContext;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/** 高级复制专用 SQL,所有读写均限定当前工厂和明确的源/目标料号 - rqrq */
@Mapper
public interface PartAdvancedCopyMapper {
/** 锁定料号及其键范围,防止检查目标与插入之间发生并发重复。 */
Part selectPartForCopy(@Param("site") String site, @Param("partNo") String partNo);
/** 读取源物料维护检验模板的 BU,供写入前完整性校验。 */
List<String> listTemplateBusinessUnits(PartAdvancedCopyContext context);
/** 复制默认供应商的全部可供关系字段;源关系不存在时返回 0。 */
int copySupplierRelation(PartAdvancedCopyContext context);
/** 删除目标检验标准、模板绑定、物料检验配置,分别执行单条 SQL。 */
int deleteInspectionItems(PartAdvancedCopyContext context);
int deleteInspectionTemplates(PartAdvancedCopyContext context);
int deleteInspectionAttributes(PartAdvancedCopyContext context);
/** 按源物料各 BU 的模板清单补建检验配置,保证复制后页面可见。 */
int copyInspectionAttributes(PartAdvancedCopyContext context);
}

249
src/main/java/com/xujie/modules/part/service/Impl/PartAdvancedCopyService.java

@ -0,0 +1,249 @@
package com.xujie.modules.part.service.Impl;
import com.xujie.modules.base.dao.PropertiesMapper;
import com.xujie.modules.part.dao.PartAdvancedCopyMapper;
import com.xujie.modules.part.dao.PartMapper;
import com.xujie.modules.part.entity.Part;
import com.xujie.modules.part.vo.PartAdvancedCopyContext;
import com.xujie.modules.part.vo.PartAdvancedCopyRequest;
import com.xujie.modules.part.vo.PartAdvancedCopyResult;
import com.xujie.modules.qms.mapper.QcMapper;
import com.xujie.modules.supplier.data.SupplierPartTierPriceItemVo;
import com.xujie.modules.supplier.data.SupplierPartTierPriceQueryVo;
import com.xujie.modules.supplier.data.SupplierPartTierPriceSaveVo;
import com.xujie.modules.supplier.mapper.SupplierPartMoqPriceMapper;
import com.xujie.modules.supplier.service.ISupplierPartMoqPriceService;
import com.xujie.modules.sys.entity.SysUserEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/** 物料高级复制事务编排,与原有按基准料号复制入口隔离 - rqrq */
@Slf4j
@Service
public class PartAdvancedCopyService {
@Autowired
private PartAdvancedCopyMapper copyMapper;
@Autowired
private PartMapper partMapper;
@Autowired
private PropertiesMapper propertiesMapper;
@Autowired
private SupplierPartMoqPriceMapper priceMapper;
@Autowired
private ISupplierPartMoqPriceService priceService;
@Autowired
private QcMapper qcMapper;
/**
* @Description 按选中物料复制主档、属性及可选的供应商/检验配置 - rqrq
* 业务目标:允许跨基准料号建档,名称和规格使用目标输入,其余业务字段继承源物料。
* 前置条件:当前工厂和源料号必须有效;供应商来自源物料主档;模板选项要求存在源模板。
* 执行步骤:1) 校验并读取源数据;2) 检查目标并请求覆盖确认;3) 替换主档/属性;
* 4) 仅按勾选项替换默认供应商关系、当前价和各 BU 的物料检验模板。
* 一致性与事务:源/目标物料加键范围锁,所有写入处于同一事务;未勾选项完全保留。
* 失败策略:前置校验失败直接抛错;待确认时不写数据;任一复制失败全部回滚。
*/
@Transactional(rollbackFor = Exception.class)
public PartAdvancedCopyResult copy(PartAdvancedCopyRequest request) {
// 1) 规范化工厂和目标输入;不读取登录态工厂,避免跨工厂复制 - rqrq
PartAdvancedCopyContext context = validateRequest(request);
log.info("开始物料高级复制 - rqrq,site={}, source={}, target={}",
context.getSite(), context.getSourcePartNo(), context.getTargetPartNo());
Part source = copyMapper.selectPartForCopy(context.getSite(), context.getSourcePartNo());
// 源料号必须精确存在,禁止回退到同系列其他物料。
if (source == null) {
throw new RuntimeException("源物料不存在,请刷新物料清单后重试");
}
context.setSourcePartNo(source.getPartNo());
context.setSupplierNo(StringUtils.trimToEmpty(source.getDefaultSupplierNo()).toUpperCase());
// 2) 先校验勾选项并读取当前价;无价格允许继续,后续会清空目标当前价 - rqrq
List<SupplierPartTierPriceItemVo> prices = Collections.emptyList();
if (Boolean.TRUE.equals(request.getCopySupplier())) {
// 默认供应商只能取源主档,不能使用客户端指定的供应商。
if (StringUtils.isBlank(context.getSupplierNo())) {
throw new RuntimeException("没有默认供应商,无法复制供应商可供物料+价格表");
}
if (partMapper.countSupplierByNo(context.getSite(), context.getSupplierNo()) <= 0) {
throw new RuntimeException("源物料的默认供应商不存在,无法复制供应商可供物料+价格表");
}
SupplierPartTierPriceQueryVo priceQuery = new SupplierPartTierPriceQueryVo();
priceQuery.setSite(context.getSite());
priceQuery.setSupplierCode(context.getSupplierNo());
priceQuery.setPartNo(context.getSourcePartNo());
prices = priceMapper.listCurrentTierPrice(priceQuery);
}
List<String> templateBusinessUnits = Collections.emptyList();
if (Boolean.TRUE.equals(request.getCopyInspectionTemplate())) {
templateBusinessUnits = copyMapper.listTemplateBusinessUnits(context);
// 检验模板包括绑定和物料专属标准,仅有物料检验主记录不算维护过模板。
if (templateBusinessUnits.isEmpty()) {
throw new RuntimeException("源物料没有维护检验模板,无法复制");
}
// 目标检验主表的 BU 非空,先报明确错误,避免删除目标后才发现源配置不完整。
if (templateBusinessUnits.stream().anyMatch(StringUtils::isBlank)) {
throw new RuntimeException("源物料检验模板缺少BU,请完善后再复制");
}
}
// 3) 目标检查与写入同事务;未确认覆盖只返回标志,不执行任何删除 - rqrq
Part target = copyMapper.selectPartForCopy(context.getSite(), context.getTargetPartNo());
// 再按数据库主键兜底,防止数据库排序规则把不同文本视为同一源料号。
if (target != null && Objects.equals(source.getId(), target.getId())) {
throw new RuntimeException("目标物料编码不能与源物料相同");
}
PartAdvancedCopyResult result = new PartAdvancedCopyResult();
result.setPartNo(context.getTargetPartNo());
if (target != null && !Boolean.TRUE.equals(request.getOverwriteExisting())) {
result.setOverwriteRequired(true);
log.info("目标物料已存在,等待覆盖确认 - rqrq,site={}, target={}",
context.getSite(), context.getTargetPartNo());
return result;
}
// 4) 固定复制项:删除目标属性子表/主表和物料,再插入源数据 - rqrq
// 不复用普通删除或新增方法,避免它们清理未勾选供应商、审批数据或自动建供应商关系。
partMapper.deletePartSubPropertiesValueBySiteAndPartNo(context.getSite(), context.getTargetPartNo());
partMapper.deletePartSubPropertiesValueHeaderBySiteAndPartNo(context.getSite(), context.getTargetPartNo());
partMapper.deletePartBySiteAndPartNo(context.getSite(), context.getTargetPartNo());
Part newPart = new Part();
BeanUtils.copyProperties(source, newPart);
newPart.setId(null);
newPart.setPartNo(context.getTargetPartNo());
newPart.setBasePartNo(request.getBasePartNo());
newPart.setPartSuffix(request.getPartSuffix());
newPart.setPartDesc(request.getPartDesc());
newPart.setPartSpec(request.getPartSpec());
// 新建记录保留业务状态,仅重建本次操作的审计信息。
newPart.setCreateBy(context.getSubmitBy());
newPart.setCreateDate(new Date());
newPart.setUpdateBy(null);
newPart.setUpdateDate(null);
partMapper.insert(newPart);
propertiesMapper.copyPartSubPropertiesValueHeader(context.getSite(), context.getSourcePartNo(), context.getTargetPartNo());
propertiesMapper.copyPartSubPropertiesValue(context.getSite(), context.getSourcePartNo(), context.getTargetPartNo());
// 5) 可选项只在勾选时执行;未勾选时不更新、不删除已有对应数据 - rqrq
if (Boolean.TRUE.equals(request.getCopySupplier())) {
copySupplierAndPrices(context, prices);
}
if (Boolean.TRUE.equals(request.getCopyInspectionTemplate())) {
copyInspectionTemplates(context, templateBusinessUnits);
}
log.info("物料高级复制完成 - rqrq,site={}, source={}, target={}, supplier={}, templates={}",
context.getSite(), context.getSourcePartNo(), context.getTargetPartNo(),
request.getCopySupplier(), request.getCopyInspectionTemplate());
return result;
}
/** 校验目标编码/名称/规格及登录人;输出可信的内部上下文,任一错误均在写入前终止 - rqrq */
private PartAdvancedCopyContext validateRequest(PartAdvancedCopyRequest request) {
if (request == null) {
throw new RuntimeException("复制参数不能为空");
}
request.setSite(StringUtils.trimToEmpty(request.getSite()).toUpperCase());
request.setSourcePartNo(StringUtils.trimToEmpty(request.getSourcePartNo()).toUpperCase());
request.setBasePartNo(StringUtils.trimToEmpty(request.getBasePartNo()).toUpperCase());
request.setPartSuffix(StringUtils.trimToEmpty(request.getPartSuffix()).toUpperCase());
request.setPartDesc(StringUtils.trimToEmpty(request.getPartDesc()));
request.setPartSpec(StringUtils.trimToEmpty(request.getPartSpec()));
// 工厂、源料号和基准号共同界定操作范围,任一为空都不允许继续。
if (StringUtils.isBlank(request.getSite()) || StringUtils.isBlank(request.getSourcePartNo())
|| StringUtils.isBlank(request.getBasePartNo())) {
throw new RuntimeException("工厂、源物料和目标基准料号不能为空(请前端传site)");
}
if (request.getPartSuffix().contains("-")) {
throw new RuntimeException("物料后缀不能包含 '-' 符号");
}
// 空后缀不拼接 '-';新基准号无需与源物料相同。
String targetPartNo = request.getBasePartNo() + (StringUtils.isBlank(request.getPartSuffix())
? "" : "-" + request.getPartSuffix());
if (targetPartNo.length() > 30) {
throw new RuntimeException("目标物料编码不能超过30个字符");
}
if (targetPartNo.equalsIgnoreCase(request.getSourcePartNo())) {
throw new RuntimeException("目标物料编码不能与源物料相同");
}
// 长度与实际 part 表一致,名称和规格保持原物料新增界面的必填要求。
if (StringUtils.isBlank(request.getPartDesc()) || StringUtils.isBlank(request.getPartSpec())) {
throw new RuntimeException("目标物料名称和规格型号不能为空");
}
if (request.getPartDesc().length() > 255 || request.getPartSpec().length() > 50) {
throw new RuntimeException("物料名称不能超过255个字符,规格型号不能超过50个字符");
}
SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
if (user == null || StringUtils.isBlank(user.getUsername())) {
throw new RuntimeException("无法获取当前操作人,请重新登录");
}
PartAdvancedCopyContext context = new PartAdvancedCopyContext();
context.setSite(request.getSite());
context.setSourcePartNo(request.getSourcePartNo());
context.setTargetPartNo(targetPartNo);
context.setSubmitBy(user.getUsername());
return context;
}
/**
* 默认供应商可供关系与价格替换 - rqrq
* 只处理当前工厂+默认供应商+目标料号,其他供应商保留;源关系缺失时按现有建档规则补建。
* 空价格清除目标当前价;非空价格复用价格保存服务,生成本次价格版本,不搬迁源历史。
* 由外层事务统一回滚,内部不开启独立事务。
*/
private void copySupplierAndPrices(PartAdvancedCopyContext context, List<SupplierPartTierPriceItemVo> prices) {
priceMapper.deleteSupplierPartRelation(context.getSite(), context.getSupplierNo(), context.getTargetPartNo());
int copied = copyMapper.copySupplierRelation(context);
// 部分历史物料只填过默认供应商、未建立可供关系,允许按默认值补建。
if (copied == 0) {
String currency = partMapper.getSupplierCurrency(context.getSite(), context.getSupplierNo());
String skipNew = partMapper.getPartFamilySkipNew(context.getSite(), context.getSourcePartNo());
partMapper.mergeSupplierForPart(context.getSite(), context.getSupplierNo(), context.getTargetPartNo(),
currency, "Y".equalsIgnoreCase(skipNew) ? "Y" : "N");
}
// 即使源没有价格也必须删除目标当前价,保证结果确实为“价格留空”。
if (prices == null || prices.isEmpty()) {
priceMapper.deleteCurrentTierPrice(context.getSite(), context.getSupplierNo(), context.getTargetPartNo());
return;
}
SupplierPartTierPriceSaveVo save = new SupplierPartTierPriceSaveVo();
save.setSite(context.getSite());
save.setSupplierCode(context.getSupplierNo());
save.setPartNo(context.getTargetPartNo());
save.setSubmitBy(context.getSubmitBy());
save.setPriceDate(new SimpleDateFormat("yyyy-MM-dd").format(prices.get(0).getPriceDate()));
save.setAttachmentRefs(prices.stream().map(SupplierPartTierPriceItemVo::getAttachmentRefs)
.filter(StringUtils::isNotBlank).findFirst().orElse(""));
save.setTierPriceList(prices);
// 通过另一个 Spring 服务加入当前事务,沿用当前价替换和历史版本生成规则。
priceService.saveTierPrice(save);
}
/** 各 BU 的物料模板及检验标准整体替换;不修改公共模板,失败回滚外层事务 - rqrq */
private void copyInspectionTemplates(PartAdvancedCopyContext context, List<String> businessUnits) {
// 先子表后主表清理,再按源配置重建,防止目标旧模板或旧检验标准残留。
copyMapper.deleteInspectionItems(context);
copyMapper.deleteInspectionTemplates(context);
copyMapper.deleteInspectionAttributes(context);
copyMapper.copyInspectionAttributes(context);
for (String buNo : businessUnits) {
int copied = qcMapper.copyPartAttributeTemplateMainToTarget(context.getSite(), buNo,
context.getSourcePartNo(), context.getTargetPartNo());
// 源模板在执行中丢失时不能返回成功,避免生成不完整的复制结果。
if (copied <= 0) {
throw new RuntimeException("源物料检验模板已变化,请刷新后重试");
}
qcMapper.copyPartAttributeTemplateItemToTarget(context.getSite(), buNo,
context.getSourcePartNo(), context.getTargetPartNo(), context.getSubmitBy());
}
}
}

11
src/main/java/com/xujie/modules/part/service/Impl/PartServiceImpl.java

@ -88,10 +88,13 @@ public class PartServiceImpl extends ServiceImpl<PartMapper, Part> implements IP
if (StringUtils.isBlank(model.getPartNo())) { if (StringUtils.isBlank(model.getPartNo())) {
model.setPartNo(buildPartNo(model.getBasePartNo(), model.getPartSuffix())); model.setPartNo(buildPartNo(model.getBasePartNo(), model.getPartSuffix()));
} else { } else {
// 兼容仅提交完整料号的旧调用;只有明确提供基准号时才按空后缀重新生成 - rqrq
boolean hasInputBasePartNo = StringUtils.isNotBlank(model.getBasePartNo());
if (StringUtils.isBlank(model.getBasePartNo())) { if (StringUtils.isBlank(model.getBasePartNo())) {
model.setBasePartNo(extractBasePartNo(model.getPartNo())); model.setBasePartNo(extractBasePartNo(model.getPartNo()));
} }
if (StringUtils.isNotBlank(model.getBasePartNo()) && StringUtils.isNotBlank(model.getPartSuffix())) {
// 新增的后缀允许为空;保留旧调用只传 partNo 时的完整编码 - rqrq
if (hasInputBasePartNo || StringUtils.isNotBlank(model.getPartSuffix())) {
model.setPartNo(buildPartNo(model.getBasePartNo(), model.getPartSuffix())); model.setPartNo(buildPartNo(model.getBasePartNo(), model.getPartSuffix()));
} }
} }
@ -473,19 +476,17 @@ public class PartServiceImpl extends ServiceImpl<PartMapper, Part> implements IP
model.setItem(StringUtils.trimToEmpty(model.getItem()).toUpperCase()); model.setItem(StringUtils.trimToEmpty(model.getItem()).toUpperCase());
} }
/** 基准料号必填,后缀可空;空后缀直接使用基准料号,供新增及原有复制共用 - rqrq */
private String buildPartNo(String basePartNo, String partSuffix) { private String buildPartNo(String basePartNo, String partSuffix) {
String normalizedBase = StringUtils.trimToEmpty(basePartNo).toUpperCase(); String normalizedBase = StringUtils.trimToEmpty(basePartNo).toUpperCase();
String normalizedSuffix = StringUtils.trimToEmpty(partSuffix).toUpperCase(); String normalizedSuffix = StringUtils.trimToEmpty(partSuffix).toUpperCase();
if (StringUtils.isBlank(normalizedBase)) { if (StringUtils.isBlank(normalizedBase)) {
throw new RuntimeException("基准料号不能为空!"); throw new RuntimeException("基准料号不能为空!");
} }
if (StringUtils.isBlank(normalizedSuffix)) {
throw new RuntimeException("物料后缀不能为空!");
}
if (normalizedSuffix.contains("-")) { if (normalizedSuffix.contains("-")) {
throw new RuntimeException("物料后缀不能包含 '-' 符号!"); throw new RuntimeException("物料后缀不能包含 '-' 符号!");
} }
return normalizedBase + "-" + normalizedSuffix;
return StringUtils.isBlank(normalizedSuffix) ? normalizedBase : normalizedBase + "-" + normalizedSuffix;
} }
private String extractBasePartNo(String partNo) { private String extractBasePartNo(String partNo) {

15
src/main/java/com/xujie/modules/part/vo/PartAdvancedCopyContext.java

@ -0,0 +1,15 @@
package com.xujie.modules.part.vo;
import lombok.Data;
/** 高级复制内部上下文,所有字段由服务端校验后生成,不直接接收客户端值 - rqrq */
@Data
public class PartAdvancedCopyContext {
private String site;
private String sourcePartNo;
private String targetPartNo;
/** 从源物料主表读取的默认供应商。 */
private String supplierNo;
/** 当前登录账号。 */
private String submitBy;
}

27
src/main/java/com/xujie/modules/part/vo/PartAdvancedCopyRequest.java

@ -0,0 +1,27 @@
package com.xujie.modules.part.vo;
import lombok.Data;
/**
* 物料清单高级复制入参;源料号必须是选中行,目标字段由弹框填写 - rqrq
*/
@Data
public class PartAdvancedCopyRequest {
/** 当前工厂,必须由前端传入。 */
private String site;
/** 精确源物料编码,不按基准料号寻找其他物料。 */
private String sourcePartNo;
/** 目标基准料号,允许与源物料不同。 */
private String basePartNo;
/** 目标后缀,可空;为空时不拼接连字符。 */
private String partSuffix;
/** 用户填写的目标名称、规格型号。 */
private String partDesc;
private String partSpec;
/** 只复制源物料默认供应商的可供关系和当前价格。 */
private Boolean copySupplier = false;
/** 复制源物料在当前工厂下的检验模板配置。 */
private Boolean copyInspectionTemplate = false;
/** 仅在用户确认覆盖后传 true。 */
private Boolean overwriteExisting = false;
}

10
src/main/java/com/xujie/modules/part/vo/PartAdvancedCopyResult.java

@ -0,0 +1,10 @@
package com.xujie.modules.part.vo;
import lombok.Data;
/** 高级复制结果:需要确认时尚未写入任何业务数据 - rqrq */
@Data
public class PartAdvancedCopyResult {
private String partNo;
private boolean overwriteRequired;
}

59
src/main/resources/mapper/part/mapperXml/PartAdvancedCopyMapper.xml

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xujie.modules.part.dao.PartAdvancedCopyMapper">
<!-- 精确读取源/目标,并将键范围锁保持到外层复制事务结束 - rqrq -->
<select id="selectPartForCopy" resultMap="com.xujie.modules.part.dao.PartMapper.BaseResultMap">
SELECT <include refid="com.xujie.modules.part.dao.PartMapper.BaseColumnList"/>
FROM part WITH (UPDLOCK, HOLDLOCK)
WHERE site = #{site} AND part_no = #{partNo}
</select>
<!-- 物料清单不区分 BU,因此保留源物料各 BU 的模板归属,不跨工厂复制 - rqrq -->
<select id="listTemplateBusinessUnits" resultType="java.lang.String">
SELECT DISTINCT bu_no
FROM qc_attribute_template
WHERE site = #{site} AND attribute_no = #{sourcePartNo} AND attribute_type = 'A'
</select>
<!-- 只复制主表默认供应商这一家,不复制其他供应商,也不改其他目标供应商 - rqrq -->
<insert id="copySupplierRelation">
INSERT INTO SupplierforPart
(site, supplier_no, part_no, active, currency, minOrderQty, supplier_contact, remark,
new_product_audited, need_new_product_audit, need_submit_test, minColorQty, minCartonQty, lead_time)
SELECT site, supplier_no, #{targetPartNo}, active, currency, minOrderQty, supplier_contact, remark,
new_product_audited, need_new_product_audit, need_submit_test, minColorQty, minCartonQty, lead_time
FROM SupplierforPart
WHERE site = #{site} AND supplier_no = #{supplierNo} AND part_no = #{sourcePartNo}
</insert>
<!-- 以下删除仅由勾选检验模板的事务分支调用;失败随外层事务回滚 - rqrq -->
<delete id="deleteInspectionItems">
DELETE FROM qc_attribute_template_item
WHERE site = #{site} AND attribute_no = #{targetPartNo}
</delete>
<delete id="deleteInspectionTemplates">
DELETE FROM qc_attribute_template
WHERE site = #{site} AND attribute_no = #{targetPartNo} AND attribute_type = 'A'
</delete>
<delete id="deleteInspectionAttributes">
DELETE FROM qc_part_attribute
WHERE site = #{site} AND attribute_no = #{targetPartNo} AND attribute_type = 'A'
</delete>
<!-- 复制配置字段并重建操作人/时间,不继承源物料已经发生的巡检时间 - rqrq -->
<insert id="copyInspectionAttributes">
INSERT INTO qc_part_attribute
(site, bu_no, attribute_no, attribute_type, supplier_no, attribute_remark,
default_sampling_quantity, exempt_inspection, Cycle_IPQC_Patrol_time,
create_by, create_time, update_by, update_date)
SELECT t.site, t.bu_no, #{targetPartNo}, 'A', a.supplier_no, a.attribute_remark,
a.default_sampling_quantity, a.exempt_inspection, a.Cycle_IPQC_Patrol_time,
#{submitBy}, GETDATE(), #{submitBy}, GETDATE()
FROM (
SELECT DISTINCT site, bu_no FROM qc_attribute_template
WHERE site = #{site} AND attribute_no = #{sourcePartNo} AND attribute_type = 'A'
) t
LEFT JOIN qc_part_attribute a ON a.site = t.site AND a.bu_no = t.bu_no
AND a.attribute_no = #{sourcePartNo} AND a.attribute_type = 'A'
</insert>
</mapper>

9
src/main/resources/mapper/qms/QcMapper.xml

@ -3983,8 +3983,9 @@
</if> </if>
group by a.seqno, a.orderno, J.part_no, J.part_desc, t.lotsize, a.qtyrequired, c.operation_desc, J.sku group by a.seqno, a.orderno, J.part_no, J.part_desc, t.lotsize, a.qtyrequired, c.operation_desc, J.sku
</select> </select>
<!-- 物料选择每次只从数据库返回筛选后的前500条,避免全量传输和渲染卡顿 - rqrq -->
<select id="searchPartInfo" parameterType="com.xujie.modules.qms.data.QcFAIRecordData" resultType="com.xujie.modules.qms.data.QcFAIRecordData"> <select id="searchPartInfo" parameterType="com.xujie.modules.qms.data.QcFAIRecordData" resultType="com.xujie.modules.qms.data.QcFAIRecordData">
select
select TOP (500)
part_no, part_no,
part_desc, part_desc,
item, item,
@ -4009,6 +4010,12 @@
<if test="query.cinvSourceCode != null and query.cinvSourceCode != ''"> <if test="query.cinvSourceCode != null and query.cinvSourceCode != ''">
AND cinv_source_code LIKE '%' + #{query.cinvSourceCode} + '%' AND cinv_source_code LIKE '%' + #{query.cinvSourceCode} + '%'
</if> </if>
<!-- 同一接口用于手输料号回填:完全匹配优先,其他按物料ID倒序稳定取前500条 - rqrq -->
ORDER BY
<if test="query.partNo != null and query.partNo != ''">
CASE WHEN part_no = #{query.partNo} THEN 0 ELSE 1 END,
</if>
id DESC
</select> </select>
<select id="getInterfaceTimeData" parameterType="String" resultType="com.xujie.modules.qms.data.InterfaceTimeData"> <select id="getInterfaceTimeData" parameterType="String" resultType="com.xujie.modules.qms.data.InterfaceTimeData">

Loading…
Cancel
Save