Browse Source

采购导入

master
han\hanst 2 weeks ago
parent
commit
a4f592a23b
  1. 80
      src/main/java/com/xujie/sys/modules/pms/controller/PartSparePurchaseImportController.java
  2. 69
      src/main/java/com/xujie/sys/modules/pms/data/PartSparePurchaseImportQueryData.java
  3. 109
      src/main/java/com/xujie/sys/modules/pms/entity/PartSparePurchaseImportEntity.java
  4. 22
      src/main/java/com/xujie/sys/modules/pms/mapper/PartSparePurchaseImportMapper.java
  5. 497
      src/main/java/com/xujie/sys/modules/pms/service/Impl/PartSparePurchaseImportServiceImpl.java
  6. 28
      src/main/java/com/xujie/sys/modules/pms/service/PartSparePurchaseImportService.java
  7. 115
      src/main/resources/mapper/pms/PartSparePurchaseImportMapper.xml

80
src/main/java/com/xujie/sys/modules/pms/controller/PartSparePurchaseImportController.java

@ -0,0 +1,80 @@
package com.xujie.sys.modules.pms.controller;
import com.xujie.sys.common.utils.PageUtils;
import com.xujie.sys.common.utils.R;
import com.xujie.sys.modules.pms.data.PartSparePurchaseImportQueryData;
import com.xujie.sys.modules.pms.entity.PartSparePurchaseImportEntity;
import com.xujie.sys.modules.pms.service.PartSparePurchaseImportService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/pms/partspare/purchaseImport")
public class PartSparePurchaseImportController {
@Autowired
private PartSparePurchaseImportService partSparePurchaseImportService;
@PostMapping("/queryPage")
public R queryPage(@RequestBody PartSparePurchaseImportQueryData data) {
PageUtils page = partSparePurchaseImportService.queryPage(data);
return R.ok()
.put("page", page)
.put("summary", partSparePurchaseImportService.querySummary(data));
}
@PostMapping("/save")
public R save(@RequestBody PartSparePurchaseImportEntity data) {
partSparePurchaseImportService.saveData(data);
return R.ok("保存成功");
}
@PostMapping("/update")
public R update(@RequestBody PartSparePurchaseImportEntity data) {
partSparePurchaseImportService.updateData(data);
return R.ok("修改成功");
}
@PostMapping("/delete")
public R delete(@RequestBody Object[] ids) {
if (ids == null || ids.length == 0) {
return R.error("请先选择需要删除的数据");
}
List<Long> idList = new ArrayList<>();
for (Object id : ids) {
if (id == null) {
continue;
}
try {
idList.add(Long.parseLong(String.valueOf(id)));
} catch (Exception e) {
return R.error("删除参数错误,ID格式无效");
}
}
if (idList.isEmpty()) {
return R.error("请先选择需要删除的数据");
}
partSparePurchaseImportService.deleteData(idList.toArray(new Long[0]));
return R.ok("删除成功");
}
@PostMapping("/importExcel")
public R importExcel(@RequestParam("file") MultipartFile file,
@RequestParam("site") String site,
@RequestParam("buNo") String buNo) {
int count = partSparePurchaseImportService.importExcel(file, site, buNo);
return R.ok("导入成功").put("count", count);
}
@GetMapping("/downloadTemplate")
public void downloadTemplate(HttpServletResponse response) {
partSparePurchaseImportService.downloadTemplate(response);
}
}

69
src/main/java/com/xujie/sys/modules/pms/data/PartSparePurchaseImportQueryData.java

@ -0,0 +1,69 @@
package com.xujie.sys.modules.pms.data;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
/**
* 备件采购订单导入记录查询条件
*/
@Data
public class PartSparePurchaseImportQueryData {
private String username;
private String site;
private String buNo;
private String supplierName;
private String currencyType;
private String orderNo;
private String itemCode;
private String itemName;
private String projectBu;
private String requestNo;
private String requestBy;
private String importBy;
private String sourceFileName;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date orderDateStart;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date orderDateEnd;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date importDateStart;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date importDateEnd;
private BigDecimal qtyStart;
private BigDecimal qtyEnd;
private BigDecimal localTotalAmountStart;
private BigDecimal localTotalAmountEnd;
private Integer page = 1;
private Integer limit = 20;
}

109
src/main/java/com/xujie/sys/modules/pms/entity/PartSparePurchaseImportEntity.java

@ -0,0 +1,109 @@
package com.xujie.sys.modules.pms.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
/**
* 备件采购订单导入记录实体
*/
@Data
@TableName("part_spare_purchase_import")
public class PartSparePurchaseImportEntity {
@TableId(type = IdType.ASSIGN_ID)
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private String site;
@TableField("bu_no")
private String buNo;
@TableField("order_date")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date orderDate;
@TableField("supplier_name")
private String supplierName;
@TableField("currency_type")
private String currencyType;
@TableField("order_no")
private String orderNo;
@TableField("item_code")
private String itemCode;
@TableField("item_name")
private String itemName;
private BigDecimal qty;
@TableField("local_unit_price")
private BigDecimal localUnitPrice;
@TableField("local_amount")
private BigDecimal localAmount;
@TableField("local_tax_amount")
private BigDecimal localTaxAmount;
@TableField("local_total_amount")
private BigDecimal localTotalAmount;
@TableField("unit_name")
private String unitName;
@TableField("project_bu")
private String projectBu;
@TableField("request_no")
private String requestNo;
@TableField("request_by")
private String requestBy;
@TableField("import_date")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date importDate;
@TableField("import_by")
private String importBy;
@TableField("source_file_name")
private String sourceFileName;
private String remark;
@TableField("created_by")
private String createdBy;
@TableField("created_date")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createdDate;
@TableField("updated_by")
private String updatedBy;
@TableField("updated_date")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updatedDate;
@TableField("is_deleted")
private String isDeleted;
}

22
src/main/java/com/xujie/sys/modules/pms/mapper/PartSparePurchaseImportMapper.java

@ -0,0 +1,22 @@
package com.xujie.sys.modules.pms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xujie.sys.modules.pms.data.PartSparePurchaseImportQueryData;
import com.xujie.sys.modules.pms.entity.PartSparePurchaseImportEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Map;
@Mapper
public interface PartSparePurchaseImportMapper extends BaseMapper<PartSparePurchaseImportEntity> {
IPage<PartSparePurchaseImportEntity> queryPage(
Page<PartSparePurchaseImportEntity> page,
@Param("query") PartSparePurchaseImportQueryData query
);
Map<String, Object> querySummary(@Param("query") PartSparePurchaseImportQueryData query);
}

497
src/main/java/com/xujie/sys/modules/pms/service/Impl/PartSparePurchaseImportServiceImpl.java

@ -0,0 +1,497 @@
package com.xujie.sys.modules.pms.service.Impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xujie.sys.common.utils.PageUtils;
import com.xujie.sys.modules.pms.data.PartSparePurchaseImportQueryData;
import com.xujie.sys.modules.pms.entity.PartSparePurchaseImportEntity;
import com.xujie.sys.modules.pms.mapper.PartSparePurchaseImportMapper;
import com.xujie.sys.modules.pms.service.PartSparePurchaseImportService;
import com.xujie.sys.modules.sys.entity.SysUserEntity;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
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.net.URLEncoder;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAccessor;
import java.util.*;
@Slf4j
@Service
public class PartSparePurchaseImportServiceImpl extends ServiceImpl<PartSparePurchaseImportMapper, PartSparePurchaseImportEntity>
implements PartSparePurchaseImportService {
private static final int IMPORT_BATCH_SIZE = 100;
@Override
public PageUtils queryPage(PartSparePurchaseImportQueryData queryData) {
queryData.setUsername(getCurrentUsername());
queryData.setBuNo(normalizeBuNo(queryData.getSite(), queryData.getBuNo()));
long pageNo = queryData.getPage() == null || queryData.getPage() < 1 ? 1 : queryData.getPage();
long pageSize = queryData.getLimit() == null || queryData.getLimit() < 1 ? 20 : queryData.getLimit();
IPage<PartSparePurchaseImportEntity> page = baseMapper.queryPage(
new Page<>(pageNo, pageSize),
queryData
);
return new PageUtils(page);
}
@Override
public Map<String, BigDecimal> querySummary(PartSparePurchaseImportQueryData queryData) {
queryData.setUsername(getCurrentUsername());
queryData.setBuNo(normalizeBuNo(queryData.getSite(), queryData.getBuNo()));
Map<String, Object> summary = baseMapper.querySummary(queryData);
Map<String, BigDecimal> result = new HashMap<>(2);
result.put("totalQty", toBigDecimal(summary == null ? null : summary.get("totalQty")));
result.put("totalLocalTotalAmount", toBigDecimal(summary == null ? null : summary.get("totalLocalTotalAmount")));
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveData(PartSparePurchaseImportEntity data) {
data.setBuNo(normalizeBuNo(data.getSite(), data.getBuNo()));
validateBaseData(data);
String username = getCurrentUsername();
Date now = new Date();
data.setId(null);
data.setImportDate(now);
data.setImportBy(username);
data.setCreatedBy(username);
data.setCreatedDate(now);
data.setUpdatedBy(username);
data.setUpdatedDate(now);
data.setIsDeleted("0");
this.save(data);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateData(PartSparePurchaseImportEntity data) {
if (data.getId() == null) {
throw new RuntimeException("参数错误:记录ID不能为空");
}
data.setBuNo(normalizeBuNo(data.getSite(), data.getBuNo()));
validateBaseData(data);
PartSparePurchaseImportEntity dbData = this.getOne(
new LambdaQueryWrapper<PartSparePurchaseImportEntity>()
.eq(PartSparePurchaseImportEntity::getId, data.getId())
.eq(PartSparePurchaseImportEntity::getIsDeleted, "0")
);
if (dbData == null) {
throw new RuntimeException("记录不存在或已删除,请刷新后重试");
}
dbData.setSite(data.getSite());
dbData.setBuNo(data.getBuNo());
dbData.setOrderDate(data.getOrderDate());
dbData.setSupplierName(data.getSupplierName());
dbData.setCurrencyType(data.getCurrencyType());
dbData.setOrderNo(data.getOrderNo());
dbData.setItemCode(data.getItemCode());
dbData.setItemName(data.getItemName());
dbData.setQty(data.getQty());
dbData.setLocalUnitPrice(data.getLocalUnitPrice());
dbData.setLocalAmount(data.getLocalAmount());
dbData.setLocalTaxAmount(data.getLocalTaxAmount());
dbData.setLocalTotalAmount(data.getLocalTotalAmount());
dbData.setUnitName(data.getUnitName());
dbData.setProjectBu(data.getProjectBu());
dbData.setRequestNo(data.getRequestNo());
dbData.setRequestBy(data.getRequestBy());
dbData.setRemark(data.getRemark());
dbData.setUpdatedBy(getCurrentUsername());
dbData.setUpdatedDate(new Date());
this.updateById(dbData);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteData(Long[] ids) {
if (ids == null || ids.length == 0) {
throw new RuntimeException("请先选择需要删除的数据");
}
List<Long> idList = Arrays.asList(ids);
long existsCount = this.lambdaQuery()
.in(PartSparePurchaseImportEntity::getId, idList)
.count();
if (existsCount == 0) {
throw new RuntimeException("记录不存在或已删除,请刷新后重试");
}
boolean success = this.removeByIds(idList);
if (!success) {
throw new RuntimeException("删除失败,请稍后重试");
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public int importExcel(MultipartFile file, String site, String buNo) {
if (!StringUtils.hasText(site)) {
throw new RuntimeException("工厂不能为空");
}
String normalizedBuNo = normalizeBuNo(site, buNo);
if (!StringUtils.hasText(normalizedBuNo)) {
throw new RuntimeException("BU不能为空");
}
if (file == null || file.isEmpty()) {
throw new RuntimeException("上传文件不能为空");
}
String fileName = file.getOriginalFilename();
if (!StringUtils.hasText(fileName)) {
throw new RuntimeException("上传文件名不能为空");
}
String lowerName = fileName.toLowerCase();
if (!lowerName.endsWith(".xlsx") && !lowerName.endsWith(".xls")) {
throw new RuntimeException("请上传Excel文件(.xlsx 或 .xls)");
}
String username = getCurrentUsername();
Date importTime = new Date();
List<PartSparePurchaseImportEntity> rows = parseExcel(file, site, normalizedBuNo, fileName, username, importTime);
if (rows.isEmpty()) {
throw new RuntimeException("未读取到有效导入数据");
}
this.saveBatch(rows, IMPORT_BATCH_SIZE);
return rows.size();
}
@Override
public void downloadTemplate(HttpServletResponse response) {
try (Workbook workbook = new XSSFWorkbook()) {
Sheet sheet = workbook.createSheet("采购订单导入");
Row header = sheet.createRow(0);
String[] headers = {
"日期", "供应商", "币种", "订单编号", "存货编码", "存货名称", "数量",
"本币单价", "本币金额", "本币税额", "本币价税合计", "单位",
"项目目录(BU)", "请单编号", "请购员"
};
for (int i = 0; i < headers.length; i++) {
Cell cell = header.createCell(i);
cell.setCellValue(headers[i]);
sheet.setColumnWidth(i, 18 * 256);
}
Row sample = sheet.createRow(1);
sample.createCell(0).setCellValue("2026-04-02");
sample.createCell(1).setCellValue("南海发展工程有限公司");
sample.createCell(2).setCellValue("人民币");
sample.createCell(3).setCellValue("CPMFL2026040019");
sample.createCell(4).setCellValue("401.000000");
sample.createCell(5).setCellValue("叉车手柄切片");
sample.createCell(6).setCellValue("3");
sample.createCell(7).setCellValue("1");
sample.createCell(8).setCellValue("3");
sample.createCell(9).setCellValue("0.39");
sample.createCell(10).setCellValue("3.39");
sample.createCell(11).setCellValue("起");
sample.createCell(12).setCellValue("39");
sample.createCell(13).setCellValue("CPMFL2026040019");
sample.createCell(14).setCellValue("段晓浩");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("UTF-8");
response.setHeader(
"Content-Disposition",
"attachment;filename=" + URLEncoder.encode("采购订单导入模板.xlsx", "UTF-8")
);
workbook.write(response.getOutputStream());
response.flushBuffer();
} catch (Exception e) {
log.error("下载采购订单导入模板失败: {}", e.getMessage(), e);
throw new RuntimeException("下载模板失败: " + e.getMessage());
}
}
private List<PartSparePurchaseImportEntity> parseExcel(
MultipartFile file,
String site,
String buNo,
String sourceFileName,
String username,
Date importTime
) {
List<PartSparePurchaseImportEntity> result = new ArrayList<>();
DataFormatter formatter = new DataFormatter();
try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) {
Sheet sheet = workbook.getSheetAt(0);
if (sheet == null) {
return result;
}
Row headerRow = sheet.getRow(0);
Map<String, Integer> headerMap = buildHeaderMap(headerRow, formatter);
HeaderIndex index = resolveHeaderIndex(headerMap);
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null || isEmptyRow(row, formatter)) {
continue;
}
PartSparePurchaseImportEntity entity = new PartSparePurchaseImportEntity();
entity.setSite(site);
entity.setBuNo(buNo);
entity.setOrderDate(parseDateCell(row.getCell(index.orderDate), formatter));
entity.setSupplierName(getCellString(row.getCell(index.supplierName), formatter));
entity.setCurrencyType(getCellString(row.getCell(index.currencyType), formatter));
entity.setOrderNo(getCellString(row.getCell(index.orderNo), formatter));
entity.setItemCode(getCellString(row.getCell(index.itemCode), formatter));
entity.setItemName(getCellString(row.getCell(index.itemName), formatter));
entity.setQty(parseDecimal(row.getCell(index.qty), formatter));
entity.setLocalUnitPrice(parseDecimal(row.getCell(index.localUnitPrice), formatter));
entity.setLocalAmount(parseDecimal(row.getCell(index.localAmount), formatter));
entity.setLocalTaxAmount(parseDecimal(row.getCell(index.localTaxAmount), formatter));
entity.setLocalTotalAmount(parseDecimal(row.getCell(index.localTotalAmount), formatter));
entity.setUnitName(getCellString(row.getCell(index.unitName), formatter));
entity.setProjectBu(getCellString(row.getCell(index.projectBu), formatter));
entity.setRequestNo(getCellString(row.getCell(index.requestNo), formatter));
entity.setRequestBy(getCellString(row.getCell(index.requestBy), formatter));
entity.setImportDate(importTime);
entity.setImportBy(username);
entity.setSourceFileName(sourceFileName);
entity.setCreatedBy(username);
entity.setCreatedDate(importTime);
entity.setUpdatedBy(username);
entity.setUpdatedDate(importTime);
entity.setIsDeleted("0");
// 至少有订单编号或存货编码才作为有效行
if (!StringUtils.hasText(entity.getOrderNo()) && !StringUtils.hasText(entity.getItemCode())) {
continue;
}
validateBaseData(entity);
result.add(entity);
}
} catch (IOException e) {
throw new RuntimeException("解析Excel失败: " + e.getMessage());
} catch (Exception e) {
throw new RuntimeException("导入失败: " + e.getMessage());
}
return result;
}
private Map<String, Integer> buildHeaderMap(Row headerRow, DataFormatter formatter) {
Map<String, Integer> headerMap = new HashMap<>();
if (headerRow == null) {
return headerMap;
}
for (int i = 0; i < headerRow.getLastCellNum(); i++) {
String value = normalizeHeader(getCellString(headerRow.getCell(i), formatter));
if (StringUtils.hasText(value)) {
headerMap.put(value, i);
}
}
return headerMap;
}
private HeaderIndex resolveHeaderIndex(Map<String, Integer> headerMap) {
HeaderIndex index = new HeaderIndex();
index.orderDate = resolveColumn(headerMap, 1, "日期", "订单日期");
index.supplierName = resolveColumn(headerMap, 2, "供应商", "供应商名称");
index.currencyType = resolveColumn(headerMap, 3, "币种");
index.orderNo = resolveColumn(headerMap, 4, "订单编号", "采购订单号");
index.itemCode = resolveColumn(headerMap, 5, "存货编码", "物料编码");
index.itemName = resolveColumn(headerMap, 6, "存货名称", "物料名称");
index.qty = resolveColumn(headerMap, 7, "数量", "订单数量");
index.localUnitPrice = resolveColumn(headerMap, 8, "本币单价");
index.localAmount = resolveColumn(headerMap, 9, "本币金额");
index.localTaxAmount = resolveColumn(headerMap, 10, "本币税额");
index.localTotalAmount = resolveColumn(headerMap, 11, "本币价税合计");
index.unitName = resolveColumn(headerMap, 12, "单位");
index.projectBu = resolveColumn(headerMap, 13, "项目目录(bu)", "项目目录(bu)", "项目目录bu", "项目目录");
index.requestNo = resolveColumn(headerMap, 14, "请单编号", "请购单号", "请购编号");
index.requestBy = resolveColumn(headerMap, 15, "请购员", "请购人", "采购员");
return index;
}
private Integer resolveColumn(Map<String, Integer> headerMap, int fallbackIndex, String... aliases) {
for (String alias : aliases) {
Integer index = headerMap.get(normalizeHeader(alias));
if (index != null) {
return index;
}
}
return fallbackIndex;
}
private String normalizeHeader(String header) {
if (!StringUtils.hasText(header)) {
return "";
}
return header.trim()
.replace("(", "(")
.replace(")", ")")
.replace(" ", "")
.toLowerCase();
}
private boolean isEmptyRow(Row row, DataFormatter formatter) {
int cells = row.getLastCellNum();
for (int i = 0; i < cells; i++) {
if (StringUtils.hasText(getCellString(row.getCell(i), formatter))) {
return false;
}
}
return true;
}
private String getCellString(Cell cell, DataFormatter formatter) {
if (cell == null) {
return "";
}
return formatter.formatCellValue(cell).trim();
}
private BigDecimal parseDecimal(Cell cell, DataFormatter formatter) {
String value = getCellString(cell, formatter);
if (!StringUtils.hasText(value)) {
return null;
}
String normalized = value.replace(",", "").replace(" ", "");
if (!StringUtils.hasText(normalized)) {
return null;
}
try {
return new BigDecimal(normalized);
} catch (Exception e) {
throw new RuntimeException("数值格式错误: " + value);
}
}
private Date parseDateCell(Cell cell, DataFormatter formatter) {
if (cell == null) {
return null;
}
if (cell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue();
}
String value = getCellString(cell, formatter);
if (!StringUtils.hasText(value)) {
return null;
}
return parseDateString(value);
}
private Date parseDateString(String value) {
List<DateTimeFormatter> formatters = Arrays.asList(
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"),
DateTimeFormatter.ofPattern("yyyy-MM-dd"),
DateTimeFormatter.ofPattern("yyyy/MM/dd"),
DateTimeFormatter.ofPattern("yyyyMMdd"),
new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ofPattern("yyyy-M-d"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy/M/d"))
.toFormatter()
);
for (DateTimeFormatter formatter : formatters) {
try {
TemporalAccessor accessor = formatter.parseBest(value, LocalDateTime::from, LocalDate::from);
if (accessor instanceof LocalDateTime) {
return Date.from(((LocalDateTime) accessor).atZone(ZoneId.systemDefault()).toInstant());
}
if (accessor instanceof LocalDate) {
return Date.from(((LocalDate) accessor).atStartOfDay(ZoneId.systemDefault()).toInstant());
}
} catch (DateTimeParseException ignored) {
}
}
throw new RuntimeException("日期格式错误: " + value);
}
private BigDecimal toBigDecimal(Object value) {
if (value == null) {
return BigDecimal.ZERO;
}
if (value instanceof BigDecimal) {
return (BigDecimal) value;
}
if (value instanceof Number) {
return new BigDecimal(value.toString());
}
String text = value.toString();
if (!StringUtils.hasText(text)) {
return BigDecimal.ZERO;
}
try {
return new BigDecimal(text.trim());
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
private String normalizeBuNo(String site, String buNo) {
if (!StringUtils.hasText(buNo)) {
return buNo;
}
String siteText = StringUtils.hasText(site) ? site.trim() : "";
String buText = buNo.trim();
if (!StringUtils.hasText(siteText)) {
return buText;
}
String prefix = siteText + "_";
if (buText.startsWith(prefix)) {
return buText.substring(prefix.length());
}
return buText;
}
private void validateBaseData(PartSparePurchaseImportEntity data) {
if (!StringUtils.hasText(data.getSite())) {
throw new RuntimeException("工厂不能为空");
}
if (!StringUtils.hasText(data.getBuNo())) {
throw new RuntimeException("BU不能为空");
}
if (!StringUtils.hasText(data.getOrderNo())) {
throw new RuntimeException("订单编号不能为空");
}
if (!StringUtils.hasText(data.getItemCode())) {
throw new RuntimeException("存货编码不能为空");
}
if (data.getQty() != null && data.getQty().compareTo(BigDecimal.ZERO) < 0) {
throw new RuntimeException("数量不能小于0");
}
}
private String getCurrentUsername() {
Object principal = SecurityUtils.getSubject().getPrincipal();
if (principal instanceof SysUserEntity) {
return ((SysUserEntity) principal).getUsername();
}
return "system";
}
private static class HeaderIndex {
private Integer orderDate;
private Integer supplierName;
private Integer currencyType;
private Integer orderNo;
private Integer itemCode;
private Integer itemName;
private Integer qty;
private Integer localUnitPrice;
private Integer localAmount;
private Integer localTaxAmount;
private Integer localTotalAmount;
private Integer unitName;
private Integer projectBu;
private Integer requestNo;
private Integer requestBy;
}
}

28
src/main/java/com/xujie/sys/modules/pms/service/PartSparePurchaseImportService.java

@ -0,0 +1,28 @@
package com.xujie.sys.modules.pms.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xujie.sys.common.utils.PageUtils;
import com.xujie.sys.modules.pms.data.PartSparePurchaseImportQueryData;
import com.xujie.sys.modules.pms.entity.PartSparePurchaseImportEntity;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Map;
public interface PartSparePurchaseImportService extends IService<PartSparePurchaseImportEntity> {
PageUtils queryPage(PartSparePurchaseImportQueryData queryData);
Map<String, BigDecimal> querySummary(PartSparePurchaseImportQueryData queryData);
void saveData(PartSparePurchaseImportEntity data);
void updateData(PartSparePurchaseImportEntity data);
void deleteData(Long[] ids);
int importExcel(MultipartFile file, String site, String buNo);
void downloadTemplate(HttpServletResponse response);
}

115
src/main/resources/mapper/pms/PartSparePurchaseImportMapper.xml

@ -0,0 +1,115 @@
<?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.sys.modules.pms.mapper.PartSparePurchaseImportMapper">
<sql id="queryWhereClause">
<where>
a.is_deleted = '0'
and a.site in (select site from eam_access_site where username = #{query.username})
and (a.site + '-' + a.bu_no) in (select * from dbo.query_bu(#{query.username}))
<if test="query.site != null and query.site != ''">
and a.site = #{query.site}
</if>
<if test="query.buNo != null and query.buNo != ''">
and a.bu_no = #{query.buNo}
</if>
<if test="query.supplierName != null and query.supplierName != ''">
and a.supplier_name like '%' + #{query.supplierName} + '%'
</if>
<if test="query.currencyType != null and query.currencyType != ''">
and a.currency_type = #{query.currencyType}
</if>
<if test="query.orderNo != null and query.orderNo != ''">
and a.order_no like '%' + #{query.orderNo} + '%'
</if>
<if test="query.itemCode != null and query.itemCode != ''">
and a.item_code like '%' + #{query.itemCode} + '%'
</if>
<if test="query.itemName != null and query.itemName != ''">
and a.item_name like '%' + #{query.itemName} + '%'
</if>
<if test="query.projectBu != null and query.projectBu != ''">
and a.project_bu like '%' + #{query.projectBu} + '%'
</if>
<if test="query.requestNo != null and query.requestNo != ''">
and a.request_no like '%' + #{query.requestNo} + '%'
</if>
<if test="query.requestBy != null and query.requestBy != ''">
and a.request_by like '%' + #{query.requestBy} + '%'
</if>
<if test="query.importBy != null and query.importBy != ''">
and a.import_by like '%' + #{query.importBy} + '%'
</if>
<if test="query.sourceFileName != null and query.sourceFileName != ''">
and a.source_file_name like '%' + #{query.sourceFileName} + '%'
</if>
<if test="query.orderDateStart != null">
and a.order_date &gt;= #{query.orderDateStart}
</if>
<if test="query.orderDateEnd != null">
and a.order_date &lt;= #{query.orderDateEnd}
</if>
<if test="query.importDateStart != null">
and a.import_date &gt;= #{query.importDateStart}
</if>
<if test="query.importDateEnd != null">
and a.import_date &lt;= #{query.importDateEnd}
</if>
<if test="query.qtyStart != null">
and a.qty &gt;= #{query.qtyStart}
</if>
<if test="query.qtyEnd != null">
and a.qty &lt;= #{query.qtyEnd}
</if>
<if test="query.localTotalAmountStart != null">
and a.local_total_amount &gt;= #{query.localTotalAmountStart}
</if>
<if test="query.localTotalAmountEnd != null">
and a.local_total_amount &lt;= #{query.localTotalAmountEnd}
</if>
</where>
</sql>
<select id="queryPage" resultType="com.xujie.sys.modules.pms.entity.PartSparePurchaseImportEntity">
select
a.id,
a.site,
a.bu_no as buNo,
a.order_date as orderDate,
a.supplier_name as supplierName,
a.currency_type as currencyType,
a.order_no as orderNo,
a.item_code as itemCode,
a.item_name as itemName,
a.qty,
a.local_unit_price as localUnitPrice,
a.local_amount as localAmount,
a.local_tax_amount as localTaxAmount,
a.local_total_amount as localTotalAmount,
a.unit_name as unitName,
a.project_bu as projectBu,
a.request_no as requestNo,
a.request_by as requestBy,
a.import_date as importDate,
a.import_by as importBy,
a.source_file_name as sourceFileName,
a.remark,
a.created_by as createdBy,
a.created_date as createdDate,
a.updated_by as updatedBy,
a.updated_date as updatedDate,
a.is_deleted as isDeleted
from part_spare_purchase_import a
<include refid="queryWhereClause"/>
order by a.import_date desc, a.id desc
</select>
<select id="querySummary" resultType="java.util.HashMap">
select
ISNULL(sum(a.qty), 0) as totalQty,
ISNULL(sum(a.local_total_amount), 0) as totalLocalTotalAmount
from part_spare_purchase_import a
<include refid="queryWhereClause"/>
</select>
</mapper>
Loading…
Cancel
Save