|
|
@ -665,11 +665,28 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
// 使用动态索引读取数据(必填列) |
|
|
// 使用动态索引读取数据(必填列) |
|
|
task.setCustomerPO(getStringCellValue(row, poIdx)); |
|
|
task.setCustomerPO(getStringCellValue(row, poIdx)); |
|
|
task.setPn(getStringCellValue(row, pnIdx)); |
|
|
task.setPn(getStringCellValue(row, pnIdx)); |
|
|
task.setQty(getNumericCellValueOrDefault(row, qtyIdx)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 读取Qty (pcs),捕获格式错误 |
|
|
|
|
|
try { |
|
|
|
|
|
task.setQty(getNumericCellValueOrDefault(row, qtyIdx, "Qty (pcs)")); |
|
|
|
|
|
} catch (RuntimeException e) { |
|
|
|
|
|
currentSheetError.addErrorDetail("第" + (j+1) + "行的 " + e.getMessage()); |
|
|
|
|
|
hasRowError = true; |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
task.setDestination(getStringCellValue(row, destinationIdx)); |
|
|
task.setDestination(getStringCellValue(row, destinationIdx)); |
|
|
task.setShippingMode(getStringCellValue(row, shippingModeIdx)); |
|
|
task.setShippingMode(getStringCellValue(row, shippingModeIdx)); |
|
|
task.setCurrency(getStringCellValue(row, currencyIdx)); |
|
|
task.setCurrency(getStringCellValue(row, currencyIdx)); |
|
|
task.setTp(getNumericCellValueOrDefault(row, tpIdx)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 读取TP,捕获格式错误 |
|
|
|
|
|
try { |
|
|
|
|
|
task.setTp(getNumericCellValueOrDefault(row, tpIdx, "TP")); |
|
|
|
|
|
} catch (RuntimeException e) { |
|
|
|
|
|
currentSheetError.addErrorDetail("第" + (j+1) + "行的 " + e.getMessage()); |
|
|
|
|
|
hasRowError = true; |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 处理CMC Invoice:如果CMC Invoice为空/0/Excel错误/超过20位则取Shipping Number,如果两者都为空则报错 |
|
|
// 处理CMC Invoice:如果CMC Invoice为空/0/Excel错误/超过20位则取Shipping Number,如果两者都为空则报错 |
|
|
String cmcInvoiceValue = getStringCellValueSafe(row, columnMap, "CMC Invoice"); |
|
|
String cmcInvoiceValue = getStringCellValueSafe(row, columnMap, "CMC Invoice"); |
|
|
@ -974,11 +991,30 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
return -1; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取数值单元格的值(无列名版本,保持向后兼容,遇到不支持的类型返回null) |
|
|
|
|
|
*/ |
|
|
private BigDecimal getNumericCellValueOrDefault(XSSFRow row, int columnIndex) { |
|
|
private BigDecimal getNumericCellValueOrDefault(XSSFRow row, int columnIndex) { |
|
|
|
|
|
return getNumericCellValueOrDefault(row, columnIndex, null); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取数值单元格的值 |
|
|
|
|
|
* @param row Excel行 |
|
|
|
|
|
* @param columnIndex 列索引 |
|
|
|
|
|
* @param columnName 列名(用于错误提示,如 "Qty (pcs)"、"TP" 等必填列会抛出异常,其他列返回null) |
|
|
|
|
|
* @return BigDecimal值 |
|
|
|
|
|
*/ |
|
|
|
|
|
private BigDecimal getNumericCellValueOrDefault(XSSFRow row, int columnIndex, String columnName) { |
|
|
Cell cell = row.getCell(columnIndex); |
|
|
Cell cell = row.getCell(columnIndex); |
|
|
if (cell == null || cell.getCellType() == CellType.BLANK) { |
|
|
if (cell == null || cell.getCellType() == CellType.BLANK) { |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 必填数字列列表 |
|
|
|
|
|
boolean isRequiredColumn = columnName != null && |
|
|
|
|
|
("Qty (pcs)".equalsIgnoreCase(columnName) || "TP".equalsIgnoreCase(columnName)); |
|
|
|
|
|
|
|
|
switch (cell.getCellType()) { |
|
|
switch (cell.getCellType()) { |
|
|
case NUMERIC: |
|
|
case NUMERIC: |
|
|
BigDecimal value = BigDecimal.valueOf(cell.getNumericCellValue()); |
|
|
BigDecimal value = BigDecimal.valueOf(cell.getNumericCellValue()); |
|
|
@ -991,7 +1027,10 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
BigDecimal stringValue = new BigDecimal(cell.getStringCellValue()); |
|
|
BigDecimal stringValue = new BigDecimal(cell.getStringCellValue()); |
|
|
return stringValue.setScale(6, RoundingMode.HALF_UP); // 四舍五入保留四位小数 |
|
|
return stringValue.setScale(6, RoundingMode.HALF_UP); // 四舍五入保留四位小数 |
|
|
} catch (NumberFormatException e) { |
|
|
} catch (NumberFormatException e) { |
|
|
throw new RuntimeException("无效的数值格式: " + cell.getStringCellValue()); |
|
|
|
|
|
|
|
|
if (isRequiredColumn) { |
|
|
|
|
|
throw new RuntimeException("[" + columnName + "] 列无效的数值格式: " + cell.getStringCellValue()); |
|
|
|
|
|
} |
|
|
|
|
|
return null; |
|
|
} |
|
|
} |
|
|
case FORMULA: |
|
|
case FORMULA: |
|
|
// 获取缓存结果 |
|
|
// 获取缓存结果 |
|
|
@ -1007,12 +1046,21 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
BigDecimal stringValue = new BigDecimal(cell.getStringCellValue()); |
|
|
BigDecimal stringValue = new BigDecimal(cell.getStringCellValue()); |
|
|
return stringValue.setScale(6, RoundingMode.HALF_UP); // 四舍五入保留四位小数 |
|
|
return stringValue.setScale(6, RoundingMode.HALF_UP); // 四舍五入保留四位小数 |
|
|
} catch (NumberFormatException e) { |
|
|
} catch (NumberFormatException e) { |
|
|
throw new RuntimeException("无效的数值格式: " + cell.getStringCellValue()); |
|
|
|
|
|
|
|
|
if (isRequiredColumn) { |
|
|
|
|
|
throw new RuntimeException("[" + columnName + "] 列无效的数值格式: " + cell.getStringCellValue()); |
|
|
} |
|
|
} |
|
|
default:return null; |
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
} |
|
|
|
|
|
default: |
|
|
|
|
|
return null; |
|
|
} |
|
|
} |
|
|
default: |
|
|
default: |
|
|
throw new RuntimeException("不支持的单元格类型: " + cell.getCellType()); |
|
|
|
|
|
|
|
|
// 如果是必填列,抛出异常提示 |
|
|
|
|
|
if (isRequiredColumn) { |
|
|
|
|
|
throw new RuntimeException("[" + columnName + "] 列不支持的单元格类型: " + cell.getCellType()); |
|
|
|
|
|
} |
|
|
|
|
|
// 其他非必填列返回null |
|
|
|
|
|
return null; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1726,7 +1774,7 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
throw new RuntimeException("导入失败:物料:" + excelData.getPn() + "不存在!"); |
|
|
throw new RuntimeException("导入失败:物料:" + excelData.getPn() + "不存在!"); |
|
|
} |
|
|
} |
|
|
excelData.setPartNo(parts.get(0).getPartNo()); |
|
|
excelData.setPartNo(parts.get(0).getPartNo()); |
|
|
excelData.setQty(getNumericCellValueOrDefault(row, 7)); |
|
|
|
|
|
|
|
|
excelData.setQty(getNumericCellValueOrDefault(row, 7, "Qty (pcs)")); |
|
|
excelData.setBoxQty(getNumericCellValueOrDefault(row, 2)); |
|
|
excelData.setBoxQty(getNumericCellValueOrDefault(row, 2)); |
|
|
excelData.setRolls(getNumericCellValueOrDefault(row, 8)); |
|
|
excelData.setRolls(getNumericCellValueOrDefault(row, 8)); |
|
|
excelData.setGrossWeight(getNumericCellValueOrDefault(row, 3)); |
|
|
excelData.setGrossWeight(getNumericCellValueOrDefault(row, 3)); |
|
|
@ -4024,7 +4072,7 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
task.setBuNo(inData.getBuNo()); // bu |
|
|
task.setBuNo(inData.getBuNo()); // bu |
|
|
task.setSku(getStringCellValue(row, 0)); |
|
|
task.setSku(getStringCellValue(row, 0)); |
|
|
task.setSo(getStringCellValue(row, 1)); |
|
|
task.setSo(getStringCellValue(row, 1)); |
|
|
task.setQty(getNumericCellValueOrDefault(row, 2)); |
|
|
|
|
|
|
|
|
task.setQty(getNumericCellValueOrDefault(row, 2, "Qty (pcs)")); |
|
|
List<EcssWalMartOrder> orderDataList = sqlSession.selectList("ecssMapper" + "." + "searchWalMartOrderList", task); |
|
|
List<EcssWalMartOrder> orderDataList = sqlSession.selectList("ecssMapper" + "." + "searchWalMartOrderList", task); |
|
|
if (!orderDataList.isEmpty()) { |
|
|
if (!orderDataList.isEmpty()) { |
|
|
if (sb.toString().length()>1) { |
|
|
if (sb.toString().length()>1) { |
|
|
@ -4424,6 +4472,349 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 批量修改装箱信息(Box和明细) |
|
|
|
|
|
* |
|
|
|
|
|
* @param batchData 包含boxList和detailList的批量更新数据 |
|
|
|
|
|
*/ |
|
|
|
|
|
@Override |
|
|
|
|
|
@Transactional |
|
|
|
|
|
public void batchUpdatePackingInfo(Map<String, Object> batchData) { |
|
|
|
|
|
String site = (String) batchData.get("site"); |
|
|
|
|
|
String buNo = (String) batchData.get("buNo"); |
|
|
|
|
|
String delNo = (String) batchData.get("delNo"); |
|
|
|
|
|
String updateBy = (String) batchData.get("updateBy"); |
|
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
|
List<Map<String, Object>> boxList = (List<Map<String, Object>>) batchData.get("boxList"); |
|
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
|
List<Map<String, Object>> detailList = (List<Map<String, Object>>) batchData.get("detailList"); |
|
|
|
|
|
|
|
|
|
|
|
log.info("=== 开始批量修改装箱信息 ==="); |
|
|
|
|
|
log.info("发货单号: {}, Box数量: {}, 明细数量: {}", |
|
|
|
|
|
delNo, |
|
|
|
|
|
boxList != null ? boxList.size() : 0, |
|
|
|
|
|
detailList != null ? detailList.size() : 0); |
|
|
|
|
|
|
|
|
|
|
|
// 获取发货通知单信息 |
|
|
|
|
|
EcssCoDelNotifyHeaderData notifyHeader = coDelMapper.getEcssCoDelNotifyHeader(site, delNo); |
|
|
|
|
|
boolean isCustomsCleared = "已报关".equals(notifyHeader.getNotifyStatus()); |
|
|
|
|
|
|
|
|
|
|
|
// 保存修改前的数据(用于邮件对比) |
|
|
|
|
|
List<Map> oldBoxList = coDelMapper.selectBoxList(notifyHeader); |
|
|
|
|
|
EcssCoDelPalletHeaderData queryData = new EcssCoDelPalletHeaderData(); |
|
|
|
|
|
queryData.setSite(site); |
|
|
|
|
|
queryData.setBuNo(buNo); |
|
|
|
|
|
queryData.setDelNo(delNo); |
|
|
|
|
|
List<EcssCoDelPalletDetailData> oldPalletDetailList = coDelMapper.searchEcssCoDelPalletDetailData(queryData); |
|
|
|
|
|
|
|
|
|
|
|
// 记录修改内容 |
|
|
|
|
|
List<Map<String, Object>> boxChanges = new ArrayList<>(); |
|
|
|
|
|
List<Map<String, Object>> detailChanges = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
// 1. 处理Box修改 |
|
|
|
|
|
if (boxList != null && !boxList.isEmpty()) { |
|
|
|
|
|
for (Map<String, Object> box : boxList) { |
|
|
|
|
|
Map<String, Object> boxChange = new HashMap<>(); |
|
|
|
|
|
boxChange.put("item_no", box.get("item_no")); |
|
|
|
|
|
|
|
|
|
|
|
// 获取修改前的Box数据 |
|
|
|
|
|
Map oldBox = oldBoxList.stream() |
|
|
|
|
|
.filter(b -> String.valueOf(((Map)b).get("item_no")).equals(String.valueOf(box.get("item_no")))) |
|
|
|
|
|
.findFirst().orElse(null); |
|
|
|
|
|
|
|
|
|
|
|
if (oldBox != null) { |
|
|
|
|
|
// 记录变更 |
|
|
|
|
|
if (box.containsKey("box_qty")) { |
|
|
|
|
|
boxChange.put("box_qty_old", oldBox.get("box_qty")); |
|
|
|
|
|
boxChange.put("box_qty_new", box.get("box_qty")); |
|
|
|
|
|
} |
|
|
|
|
|
if (box.containsKey("grossWeight")) { |
|
|
|
|
|
boxChange.put("grossWeight_old", oldBox.get("grossWeight")); |
|
|
|
|
|
boxChange.put("grossWeight_new", box.get("grossWeight")); |
|
|
|
|
|
} |
|
|
|
|
|
if (box.containsKey("netWeight")) { |
|
|
|
|
|
boxChange.put("netWeight_old", oldBox.get("netWeight")); |
|
|
|
|
|
boxChange.put("netWeight_new", box.get("netWeight")); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
boxChanges.add(boxChange); |
|
|
|
|
|
|
|
|
|
|
|
// 执行更新 |
|
|
|
|
|
Map<String, Object> updateParams = new HashMap<>(); |
|
|
|
|
|
updateParams.put("site", site); |
|
|
|
|
|
updateParams.put("buNo", buNo); |
|
|
|
|
|
updateParams.put("delNo", delNo); |
|
|
|
|
|
updateParams.put("item_no", box.get("item_no")); |
|
|
|
|
|
updateParams.put("palletRemark", box.get("palletRemark")); |
|
|
|
|
|
updateParams.put("box_qty", box.get("box_qty")); |
|
|
|
|
|
updateParams.put("grossWeight", box.get("grossWeight")); |
|
|
|
|
|
updateParams.put("netWeight", box.get("netWeight")); |
|
|
|
|
|
updateParams.put("updateBy", updateBy); |
|
|
|
|
|
|
|
|
|
|
|
coDelMapper.updateBoxInfo(updateParams); |
|
|
|
|
|
log.info("更新Box: item_no={}", box.get("item_no")); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 2. 处理明细修改 |
|
|
|
|
|
if (detailList != null && !detailList.isEmpty()) { |
|
|
|
|
|
for (Map<String, Object> detail : detailList) { |
|
|
|
|
|
Map<String, Object> detailChange = new HashMap<>(); |
|
|
|
|
|
detailChange.put("seqNo", detail.get("seqNo")); |
|
|
|
|
|
detailChange.put("itemNo", detail.get("itemNo")); |
|
|
|
|
|
detailChange.put("poNo", detail.get("poNo")); |
|
|
|
|
|
detailChange.put("pn", detail.get("pn")); |
|
|
|
|
|
|
|
|
|
|
|
// 获取修改前的明细数据 |
|
|
|
|
|
EcssCoDelPalletDetailData oldDetail = oldPalletDetailList.stream() |
|
|
|
|
|
.filter(d -> String.valueOf(d.getSeqNo()).equals(String.valueOf(detail.get("seqNo"))) |
|
|
|
|
|
&& String.valueOf(d.getItemNo()).equals(String.valueOf(detail.get("itemNo")))) |
|
|
|
|
|
.findFirst().orElse(null); |
|
|
|
|
|
|
|
|
|
|
|
BigDecimal oldQty = null; |
|
|
|
|
|
if (oldDetail != null) { |
|
|
|
|
|
oldQty = oldDetail.getQty(); |
|
|
|
|
|
// 记录变更 |
|
|
|
|
|
if (detail.containsKey("qty")) { |
|
|
|
|
|
detailChange.put("qty_old", oldDetail.getQty()); |
|
|
|
|
|
detailChange.put("qty_new", detail.get("qty")); |
|
|
|
|
|
} |
|
|
|
|
|
if (detail.containsKey("rolls")) { |
|
|
|
|
|
detailChange.put("rolls_old", oldDetail.getRolls()); |
|
|
|
|
|
detailChange.put("rolls_new", detail.get("rolls")); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
detailChanges.add(detailChange); |
|
|
|
|
|
|
|
|
|
|
|
// 构造更新参数 |
|
|
|
|
|
EcssCoDelPalletData detailData = new EcssCoDelPalletData(); |
|
|
|
|
|
detailData.setSite(site); |
|
|
|
|
|
detailData.setBuNo(buNo); |
|
|
|
|
|
detailData.setDelNo(delNo); |
|
|
|
|
|
detailData.setSeqNo(detail.get("seqNo") != null ? Integer.valueOf(detail.get("seqNo").toString()) : null); |
|
|
|
|
|
detailData.setItemNo(detail.get("itemNo") != null ? Integer.valueOf(detail.get("itemNo").toString()) : null); |
|
|
|
|
|
detailData.setNotifyDetailItemNo(detail.get("notifyDetailItemNo") != null ? Integer.valueOf(detail.get("notifyDetailItemNo").toString()) : null); |
|
|
|
|
|
detailData.setPoNo((String) detail.get("poNo")); |
|
|
|
|
|
detailData.setPn((String) detail.get("pn")); |
|
|
|
|
|
detailData.setQty(detail.get("qty") != null ? new BigDecimal(detail.get("qty").toString()) : null); |
|
|
|
|
|
detailData.setOldQty(oldQty); |
|
|
|
|
|
detailData.setRolls(detail.get("rolls") != null ? new BigDecimal(detail.get("rolls").toString()) : null); |
|
|
|
|
|
detailData.setUpdateBy(updateBy); |
|
|
|
|
|
|
|
|
|
|
|
// 执行更新 |
|
|
|
|
|
coDelMapper.updateDetailInfo(detailData); |
|
|
|
|
|
|
|
|
|
|
|
// 更新发货通知单明细的剩余可装箱数量 |
|
|
|
|
|
Integer notifyDetailItemNo = detailData.getNotifyDetailItemNo(); |
|
|
|
|
|
BigDecimal qty = detailData.getQty(); |
|
|
|
|
|
if (notifyDetailItemNo != null && qty != null && oldQty != null) { |
|
|
|
|
|
EcssCoDelNotifyDetailData notifyDetail = coDelMapper.getEcssCoDelNotifyDetailByItemNo( |
|
|
|
|
|
site, buNo, delNo, notifyDetailItemNo |
|
|
|
|
|
); |
|
|
|
|
|
if (notifyDetail != null) { |
|
|
|
|
|
BigDecimal currentSurplusQty = notifyDetail.getSurplusQty() != null ? notifyDetail.getSurplusQty() : BigDecimal.ZERO; |
|
|
|
|
|
BigDecimal newSurplusQty = currentSurplusQty.add(oldQty).subtract(qty); |
|
|
|
|
|
notifyDetail.setSurplusQty(newSurplusQty); |
|
|
|
|
|
coDelMapper.updateEcssCoDelNotifyDetailSurplus(notifyDetail); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log.info("更新明细: seqNo={}, itemNo={}", detail.get("seqNo"), detail.get("itemNo")); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log.info("=== 批量修改装箱信息完成 === Box: {}, 明细: {}", boxChanges.size(), detailChanges.size()); |
|
|
|
|
|
|
|
|
|
|
|
// 3. 如果状态为已报关,发送邮件通知 |
|
|
|
|
|
if (isCustomsCleared && (!boxChanges.isEmpty() || !detailChanges.isEmpty())) { |
|
|
|
|
|
sendBatchUpdateNotificationEmail(notifyHeader, boxChanges, detailChanges, updateBy); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 发送批量修改通知邮件 |
|
|
|
|
|
* |
|
|
|
|
|
* @param notifyHeader 发货通知单头数据 |
|
|
|
|
|
* @param boxChanges Box修改记录 |
|
|
|
|
|
* @param detailChanges 明细修改记录 |
|
|
|
|
|
* @param updateBy 修改人 |
|
|
|
|
|
*/ |
|
|
|
|
|
private void sendBatchUpdateNotificationEmail(EcssCoDelNotifyHeaderData notifyHeader, |
|
|
|
|
|
List<Map<String, Object>> boxChanges, |
|
|
|
|
|
List<Map<String, Object>> detailChanges, |
|
|
|
|
|
String updateBy) { |
|
|
|
|
|
try { |
|
|
|
|
|
log.info("开始发送批量修改通知邮件,发货通知单号:{}", notifyHeader.getDelNo()); |
|
|
|
|
|
|
|
|
|
|
|
// 生成邮件内容 |
|
|
|
|
|
String emailContent = generateBatchUpdateEmailContent(notifyHeader, boxChanges, detailChanges, updateBy); |
|
|
|
|
|
|
|
|
|
|
|
// 获取发货通知单创建人邮箱 |
|
|
|
|
|
SysUserEntity creator = coDelMapper.queryByUserName(notifyHeader.getCreateBy()); |
|
|
|
|
|
if (creator == null || StringUtils.isBlank(creator.getEmail())) { |
|
|
|
|
|
log.warn("发货通知单创建人{}不存在或没有配置邮箱地址", notifyHeader.getCreateBy()); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
String creatorEmail = creator.getEmail(); |
|
|
|
|
|
|
|
|
|
|
|
// 发送邮件 |
|
|
|
|
|
String subject = String.format("发货通知单%s【发票:%s】批量修改通知", |
|
|
|
|
|
notifyHeader.getDelNo(), notifyHeader.getCmcInvoice()); |
|
|
|
|
|
String[] mailAddress = {creatorEmail}; |
|
|
|
|
|
|
|
|
|
|
|
sendMailUtil(subject, emailContent, mailAddress, notifyHeader); |
|
|
|
|
|
|
|
|
|
|
|
log.info("批量修改通知邮件发送成功,收件人:{}", creatorEmail); |
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
|
log.error("发送批量修改通知邮件失败,发货通知单号:{}, 错误信息:{}", |
|
|
|
|
|
notifyHeader.getDelNo(), e.getMessage(), e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 生成批量修改邮件内容 |
|
|
|
|
|
* |
|
|
|
|
|
* @param notifyHeader 发货通知单头数据 |
|
|
|
|
|
* @param boxChanges Box修改记录 |
|
|
|
|
|
* @param detailChanges 明细修改记录 |
|
|
|
|
|
* @param updateBy 修改人 |
|
|
|
|
|
* @return HTML格式的邮件内容 |
|
|
|
|
|
*/ |
|
|
|
|
|
private String generateBatchUpdateEmailContent(EcssCoDelNotifyHeaderData notifyHeader, |
|
|
|
|
|
List<Map<String, Object>> boxChanges, |
|
|
|
|
|
List<Map<String, Object>> detailChanges, |
|
|
|
|
|
String updateBy) { |
|
|
|
|
|
StringBuilder emailContent = new StringBuilder(); |
|
|
|
|
|
|
|
|
|
|
|
emailContent.append("<!DOCTYPE html>"); |
|
|
|
|
|
emailContent.append("<html>"); |
|
|
|
|
|
emailContent.append("<head>"); |
|
|
|
|
|
emailContent.append("<meta charset='UTF-8'>"); |
|
|
|
|
|
emailContent.append("<style>"); |
|
|
|
|
|
emailContent.append("body { font-family: Arial, sans-serif; margin: 20px; }"); |
|
|
|
|
|
emailContent.append("table { border-collapse: collapse; width: 100%; margin: 10px 0; }"); |
|
|
|
|
|
emailContent.append("th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }"); |
|
|
|
|
|
emailContent.append("th { background-color: #beb256; color: white; font-weight: bold; }"); |
|
|
|
|
|
emailContent.append(".old-value { color: #999; text-decoration: line-through; }"); |
|
|
|
|
|
emailContent.append(".new-value { color: #e74c3c; font-weight: bold; }"); |
|
|
|
|
|
emailContent.append(".arrow { color: #3498db; margin: 0 5px; }"); |
|
|
|
|
|
emailContent.append(".section-title { color: #333; font-size: 16px; font-weight: bold; margin: 20px 0 10px 0; border-left: 4px solid #4CAF50; padding-left: 10px; }"); |
|
|
|
|
|
emailContent.append(".summary { background-color: #f9f9f9; padding: 15px; border-radius: 5px; margin: 10px 0; }"); |
|
|
|
|
|
emailContent.append("</style>"); |
|
|
|
|
|
emailContent.append("</head>"); |
|
|
|
|
|
emailContent.append("<body>"); |
|
|
|
|
|
|
|
|
|
|
|
// 邮件标题 |
|
|
|
|
|
emailContent.append("<h2 style='color: #2c3e50;'>📦 发货通知单批量修改通知</h2>"); |
|
|
|
|
|
|
|
|
|
|
|
// 基本信息 |
|
|
|
|
|
emailContent.append("<div class='summary'>"); |
|
|
|
|
|
emailContent.append("<p><strong>发货通知单号:</strong>").append(notifyHeader.getDelNo()).append("</p>"); |
|
|
|
|
|
emailContent.append("<p><strong>发票号:</strong>").append(notifyHeader.getCmcInvoice()).append("</p>"); |
|
|
|
|
|
emailContent.append("<p><strong>客户:</strong>").append(notifyHeader.getCustomerName() != null ? notifyHeader.getCustomerName() : "-").append("</p>"); |
|
|
|
|
|
emailContent.append("<p><strong>修改人:</strong>").append(updateBy).append("</p>"); |
|
|
|
|
|
emailContent.append("<p><strong>修改时间:</strong>").append(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date())).append("</p>"); |
|
|
|
|
|
emailContent.append("</div>"); |
|
|
|
|
|
|
|
|
|
|
|
// Box修改记录 |
|
|
|
|
|
if (boxChanges != null && !boxChanges.isEmpty()) { |
|
|
|
|
|
emailContent.append("<div class='section-title'>📋 箱信息修改(共 ").append(boxChanges.size()).append(" 条)</div>"); |
|
|
|
|
|
emailContent.append("<table>"); |
|
|
|
|
|
emailContent.append("<tr><th>序号</th><th>箱数</th><th>毛重</th><th>净重</th></tr>"); |
|
|
|
|
|
|
|
|
|
|
|
for (Map<String, Object> change : boxChanges) { |
|
|
|
|
|
emailContent.append("<tr>"); |
|
|
|
|
|
emailContent.append("<td>").append(change.get("item_no")).append("</td>"); |
|
|
|
|
|
|
|
|
|
|
|
// 箱数 |
|
|
|
|
|
emailContent.append("<td>"); |
|
|
|
|
|
if (change.containsKey("box_qty_old") && change.containsKey("box_qty_new")) { |
|
|
|
|
|
emailContent.append("<span class='old-value'>").append(change.get("box_qty_old")).append("</span>"); |
|
|
|
|
|
emailContent.append("<span class='arrow'>→</span>"); |
|
|
|
|
|
emailContent.append("<span class='new-value'>").append(change.get("box_qty_new")).append("</span>"); |
|
|
|
|
|
} else { |
|
|
|
|
|
emailContent.append("-"); |
|
|
|
|
|
} |
|
|
|
|
|
emailContent.append("</td>"); |
|
|
|
|
|
|
|
|
|
|
|
// 毛重 |
|
|
|
|
|
emailContent.append("<td>"); |
|
|
|
|
|
if (change.containsKey("grossWeight_old") && change.containsKey("grossWeight_new")) { |
|
|
|
|
|
emailContent.append("<span class='old-value'>").append(change.get("grossWeight_old")).append("</span>"); |
|
|
|
|
|
emailContent.append("<span class='arrow'>→</span>"); |
|
|
|
|
|
emailContent.append("<span class='new-value'>").append(change.get("grossWeight_new")).append("</span>"); |
|
|
|
|
|
} else { |
|
|
|
|
|
emailContent.append("-"); |
|
|
|
|
|
} |
|
|
|
|
|
emailContent.append("</td>"); |
|
|
|
|
|
|
|
|
|
|
|
// 净重 |
|
|
|
|
|
emailContent.append("<td>"); |
|
|
|
|
|
if (change.containsKey("netWeight_old") && change.containsKey("netWeight_new")) { |
|
|
|
|
|
emailContent.append("<span class='old-value'>").append(change.get("netWeight_old")).append("</span>"); |
|
|
|
|
|
emailContent.append("<span class='arrow'>→</span>"); |
|
|
|
|
|
emailContent.append("<span class='new-value'>").append(change.get("netWeight_new")).append("</span>"); |
|
|
|
|
|
} else { |
|
|
|
|
|
emailContent.append("-"); |
|
|
|
|
|
} |
|
|
|
|
|
emailContent.append("</td>"); |
|
|
|
|
|
|
|
|
|
|
|
emailContent.append("</tr>"); |
|
|
|
|
|
} |
|
|
|
|
|
emailContent.append("</table>"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 明细修改记录 |
|
|
|
|
|
if (detailChanges != null && !detailChanges.isEmpty()) { |
|
|
|
|
|
emailContent.append("<div class='section-title'>📝 明细信息修改(共 ").append(detailChanges.size()).append(" 条)</div>"); |
|
|
|
|
|
emailContent.append("<table>"); |
|
|
|
|
|
emailContent.append("<tr><th>序号</th><th>PO</th><th>PN</th><th>数量</th><th>Rolls</th></tr>"); |
|
|
|
|
|
|
|
|
|
|
|
for (Map<String, Object> change : detailChanges) { |
|
|
|
|
|
emailContent.append("<tr>"); |
|
|
|
|
|
emailContent.append("<td>").append(change.get("seqNo")).append("-").append(change.get("itemNo")).append("</td>"); |
|
|
|
|
|
emailContent.append("<td>").append(change.get("poNo") != null ? change.get("poNo") : "-").append("</td>"); |
|
|
|
|
|
emailContent.append("<td>").append(change.get("pn") != null ? change.get("pn") : "-").append("</td>"); |
|
|
|
|
|
|
|
|
|
|
|
// 数量 |
|
|
|
|
|
emailContent.append("<td>"); |
|
|
|
|
|
if (change.containsKey("qty_old") && change.containsKey("qty_new")) { |
|
|
|
|
|
emailContent.append("<span class='old-value'>").append(change.get("qty_old")).append("</span>"); |
|
|
|
|
|
emailContent.append("<span class='arrow'>→</span>"); |
|
|
|
|
|
emailContent.append("<span class='new-value'>").append(change.get("qty_new")).append("</span>"); |
|
|
|
|
|
} else { |
|
|
|
|
|
emailContent.append("-"); |
|
|
|
|
|
} |
|
|
|
|
|
emailContent.append("</td>"); |
|
|
|
|
|
|
|
|
|
|
|
// Rolls |
|
|
|
|
|
emailContent.append("<td>"); |
|
|
|
|
|
if (change.containsKey("rolls_old") && change.containsKey("rolls_new")) { |
|
|
|
|
|
emailContent.append("<span class='old-value'>").append(change.get("rolls_old")).append("</span>"); |
|
|
|
|
|
emailContent.append("<span class='arrow'>→</span>"); |
|
|
|
|
|
emailContent.append("<span class='new-value'>").append(change.get("rolls_new")).append("</span>"); |
|
|
|
|
|
} else { |
|
|
|
|
|
emailContent.append("-"); |
|
|
|
|
|
} |
|
|
|
|
|
emailContent.append("</td>"); |
|
|
|
|
|
|
|
|
|
|
|
emailContent.append("</tr>"); |
|
|
|
|
|
} |
|
|
|
|
|
emailContent.append("</table>"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 页脚 |
|
|
|
|
|
emailContent.append("<hr style='margin-top: 30px; border: none; border-top: 1px solid #ddd;'>"); |
|
|
|
|
|
emailContent.append("<p style='color: #999; font-size: 12px;'>此邮件由系统自动发送,请勿直接回复。如有疑问请联系相关人员。</p>"); |
|
|
|
|
|
|
|
|
|
|
|
emailContent.append("</body>"); |
|
|
|
|
|
emailContent.append("</html>"); |
|
|
|
|
|
|
|
|
|
|
|
return emailContent.toString(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public List<Map<String, Object>> getCustomerTemplateList(Map<String, Object> params) { |
|
|
public List<Map<String, Object>> getCustomerTemplateList(Map<String, Object> params) { |
|
|
return coDelMapper.getCustomerTemplateList(params); |
|
|
return coDelMapper.getCustomerTemplateList(params); |
|
|
|