Browse Source

npc-iqc导入功能

master
qiankanghui 2 weeks ago
parent
commit
6ef2542d78
  1. 141
      src/main/java/com/xujie/modules/npcIqc/controller/NpcIqcController.java
  2. 93
      src/main/java/com/xujie/modules/npcIqc/data/NpcIqcExcelDTO.java
  3. 3
      src/main/java/com/xujie/modules/npcIqc/entity/NpcIqc.java
  4. 15
      src/main/java/com/xujie/modules/npcIqc/service/NpcIqcService.java
  5. 193
      src/main/java/com/xujie/modules/npcIqc/service/impl/NpcIqcServiceImpl.java
  6. 4
      src/main/resources/mapper/npcIqc/NpcIqcMapper.xml

141
src/main/java/com/xujie/modules/npcIqc/controller/NpcIqcController.java

@ -2,13 +2,24 @@ package com.xujie.modules.npcIqc.controller;
import com.xujie.common.utils.PageUtils;
import com.xujie.common.utils.R;
import com.xujie.modules.npcIqc.data.NpcIqcExcelDTO;
import com.xujie.modules.npcIqc.entity.NpcIqc;
import com.xujie.modules.npcIqc.service.NpcIqcService;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
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;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
@RestController
@RequestMapping("npcIqc")
@ -26,4 +37,126 @@ public class NpcIqcController {
return R.ok().put("page", page);
}
/**
* 下载NPC IQC导入模板
*/
@PostMapping("/downloadTemplate")
public ResponseEntity<Resource> downloadTemplate() {
try {
// 直接在内存中生成 Excel 模板
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("NPC IQC数据");
// 创建表头样式
CellStyle headerStyle = workbook.createCellStyle();
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerStyle.setFont(headerFont);
headerStyle.setAlignment(HorizontalAlignment.CENTER);
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置边框
headerStyle.setBorderTop(BorderStyle.THIN);
headerStyle.setBorderBottom(BorderStyle.THIN);
headerStyle.setBorderLeft(BorderStyle.THIN);
headerStyle.setBorderRight(BorderStyle.THIN);
// 设置背景色
headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// 创建表头行
Row headerRow = sheet.createRow(0);
String[] headers = {
"Inspection Type", "PUR ORDER", "Supplier", "Date Received", "Item",
"Quantity", "Sample Size", "Dim A", "Dim B", "Dim C", "Dim D", "Dim E",
"Total", "Status", "PROBLEM", "Comments", "INSPECTOR NAME",
"SUPPLIER EMAIL ADDRESS", "CA Request", "Rework Hours", "Rework Rate",
"Rework Total", "Material Cost", "Created By", "Collection", "Entry Date"
};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headerStyle);
}
// 添加示例数据行
Row dataRow1 = sheet.createRow(1);
dataRow1.createCell(0).setCellValue("STANDARD"); // Inspection Type
dataRow1.createCell(1).setCellValue("C6304"); // PUR ORDER
dataRow1.createCell(2).setCellValue("REBEC INDUSTRY (VIET NAM) CO., LTD"); // Supplier
dataRow1.createCell(3).setCellValue("21-Apr-26"); // Date Received
dataRow1.createCell(4).setCellValue("NDB-RBLU-PAD-FSC"); // Item
dataRow1.createCell(5).setCellValue(7600); // Quantity
dataRow1.createCell(6).setCellValue(200); // Sample Size
dataRow1.createCell(7).setCellValue(0); // Dim A
dataRow1.createCell(8).setCellValue(0); // Dim B
dataRow1.createCell(9).setCellValue(200); // Dim C
dataRow1.createCell(10).setCellValue(0); // Dim D
dataRow1.createCell(11).setCellValue(0); // Dim E
dataRow1.createCell(12).setCellValue("200"); // Total
dataRow1.createCell(13).setCellValue("Reject"); // Status
dataRow1.createCell(14).setCellValue("COLOUR COMES OFF ONTO YOUR HANDS"); // PROBLEM
dataRow1.createCell(15).setCellValue("RETURN SHIPMENT"); // Comments
dataRow1.createCell(16).setCellValue("MCHURCHILL"); // INSPECTOR NAME
dataRow1.createCell(17).setCellValue(""); // SUPPLIER EMAIL ADDRESS
dataRow1.createCell(18).setCellValue(""); // CA Request
dataRow1.createCell(19).setCellValue(0); // Rework Hours
dataRow1.createCell(20).setCellValue(0.79642); // Rework Rate
dataRow1.createCell(21).setCellValue(0); // Rework Total
dataRow1.createCell(22).setCellValue(0); // Material Cost
dataRow1.createCell(23).setCellValue("MCHURCHILL"); // Created By
dataRow1.createCell(24).setCellValue("1521165"); // Collection
dataRow1.createCell(25).setCellValue("2026/4/30 9:58"); // Entry Date
// 设置列宽
for (int i = 0; i < headers.length; i++) {
sheet.setColumnWidth(i, 18 * 256);
}
// 写入到字节数组
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
workbook.write(outputStream);
workbook.close();
byte[] bytes = outputStream.toByteArray();
ByteArrayResource resource = new ByteArrayResource(bytes);
String fileName = "NPC_IQC导入模板.xlsx";
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString())
.replaceAll("\\+", "%20");
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename*=UTF-8''" + encodedFileName)
.header(HttpHeaders.CONTENT_LENGTH, String.valueOf(bytes.length))
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.internalServerError().build();
}
}
/**
* 预览上传的 Excel 数据
*/
@PostMapping("/previewUpload")
public R previewUpload(@RequestParam("file") MultipartFile file) throws Exception {
List<NpcIqcExcelDTO> list = npcIqcService.previewUpload(file);
return R.ok().put("data", list);
}
/**
* 批量保存上传的数据
*/
@PostMapping("/batchSave")
public R batchSave(@RequestParam("file") MultipartFile file) {
try {
npcIqcService.batchSave(file);
return R.ok();
} catch (Exception e) {
return R.error(e.getMessage());
}
}
}

93
src/main/java/com/xujie/modules/npcIqc/data/NpcIqcExcelDTO.java

@ -0,0 +1,93 @@
package com.xujie.modules.npcIqc.data;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* NPC IQC Excel导入DTO
*/
@Data
public class NpcIqcExcelDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty(value = "Inspection Type", index = 0)
private String inspectionType;
@ExcelProperty(value = "PUR ORDER", index = 1)
private String purOrder;
@ExcelProperty(value = "Supplier", index = 2)
private String supplier;
@ExcelProperty(value = "Date Received", index = 3)
private String dateReceived;
@ExcelProperty(value = "Item", index = 4)
private String item;
@ExcelProperty(value = "Quantity", index = 5)
private Integer quantity;
@ExcelProperty(value = "Sample Size", index = 6)
private Integer sampleSize;
@ExcelProperty(value = "Dim A", index = 7)
private BigDecimal dimA;
@ExcelProperty(value = "Dim B", index = 8)
private BigDecimal dimB;
@ExcelProperty(value = "Dim C", index = 9)
private BigDecimal dimC;
@ExcelProperty(value = "Dim D", index = 10)
private BigDecimal dimD;
@ExcelProperty(value = "Dim E", index = 11)
private BigDecimal dimE;
@ExcelProperty(value = "Total", index = 12)
private String total;
@ExcelProperty(value = "Status", index = 13)
private String status;
@ExcelProperty(value = "PROBLEM", index = 14)
private String problem;
@ExcelProperty(value = "Comments", index = 15)
private String comments;
@ExcelProperty(value = "INSPECTOR NAME", index = 16)
private String inspectorName;
@ExcelProperty(value = "SUPPLIER EMAIL ADDRESS", index = 17)
private String supplierEmail;
@ExcelProperty(value = "CA Request", index = 18)
private String caRequest;
@ExcelProperty(value = "Rework Hours", index = 19)
private BigDecimal reworkHours;
@ExcelProperty(value = "Rework Rate", index = 20)
private BigDecimal reworkRate;
@ExcelProperty(value = "Rework Total", index = 21)
private BigDecimal reworkTotal;
@ExcelProperty(value = "Material Cost", index = 22)
private BigDecimal materialCost;
@ExcelProperty(value = "Created By", index = 23)
private String createdBy;
@ExcelProperty(value = "Collection", index = 24)
private String collection;
@ExcelProperty(value = "Entry Date", index = 25)
private String entryDate;
}

3
src/main/java/com/xujie/modules/npcIqc/entity/NpcIqc.java

@ -1,5 +1,6 @@
package com.xujie.modules.npcIqc.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.xujie.common.utils.QueryPage;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
@ -20,6 +21,7 @@ public class NpcIqc extends QueryPage {
private String supplierNo;
@TableField(exist = false)
private String supplierName;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ -28,6 +30,7 @@ public class NpcIqc extends QueryPage {
private String itemCode;
@TableField(exist = false)
private String itemName;
private Integer quantity;

15
src/main/java/com/xujie/modules/npcIqc/service/NpcIqcService.java

@ -2,8 +2,23 @@ package com.xujie.modules.npcIqc.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xujie.common.utils.PageUtils;
import com.xujie.modules.npcIqc.data.NpcIqcExcelDTO;
import com.xujie.modules.npcIqc.entity.NpcIqc;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
public interface NpcIqcService extends IService<NpcIqc> {
PageUtils myPage(NpcIqc npciqc);
/**
* 预览上传的 Excel 数据
*/
List<NpcIqcExcelDTO> previewUpload(MultipartFile file) throws IOException;
/**
* 批量保存上传的数据
*/
void batchSave(MultipartFile file) throws Exception;
}

193
src/main/java/com/xujie/modules/npcIqc/service/impl/NpcIqcServiceImpl.java

@ -1,19 +1,212 @@
package com.xujie.modules.npcIqc.service.impl;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xujie.common.utils.PageUtils;
import com.xujie.modules.npcIqc.data.NpcIqcExcelDTO;
import com.xujie.modules.npcIqc.entity.NpcIqc;
import com.xujie.modules.npcIqc.mapper.NpcIqcMapper;
import com.xujie.modules.npcIqc.service.NpcIqcService;
import com.xujie.modules.srm.mapper.SrmSupplierMapper;
import com.xujie.modules.sys.entity.SysUserEntity;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@Service
public class NpcIqcServiceImpl extends ServiceImpl<NpcIqcMapper, NpcIqc> implements NpcIqcService {
@Autowired
private SrmSupplierMapper srmSupplierMapper;
@Override
public PageUtils myPage(NpcIqc npciqc) {
Page<NpcIqc> page = new Page<>(npciqc.getPage(), npciqc.getLimit());
Page<NpcIqc> resultList = baseMapper.myPage(page, npciqc);
return new PageUtils(resultList);
}
@Override
public List<NpcIqcExcelDTO> previewUpload(MultipartFile file) throws IOException {
// 使用 EasyExcel 读取 Excel 数据
List<NpcIqcExcelDTO> list = EasyExcel.read(file.getInputStream())
.head(NpcIqcExcelDTO.class)
.sheet()
.doReadSync();
return list;
}
@Transactional(rollbackFor = Exception.class)
@Override
public void batchSave(MultipartFile file) throws Exception {
// 获取当前用户信息
SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
String site = user.getSite();
// 定义多种日期格式
SimpleDateFormat[] dateFormats = {
new SimpleDateFormat("dd-MMM-yy", java.util.Locale.ENGLISH), // 21-Apr-26
new SimpleDateFormat("dd-M月-yy", java.util.Locale.CHINA), // 21-4月-26 (中文月份)
new SimpleDateFormat("yyyy-MM-dd"), // 2026-04-21
new SimpleDateFormat("yyyy/MM/dd"), // 2026/04/21
new SimpleDateFormat("MM/dd/yyyy"), // 04/21/2026
new SimpleDateFormat("dd/MM/yyyy"), // 21/04/2026
new SimpleDateFormat("yyyy年MM月dd日"), // 2026年04月21日
new SimpleDateFormat("MMM dd, yyyy", java.util.Locale.ENGLISH), // Apr 21, 2026
new SimpleDateFormat("dd-MMM-yyyy", java.util.Locale.ENGLISH), // 21-Apr-2026
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), // 2026-04-21 10:30:00
new SimpleDateFormat("yyyy/MM/dd HH:mm") // 2026/04/21 10:30
};
SimpleDateFormat entryDateFormat = new SimpleDateFormat("yyyy/M/d H:mm");
// 1. 读取 Excel 数据
List<NpcIqcExcelDTO> excelList = EasyExcel.read(file.getInputStream())
.head(NpcIqcExcelDTO.class)
.sheet()
.doReadSync();
if (excelList == null || excelList.isEmpty()) {
throw new RuntimeException("导入数据不能为空!");
}
// 2. 逐行校验并转换
int rowNum = 1; // Excel 行号从1开始表头不计
for (NpcIqcExcelDTO excelDTO : excelList) {
rowNum++;
// 校验必填字段
if (!StringUtils.hasText(excelDTO.getPurOrder())) {
throw new RuntimeException("第" + rowNum + "行:PUR ORDER不能为空");
}
if (!StringUtils.hasText(excelDTO.getItem())) {
throw new RuntimeException("第" + rowNum + "行:Item不能为空");
}
// 生成 IQC 单号
srmSupplierMapper.updateTransNo(site, "IQC");
String iqcNo = srmSupplierMapper.getTransNo(site, "IQC");
// 创建 NpcIqc 实体
NpcIqc npciqc = new NpcIqc();
// 设置主键字段
npciqc.setSite(site);
npciqc.setIqcNo(iqcNo);
// 基本字段映射
npciqc.setInspectionType(excelDTO.getInspectionType());
npciqc.setPurOrder(excelDTO.getPurOrder());
// 供应商信息Excel中是完整名称暂时保存到 supplierNo 字段
// 如果后续需要关联查询建议建立供应商映射表
if (StringUtils.hasText(excelDTO.getSupplier())) {
String supplierFull = excelDTO.getSupplier().trim();
npciqc.setSupplierNo(supplierFull); // 保存完整名称到 supplier_no
npciqc.setSupplierName(supplierFull); // 同时保存到非持久化字段用于显示
}
// 解析 Date Received (支持多种格式)
if (StringUtils.hasText(excelDTO.getDateReceived())) {
Date dateReceived = parseDate(excelDTO.getDateReceived().trim(), dateFormats, rowNum, "Date Received");
npciqc.setDateReceived(dateReceived);
}
// Item 作为产品编码
if (StringUtils.hasText(excelDTO.getItem())) {
npciqc.setItemCode(excelDTO.getItem().trim());
}
npciqc.setQuantity(excelDTO.getQuantity());
npciqc.setSampleSize(excelDTO.getSampleSize());
npciqc.setDimA(excelDTO.getDimA());
npciqc.setDimB(excelDTO.getDimB());
npciqc.setDimC(excelDTO.getDimC());
npciqc.setDimD(excelDTO.getDimD());
npciqc.setDimE(excelDTO.getDimE());
npciqc.setInspectionTotal(excelDTO.getTotal());
npciqc.setInspectionStatus(excelDTO.getStatus());
npciqc.setProblem(excelDTO.getProblem());
npciqc.setComments(excelDTO.getComments());
npciqc.setInspectorName(excelDTO.getInspectorName());
npciqc.setSupplierEmail(excelDTO.getSupplierEmail());
// 解析 CA Request可能是 Yes/No true/false空值默认为 false
if (StringUtils.hasText(excelDTO.getCaRequest())) {
String caReq = excelDTO.getCaRequest().trim().toLowerCase();
npciqc.setCaRequest("yes".equals(caReq) || "true".equals(caReq));
} else {
npciqc.setCaRequest(false);
}
npciqc.setReworkHours(excelDTO.getReworkHours());
npciqc.setReworkRate(excelDTO.getReworkRate());
npciqc.setReworkTotal(excelDTO.getReworkTotal());
npciqc.setMaterialCost(excelDTO.getMaterialCost());
// 设置创建人优先使用 Excel 中的值否则使用当前用户
if (StringUtils.hasText(excelDTO.getCreatedBy())) {
npciqc.setCreatedBy(excelDTO.getCreatedBy().trim());
} else {
npciqc.setCreatedBy(user.getUsername());
}
// Collection 可能是数字或字符串
if (StringUtils.hasText(excelDTO.getCollection())) {
npciqc.setCollectionBatch(excelDTO.getCollection().trim());
}
// 解析 Entry Date (优先使用带时间的格式其次尝试其他格式)
if (StringUtils.hasText(excelDTO.getEntryDate())) {
String entryDateStr = excelDTO.getEntryDate().trim();
Date entryDate = null;
// 先尝试带时间的格式
try {
entryDate = entryDateFormat.parse(entryDateStr);
} catch (Exception e) {
// 再尝试其他日期格式
entryDate = parseDate(entryDateStr, dateFormats, rowNum, "Entry Date");
}
npciqc.setEntryDate(entryDate);
} else {
// 如果没有提供 Entry Date使用当前时间
npciqc.setEntryDate(new Date());
}
// 保存到数据库
this.save(npciqc);
}
}
/**
* 尝试使用多种日期格式解析日期字符串
* @param dateStr 日期字符串
* @param formats 日期格式数组
* @param rowNum 行号用于错误提示
* @param fieldName 字段名称用于错误提示
* @return 解析后的日期
*/
private Date parseDate(String dateStr, SimpleDateFormat[] formats, int rowNum, String fieldName) {
for (SimpleDateFormat format : formats) {
try {
return format.parse(dateStr);
} catch (Exception e) {
// 继续尝试下一个格式
}
}
throw new RuntimeException("第" + rowNum + "行:" + fieldName + "日期格式错误:" + dateStr +
",支持的格式包括:yyyy-MM-dd, dd-MMM-yy, yyyy/MM/dd, MM/dd/yyyy 等");
}
}

4
src/main/resources/mapper/npcIqc/NpcIqcMapper.xml

@ -12,7 +12,7 @@
s.supplier_name,
n.date_received,
n.item_code,
p.item_name,
p.part_desc,
n.quantity,
n.sample_size,
n.dim_a,
@ -40,7 +40,7 @@
FROM
npc_iqc n
LEFT JOIN
npc_supplier s ON n.supplier_no = s.supplier_no
srm_supplier s ON n.supplier_no = s.supplier_no
LEFT JOIN
part p ON n.item_code = p.part_no
left join

Loading…
Cancel
Save