Browse Source

2025.05.19 qms 物料属性设置导入优化

master
jiayang yue 10 months ago
parent
commit
daea1b9b71
  1. 19
      src/main/java/com/xujie/sys/modules/pms/mapper/QcMapper.java
  2. 136
      src/main/java/com/xujie/sys/modules/pms/service/Impl/QcServiceImpl.java
  3. 24
      src/main/resources/mapper/pms/QcMapper.xml

19
src/main/java/com/xujie/sys/modules/pms/mapper/QcMapper.java

@ -9,10 +9,13 @@ import com.xujie.sys.modules.pms.entity.DetailTree;
import com.xujie.sys.modules.sys.entity.SysSceneDynamicControlModelEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @description: 质量管理持久层
* @author: fengyuan_yang
@ -611,4 +614,20 @@ public interface QcMapper {
List<QcDetailInformationData> getIPQCDetailInfo(@Param("site") String site, @Param("buNo") String buNo, @Param("inspectionNo") String inspectionNo);
void updateIPQCRecord(QcFAIRecordData recordData);
@Select("SELECT attribute_no FROM qc_part_attribute WHERE site = #{site} AND bu_no = #{buNo}")
Set<String> selectAllAttributeNos(String site, String buNo);
@Select("SELECT template_id,sampling_level_no,inspection_cycle,sampling_programme_no,AQL,AC,RE," +
"site,bu_no " +
"FROM " +
"qc_template" +
" WHERE site = #{site} " +
"AND bu_no = " +
"#{buNo}")
List<QcTemplateData> selectAllTemplateData(String site, String buNo);
void batchSavePartAttribute(List<QcPartAttributeData> newAttrs);
void batchSavePartAttributeDetails(List<QcTemplateData> newDetails);
}

136
src/main/java/com/xujie/sys/modules/pms/service/Impl/QcServiceImpl.java

@ -24,9 +24,12 @@ import com.xujie.sys.modules.pms.util.HttpClientUtil;
import com.xujie.sys.modules.pms.util.ResponseData;
import com.xujie.sys.modules.report.dao.ProcedureDao;
import com.xujie.sys.modules.sys.entity.SysSceneDynamicControlModelEntity;
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
@ -43,6 +46,11 @@ import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.xml.sax.XMLReader;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletOutputStream;
@ -58,6 +66,7 @@ import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -1452,60 +1461,101 @@ public class QcServiceImpl implements QcService {
@Override
@Transactional
public void uploadPartAttributeExcel(MultipartFile file, GetParamInData paramData) {
try(InputStream is = file.getInputStream();
XSSFWorkbook workbook = new XSSFWorkbook(is)) {
DataFormatter formatter = new DataFormatter();
List<QcPartAttributeData> newAttrs = new ArrayList<>();
List<QcTemplateData> newDetails = new ArrayList<>();
// 1. 预加载已有 attributeNo 模板主数据
Set<String> existNos = new HashSet<>(
qcMapper.selectAllAttributeNos(paramData.getSite(), paramData.getBuNo())
);
Map<String, QcTemplateData> templateMap = qcMapper.selectAllTemplateData(paramData.getSite(), paramData.getBuNo())
.stream()
.collect(Collectors.toMap(QcTemplateData::getTemplateId, Function.identity()));
try (InputStream is = file.getInputStream();
XSSFWorkbook workbook = new XSSFWorkbook(is)) {
XSSFSheet sheet = workbook.getSheetAt(0);
int rows = sheet.getPhysicalNumberOfRows();
for (int rowIdx = 1; rowIdx <= sheet.getLastRowNum(); rowIdx++) {
XSSFRow row = sheet.getRow(rowIdx);
if (row == null) continue;
// 解析 partNo
String partNo = formatter.formatCellValue(row.getCell(0));
if (partNo == null || partNo.isEmpty()) {
throw new RuntimeException("第 " + (rowIdx+1) + " 行:[物料编码] 不能为空");
}
// 遍历每一行从第二行开始
for (int j = 1; j < rows; j++) {
// 实例化对象
QcPartAttributeData task = new QcPartAttributeData();
// 获得该行
XSSFRow row = sheet.getRow(j);
// 为对象赋值
task.setSite(paramData.getSite());
task.setPartNo(row.getCell(0).getRawValue());
task.setSupplierNo(row.getCell(1).getRawValue());
task.setAttributeType("A");
task.setAttributeRemark(row.getCell(2).getStringCellValue());
task.setCreateBy(paramData.getCreateBy());
// 查重
task.setAttributeNo(task.getPartNo());
QcPartAttributeData partAttributeData = qcMapper.selectPartAttributeByNo(task);
if(partAttributeData != null){
throw new RuntimeException("该物料属性已存在!");
// 如果数据库已存在跳过新增属性只插入新明细
boolean isNewAttr = existNos.add(partNo);
if (isNewAttr) {
QcPartAttributeData attr = new QcPartAttributeData();
attr.setSite(paramData.getSite());
attr.setBuNo(paramData.getBuNo());
attr.setAttributeNo(partNo);
attr.setPartNo(partNo);
attr.setSupplierNo(formatter.formatCellValue(row.getCell(1)));
attr.setAttributeType("A");
attr.setAttributeRemark(formatter.formatCellValue(row.getCell(2)));
attr.setCreateBy(paramData.getCreateBy());
newAttrs.add(attr);
}
// 新增物料属性
qcMapper.qcPartAttributeSave(task);
QcTemplateData templateData = new QcTemplateData();
templateData.setSite(task.getSite());
templateData.setAttributeNo(task.getPartNo());
// 新增物料属性中的模板
int cells = row.getLastCellNum();
for (int i = 1; i <= cells - 3; i++) {
templateData.setTemplateId(row.getCell(2 + i).getRawValue());
QcTemplateData data = qcMapper.selectTemplateData(templateData);
templateData.setSamplingLevelNo(data.getSamplingLevelNo());
templateData.setInspectionCycle(data.getInspectionCycle());
templateData.setSamplingProgrammeNo(data.getSamplingProgrammeNo());
templateData.setAql(data.getAql());
templateData.setAc(data.getAc());
templateData.setRe(data.getRe());
templateData.setAttributeType(task.getAttributeType());
// 新增
qcMapper.savePartAttributeDetails(templateData);
// 解析模板明细列 3 列以后
for (int c = 3; c < row.getLastCellNum(); c++) {
String tplId = formatter.formatCellValue(row.getCell(c));
if (tplId == null || tplId.isEmpty()) continue;
QcTemplateData master = templateMap.get(tplId);
if (master == null) {
throw new RuntimeException("找不到模板配置:" + tplId);
}
// 复制主数据字段到明细
QcTemplateData detail = new QcTemplateData();
detail.setSite(paramData.getSite());
detail.setBuNo(paramData.getBuNo());
detail.setAttributeNo(partNo);
detail.setTemplateId(master.getTemplateId());
detail.setSamplingLevelNo(master.getSamplingLevelNo());
detail.setInspectionCycle(master.getInspectionCycle());
detail.setSamplingProgrammeNo(master.getSamplingProgrammeNo());
detail.setAql(master.getAql());
detail.setAc(master.getAc());
detail.setRe(master.getRe());
detail.setAttributeType("A");
newDetails.add(detail);
}
}
} catch (IOException e) {
throw new RuntimeException("Failed to read Excel file.", e);
} catch (DataAccessException e) {
throw new RuntimeException("Database access failed.", e);
throw new RuntimeException("读取 Excel 失败", e);
}
// 4. 批量写库
// 批量插入属性
if (!newAttrs.isEmpty()) {
int attrBatch = 200; // 根据字段数和参数限制设定
for (int i = 0; i < newAttrs.size(); i += attrBatch) {
int end = Math.min(i + attrBatch, newAttrs.size());
qcMapper.batchSavePartAttribute(newAttrs.subList(i, end));
}
}
// 批量插入明细
if (!newDetails.isEmpty()) {
int detailBatch = 100;
for (int i = 0; i < newDetails.size(); i += detailBatch) {
int end = Math.min(i + detailBatch, newDetails.size());
qcMapper.batchSavePartAttributeDetails(newDetails.subList(i, end));
}
}
}
// ======================= 类别属性设置维护 =======================
/**

24
src/main/resources/mapper/pms/QcMapper.xml

@ -972,8 +972,8 @@
qa.site,
qa.bu_no,
dbo.get_bu_desc(qa.site, qa.bu_no) as buDesc,
p.PartNo as partNo,
dbo.Get_Part_DescSpec(qa.site, p.PartNo) as part_desc,
qa.attribute_no as partNo,
dbo.Get_Part_DescSpec(qa.site, qa.attribute_no) as part_desc,
p.FamilyID,
p.spec as FamilyName,
p.umid,
@ -4203,6 +4203,26 @@
VALUES
(#{site}, #{buNo}, #{templateId}, #{itemNo}, #{defaultValue}, #{maxValue,jdbcType=DECIMAL}, #{minValue,jdbcType=DECIMAL}, #{serialNo})
</insert>
<insert id="batchSavePartAttribute" parameterType="list">
INSERT INTO qc_part_attribute (attribute_no, supplier_no, attribute_remark, create_time, create_by, attribute_type, site, exempt_inspection, bu_no)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.attributeNo}, #{item.supplierNo}, #{item.attributeRemark}, getDate(), #{item.createBy}, #{item.attributeType}, #{item.site}, #{item.exemptInspection}, #{item.buNo})
</foreach>
</insert>
<insert id="batchSavePartAttributeDetails" parameterType="list">
INSERT INTO qc_attribute_template
(site, bu_no, attribute_no, template_id,
sampling_level_no, inspection_cycle,
sampling_programme_no, aql, ac, re, attribute_type)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.site}, #{item.buNo}, #{item.attributeNo},
#{item.templateId}, #{item.samplingLevelNo},
#{item.inspectionCycle}, #{item.samplingProgrammeNo},
#{item.aql}, #{item.ac}, #{item.re}, #{item.attributeType})
</foreach>
</insert>
<!-- 校验物料属性设置中的模板是否已存在 -->
<select id="getPA" parameterType="QcTemplateData" resultType="QcTemplateData">

Loading…
Cancel
Save