diff --git a/src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java b/src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java
index 0bd9c89b..e2caf314 100644
--- a/src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java
+++ b/src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java
@@ -492,7 +492,11 @@ public class CoDelServiceImpl implements CoDelService {
data.getCmcInvoice()+"】订单取消" + "";
String textHead = data.getCmcInvoice()+"【发票:"+ data.getCmcInvoice()+"】订单取消";
String[] mailAddress = coDelMapper.queryUsersByRoleName("关务仓库",data.getSite()).stream().map(SysUserEntity::getEmail).toArray(String[]::new);
- String[] mailAddress2 = new String[]{coDelMapper.queryByUserName(data.getCreateBy()).getEmail()};
+
+ // 安全获取创建人邮箱,防止用户不存在或邮箱为空的空指针异常
+ SysUserEntity creator = coDelMapper.queryByUserName(data.getCreateBy());
+ String[] mailAddress2 = (creator != null && creator.getEmail() != null) ?
+ new String[]{creator.getEmail()} : new String[]{};
String[] mailAddressAll = ArrayUtils.addAll(mailAddress, mailAddress2);
if (mailAddressAll.length>0) {
sendMailUtil(textHead, text,mailAddressAll, data);
@@ -512,7 +516,11 @@ public class CoDelServiceImpl implements CoDelService {
data.getCmcInvoice()+"】取消废弃,恢复正常" + "";
String textHead = data.getCmcInvoice()+"【发票:"+ data.getCmcInvoice()+"】取消废弃";
String[] mailAddress = coDelMapper.queryUsersByRoleName("关务仓库",data.getSite()).stream().map(SysUserEntity::getEmail).toArray(String[]::new);
- String[] mailAddress2 = new String[]{coDelMapper.queryByUserName(data.getCreateBy()).getEmail()};
+
+ // 安全获取创建人邮箱,防止用户不存在或邮箱为空的空指针异常
+ SysUserEntity creator = coDelMapper.queryByUserName(data.getCreateBy());
+ String[] mailAddress2 = (creator != null && creator.getEmail() != null) ?
+ new String[]{creator.getEmail()} : new String[]{};
String[] mailAddressAll = ArrayUtils.addAll(mailAddress, mailAddress2);
if (mailAddressAll.length>0) {
sendMailUtil(textHead, text,mailAddressAll, data);
@@ -643,7 +651,11 @@ public class CoDelServiceImpl implements CoDelService {
+" 变更后数量:"+data.getQty()+"";
String textHead = data.getDelNo()+"【发票:"+ data.getCmcInvoice()+"】改单[发货数量变更]";
String[] mailAddress = coDelMapper.queryUsersByRoleName("关务仓库",data.getSite()).stream().map(SysUserEntity::getEmail).toArray(String[]::new);
- String[] mailAddress2 = new String[]{coDelMapper.queryByUserName(checkHeader.get(0).getCreateBy()).getEmail()};
+
+ // 安全获取创建人邮箱,防止用户不存在或邮箱为空的空指针异常
+ SysUserEntity creator = coDelMapper.queryByUserName(checkHeader.get(0).getCreateBy());
+ String[] mailAddress2 = (creator != null && creator.getEmail() != null) ?
+ new String[]{creator.getEmail()} : new String[]{};
String[] mailAddressAll = ArrayUtils.addAll(mailAddress, mailAddress2);
if (mailAddressAll.length>0) {
sendMailUtil(textHead, text,mailAddressAll, checkHeader.get(0));
@@ -666,7 +678,11 @@ public class CoDelServiceImpl implements CoDelService {
" 新增发货";
String textHead = data.getDelNo()+"【发票:"+ data.getCmcInvoice()+"】改单[新增发货]";
String[] mailAddress = coDelMapper.queryUsersByRoleName("关务仓库",data.getSite()).stream().map(SysUserEntity::getEmail).toArray(String[]::new);
- String[] mailAddress2 = new String[]{coDelMapper.queryByUserName(checkHeader.get(0).getCreateBy()).getEmail()};
+
+ // 安全获取创建人邮箱,防止用户不存在或邮箱为空的空指针异常
+ SysUserEntity creator = coDelMapper.queryByUserName(checkHeader.get(0).getCreateBy());
+ String[] mailAddress2 = (creator != null && creator.getEmail() != null) ?
+ new String[]{creator.getEmail()} : new String[]{};
String[] mailAddressAll = ArrayUtils.addAll(mailAddress, mailAddress2);
if (mailAddressAll.length>0) {
sendMailUtil(textHead, text,mailAddressAll, checkHeader.get(0));
@@ -703,7 +719,11 @@ public class CoDelServiceImpl implements CoDelService {
" 取消发货";
String textHead = data.getDelNo()+"【发票:"+ data.getCmcInvoice()+"】改单[取消发货]";
String[] mailAddress = coDelMapper.queryUsersByRoleName("关务仓库",data.getSite()).stream().map(SysUserEntity::getEmail).toArray(String[]::new);
- String[] mailAddress2 = new String[]{coDelMapper.queryByUserName(checkHeader.get(0).getCreateBy()).getEmail()};
+
+ // 安全获取创建人邮箱,防止用户不存在或邮箱为空的空指针异常
+ SysUserEntity creator = coDelMapper.queryByUserName(checkHeader.get(0).getCreateBy());
+ String[] mailAddress2 = (creator != null && creator.getEmail() != null) ?
+ new String[]{creator.getEmail()} : new String[]{};
String[] mailAddressAll = ArrayUtils.addAll(mailAddress, mailAddress2);
if (mailAddressAll.length>0) {
sendMailUtil(textHead, text,mailAddressAll, checkHeader.get(0));
@@ -725,8 +745,15 @@ public class CoDelServiceImpl implements CoDelService {
//设置邮件内容
String text = "" + "
发货通知单" +data.getDelNo()+"【发票:"+ data.getCmcInvoice()+"】仓库已确认" + "
";
String textHead = "发货通知单"+data.getDelNo()+"【发票:"+ data.getCmcInvoice()+"】仓库已确认";
- String[] mailAddress = new String[]{coDelMapper.queryByUserName(checkHeader.get(0).getCreateBy()).getEmail()};
- sendMailUtil(textHead, text, mailAddress, data);
+
+ // 安全获取创建人邮箱,防止用户不存在或邮箱为空的空指针异常
+ SysUserEntity creator = coDelMapper.queryByUserName(checkHeader.get(0).getCreateBy());
+ if (creator != null && creator.getEmail() != null && !creator.getEmail().trim().isEmpty()) {
+ String[] mailAddress = new String[]{creator.getEmail()};
+ sendMailUtil(textHead, text, mailAddress, data);
+ } else {
+ log.warn("仓库确认邮件发送失败:创建人{}不存在或邮箱为空", checkHeader.get(0).getCreateBy());
+ }
}
@Override
@@ -782,20 +809,24 @@ public class CoDelServiceImpl implements CoDelService {
// 先删除全部明细,再新建明细
coDelMapper.deleteAllEcssDelDetail(headerData);
- // 构建原数据Map,用于比较数量是否变化
- Map originalQtyMap = dbData.stream()
- .collect(Collectors.toMap(EcssCoDelNotifyDetail::getPn, EcssCoDelNotifyDetail::getQty));
+ // 构建原数据Map,使用itemNo作为唯一标识
+ // 注意:不能用pn作为key,因为同一个pn可能有多行记录,每行都需要独立比较
+ Map originalDataMap = dbData.stream()
+ .collect(Collectors.toMap(EcssCoDelNotifyDetail::getItemNo, detail -> detail, (v1, v2) -> v1));
for (int i = 0; i < excelList.size(); i++) {
excelList.get(i).setDelNo(headerData.getDelNo());
excelList.get(i).setItemNo(i + 1);
excelList.get(i).setModifyFlag(true);
- // 判断数量是否变化:新增物料或数量不同时设置 modifyQtyFlag=true
- String pn = excelList.get(i).getPn();
- BigDecimal newQty = excelList.get(i).getQty();
- if (!originalQtyMap.containsKey(pn) ||
- !originalQtyMap.get(pn).equals(newQty)) {
+ // 判断数量是否变化:按itemNo匹配原数据,比较同一行的数量是否变化
+ Integer itemNo = i + 1;
+ EcssCoDelNotifyDetailData originalDetail = originalDataMap.get(itemNo);
+
+ // 如果原数据中不存在该itemNo(新增行),或者pn不同(换料),或者数量不同,则标记modifyQtyFlag=true
+ if (originalDetail == null ||
+ !originalDetail.getPn().equals(excelList.get(i).getPn()) ||
+ !originalDetail.getQty().equals(excelList.get(i).getQty())) {
excelList.get(i).setModifyQtyFlag(true);
}
}
@@ -810,10 +841,16 @@ public class CoDelServiceImpl implements CoDelService {
String textHead = headerData.getDelNo()+"【发票:"+ headerData.getCmcInvoice()+"】改单";
String[] mailAddress = coDelMapper.queryUsersByRoleName("关务仓库",headerData.getSite()).stream().map(SysUserEntity::getEmail).toArray(String[]::new);
- String[] mailAddress2 = new String[]{coDelMapper.queryByUserName(headerData.getCreateBy()).getEmail()};
+
+ // 安全获取创建人邮箱,防止用户不存在或邮箱为空的空指针异常
+ SysUserEntity creator = coDelMapper.queryByUserName(headerData.getCreateBy());
+ String[] mailAddress2 = (creator != null && creator.getEmail() != null) ?
+ new String[]{creator.getEmail()} : new String[]{};
+
// 合并 + 去重
String[] mailAddressAll = Stream.concat(Arrays.stream(mailAddress), Arrays.stream(mailAddress2))
.filter(Objects::nonNull) // 防止 null
+ .filter(email -> !email.trim().isEmpty()) // 过滤空字符串
.distinct() // 去重
.toArray(String[]::new);
if (mailAddressAll.length>0) {
@@ -832,8 +869,30 @@ public class CoDelServiceImpl implements CoDelService {
List dbData,
List newData) {
StringBuilder emailContent = new StringBuilder();
- emailContent.append("发货通知单").append(newHeaderData.getDelNo())
- .append("【发票:").append(newHeaderData.getCmcInvoice()).append("】改单
");
+
+ // HTML头部和样式
+ emailContent.append("");
+ emailContent.append("");
+ emailContent.append("");
+ emailContent.append("");
+ emailContent.append("");
+ emailContent.append("");
+ emailContent.append("");
+
+ // 邮件标题
+ emailContent.append("发货通知单改单通知
");
+ emailContent.append("发货通知单号:").append(newHeaderData.getDelNo()).append("
");
+ emailContent.append("发票号:").append(newHeaderData.getCmcInvoice()).append("
");
+ emailContent.append("操作时间:").append(DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")).append("
");
// 检查头表字段变更
StringBuilder headerChanges = new StringBuilder();
@@ -846,8 +905,8 @@ public class CoDelServiceImpl implements CoDelService {
DateUtils.format(originalHeaderData.getReadyDate(), "yyyy-MM-dd") : "无";
String newDate = newHeaderData.getReadyDate() != null ?
DateUtils.format(newHeaderData.getReadyDate(), "yyyy-MM-dd") : "无";
- headerChanges.append("Ready Date: ")
- .append(originalDate).append(" → ").append(newDate).append("");
+ headerChanges.append("Ready Date: ")
+ .append(originalDate).append(" → ").append(newDate).append("");
}
// 检查ShippingMode变更
@@ -855,8 +914,8 @@ public class CoDelServiceImpl implements CoDelService {
hasHeaderChanges = true;
String originalMode = originalHeaderData.getShippingMode() != null ? originalHeaderData.getShippingMode() : "无";
String newMode = newHeaderData.getShippingMode() != null ? newHeaderData.getShippingMode() : "无";
- headerChanges.append("Shipping Mode: ")
- .append(originalMode).append(" → ").append(newMode).append("");
+ headerChanges.append("Shipping Mode: ")
+ .append(originalMode).append(" → ").append(newMode).append("");
}
// 检查Destination变更
@@ -864,87 +923,105 @@ public class CoDelServiceImpl implements CoDelService {
hasHeaderChanges = true;
String originalDest = originalHeaderData.getDestination() != null ? originalHeaderData.getDestination() : "无";
String newDest = newHeaderData.getDestination() != null ? newHeaderData.getDestination() : "无";
- headerChanges.append("Destination: ")
- .append(originalDest).append(" → ").append(newDest).append("");
+ headerChanges.append("Destination: ")
+ .append(originalDest).append(" → ").append(newDest).append("");
}
// 如果有头表字段变更,添加到邮件内容
if (hasHeaderChanges) {
- emailContent.append("头表字段变更
")
- .append("").append(headerChanges).append("
");
- }
-
- // 处理明细变更
- Map> dbMap = dbData.stream().collect(Collectors.groupingBy(EcssCoDelNotifyDetail::getPn));
- Map> newMap = newData.stream().collect(Collectors.groupingBy(EcssCoDelNotifyDetail::getPn));
-
- // 构建原数据明细
- StringBuilder originalDetails = new StringBuilder();
- originalDetails.append("");
- for (EcssCoDelNotifyDetailData detail : dbData) {
- if (!newMap.containsKey(detail.getPn())) {
- // 删除的项目用红色显示
- originalDetails.append("- ")
- .append("PN:").append(detail.getPn()).append(" 数量:")
- .append(detail.getQty().setScale(0, RoundingMode.HALF_UP))
- .append(" [已删除]
");
- } else {
- // 检查数量是否有变更
- EcssCoDelNotifyDetailData newDetail = newMap.get(detail.getPn()).get(0);
- if (!detail.getQty().equals(newDetail.getQty())) {
- // 数量有变更,用红色显示
- originalDetails.append("- ")
- .append("PN:").append(detail.getPn()).append(" 数量:")
- .append(detail.getQty().setScale(0, RoundingMode.HALF_UP))
- .append("
");
- } else {
- // 无变更
- originalDetails.append("- ")
- .append("PN:").append(detail.getPn()).append(" 数量:")
- .append(detail.getQty().setScale(0, RoundingMode.HALF_UP))
- .append("
");
- }
- }
+ emailContent.append("头表字段变更
");
+ emailContent.append("").append(headerChanges).append("
");
}
- originalDetails.append("
");
-
- // 构建新数据明细
- StringBuilder newDetails = new StringBuilder();
- newDetails.append("");
- for (EcssCoDelNotifyDetailData detail : newData) {
- if (!dbMap.containsKey(detail.getPn())) {
- // 新增的项目用红色显示
- newDetails.append("- ")
- .append("PN:").append(detail.getPn()).append(" 数量:")
- .append(detail.getQty().setScale(0, RoundingMode.HALF_UP))
- .append(" [新增]
");
- } else {
- // 检查数量是否有变更
- EcssCoDelNotifyDetailData originalDetail = dbMap.get(detail.getPn()).get(0);
- if (!detail.getQty().equals(originalDetail.getQty())) {
- // 数量有变更,用红色显示
- newDetails.append("- ")
- .append("PN:").append(detail.getPn()).append(" 数量:")
- .append(detail.getQty().setScale(0, RoundingMode.HALF_UP))
- .append("
");
- } else {
- // 无变更
- newDetails.append("- ")
- .append("PN:").append(detail.getPn()).append(" 数量:")
- .append(detail.getQty().setScale(0, RoundingMode.HALF_UP))
- .append("
");
- }
- }
- }
- newDetails.append("
");
- // 添加明细变更到邮件内容
- String oldText = "原数据
" + originalDetails + "
";
- String newText = "新数据
" + newDetails + "
";
- emailContent.append(oldText).append(newText);
+ // 处理明细变更 - 生成对比表格
+ emailContent.append("明细数据对比
");
+ emailContent.append(generateDetailComparisonTable(dbData, newData));
+
+ emailContent.append("");
+ emailContent.append("");
return emailContent;
}
+
+ /**
+ * 生成明细对比表格
+ * @param dbData 原数据
+ * @param newData 新数据
+ * @return 表格HTML
+ */
+ private String generateDetailComparisonTable(List dbData,
+ List newData) {
+ StringBuilder table = new StringBuilder();
+
+ // 注意:不能用pn作为key,因为同一个pn可能有多行记录
+ // 应该用itemNo进行一对一匹配,比较每一行的变化
+ Map dbMap = dbData.stream()
+ .collect(Collectors.toMap(EcssCoDelNotifyDetail::getItemNo, detail -> detail, (v1, v2) -> v1));
+ Map newMap = newData.stream()
+ .collect(Collectors.toMap(EcssCoDelNotifyDetail::getItemNo, detail -> detail, (v1, v2) -> v1));
+
+ // 获取所有itemNo
+ Set allItemNos = new HashSet<>();
+ allItemNos.addAll(dbMap.keySet());
+ allItemNos.addAll(newMap.keySet());
+ List sortedItemNos = new ArrayList<>(allItemNos);
+ sortedItemNos.sort(Integer::compareTo);
+
+ table.append("");
+ table.append("");
+ table.append("| 项次 | ");
+ table.append("PN | ");
+ table.append("数量(原) | ");
+ table.append("数量(新) | ");
+ table.append("变更说明 | ");
+ table.append("
");
+
+ for (Integer itemNo : sortedItemNos) {
+ EcssCoDelNotifyDetailData oldDetail = dbMap.get(itemNo);
+ EcssCoDelNotifyDetailData newDetail = newMap.get(itemNo);
+
+ table.append("");
+ table.append("| ").append(itemNo).append(" | ");
+
+ // 判断变更类型
+ if (oldDetail == null) {
+ // 新增行
+ table.append("").append(newDetail.getPn()).append(" | ");
+ table.append("- | ");
+ table.append("").append(newDetail.getQty().setScale(0, RoundingMode.HALF_UP)).append(" | ");
+ table.append("新增 | ");
+ } else if (newDetail == null) {
+ // 删除行
+ table.append("").append(oldDetail.getPn()).append(" | ");
+ table.append("").append(oldDetail.getQty().setScale(0, RoundingMode.HALF_UP)).append(" | ");
+ table.append("- | ");
+ table.append("已删除 | ");
+ } else if (!oldDetail.getPn().equals(newDetail.getPn())) {
+ // 换料
+ table.append("").append(oldDetail.getPn()).append(" → ").append(newDetail.getPn()).append(" | ");
+ table.append("").append(oldDetail.getQty().setScale(0, RoundingMode.HALF_UP)).append(" | ");
+ table.append("").append(newDetail.getQty().setScale(0, RoundingMode.HALF_UP)).append(" | ");
+ table.append("换料 | ");
+ } else if (!oldDetail.getQty().equals(newDetail.getQty())) {
+ // 数量变化
+ table.append("").append(newDetail.getPn()).append(" | ");
+ table.append("").append(oldDetail.getQty().setScale(0, RoundingMode.HALF_UP)).append(" | ");
+ table.append("").append(newDetail.getQty().setScale(0, RoundingMode.HALF_UP)).append(" | ");
+ table.append("数量变更 | ");
+ } else {
+ // 无变化
+ table.append("").append(newDetail.getPn()).append(" | ");
+ table.append("").append(oldDetail.getQty().setScale(0, RoundingMode.HALF_UP)).append(" | ");
+ table.append("").append(newDetail.getQty().setScale(0, RoundingMode.HALF_UP)).append(" | ");
+ table.append("- | ");
+ }
+
+ table.append("
");
+ }
+
+ table.append("
");
+ return table.toString();
+ }
@Override
public void updateEcssDel(EcssCoDelNotifyHeaderData data) {
@@ -3721,11 +3798,12 @@ public class CoDelServiceImpl implements CoDelService {
oldPalletDetailList, newPalletDetailList);
// 获取发货通知单创建人邮箱
- String creatorEmail = coDelMapper.queryByUserName(notifyHeader.getCreateBy()).getEmail();
- if (StringUtils.isBlank(creatorEmail)) {
- log.warn("发货通知单创建人{}没有配置邮箱地址", notifyHeader.getCreateBy());
+ 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】一键装箱数据变更通知",
@@ -4028,11 +4106,12 @@ public class CoDelServiceImpl implements CoDelService {
String emailContent = generateBoxChangeEmailContent(notifyHeader, oldBoxList, newBoxList, operation, boxData);
// 获取发货通知单创建人邮箱
- String creatorEmail = coDelMapper.queryByUserName(notifyHeader.getCreateBy()).getEmail();
- if (StringUtils.isBlank(creatorEmail)) {
- log.warn("发货通知单创建人{}没有配置邮箱地址", notifyHeader.getCreateBy());
+ 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】箱子%s通知",
@@ -4078,11 +4157,12 @@ public class CoDelServiceImpl implements CoDelService {
String emailContent = generateDetailChangeEmailContent(notifyHeader, oldPalletDetailList, newPalletDetailList, operation, detailData);
// 获取发货通知单创建人邮箱
- String creatorEmail = coDelMapper.queryByUserName(notifyHeader.getCreateBy()).getEmail();
- if (StringUtils.isBlank(creatorEmail)) {
- log.warn("发货通知单创建人{}没有配置邮箱地址", notifyHeader.getCreateBy());
+ 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】箱明细%s通知",