Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X
This commit is contained in:
@@ -10,7 +10,9 @@ import java.math.BigDecimal;
|
|||||||
* 采购计划到货导入模板(对应到货 Excel,一行一卷)
|
* 采购计划到货导入模板(对应到货 Excel,一行一卷)
|
||||||
*
|
*
|
||||||
* 列:日期 牌号 规格 卷号 单卷重量 车号 数量 件数 销售 钢厂到站
|
* 列:日期 牌号 规格 卷号 单卷重量 车号 数量 件数 销售 钢厂到站
|
||||||
* 注:车号/数量/件数 为合并单元格,仅首行有值,导入时向下填充。
|
* 注:车号/数量/件数 为合并单元格,仅首行有值;
|
||||||
|
* 数量/件数 使用 String 类型读取以避开 EasyExcel 对合并空白格的数值转换异常,
|
||||||
|
* 在 Service 层统一 parse 并校验。
|
||||||
*
|
*
|
||||||
* @author klp
|
* @author klp
|
||||||
* @date 2026-06-22
|
* @date 2026-06-22
|
||||||
@@ -37,11 +39,13 @@ public class ErpPurchasePlanDeliveryImportVo {
|
|||||||
@ExcelProperty("车号")
|
@ExcelProperty("车号")
|
||||||
private String truckNo;
|
private String truckNo;
|
||||||
|
|
||||||
|
/** 整车总重(合并单元格,仅首行有值;读为 String 以兼容空白/点号等占位符) */
|
||||||
@ExcelProperty("数量")
|
@ExcelProperty("数量")
|
||||||
private BigDecimal truckWeight;
|
private String truckWeight;
|
||||||
|
|
||||||
|
/** 整车件数(合并单元格,仅首行有值;读为 String 以兼容空白/点号等占位符) */
|
||||||
@ExcelProperty("件数")
|
@ExcelProperty("件数")
|
||||||
private Integer pieceCount;
|
private String pieceCount;
|
||||||
|
|
||||||
@ExcelProperty("销售")
|
@ExcelProperty("销售")
|
||||||
private String salesCode;
|
private String salesCode;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.alibaba.excel.event.AnalysisEventListener;
|
|||||||
import com.alibaba.excel.exception.ExcelDataConvertException;
|
import com.alibaba.excel.exception.ExcelDataConvertException;
|
||||||
import com.klp.common.exception.ServiceException;
|
import com.klp.common.exception.ServiceException;
|
||||||
import com.klp.erp.domain.vo.ErpPurchasePlanDeliveryImportVo;
|
import com.klp.erp.domain.vo.ErpPurchasePlanDeliveryImportVo;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -58,6 +59,11 @@ public class ErpDeliveryExcelListener extends AnalysisEventListener<ErpPurchaseP
|
|||||||
}
|
}
|
||||||
if (exception instanceof ExcelDataConvertException) {
|
if (exception instanceof ExcelDataConvertException) {
|
||||||
ExcelDataConvertException e = (ExcelDataConvertException) exception;
|
ExcelDataConvertException e = (ExcelDataConvertException) exception;
|
||||||
|
// 合并单元格会在被合并的下方行留下空白/点号等占位符;
|
||||||
|
// 数量/件数已改为 String 读取,此处仅处理单卷重量等仍为数值型的列
|
||||||
|
if (isBlankCell(e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
String head = headMap != null ? headMap.get(e.getColumnIndex()) : null;
|
String head = headMap != null ? headMap.get(e.getColumnIndex()) : null;
|
||||||
String headName = head != null ? head : ("第" + (e.getColumnIndex() + 1) + "列");
|
String headName = head != null ? head : ("第" + (e.getColumnIndex() + 1) + "列");
|
||||||
errors.add("第" + (e.getRowIndex() + 1) + "行「" + headName + "」列的值无法识别(应为数字)");
|
errors.add("第" + (e.getRowIndex() + 1) + "行「" + headName + "」列的值无法识别(应为数字)");
|
||||||
@@ -67,6 +73,34 @@ public class ErpDeliveryExcelListener extends AnalysisEventListener<ErpPurchaseP
|
|||||||
// 转换类异常不抛出,继续解析以收集所有错误行
|
// 转换类异常不抛出,继续解析以收集所有错误行
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 判断转换失败的单元格是否为空(合并单元格残留的空白/占位符) */
|
||||||
|
private boolean isBlankCell(ExcelDataConvertException e) {
|
||||||
|
try {
|
||||||
|
com.alibaba.excel.metadata.data.CellData<?> cd = e.getCellData();
|
||||||
|
if (cd == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (cd.getType() == com.alibaba.excel.enums.CellDataTypeEnum.EMPTY) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String s = cd.getStringValue();
|
||||||
|
// StringUtils.isBlank 覆盖全角空格、不间断空格等 Unicode 空白
|
||||||
|
// 额外忽略 "." 等 Excel 合并单元格常见占位符
|
||||||
|
if (StringUtils.isBlank(s)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (s != null) {
|
||||||
|
String t = s.trim();
|
||||||
|
if (t.isEmpty() || ".".equals(t) || ".".equals(t) || "/".equals(t) || "-".equals(t)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||||
// no-op
|
// no-op
|
||||||
|
|||||||
@@ -389,23 +389,21 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
|
|||||||
batch.setFileName(StringUtils.isNotBlank(fileName) ? fileName : "到货表");
|
batch.setFileName(StringUtils.isNotBlank(fileName) ? fileName : "到货表");
|
||||||
deliveryBatchMapper.insert(batch);
|
deliveryBatchMapper.insert(batch);
|
||||||
|
|
||||||
// 6) 合并单元格向下填充 + 单位换算 + 落库 + WMS到货标记
|
// 6) 落库 + 单位换算 + WMS到货标记
|
||||||
|
// 合并单元格:车号(F)几卷共用一车 → 向下填充让每卷都带车号;
|
||||||
|
// 数量(G=整车总重)/件数(H=整车件数) 是「整车合计」,只记在该车首行(其余行留空),
|
||||||
|
// 避免按行重复计数(用户:一共3件,不是每行3件)。
|
||||||
String lastTruckNo = null;
|
String lastTruckNo = null;
|
||||||
BigDecimal lastTruckWeight = null;
|
|
||||||
Integer lastPieceCount = null;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int matched = 0;
|
int matched = 0;
|
||||||
for (ErpPurchasePlanDeliveryImportVo row : rows) {
|
for (ErpPurchasePlanDeliveryImportVo row : rows) {
|
||||||
if (StringUtils.isNotBlank(row.getTruckNo())) {
|
if (StringUtils.isNotBlank(row.getTruckNo())) {
|
||||||
lastTruckNo = row.getTruckNo();
|
lastTruckNo = row.getTruckNo();
|
||||||
lastTruckWeight = row.getTruckWeight();
|
|
||||||
lastPieceCount = row.getPieceCount();
|
|
||||||
}
|
}
|
||||||
if (StringUtils.isBlank(row.getCoilNo()) && row.getCoilWeight() == null) {
|
if (StringUtils.isBlank(row.getCoilNo()) && row.getCoilWeight() == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
boolean arrived = StringUtils.isNotBlank(row.getCoilNo()) && wmsArrivedSet.contains(normCoil(row.getCoilNo()));
|
boolean arrived = StringUtils.isNotBlank(row.getCoilNo()) && wmsArrivedSet.contains(normCoil(row.getCoilNo()));
|
||||||
BigDecimal truckWeight = row.getTruckWeight() != null ? row.getTruckWeight() : lastTruckWeight;
|
|
||||||
ErpPurchasePlanDelivery d = new ErpPurchasePlanDelivery();
|
ErpPurchasePlanDelivery d = new ErpPurchasePlanDelivery();
|
||||||
d.setPlanId(planId);
|
d.setPlanId(planId);
|
||||||
d.setBatchId(batch.getBatchId());
|
d.setBatchId(batch.getBatchId());
|
||||||
@@ -415,9 +413,12 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
|
|||||||
d.setSpec(row.getSpec());
|
d.setSpec(row.getSpec());
|
||||||
d.setCoilNo(row.getCoilNo());
|
d.setCoilNo(row.getCoilNo());
|
||||||
d.setCoilWeight(convertWeight(row.getCoilWeight(), kgConverted));
|
d.setCoilWeight(convertWeight(row.getCoilWeight(), kgConverted));
|
||||||
|
// 车号:每卷归属的车(向下填充)
|
||||||
d.setTruckNo(StringUtils.isNotBlank(row.getTruckNo()) ? row.getTruckNo() : lastTruckNo);
|
d.setTruckNo(StringUtils.isNotBlank(row.getTruckNo()) ? row.getTruckNo() : lastTruckNo);
|
||||||
d.setTruckWeight(convertWeight(truckWeight, kgConverted));
|
// 整车总重 / 件数:整车合计,仅该车首行有值,不向下填充
|
||||||
d.setPieceCount(row.getPieceCount() != null ? row.getPieceCount() : lastPieceCount);
|
// 数量/件数 作为 String 读取以兼容合并单元格的空白/点号等占位符,在此 parse
|
||||||
|
d.setTruckWeight(convertWeight(parseDecimal(row.getTruckWeight()), kgConverted));
|
||||||
|
d.setPieceCount(parseInteger(row.getPieceCount()));
|
||||||
d.setSalesCode(row.getSalesCode());
|
d.setSalesCode(row.getSalesCode());
|
||||||
d.setArrivalStation(row.getArrivalStation());
|
d.setArrivalStation(row.getArrivalStation());
|
||||||
deliveryMapper.insert(d);
|
deliveryMapper.insert(d);
|
||||||
@@ -458,6 +459,47 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
|
|||||||
return kgConverted ? v.divide(KG_TO_T, 3, RoundingMode.HALF_UP) : v;
|
return kgConverted ? v.divide(KG_TO_T, 3, RoundingMode.HALF_UP) : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将数量列 String 转为 BigDecimal,兼容合并单元格中的空白、点号、横线等占位符。
|
||||||
|
* 无法解析时返回 null,由 Service 按合并单元格语义(仅首行有值)处理。
|
||||||
|
*/
|
||||||
|
private static BigDecimal parseDecimal(String s) {
|
||||||
|
if (StringUtils.isBlank(s)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String t = s.trim();
|
||||||
|
// 合并单元格常见占位符:半角/全角点、横线、斜线
|
||||||
|
if (".".equals(t) || ".".equals(t) || "-".equals(t) || "--".equals(t)
|
||||||
|
|| "/".equals(t) || "\\".equals(t) || "、".equals(t)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new BigDecimal(t);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将件数列 String 转为 Integer,兼容合并单元格中的空白、点号、横线等占位符。
|
||||||
|
* 无法解析时返回 null。
|
||||||
|
*/
|
||||||
|
private static Integer parseInteger(String s) {
|
||||||
|
if (StringUtils.isBlank(s)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String t = s.trim();
|
||||||
|
if (".".equals(t) || ".".equals(t) || "-".equals(t) || "--".equals(t)
|
||||||
|
|| "/".equals(t) || "\\".equals(t) || "、".equals(t)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new BigDecimal(t).intValue();
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ErpPurchasePlanDeliveryVo> queryDeliveryList(Long planId) {
|
public List<ErpPurchasePlanDeliveryVo> queryDeliveryList(Long planId) {
|
||||||
return deliveryMapper.selectVoList(Wrappers.lambdaQuery(ErpPurchasePlanDelivery.class)
|
return deliveryMapper.selectVoList(Wrappers.lambdaQuery(ErpPurchasePlanDelivery.class)
|
||||||
|
|||||||
@@ -148,7 +148,6 @@
|
|||||||
<el-table-column label="卷号" prop="coilNo" width="120" align="center" />
|
<el-table-column label="卷号" prop="coilNo" width="120" align="center" />
|
||||||
<el-table-column label="单卷(T)" prop="coilWeight" width="78" align="right" />
|
<el-table-column label="单卷(T)" prop="coilWeight" width="78" align="right" />
|
||||||
<el-table-column label="车号" prop="truckNo" width="95" align="center" />
|
<el-table-column label="车号" prop="truckNo" width="95" align="center" />
|
||||||
<el-table-column label="件数" prop="pieceCount" width="56" align="center" />
|
|
||||||
<el-table-column label="销售" prop="salesCode" width="80" align="center" />
|
<el-table-column label="销售" prop="salesCode" width="80" align="center" />
|
||||||
<el-table-column label="到货" width="72" align="center">
|
<el-table-column label="到货" width="72" align="center">
|
||||||
<template slot-scope="s">
|
<template slot-scope="s">
|
||||||
|
|||||||
Reference in New Issue
Block a user