Browse Source

导入支持动态列

java8
han\hanst 5 months ago
parent
commit
d7966922a5
  1. 6
      src/main/java/com/xujie/sys/modules/ecss/entity/EcssCoDelNotify.java
  2. 319
      src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java
  3. 43
      src/main/resources/mapper/ecss/CoDelMapper.xml

6
src/main/java/com/xujie/sys/modules/ecss/entity/EcssCoDelNotify.java

@ -204,5 +204,11 @@ public class EcssCoDelNotify extends QueryPage {
private String saleslt;
private String manufacturerName;
private String category;
private String qtyRoll;
private String qtyBox;
}

319
src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java

@ -310,6 +310,89 @@ public class CoDelServiceImpl implements CoDelService {
}
/**
* 安全获取字符串列值支持可选列
* 如果列不存在返回空字符串
*
* @param row 数据行
* @param columnMap 列索引映射
* @param columnName 列名
* @return 单元格字符串值如果列不存在返回空字符串
*/
private String getStringCellValueSafe(XSSFRow row, Map<String, Integer> columnMap, String columnName) {
Integer columnIndex = columnMap.get(columnName);
if (columnIndex == null) {
return ""; // 列不存在返回空字符串
}
return getStringCellValue(row, columnIndex);
}
/**
* 安全获取数字列值支持可选列
* 如果列不存在返回null
*
* @param row 数据行
* @param columnMap 列索引映射
* @param columnName 列名
* @return 单元格数字值如果列不存在返回null
*/
private BigDecimal getNumericCellValueSafe(XSSFRow row, Map<String, Integer> columnMap, String columnName) {
Integer columnIndex = columnMap.get(columnName);
if (columnIndex == null) {
return null; // 列不存在返回null
}
return getNumericCellValueOrDefault(row, columnIndex);
}
/**
* 解析Excel第一行建立列名到列索引的映射关系
*
* @param headerRow 第一行表头行
* @return 列名到列索引的映射Map
*/
private Map<String, Integer> parseExcelHeader(XSSFRow headerRow) {
Map<String, Integer> columnIndexMap = new HashMap<>();
if (headerRow == null) {
throw new RuntimeException("Excel表头行不能为空!");
}
// 遍历第一行的所有单元格建立列名到索引的映射
int lastCellNum = headerRow.getLastCellNum();
for (int i = 0; i < lastCellNum; i++) {
String columnName = getStringCellValue(headerRow, i);
if (StringUtils.isNotBlank(columnName)) {
// 去除空格并统一格式
columnName = columnName.trim();
columnIndexMap.put(columnName, i);
}
}
// 验证必填列是否存在根据代码中的验证逻辑确定
String[] requiredColumns = {
"PO#", // 必填
"PN", // 必填
"Qty (pcs)", // 必填
"Cargo Ready Date", // 必填
"Destination", // 必填
"Shipping Mode", // 必填
"Currency", // 必填
"TP" // 必填
};
List<String> missingColumns = new ArrayList<>();
for (String column : requiredColumns) {
if (!columnIndexMap.containsKey(column)) {
missingColumns.add(column);
}
}
if (!missingColumns.isEmpty()) {
throw new RuntimeException("Excel表头缺少必填列: " + String.join(", ", missingColumns));
}
return columnIndexMap;
}
private void importNotifyExcel(EcssCoDelNotifyHeaderData inData, XSSFWorkbook workbook, String site,
SysUserEntity currentUser, List<EcssCoDelNotifyData> excelList) {
for (int s = 0; s < workbook.getNumberOfSheets(); s++) {
@ -319,74 +402,159 @@ public class CoDelServiceImpl implements CoDelService {
deleteEmptyRow(sheet);
// 获取行数
int rows = sheet.getPhysicalNumberOfRows();
// 遍历每一行从第二行开始
for (int j = 1; j < rows; j++) {
// 创建对象
EcssCoDelNotifyData task = new EcssCoDelNotifyData();
XSSFRow row0 = sheet.getRow(0);
if (row0.getCell(0) == null || StringUtils.isBlank(getStringCellValue(row0, 0))
|| !getStringCellValue(row0, 0).equals("Ready Date")) {
continue;
}
if (rows < 4) {
continue; // 至少需要前2行表头行第3行和一行数据第4行
}
// 获取第三行表头行
XSSFRow headerRow = sheet.getRow(2);
// 验证第一列第3行必须是"PO Rec. Date"且不能为空
if (headerRow == null || headerRow.getCell(0) == null
|| StringUtils.isBlank(getStringCellValue(headerRow, 0))
|| !getStringCellValue(headerRow, 0).trim().equals("PO Rec. Date")) {
log.warn("Sheet {} 的第一列第3行不是 'PO Rec. Date' 或为空,跳过该Sheet", sheet.getSheetName());
continue; // 跳过该Sheet
}
// 解析表头行第3行获取列索引映射
Map<String, Integer> columnMap = parseExcelHeader(headerRow);
// 遍历每一行从第四行开始即索引3
for (int j = 3; j < rows; j++) {
// 获得该行
XSSFRow row = sheet.getRow(j);
if (row==null) {
if (row == null) {
continue;
}
if (row.getCell(13) == null || StringUtils.isBlank(getStringCellValue(row, 13))) {
// 检查第一列如果没有值或者值是空字符串则跳过该行
if (row.getCell(0).getCellType() == CellType.BLANK || row.getCell(0).getCellType() == CellType.ERROR
|| row.getCell(0) == null || StringUtils.isBlank(getStringCellValue(row, 0))) {
log.debug("第{}行第一列为空,跳过该行", j+1);
continue;
}
if (row.getCell(18) != null && getStringCellValue(row, 18).equals("内销")) {
// 跳过内销数据如果"内外销方式"列存在
Integer saleTypeIdx = columnMap.get("内外销方式");
if (saleTypeIdx != null && row.getCell(saleTypeIdx) != null
&& getStringCellValue(row, saleTypeIdx).equals("内销")) {
continue;
}
if (row.getCell(0) == null ) {
throw new RuntimeException("第" + (j+1) + "行的Ready Date不能为空!");
// 必填字段验证
Integer cargoReadyDateIdx = columnMap.get("Cargo Ready Date");
if (row.getCell(cargoReadyDateIdx) == null) {
throw new RuntimeException("第" + (j+1) + "行的Cargo Ready Date不能为空!");
}
if (row.getCell(1) == null) {
Integer poIdx = columnMap.get("PO#");
if (row.getCell(poIdx) == null) {
throw new RuntimeException("第" + (j+1) + "行的PO#不能为空!");
}
if (row.getCell(8) == null) {
Integer pnIdx = columnMap.get("PN");
if (row.getCell(pnIdx) == null) {
throw new RuntimeException("第" + (j+1) + "行的PN不能为空!");
}
if (row.getCell(11) == null) {
Integer qtyIdx = columnMap.get("Qty (pcs)");
if (row.getCell(qtyIdx) == null) {
throw new RuntimeException("第" + (j+1) + "行的Qty不能为空!");
}
if (row.getCell(13) == null) {
throw new RuntimeException("第" + (j+1) + "行的CMC Invoice不能为空!");
}
if (row.getCell(15) == null) {
Integer destinationIdx = columnMap.get("Destination");
if (row.getCell(destinationIdx) == null) {
throw new RuntimeException("第" + (j+1) + "行的Destination不能为空!");
}
if (row.getCell(17) == null) {
Integer shippingModeIdx = columnMap.get("Shipping Mode");
if (row.getCell(shippingModeIdx) == null) {
throw new RuntimeException("第" + (j+1) + "行的Shipping Mode不能为空!");
}
if (row.getCell(21) == null) {
Integer currencyIdx = columnMap.get("Currency");
if (row.getCell(currencyIdx) == null) {
throw new RuntimeException("第" + (j+1) + "行的Currency不能为空!");
}
if (row.getCell(22) == null) {
Integer tpIdx = columnMap.get("TP");
if (row.getCell(tpIdx) == null) {
throw new RuntimeException("第" + (j+1) + "行的TP不能为空!");
}
// 为对象赋值
// 创建对象并为对象赋值
EcssCoDelNotifyData task = new EcssCoDelNotifyData();
task.setSite(site); // site
task.setBuNo(inData.getBuNo()); // bu
// 解析日期
Date readDate;
try {
//String date = getStringCellValue(row, 0);
LocalDate localDate = parseDateCell(row.getCell(0));
LocalDate localDate = parseDateCell(row.getCell(cargoReadyDateIdx));
String formatted = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
readDate = DateUtils.getDateByParten(formatted, "yyyy-MM-dd");
} catch (ParseException e) {
throw new RuntimeException("第" + (j+1) + "行的ReadyDate格式有误!");
}
task.setReadyDate(readDate);
task.setCustomerPO(getStringCellValue(row, 1));
task.setSalesOrder(getStringCellValue(row, 4));
task.setLine(getStringCellValue(row, 2));
task.setVersion(getStringCellValue(row, 3));
task.setSaleslt(getStringCellValue(row, 5));
task.setStatus(getStringCellValue(row, 6));
task.setFamily(getStringCellValue(row, 7));
task.setPn(getStringCellValue(row, 8));
// 使用动态索引读取数据必填列
task.setCustomerPO(getStringCellValue(row, poIdx));
task.setPn(getStringCellValue(row, pnIdx));
task.setQty(getNumericCellValueOrDefault(row, qtyIdx));
task.setDestination(getStringCellValue(row, destinationIdx));
task.setShippingMode(getStringCellValue(row, shippingModeIdx));
task.setCurrency(getStringCellValue(row, currencyIdx));
task.setTp(getNumericCellValueOrDefault(row, tpIdx));
// 处理CMC Invoice如果CMC Invoice为空则取Shipping Number如果两者都为空则报错
String cmcInvoiceValue = getStringCellValueSafe(row, columnMap, "CMC Invoice");
String shippingNumberValue = getStringCellValueSafe(row, columnMap, "Shipping Number");
if (StringUtils.isBlank(cmcInvoiceValue) && StringUtils.isBlank(shippingNumberValue)) {
throw new RuntimeException("第" + (j+1) + "行的CMC Invoice和Shipping Number不能同时为空!");
}
// 如果CMC Invoice为空则使用Shipping Number
if (StringUtils.isBlank(cmcInvoiceValue)) {
task.setCmcInvoice(shippingNumberValue);
} else {
task.setCmcInvoice(cmcInvoiceValue);
}
task.setShippingNumber(shippingNumberValue);
// 读取可选列列不存在时返回空值或null
task.setSalesOrder(getStringCellValueSafe(row, columnMap, "Sales Order"));
task.setLine(getStringCellValueSafe(row, columnMap, "Line#"));
task.setVersion(getStringCellValueSafe(row, columnMap, "Version#"));
task.setSaleslt(getStringCellValueSafe(row, columnMap, "Saleslt"));
task.setStatus(getStringCellValueSafe(row, columnMap, "Status"));
task.setFamily(getStringCellValueSafe(row, columnMap, "Family"));
task.setPartDescription(getStringCellValueSafe(row, columnMap, "Description"));
task.setManufacturerName(getStringCellValueSafe(row, columnMap, "Manufacturer Name"));
task.setCmcComment(getStringCellValueSafe(row, columnMap, "CMC Comment"));
task.setAwbBl(getStringCellValueSafe(row, columnMap, "AWB/ BL#"));
task.setForwarderInfo(getStringCellValueSafe(row, columnMap, "Forwarder Info"));
task.setSo(getStringCellValueSafe(row, columnMap, "SO"));
task.setUpc(getStringCellValueSafe(row, columnMap, "UPC"));
task.setRemark(getStringCellValueSafe(row, columnMap, "备注"));
task.setCategory(getStringCellValueSafe(row, columnMap, "Category"));
task.setQtyRoll(getStringCellValueSafe(row, columnMap, "QTY/ROLL"));
task.setQtyBox(getStringCellValueSafe(row, columnMap, "qty/box"));
task.setSaleType(getStringCellValueSafe(row, columnMap, "内外销方式")); // 内外销
task.setLt(getNumericCellValueSafe(row, columnMap, "LT (wks)"));
task.setTtlAmount(getNumericCellValueSafe(row, columnMap, "TTL Amount"));
task.setVat(getNumericCellValueSafe(row, columnMap, "VAT"));
task.setSumPrice(getNumericCellValueSafe(row, columnMap, "价税合计")); // 价税合计
task.setRoll(getNumericCellValueSafe(row, columnMap, "Roll"));
BigDecimal carton = getNumericCellValueSafe(row, columnMap, "BOX");
task.setCarton(carton != null ? carton.setScale(1, RoundingMode.HALF_UP) : null);
// 查询物料信息
List<PartData> parts = coDelMapper.getPartNo(site, task.getPn(), currentUser.getUsername(), inData.getBuNo());
if (parts.isEmpty()) {
// 物料不存在时设置 partNo pn后续会在批量检查阶段被筛选掉
@ -394,34 +562,14 @@ public class CoDelServiceImpl implements CoDelService {
} else {
task.setPartNo(parts.get(0).getPartNo());
}
task.setPartDescription(getStringCellValue(row, 9));
task.setManufacturerName(getStringCellValue(row, 10));
task.setQty(getNumericCellValueOrDefault(row, 11));
if (task.getQty().compareTo(BigDecimal.ZERO)==0) {
if (task.getQty().compareTo(BigDecimal.ZERO) == 0) {
task.setStatus("取消发货");
}
task.setLt(getNumericCellValueOrDefault(row, 12));
task.setCmcInvoice(getStringCellValue(row, 13));
task.setCmcComment(getStringCellValue(row, 14));
task.setDestination(getStringCellValue(row, 15));
task.setSaleType(getStringCellValue(row, 18));
task.setAwbBl(getStringCellValue(row, 19));
task.setShippingNumber(getStringCellValue(row, 16));
task.setShippingMode(getStringCellValue(row, 17));
task.setForwarderInfo(getStringCellValue(row, 20));
task.setCurrency(getStringCellValue(row, 21));
task.setTp(getNumericCellValueOrDefault(row, 22));
task.setTtlAmount(getNumericCellValueOrDefault(row, 23));
task.setVat(getNumericCellValueOrDefault(row, 24));
task.setSumPrice(getNumericCellValueOrDefault(row, 25));
task.setSo(getStringCellValue(row, 26));
task.setUpc(getStringCellValue(row, 27));
task.setRemark(getStringCellValue(row, 28));
task.setRoll(getNumericCellValueOrDefault(row, 29));
task.setCarton(getNumericCellValueOrDefault(row, 30)!=null? Objects.requireNonNull(getNumericCellValueOrDefault(row, 30)).setScale(1, RoundingMode.HALF_UP):null);
task.setErpFlag("N");
task.setNotifyStatus("已计划");
task.setUsername(inData.getUsername());
// 物料存在性检查已移至批量处理阶段此处不再单独检查
excelList.add(task);
}
@ -813,37 +961,48 @@ public class CoDelServiceImpl implements CoDelService {
// 先删除全部明细再新建明细
coDelMapper.deleteAllEcssDelDetail(headerData);
// 构建原数据Map使用itemNo作为唯一标识
// 注意不能用pn作为key因为同一个pn可能有多行记录每行都需要独立比较
Map<Integer, EcssCoDelNotifyDetailData> originalDataMap = dbData.stream()
.collect(Collectors.toMap(EcssCoDelNotifyDetail::getItemNo, detail -> detail, (v1, v2) -> v1));
// 智能判断改单逻辑按PN分组汇总数量避免因顺序变化导致误判
// 构建原数据Map按PN分组计算每个PN的总数量
Map<String, BigDecimal> originalPnQtyMap = new HashMap<>();
for (EcssCoDelNotifyDetailData detail : dbData) {
String pn = detail.getPn();
BigDecimal qty = detail.getQty();
originalPnQtyMap.put(pn, originalPnQtyMap.getOrDefault(pn, BigDecimal.ZERO).add(qty));
}
// 构建新数据Map按PN分组计算每个PN的总数量
Map<String, BigDecimal> newPnQtyMap = new HashMap<>();
for (EcssCoDelNotifyData excelData : excelList) {
String pn = excelData.getPn();
BigDecimal qty = excelData.getQty();
newPnQtyMap.put(pn, newPnQtyMap.getOrDefault(pn, BigDecimal.ZERO).add(qty));
}
// 设置itemNo并判断每一行是否有变化智能判断按PN比较总数量
for (int i = 0; i < excelList.size(); i++) {
excelList.get(i).setDelNo(headerData.getDelNo());
excelList.get(i).setItemNo(i + 1);
// 判断数据是否变化按itemNo匹配原数据对比PN和数量
Integer itemNo = i + 1;
EcssCoDelNotifyDetailData originalDetail = originalDataMap.get(itemNo);
String pn = excelList.get(i).getPn();
BigDecimal originalTotalQty = originalPnQtyMap.get(pn);
BigDecimal newTotalQty = newPnQtyMap.get(pn);
// 判断是否有修改包括新增换料数量变更
// 判断是否有修改按PN比较总数量避免因顺序变化误判
boolean isModified = false;
boolean isQtyModified = false;
if (originalDetail == null) {
// 新增原数据中不存在该itemNo
if (originalTotalQty == null) {
// 新增PN原数据中不存在该PN
isModified = true;
isQtyModified = true;
} else if (!originalDetail.getPn().equals(excelList.get(i).getPn())) {
// 换料PN不同
isModified = true;
isQtyModified = true;
} else if (!originalDetail.getQty().equals(excelList.get(i).getQty())) {
// 数量变更PN相同但数量不同
log.info("检测到新增PN: {}, 数量: {}", pn, newTotalQty);
} else if (originalTotalQty.compareTo(newTotalQty) != 0) {
// 数量变更PN存在但总数量不同
isModified = true;
isQtyModified = true;
log.info("检测到PN数量变更: {}, 原数量: {}, 新数量: {}", pn, originalTotalQty, newTotalQty);
}
// 其他情况PN和数量都相同无变化isModified保持false
// 其他情况PN和数量都相同无变化isModified保持false
// 只有真正有变化的才标记modifyFlag=true
excelList.get(i).setModifyFlag(isModified);
@ -853,6 +1012,13 @@ public class CoDelServiceImpl implements CoDelService {
excelList.get(i).setModifyQtyFlag(true);
}
}
// 检查是否有PN被删除在原数据中存在但新数据中不存在
for (String originalPn : originalPnQtyMap.keySet()) {
if (!newPnQtyMap.containsKey(originalPn)) {
log.info("检测到PN被删除: {}, 原数量: {}", originalPn, originalPnQtyMap.get(originalPn));
}
}
coDelMapper.batchSaveEcssCoDelNotifyDetail(excelList);
headerData.setModifyFlag(true);
// 更新头表字段包括ReadyDateShippingModeDestination
@ -3586,7 +3752,8 @@ public class CoDelServiceImpl implements CoDelService {
}
private static void deleteEmptyRow(XSSFSheet sheet) {
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
// 从第三行开始遍历检查每一行是否为空
for (int i = 2; i <= sheet.getLastRowNum(); i++) {
XSSFRow row = sheet.getRow(i);
boolean isEmptyRow = true;
if (row != null) {

43
src/main/resources/mapper/ecss/CoDelMapper.xml

@ -176,13 +176,14 @@
insert into ecss_CoDelNotifyDetail (site,bu_no,delNo,item_no,salesOrder,salesOrder_item_no,customerPO,line,version,
status,family,part_no,part_description,qty,lt,cmc_comment,saleType,
awb_bl,shipping_number,forwarder_info,currency,tp,ttl_amount,sum_price,
so,upc,remark,pn,surplus_qty,vat,roll,carton,saleslt,manufacturer_name,modifyFlag,modifyQtyFlag)
so,upc,remark,pn,surplus_qty,vat,roll,carton,saleslt,manufacturer_name,modifyFlag,modifyQtyFlag,category,qty_roll,qty_box)
values
<foreach collection="list" separator="," item="item">
(#{item.site},#{item.buNo},#{item.delNo},#{item.itemNo,jdbcType=INTEGER},#{item.salesOrder,jdbcType=NVARCHAR},#{item.salesOrderItemNo},#{item.customerPO,jdbcType=NVARCHAR},#{item.line,jdbcType=NVARCHAR},#{item.version,jdbcType=NVARCHAR},
#{item.status,jdbcType=NVARCHAR},#{item.family,jdbcType=NVARCHAR},#{item.partNo},#{item.partDescription,jdbcType=NVARCHAR},#{item.qty,jdbcType=DECIMAL},#{item.lt,jdbcType=DECIMAL},#{item.cmcComment,jdbcType=NVARCHAR},#{item.saleType,jdbcType=NVARCHAR},
#{item.awbBl,jdbcType=NVARCHAR},#{item.shippingNumber,jdbcType=NVARCHAR},#{item.forwarderInfo,jdbcType=NVARCHAR},#{item.currency,jdbcType=NVARCHAR},#{item.tp,jdbcType=DECIMAL},#{item.ttlAmount,jdbcType=DECIMAL},#{item.sumPrice,jdbcType=DECIMAL},
#{item.so,jdbcType=NVARCHAR},#{item.upc,jdbcType=NVARCHAR},#{item.remark,jdbcType=NVARCHAR},#{item.pn,jdbcType=NVARCHAR},#{item.qty},#{item.vat},#{item.roll},#{item.carton},#{item.saleslt,jdbcType=NVARCHAR},#{item.manufacturerName,jdbcType=NVARCHAR},#{item.modifyFlag},#{item.modifyQtyFlag})
#{item.so,jdbcType=NVARCHAR},#{item.upc,jdbcType=NVARCHAR},#{item.remark,jdbcType=NVARCHAR},#{item.pn,jdbcType=NVARCHAR},#{item.qty},#{item.vat},#{item.roll},#{item.carton},#{item.saleslt,jdbcType=NVARCHAR},#{item.manufacturerName,jdbcType=NVARCHAR},
#{item.modifyFlag},#{item.modifyQtyFlag},#{item.category,jdbcType=NVARCHAR},#{item.qtyRoll,jdbcType=NVARCHAR},#{item.qtyBox,jdbcType=NVARCHAR})
</foreach>
</insert>
@ -216,11 +217,11 @@
</update>
<update id="updateEcssDelHeaderForModify" >
update ecss_CoDelNotifyHeader
update ecss_CoDelNotifyHeader
set modifyFlag=#{modifyFlag},
modify_count = CASE
WHEN #{modifyFlag} = 1 THEN ISNULL(modify_count, 0) + 1
ELSE 0
modify_count = CASE
WHEN #{modifyFlag} = 1 THEN ISNULL(modify_count, 0) + 1
ELSE 0
END
where site=#{site} and delNo=#{delNo}
</update>
@ -851,7 +852,7 @@ left join ecss_CoDelNotifyHeader noHeader on a.site=noHeader.site and a.delNo=no
<select id="exportCoDelPalletDetail" resultType="java.util.Map">
-- 修复净重毛重重复计算问题:按数量比例分配箱子重量
WITH BoxDetail AS (
SELECT
SELECT
b.part_no,
b.qty,
b.rolls,
@ -863,16 +864,16 @@ left join ecss_CoDelNotifyHeader noHeader on a.site=noHeader.site and a.delNo=no
b.delNo,
b.seq_no,
-- 计算该零件数量占该箱子总数量的比例
CASE
WHEN SUM(b.qty) OVER (PARTITION BY b.site, b.bu_no, b.delNo, b.seq_no) > 0
CASE
WHEN SUM(b.qty) OVER (PARTITION BY b.site, b.bu_no, b.delNo, b.seq_no) > 0
THEN b.qty * 1.0 / SUM(b.qty) OVER (PARTITION BY b.site, b.bu_no, b.delNo, b.seq_no)
ELSE 0
END as qtyRatio
FROM ecss_CoDelBoxList a
FROM ecss_CoDelBoxList a
LEFT JOIN ecss_CoDelPalletDetail b ON a.site=b.site AND a.bu_no=b.bu_no AND a.delNo=b.delNo AND a.item_no=b.seq_no
WHERE a.site=#{site} AND a.bu_no=#{buNo} AND a.delNo=#{delNo} AND b.site IS NOT NULL
)
SELECT
SELECT
part_no,
CONVERT(DECIMAL(20, 0), SUM(qty)) as total_qty,
CONVERT(DECIMAL(20, 0), SUM(DISTINCT box_qty)) as box_qty,
@ -888,7 +889,7 @@ left join ecss_CoDelNotifyHeader noHeader on a.site=noHeader.site and a.delNo=no
<select id="getCoDelPalletDetailGroupByPn" resultType="java.util.Map">
-- 修复净重毛重重复计算问题:按数量比例分配箱子重量
WITH BoxDetail AS (
SELECT
SELECT
b.pn,
b.qty,
b.rolls,
@ -900,16 +901,16 @@ left join ecss_CoDelNotifyHeader noHeader on a.site=noHeader.site and a.delNo=no
b.delNo,
b.seq_no,
-- 计算该零件数量占该箱子总数量的比例
CASE
WHEN SUM(b.qty) OVER (PARTITION BY b.site, b.bu_no, b.delNo, b.seq_no) > 0
CASE
WHEN SUM(b.qty) OVER (PARTITION BY b.site, b.bu_no, b.delNo, b.seq_no) > 0
THEN b.qty * 1.0 / SUM(b.qty) OVER (PARTITION BY b.site, b.bu_no, b.delNo, b.seq_no)
ELSE 0
END as qtyRatio
FROM ecss_CoDelBoxList a
FROM ecss_CoDelBoxList a
LEFT JOIN ecss_CoDelPalletDetail b ON a.site=b.site AND a.bu_no=b.bu_no AND a.delNo=b.delNo AND a.item_no=b.seq_no
WHERE a.site=#{site} AND a.bu_no=#{buNo} AND a.delNo=#{delNo}
)
SELECT
SELECT
pn,
CONVERT(DECIMAL(20, 0), SUM(qty)) as total_qty,
CONVERT(DECIMAL(20, 0), SUM(DISTINCT box_qty)) as box_qty,
@ -927,7 +928,7 @@ left join ecss_CoDelNotifyHeader noHeader on a.site=noHeader.site and a.delNo=no
<select id="exportCoDelPalletDetailGroupByItemNo" resultType="java.util.Map">
-- 按发货通知单明细行号分组,汇总该行对应的装箱重量
WITH BoxDetail AS (
SELECT
SELECT
b.notify_detail_item_no,
b.part_no,
b.qty,
@ -940,16 +941,16 @@ left join ecss_CoDelNotifyHeader noHeader on a.site=noHeader.site and a.delNo=no
b.delNo,
b.seq_no,
-- 计算该零件数量占该箱子总数量的比例
CASE
WHEN SUM(b.qty) OVER (PARTITION BY b.site, b.bu_no, b.delNo, b.seq_no) > 0
CASE
WHEN SUM(b.qty) OVER (PARTITION BY b.site, b.bu_no, b.delNo, b.seq_no) > 0
THEN b.qty * 1.0 / SUM(b.qty) OVER (PARTITION BY b.site, b.bu_no, b.delNo, b.seq_no)
ELSE 0
END as qtyRatio
FROM ecss_CoDelBoxList a
FROM ecss_CoDelBoxList a
LEFT JOIN ecss_CoDelPalletDetail b ON a.site=b.site AND a.bu_no=b.bu_no AND a.delNo=b.delNo AND a.item_no=b.seq_no
WHERE a.site=#{site} AND a.bu_no=#{buNo} AND a.delNo=#{delNo} AND b.notify_detail_item_no IS NOT NULL
)
SELECT
SELECT
notify_detail_item_no as item_no,
part_no,
CONVERT(DECIMAL(20, 0), SUM(qty)) as total_qty,

Loading…
Cancel
Save