diff --git a/src/main/java/com/xujie/sys/modules/ecss/entity/EcssTemplate.java b/src/main/java/com/xujie/sys/modules/ecss/entity/EcssTemplate.java index f413a8d6..70164475 100644 --- a/src/main/java/com/xujie/sys/modules/ecss/entity/EcssTemplate.java +++ b/src/main/java/com/xujie/sys/modules/ecss/entity/EcssTemplate.java @@ -50,6 +50,7 @@ public class EcssTemplate extends QueryPage { private Boolean boxChange; private String customName; private Boolean highPalletFlag; + private Boolean showWeight; /** * 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 48607a60..42b8ccd5 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 @@ -1510,13 +1510,123 @@ public class CoDelServiceImpl implements CoDelService { } @Override + @Transactional public void updateCodelPalletHeaderPalletQty(EcssCoDelPalletHeaderData inData) { + // 获取发货通知单信息 + EcssCoDelNotifyHeaderData notifyHeader = coDelMapper.getEcssCoDelNotifyHeader(inData.getSite(), inData.getDelNo()); + + // 检查发货通知单状态是否为已报关 + boolean isCustomsCleared = "已报关".equals(notifyHeader.getNotifyStatus()); + + // 保存修改前的托数据(用于邮件通知) + List oldPalletHeaderList = null; + List deletedDeclarations = null; + + if (isCustomsCleared) { + log.info("托数修改:发货通知单{}状态为已报关,开始删除对应的报关单", inData.getDelNo()); + + // 保存修改前的托数据 + EcssCoDelNotifyHeaderData queryData = new EcssCoDelNotifyHeaderData(); + queryData.setSite(inData.getSite()); + queryData.setBuNo(inData.getBuNo()); + queryData.setDelNo(inData.getDelNo()); + List allPalletHeaders = coDelMapper.searchEcssCoDelPalletHeaderData(queryData); + // 根据seqNo过滤出当前修改的托盘 + oldPalletHeaderList = allPalletHeaders.stream() + .filter(p -> p.getSeqNo() != null && p.getSeqNo().equals(inData.getSeqNo())) + .collect(Collectors.toList()); + + // 查找对应的报关单 + EcssDeclarationHeaderData declarationQuery = new EcssDeclarationHeaderData(); + declarationQuery.setSite(inData.getSite()); + declarationQuery.setDelNo(inData.getDelNo()); + + deletedDeclarations = coDelMapper.searchDeclarationHeader( + new Page(1, 1000), declarationQuery).getRecords(); + + // 删除找到的报关单 + for (EcssDeclarationHeaderData declaration : deletedDeclarations) { + log.info("删除报关单,报关单号:{}", declaration.getDeclarationNo()); + coDelMapper.deleteDeclarationHeader(declaration); + coDelMapper.deleteDeclarationDetail(declaration); + } + + log.info("已删除发货通知单{}对应的{}个报关单", inData.getDelNo(), deletedDeclarations.size()); + + // 将通知单状态更新为仓库已确认 + notifyHeader.setNotifyStatus("仓库已确认"); + coDelMapper.changeEcssDelStatus(notifyHeader); + + log.info("发货通知单{}状态已更新为仓库已确认", inData.getDelNo()); + } + + // 执行修改操作 coDelMapper.updateCodelPalletHeaderPalletQty(inData); + + // 如果状态为已报关,发送邮件通知创建人 + if (isCustomsCleared && deletedDeclarations != null && !deletedDeclarations.isEmpty()) { + sendPalletQtyChangeNotificationEmail(notifyHeader, oldPalletHeaderList, deletedDeclarations, inData); + } } @Override + @Transactional public void deletePalletHeader(EcssCoDelPalletHeaderData inData) { + // 获取发货通知单信息 + EcssCoDelNotifyHeaderData notifyHeader = coDelMapper.getEcssCoDelNotifyHeader(inData.getSite(), inData.getDelNo()); + + // 检查发货通知单状态是否为已报关 + boolean isCustomsCleared = "已报关".equals(notifyHeader.getNotifyStatus()); + + // 保存删除前的托数据(用于邮件通知) + List oldPalletHeaderList = null; + List deletedDeclarations = null; + + if (isCustomsCleared) { + log.info("托数删除:发货通知单{}状态为已报关,开始删除对应的报关单", inData.getDelNo()); + + // 保存删除前的托数据 + EcssCoDelNotifyHeaderData queryData = new EcssCoDelNotifyHeaderData(); + queryData.setSite(inData.getSite()); + queryData.setBuNo(inData.getBuNo()); + queryData.setDelNo(inData.getDelNo()); + List allPalletHeaders = coDelMapper.searchEcssCoDelPalletHeaderData(queryData); + // 根据seqNo过滤出当前删除的托盘 + oldPalletHeaderList = allPalletHeaders.stream() + .filter(p -> p.getSeqNo() != null && p.getSeqNo().equals(inData.getSeqNo())) + .collect(Collectors.toList()); + + // 查找对应的报关单 + EcssDeclarationHeaderData declarationQuery = new EcssDeclarationHeaderData(); + declarationQuery.setSite(inData.getSite()); + declarationQuery.setDelNo(inData.getDelNo()); + + deletedDeclarations = coDelMapper.searchDeclarationHeader( + new Page(1, 1000), declarationQuery).getRecords(); + + // 删除找到的报关单 + for (EcssDeclarationHeaderData declaration : deletedDeclarations) { + log.info("删除报关单,报关单号:{}", declaration.getDeclarationNo()); + coDelMapper.deleteDeclarationHeader(declaration); + coDelMapper.deleteDeclarationDetail(declaration); + } + + log.info("已删除发货通知单{}对应的{}个报关单", inData.getDelNo(), deletedDeclarations.size()); + + // 将通知单状态更新为仓库已确认 + notifyHeader.setNotifyStatus("仓库已确认"); + coDelMapper.changeEcssDelStatus(notifyHeader); + + log.info("发货通知单{}状态已更新为仓库已确认", inData.getDelNo()); + } + + // 执行删除操作 coDelMapper.deletePalletHeader(inData); + + // 如果状态为已报关,发送邮件通知创建人 + if (isCustomsCleared && deletedDeclarations != null && !deletedDeclarations.isEmpty()) { + sendPalletDeleteNotificationEmail(notifyHeader, oldPalletHeaderList, deletedDeclarations, inData); + } } @@ -3195,7 +3305,33 @@ public class CoDelServiceImpl implements CoDelService { // 如果状态为已报关,发送邮件通知创建人 if (isCustomsCleared) { - sendPackingChangeNotificationEmail(notifyHeader, oldBoxList, oldPalletDetailList, inData); + log.info("一键装箱:发货通知单{}状态为已报关,开始删除对应的报关单", inData.getDelNo()); + + // 查找对应的报关单 + EcssDeclarationHeaderData declarationQuery = new EcssDeclarationHeaderData(); + declarationQuery.setSite(inData.getSite()); + declarationQuery.setDelNo(inData.getDelNo()); + + List deletedDeclarations = coDelMapper.searchDeclarationHeader( + new Page(1, 1000), declarationQuery).getRecords(); + + // 删除找到的报关单 + for (EcssDeclarationHeaderData declaration : deletedDeclarations) { + log.info("删除报关单,报关单号:{}", declaration.getDeclarationNo()); + coDelMapper.deleteDeclarationHeader(declaration); + coDelMapper.deleteDeclarationDetail(declaration); + } + + log.info("已删除发货通知单{}对应的{}个报关单", inData.getDelNo(), deletedDeclarations.size()); + + // 将通知单状态更新为仓库已确认 + notifyHeader.setNotifyStatus("仓库已确认"); + coDelMapper.changeEcssDelStatus(notifyHeader); + + log.info("发货通知单{}状态已更新为仓库已确认", inData.getDelNo()); + + // 发送邮件通知(包含报关单删除信息) + sendPackingChangeNotificationEmail(notifyHeader, oldBoxList, oldPalletDetailList, deletedDeclarations, inData); } } @@ -3455,18 +3591,46 @@ public class CoDelServiceImpl implements CoDelService { // 检查发货通知单状态是否为已报关 boolean isCustomsCleared = "已报关".equals(notifyHeader.getNotifyStatus()); - // 如果状态为已报关,保存修改前的装箱数据用于对比 + // 保存修改前的装箱数据(用于邮件通知) List oldBoxList = new ArrayList<>(); + List deletedDeclarations = null; + if (isCustomsCleared) { + log.info("装箱数据修改:发货通知单{}状态为已报关,开始删除对应的报关单", delNo); + + // 保存修改前的装箱数据 oldBoxList = coDelMapper.selectBoxList(notifyHeader); + + // 查找对应的报关单 + EcssDeclarationHeaderData declarationQuery = new EcssDeclarationHeaderData(); + declarationQuery.setSite(site); + declarationQuery.setDelNo(delNo); + + deletedDeclarations = coDelMapper.searchDeclarationHeader( + new Page(1, 1000), declarationQuery).getRecords(); + + // 删除找到的报关单 + for (EcssDeclarationHeaderData declaration : deletedDeclarations) { + log.info("删除报关单,报关单号:{}", declaration.getDeclarationNo()); + coDelMapper.deleteDeclarationHeader(declaration); + coDelMapper.deleteDeclarationDetail(declaration); + } + + log.info("已删除发货通知单{}对应的{}个报关单", delNo, deletedDeclarations.size()); + + // 将通知单状态更新为仓库已确认 + notifyHeader.setNotifyStatus("仓库已确认"); + coDelMapper.changeEcssDelStatus(notifyHeader); + + log.info("发货通知单{}状态已更新为仓库已确认", delNo); } // 执行修改操作 coDelMapper.updateBoxInfo(boxData); // 如果状态为已报关,发送邮件通知创建人 - if (isCustomsCleared) { - sendBoxChangeNotificationEmail(notifyHeader, oldBoxList, "修改", boxData); + if (isCustomsCleared && deletedDeclarations != null && !deletedDeclarations.isEmpty()) { + sendBoxChangeNotificationEmailWithDeclaration(notifyHeader, oldBoxList, deletedDeclarations, "修改", boxData); } } @@ -3481,10 +3645,38 @@ public class CoDelServiceImpl implements CoDelService { // 检查发货通知单状态是否为已报关 boolean isCustomsCleared = "已报关".equals(notifyHeader.getNotifyStatus()); - // 如果状态为已报关,保存删除前的装箱数据用于对比 + // 保存删除前的装箱数据(用于邮件通知) List oldBoxList = new ArrayList<>(); + List deletedDeclarations = null; + if (isCustomsCleared) { + log.info("装箱数据删除:发货通知单{}状态为已报关,开始删除对应的报关单", delNo); + + // 保存删除前的装箱数据 oldBoxList = coDelMapper.selectBoxList(notifyHeader); + + // 查找对应的报关单 + EcssDeclarationHeaderData declarationQuery = new EcssDeclarationHeaderData(); + declarationQuery.setSite(site); + declarationQuery.setDelNo(delNo); + + deletedDeclarations = coDelMapper.searchDeclarationHeader( + new Page(1, 1000), declarationQuery).getRecords(); + + // 删除找到的报关单 + for (EcssDeclarationHeaderData declaration : deletedDeclarations) { + log.info("删除报关单,报关单号:{}", declaration.getDeclarationNo()); + coDelMapper.deleteDeclarationHeader(declaration); + coDelMapper.deleteDeclarationDetail(declaration); + } + + log.info("已删除发货通知单{}对应的{}个报关单", delNo, deletedDeclarations.size()); + + // 将通知单状态更新为仓库已确认 + notifyHeader.setNotifyStatus("仓库已确认"); + coDelMapper.changeEcssDelStatus(notifyHeader); + + log.info("发货通知单{}状态已更新为仓库已确认", delNo); } // 获取该箱下的全部箱明细 @@ -3523,8 +3715,8 @@ public class CoDelServiceImpl implements CoDelService { coDelMapper.deleteBoxInfo(boxData); // 如果状态为已报关,发送邮件通知创建人 - if (isCustomsCleared) { - sendBoxChangeNotificationEmail(notifyHeader, oldBoxList, "删除", boxData); + if (isCustomsCleared && deletedDeclarations != null && !deletedDeclarations.isEmpty()) { + sendBoxChangeNotificationEmailWithDeclaration(notifyHeader, oldBoxList, deletedDeclarations, "删除", boxData); } } @@ -3770,6 +3962,7 @@ public class CoDelServiceImpl implements CoDelService { * @param notifyHeader 发货通知单头数据 * @param oldBoxList 计算前的箱子列表 * @param oldPalletDetailList 计算前的装箱明细列表 + * @param deletedDeclarations 已删除的报关单列表 * @param inData 输入参数 * @author AI Assistant * @date 2024-10-09 @@ -3777,6 +3970,7 @@ public class CoDelServiceImpl implements CoDelService { private void sendPackingChangeNotificationEmail(EcssCoDelNotifyHeaderData notifyHeader, List oldBoxList, List oldPalletDetailList, + List deletedDeclarations, EcssCoDelPalletHeaderData inData) { try { log.info("开始发送装箱变更通知邮件,发货通知单号:{}", notifyHeader.getDelNo()); @@ -3789,9 +3983,9 @@ public class CoDelServiceImpl implements CoDelService { queryData.setDelNo(inData.getDelNo()); List newPalletDetailList = coDelMapper.searchEcssCoDelPalletDetailData(queryData); - // 生成对比邮件内容 + // 生成对比邮件内容(包含报关单删除信息) String emailContent = generatePackingComparisonEmailContent(notifyHeader, oldBoxList, newBoxList, - oldPalletDetailList, newPalletDetailList); + oldPalletDetailList, newPalletDetailList, deletedDeclarations); // 获取发货通知单创建人邮箱 SysUserEntity creator = coDelMapper.queryByUserName(notifyHeader.getCreateBy()); @@ -3802,7 +3996,7 @@ public class CoDelServiceImpl implements CoDelService { String creatorEmail = creator.getEmail(); // 发送邮件 - String subject = String.format("发货通知单%s【发票:%s】一键装箱数据变更通知", + String subject = String.format("发货通知单%s【发票:%s】一键装箱数据变更及报关单删除通知", notifyHeader.getDelNo(), notifyHeader.getCmcInvoice()); String[] mailAddress = {creatorEmail}; @@ -3825,6 +4019,7 @@ public class CoDelServiceImpl implements CoDelService { * @param newBoxList 计算后的箱子列表 * @param oldPalletDetailList 计算前的装箱明细列表 * @param newPalletDetailList 计算后的装箱明细列表 + * @param deletedDeclarations 已删除的报关单列表 * @return HTML格式的邮件内容 * @author AI Assistant * @date 2024-10-09 @@ -3833,7 +4028,8 @@ public class CoDelServiceImpl implements CoDelService { List oldBoxList, List newBoxList, List oldPalletDetailList, - List newPalletDetailList) { + List newPalletDetailList, + List deletedDeclarations) { StringBuilder emailContent = new StringBuilder(); emailContent.append(""); @@ -3846,19 +4042,36 @@ public class CoDelServiceImpl implements CoDelService { emailContent.append("th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }"); emailContent.append("th { background-color: #f2f2f2; font-weight: bold; }"); emailContent.append(".changed { color: red; font-weight: bold; }"); + emailContent.append(".warning { color: #ff6600; font-size: 16px; font-weight: bold; margin: 20px 0; padding: 10px; background-color: #fff3cd; border: 1px solid #ff6600; }"); emailContent.append(".section-title { color: #333; font-size: 16px; font-weight: bold; margin: 20px 0 10px 0; }"); emailContent.append(""); emailContent.append(""); emailContent.append(""); // 邮件标题 - emailContent.append("

发货通知单一键装箱数据变更通知

"); + emailContent.append("

发货通知单一键装箱数据变更及报关单删除通知

"); emailContent.append("

发货通知单号:").append(notifyHeader.getDelNo()).append("

"); emailContent.append("

发票号:").append(notifyHeader.getCmcInvoice()).append("

"); emailContent.append("

客户:").append(notifyHeader.getCustomerName()).append("

"); emailContent.append("

操作时间:").append(DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")).append("

"); emailContent.append("

操作类型:一键装箱重新计算

"); + // 报关单删除警告信息 + if (deletedDeclarations != null && !deletedDeclarations.isEmpty()) { + emailContent.append("
"); + emailContent.append("⚠️ 重要提示:由于执行了一键装箱重新计算,以下报关单已被删除,发货通知单状态已更新为'仓库已确认':"); + emailContent.append("
    "); + for (EcssDeclarationHeaderData declaration : deletedDeclarations) { + emailContent.append("
  • ") + .append(notifyHeader.getCmcInvoice()) + .append(" 发票报关单【报关单号:") + .append(declaration.getDeclarationNo()) + .append("】已删除
  • "); + } + emailContent.append("
"); + emailContent.append("
"); + } + // 箱子信息对比 emailContent.append("
箱子信息对比
"); emailContent.append(generateBoxListComparisonTable(oldBoxList, newBoxList)); @@ -4357,4 +4570,438 @@ public class CoDelServiceImpl implements CoDelService { return result; } + /** + * 发送装箱数据变更通知邮件(包含报关单删除信息) + * + * @param notifyHeader 发货通知单头数据 + * @param oldBoxList 操作前的箱子列表 + * @param deletedDeclarations 已删除的报关单列表 + * @param operation 操作类型(修改/删除) + * @param boxData 操作的箱子数据 + * @author AI Assistant + * @date 2025-01-20 + */ + private void sendBoxChangeNotificationEmailWithDeclaration(EcssCoDelNotifyHeaderData notifyHeader, + List oldBoxList, + List deletedDeclarations, + String operation, + Map boxData) { + try { + log.info("开始发送装箱{}通知邮件(含报关单删除信息),发货通知单号:{}", operation, notifyHeader.getDelNo()); + + // 获取操作后的装箱数据 + List newBoxList = coDelMapper.selectBoxList(notifyHeader); + + // 生成对比邮件内容(包含报关单删除信息) + String emailContent = generateBoxChangeEmailContentWithDeclaration(notifyHeader, oldBoxList, newBoxList, + deletedDeclarations, operation, boxData); + + // 获取发货通知单创建人邮箱 + 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及报关单删除通知", + notifyHeader.getDelNo(), notifyHeader.getCmcInvoice(), operation); + String[] mailAddress = {creatorEmail}; + + sendMailUtil(subject, emailContent, mailAddress, notifyHeader); + + log.info("装箱{}通知邮件发送成功(含报关单删除信息),收件人:{}", operation, creatorEmail); + + } catch (Exception e) { + log.error("发送装箱{}通知邮件失败(含报关单删除信息),发货通知单号:{}, 错误信息:{}", + operation, notifyHeader.getDelNo(), e.getMessage(), e); + // 邮件发送失败不影响主流程,只记录日志 + } + } + + /** + * 生成装箱数据变更邮件内容(包含报关单删除信息) + * + * @param notifyHeader 发货通知单头数据 + * @param oldBoxList 操作前的箱子列表 + * @param newBoxList 操作后的箱子列表 + * @param deletedDeclarations 已删除的报关单列表 + * @param operation 操作类型 + * @param boxData 操作的箱子数据 + * @return HTML格式的邮件内容 + */ + private String generateBoxChangeEmailContentWithDeclaration(EcssCoDelNotifyHeaderData notifyHeader, + List oldBoxList, + List newBoxList, + List deletedDeclarations, + String operation, + Map boxData) { + StringBuilder emailContent = new StringBuilder(); + + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + + // 邮件标题 + emailContent.append("

发货通知单装箱数据").append(operation).append("及报关单删除通知

"); + emailContent.append("

发货通知单号:").append(notifyHeader.getDelNo()).append("

"); + emailContent.append("

发票号:").append(notifyHeader.getCmcInvoice()).append("

"); + emailContent.append("

客户:").append(notifyHeader.getCustomerName()).append("

"); + emailContent.append("

操作时间:").append(DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")).append("

"); + emailContent.append("

操作类型:").append(operation).append("装箱数据(序号:").append(boxData.get("item_no")).append(")

"); + + // 报关单删除警告信息 + if (deletedDeclarations != null && !deletedDeclarations.isEmpty()) { + emailContent.append("
"); + emailContent.append("⚠️ 重要提示:由于").append(operation).append("了装箱数据,以下报关单已被删除,发货通知单状态已更新为'仓库已确认':"); + emailContent.append("
    "); + for (EcssDeclarationHeaderData declaration : deletedDeclarations) { + emailContent.append("
  • ") + .append(notifyHeader.getCmcInvoice()) + .append(" 发票报关单【报关单号:") + .append(declaration.getDeclarationNo()) + .append("】已删除
  • "); + } + emailContent.append("
"); + emailContent.append("
"); + } + + // 装箱数据信息对比 + emailContent.append("
装箱数据信息对比
"); + emailContent.append(generateBoxListComparisonTable(oldBoxList, newBoxList)); + + emailContent.append("

备注:请重新生成报关单。

"); + + emailContent.append(""); + emailContent.append(""); + + return emailContent.toString(); + } + + /** + * 发送托数修改通知邮件(托盘头表) + * + * @param notifyHeader 发货通知单头数据 + * @param oldPalletHeaderList 修改前的托盘头表数据列表 + * @param deletedDeclarations 已删除的报关单列表 + * @param inData 托盘头表数据 + * @author AI Assistant + * @date 2025-01-20 + */ + private void sendPalletQtyChangeNotificationEmail(EcssCoDelNotifyHeaderData notifyHeader, + List oldPalletHeaderList, + List deletedDeclarations, + EcssCoDelPalletHeaderData inData) { + try { + log.info("开始发送托数修改通知邮件,发货通知单号:{}", notifyHeader.getDelNo()); + + // 生成邮件内容 + String emailContent = generatePalletQtyChangeEmailContent(notifyHeader, oldPalletHeaderList, + deletedDeclarations, inData); + + // 获取发货通知单创建人邮箱 + 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 oldPalletHeaderList 删除前的托盘头表数据列表 + * @param deletedDeclarations 已删除的报关单列表 + * @param inData 托盘头表数据 + * @author AI Assistant + * @date 2025-01-29 + */ + private void sendPalletDeleteNotificationEmail(EcssCoDelNotifyHeaderData notifyHeader, + List oldPalletHeaderList, + List deletedDeclarations, + EcssCoDelPalletHeaderData inData) { + try { + log.info("开始发送托数删除通知邮件,发货通知单号:{}", notifyHeader.getDelNo()); + + // 生成邮件内容 + String emailContent = generatePalletDeleteEmailContent(notifyHeader, oldPalletHeaderList, + deletedDeclarations, inData); + + // 获取发货通知单创建人邮箱 + 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 oldPalletHeaderList 删除前的托盘头表数据列表 + * @param deletedDeclarations 已删除的报关单列表 + * @param inData 托盘头表数据 + * @return HTML格式的邮件内容 + */ + private String generatePalletDeleteEmailContent(EcssCoDelNotifyHeaderData notifyHeader, + List oldPalletHeaderList, + List deletedDeclarations, + EcssCoDelPalletHeaderData inData) { + StringBuilder emailContent = new StringBuilder(); + + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + + // 邮件标题 + emailContent.append("

发货通知单托数删除及报关单删除通知

"); + emailContent.append("

发货通知单号:").append(notifyHeader.getDelNo()).append("

"); + emailContent.append("

发票号:").append(notifyHeader.getCmcInvoice()).append("

"); + emailContent.append("

客户:").append(notifyHeader.getCustomerName()).append("

"); + emailContent.append("

操作时间:").append(DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")).append("

"); + emailContent.append("

操作类型:删除栈板

"); + + // 报关单删除警告信息 + if (deletedDeclarations != null && !deletedDeclarations.isEmpty()) { + emailContent.append("
"); + emailContent.append("⚠️ 重要提示:由于删除了托数,以下报关单已被删除,发货通知单状态已更新为'仓库已确认':"); + emailContent.append("
    "); + for (EcssDeclarationHeaderData declaration : deletedDeclarations) { + emailContent.append("
  • ") + .append(notifyHeader.getCmcInvoice()) + .append(" 发票报关单【报关单号:") + .append(declaration.getDeclarationNo()) + .append("】已删除
  • "); + } + emailContent.append("
"); + emailContent.append("
"); + } + + // 已删除的托数信息 + emailContent.append("
已删除的托数信息
"); + emailContent.append("

托盘序号:").append(inData.getSeqNo()).append("

"); + + if (oldPalletHeaderList != null && !oldPalletHeaderList.isEmpty()) { + EcssCoDelPalletHeaderData oldData = oldPalletHeaderList.get(0); + emailContent.append(""); + emailContent.append(""); + + // 托数 + if (oldData.getPalletQty() != null) { + emailContent.append(""); + } + + // 高度 + if (oldData.getHeight() != null) { + emailContent.append(""); + } + + // 托盘编号 + + // 毛重 + if (oldData.getGrossWeight() != null) { + emailContent.append(""); + } + + // 净重 + if (oldData.getNetWeight() != null) { + emailContent.append(""); + } + + // 箱数 + if (oldData.getBoxQty() != null) { + emailContent.append(""); + } + + emailContent.append("
字段删除前的数据
托数") + .append(oldData.getPalletQty()) + .append("
高度") + .append(oldData.getHeight()) + .append("
毛重") + .append(oldData.getGrossWeight()) + .append("
净重") + .append(oldData.getNetWeight()) + .append("
箱数") + .append(oldData.getBoxQty()) + .append("
"); + } + + emailContent.append("

备注:请重新生成报关单。

"); + + emailContent.append(""); + emailContent.append(""); + + return emailContent.toString(); + } + + /** + * 生成托数修改邮件内容 + * + * @param notifyHeader 发货通知单头数据 + * @param oldPalletHeaderList 修改前的托盘头表数据列表 + * @param deletedDeclarations 已删除的报关单列表 + * @param inData 托盘头表数据 + * @return HTML格式的邮件内容 + */ + private String generatePalletQtyChangeEmailContent(EcssCoDelNotifyHeaderData notifyHeader, + List oldPalletHeaderList, + List deletedDeclarations, + EcssCoDelPalletHeaderData inData) { + StringBuilder emailContent = new StringBuilder(); + + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + emailContent.append(""); + + // 邮件标题 + emailContent.append("

发货通知单托数修改及报关单删除通知

"); + emailContent.append("

发货通知单号:").append(notifyHeader.getDelNo()).append("

"); + emailContent.append("

发票号:").append(notifyHeader.getCmcInvoice()).append("

"); + emailContent.append("

客户:").append(notifyHeader.getCustomerName()).append("

"); + emailContent.append("

操作时间:").append(DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")).append("

"); + + // 报关单删除警告信息 + if (deletedDeclarations != null && !deletedDeclarations.isEmpty()) { + emailContent.append("
"); + emailContent.append("⚠️ 重要提示:由于修改了托数,以下报关单已被删除,发货通知单状态已更新为'仓库已确认':"); + emailContent.append("
    "); + for (EcssDeclarationHeaderData declaration : deletedDeclarations) { + emailContent.append("
  • ") + .append(notifyHeader.getCmcInvoice()) + .append(" 发票报关单【报关单号:") + .append(declaration.getDeclarationNo()) + .append("】已删除
  • "); + } + emailContent.append("
"); + emailContent.append("
"); + } + + // 托数修改信息 + emailContent.append("
托数修改信息
"); + emailContent.append("

托盘序号:").append(inData.getSeqNo()).append("

"); + + if (oldPalletHeaderList != null && !oldPalletHeaderList.isEmpty()) { + EcssCoDelPalletHeaderData oldData = oldPalletHeaderList.get(0); + emailContent.append(""); + emailContent.append(""); + + // 比较托数字段 + if (!Objects.equals(oldData.getPalletQty(), inData.getPalletQty())) { + emailContent.append(""); + } + + // 比较高度字段 + if (!Objects.equals(oldData.getHeight(), inData.getHeight())) { + emailContent.append(""); + } + + if (oldData.getGrossWeight() != null) { + emailContent.append(""); + } + + if (oldData.getNetWeight() != null) { + emailContent.append(""); + } + + if (oldData.getBoxQty() != null) { + emailContent.append(""); + } + + emailContent.append("
字段修改前修改后
托数") + .append(oldData.getPalletQty() != null ? oldData.getPalletQty() : "") + .append("") + .append(inData.getPalletQty() != null ? inData.getPalletQty() : "") + .append("
高度") + .append(oldData.getHeight() != null ? oldData.getHeight() : "") + .append("") + .append(inData.getHeight() != null ? inData.getHeight() : "") + .append("
毛重") + .append(oldData.getGrossWeight()) + .append("
净重") + .append(oldData.getNetWeight()) + .append("
箱数") + .append(oldData.getBoxQty()) + .append("
"); + } + + emailContent.append("

备注:请重新生成报关单。

"); + + emailContent.append(""); + emailContent.append(""); + + return emailContent.toString(); + } + } diff --git a/src/main/resources/mapper/ecss/CoDelMapper.xml b/src/main/resources/mapper/ecss/CoDelMapper.xml index 32c0265b..20303e18 100644 --- a/src/main/resources/mapper/ecss/CoDelMapper.xml +++ b/src/main/resources/mapper/ecss/CoDelMapper.xml @@ -1079,11 +1079,11 @@ left join ecss_CoDelNotifyHeader noHeader on a.site=noHeader.site and a.delNo=no insert into ecss_template (customName,site,buNo,name,type,upc,so,origin,palletWeight,material,hsCode,packaging,itemNo, kgs,shippingMark,boxChange,hsCodeDesc,contractFlag,hsCodeDescType,goodsLabel,hsCodeFlag,shippingMode,CreateBy,CreateDate, - salesMethod,currency,madeArea,sendPort,shipper,voyage,deliveryGoodsDate,shippingDate,fscWeight, remark,highPalletFlag) + salesMethod,currency,madeArea,sendPort,shipper,voyage,deliveryGoodsDate,shippingDate,fscWeight, remark,highPalletFlag,showWeight) values(#{customName,jdbcType=NVARCHAR},#{site},#{buNo},#{name},#{type},#{upc},#{so},#{origin},#{palletWeight},#{material},#{hsCode},#{packaging}, #{itemNo},#{kgs},#{shippingMark},#{boxChange}, #{hsCodeDesc},#{contractFlag},#{hsCodeDescType},#{goodsLabel},#{hsCodeFlag},#{shippingMode},#{createBy},GetDate(), - #{salesMethod},#{currency},#{madeArea},#{sendPort},#{shipper},#{voyage},#{deliveryGoodsDate},#{shippingDate},#{fscWeight},#{remark},#{highPalletFlag}) + #{salesMethod},#{currency},#{madeArea},#{sendPort},#{shipper},#{voyage},#{deliveryGoodsDate},#{shippingDate},#{fscWeight},#{remark},#{highPalletFlag},#{showWeight}) @@ -1093,7 +1093,7 @@ left join ecss_CoDelNotifyHeader noHeader on a.site=noHeader.site and a.delNo=no contractFlag=#{contractFlag},hsCodeDescType=#{hsCodeDescType},goodsLabel=#{goodsLabel},hsCodeFlag=#{hsCodeFlag}, shippingMode=#{shippingMode},UpdateDate=GetDate(),UpdateBy=#{updateBy},customName=#{customName,jdbcType=NVARCHAR},salesMethod= #{salesMethod}, currency= #{currency},madeArea= #{madeArea},sendPort= #{sendPort},shipper= #{shipper},remark= #{remark}, - voyage= #{voyage},deliveryGoodsDate= #{deliveryGoodsDate},shippingDate= #{shippingDate},fscWeight=#{fscWeight},highPalletFlag=#{highPalletFlag} + voyage= #{voyage},deliveryGoodsDate= #{deliveryGoodsDate},shippingDate= #{shippingDate},fscWeight=#{fscWeight},highPalletFlag=#{highPalletFlag},showWeight=#{showWeight} where buNo=#{buNo} and name=#{nameNative}