@ -2655,6 +2655,23 @@ public class CoDelServiceImpl implements CoDelService {
public void saveOneClickPacking ( EcssCoDelPalletHeaderData inData ) {
/ / 发货通知单
EcssCoDelNotifyHeaderData notifyHeader = coDelMapper . getEcssCoDelNotifyHeader ( inData . getSite ( ) , inData . getDelNo ( ) ) ;
/ / 检查发货通知单状态是否为已报关
boolean isCustomsCleared = "已报关" . equals ( notifyHeader . getNotifyStatus ( ) ) ;
/ / 如果状态为已报关 , 保存计算前的装箱数据用于对比
List < Map > oldBoxList = new ArrayList < > ( ) ;
List < EcssCoDelPalletDetailData > oldPalletDetailList = new ArrayList < > ( ) ;
if ( isCustomsCleared ) {
/ / 获取计算前的装箱数据
oldBoxList = coDelMapper . selectBoxList ( notifyHeader ) ;
EcssCoDelPalletHeaderData queryData = new EcssCoDelPalletHeaderData ( ) ;
queryData . setSite ( inData . getSite ( ) ) ;
queryData . setBuNo ( inData . getBuNo ( ) ) ;
queryData . setDelNo ( inData . getDelNo ( ) ) ;
oldPalletDetailList = coDelMapper . searchEcssCoDelPalletDetailData ( queryData ) ;
}
/ / 先删除已存在的装箱数据
clearPalletData ( notifyHeader ) ;
SysUserEntity currentUser = ( SysUserEntity ) SecurityUtils . getSubject ( ) . getPrincipal ( ) ;
@ -2851,6 +2868,11 @@ public class CoDelServiceImpl implements CoDelService {
/ / notifyHeader . setModifyFlag ( false ) ;
coDelMapper . updateEcssDelHeaderForModify ( notifyHeader ) ;
coDelMapper . updateEcssDelDetailForModify ( notifyHeader ) ;
/ / 如果状态为已报关 , 发送邮件通知创建人
if ( isCustomsCleared ) {
sendPackingChangeNotificationEmail ( notifyHeader , oldBoxList , oldPalletDetailList , inData ) ;
}
}
private void clearPalletData ( EcssCoDelNotifyHeaderData inData ) {
@ -3101,12 +3123,46 @@ public class CoDelServiceImpl implements CoDelService {
@Override
@Transactional
public void updateBoxInfo ( Map < String , Object > boxData ) {
/ / 获取发货通知单信息
String site = boxData . get ( "site" ) . toString ( ) ;
String delNo = boxData . get ( "delNo" ) . toString ( ) ;
EcssCoDelNotifyHeaderData notifyHeader = coDelMapper . getEcssCoDelNotifyHeader ( site , delNo ) ;
/ / 检查发货通知单状态是否为已报关
boolean isCustomsCleared = "已报关" . equals ( notifyHeader . getNotifyStatus ( ) ) ;
/ / 如果状态为已报关 , 保存修改前的装箱数据用于对比
List < Map > oldBoxList = new ArrayList < > ( ) ;
if ( isCustomsCleared ) {
oldBoxList = coDelMapper . selectBoxList ( notifyHeader ) ;
}
/ / 执行修改操作
coDelMapper . updateBoxInfo ( boxData ) ;
/ / 如果状态为已报关 , 发送邮件通知创建人
if ( isCustomsCleared ) {
sendBoxChangeNotificationEmail ( notifyHeader , oldBoxList , "修改" , boxData ) ;
}
}
@Override
@Transactional
public void deleteBoxInfo ( Map < String , Object > boxData ) {
/ / 获取发货通知单信息
String site = boxData . get ( "site" ) . toString ( ) ;
String delNo = boxData . get ( "delNo" ) . toString ( ) ;
EcssCoDelNotifyHeaderData notifyHeader = coDelMapper . getEcssCoDelNotifyHeader ( site , delNo ) ;
/ / 检查发货通知单状态是否为已报关
boolean isCustomsCleared = "已报关" . equals ( notifyHeader . getNotifyStatus ( ) ) ;
/ / 如果状态为已报关 , 保存删除前的装箱数据用于对比
List < Map > oldBoxList = new ArrayList < > ( ) ;
if ( isCustomsCleared ) {
oldBoxList = coDelMapper . selectBoxList ( notifyHeader ) ;
}
/ / 获取该箱下的全部箱明细
EcssCoDelPalletHeaderData inData = new EcssCoDelPalletHeaderData ( ) ;
inData . setSite ( boxData . get ( "site" ) . toString ( ) ) ;
@ -3141,11 +3197,32 @@ public class CoDelServiceImpl implements CoDelService {
boxData . get ( "buNo" ) . toString ( ) , boxData . get ( "delNo" ) . toString ( ) ,
Integer . parseInt ( boxData . get ( "item_no" ) . toString ( ) ) , null ) ;
coDelMapper . deleteBoxInfo ( boxData ) ;
/ / 如果状态为已报关 , 发送邮件通知创建人
if ( isCustomsCleared ) {
sendBoxChangeNotificationEmail ( notifyHeader , oldBoxList , "删除" , boxData ) ;
}
}
@Override
@Transactional
public void updateDetailInfo ( EcssCoDelPalletData detailData ) {
/ / 获取发货通知单信息
EcssCoDelNotifyHeaderData notifyHeader = coDelMapper . getEcssCoDelNotifyHeader ( detailData . getSite ( ) , detailData . getDelNo ( ) ) ;
/ / 检查发货通知单状态是否为已报关
boolean isCustomsCleared = "已报关" . equals ( notifyHeader . getNotifyStatus ( ) ) ;
/ / 如果状态为已报关 , 保存修改前的装箱数据用于对比
List < EcssCoDelPalletDetailData > oldPalletDetailList = new ArrayList < > ( ) ;
if ( isCustomsCleared ) {
EcssCoDelPalletHeaderData queryData = new EcssCoDelPalletHeaderData ( ) ;
queryData . setSite ( detailData . getSite ( ) ) ;
queryData . setBuNo ( detailData . getBuNo ( ) ) ;
queryData . setDelNo ( detailData . getDelNo ( ) ) ;
oldPalletDetailList = coDelMapper . searchEcssCoDelPalletDetailData ( queryData ) ;
}
Integer notifyDetailItemNo = detailData . getNotifyDetailItemNo ( ) ;
BigDecimal qty = detailData . getQty ( ) ;
BigDecimal oldQty = detailData . getOldQty ( ) ;
@ -3170,11 +3247,32 @@ public class CoDelServiceImpl implements CoDelService {
coDelMapper . updateEcssCoDelNotifyDetailSurplus ( notifyDetail ) ;
}
}
/ / 如果状态为已报关 , 发送邮件通知创建人
if ( isCustomsCleared ) {
sendDetailChangeNotificationEmail ( notifyHeader , oldPalletDetailList , "修改" , detailData ) ;
}
}
@Override
@Transactional
public void deleteDetailInfo ( EcssCoDelPalletData detailData ) {
/ / 获取发货通知单信息
EcssCoDelNotifyHeaderData notifyHeader = coDelMapper . getEcssCoDelNotifyHeader ( detailData . getSite ( ) , detailData . getDelNo ( ) ) ;
/ / 检查发货通知单状态是否为已报关
boolean isCustomsCleared = "已报关" . equals ( notifyHeader . getNotifyStatus ( ) ) ;
/ / 如果状态为已报关 , 保存删除前的装箱数据用于对比
List < EcssCoDelPalletDetailData > oldPalletDetailList = new ArrayList < > ( ) ;
if ( isCustomsCleared ) {
EcssCoDelPalletHeaderData queryData = new EcssCoDelPalletHeaderData ( ) ;
queryData . setSite ( detailData . getSite ( ) ) ;
queryData . setBuNo ( detailData . getBuNo ( ) ) ;
queryData . setDelNo ( detailData . getDelNo ( ) ) ;
oldPalletDetailList = coDelMapper . searchEcssCoDelPalletDetailData ( queryData ) ;
}
/ / 删除明细前 , 先获取被删除明细的数量和notifyDetailItemNo
Integer notifyDetailItemNo = detailData . getNotifyDetailItemNo ( ) ;
BigDecimal deletedQty = detailData . getQty ( ) ;
@ -3205,6 +3303,11 @@ public class CoDelServiceImpl implements CoDelService {
coDelMapper . updateEcssCoDelNotifyDetailSurplus ( notifyDetail ) ;
}
}
/ / 如果状态为已报关 , 发送邮件通知创建人
if ( isCustomsCleared ) {
sendDetailChangeNotificationEmail ( notifyHeader , oldPalletDetailList , "删除" , detailData ) ;
}
}
@Override
@ -3337,4 +3440,515 @@ public class CoDelServiceImpl implements CoDelService {
}
}
/ * *
* 发送装箱变更通知邮件
*
* @param notifyHeader 发货通知单头数据
* @param oldBoxList 计算前的箱子列表
* @param oldPalletDetailList 计算前的装箱明细列表
* @param inData 输入参数
* @author AI Assistant
* @date 2024 - 10 - 09
* /
private void sendPackingChangeNotificationEmail ( EcssCoDelNotifyHeaderData notifyHeader ,
List < Map > oldBoxList ,
List < EcssCoDelPalletDetailData > oldPalletDetailList ,
EcssCoDelPalletHeaderData inData ) {
try {
log . info ( "开始发送装箱变更通知邮件,发货通知单号:{}" , notifyHeader . getDelNo ( ) ) ;
/ / 获取计算后的装箱数据
List < Map > newBoxList = coDelMapper . selectBoxList ( notifyHeader ) ;
EcssCoDelPalletHeaderData queryData = new EcssCoDelPalletHeaderData ( ) ;
queryData . setSite ( inData . getSite ( ) ) ;
queryData . setBuNo ( inData . getBuNo ( ) ) ;
queryData . setDelNo ( inData . getDelNo ( ) ) ;
List < EcssCoDelPalletDetailData > newPalletDetailList = coDelMapper . searchEcssCoDelPalletDetailData ( queryData ) ;
/ / 生成对比邮件内容
String emailContent = generatePackingComparisonEmailContent ( notifyHeader , oldBoxList , newBoxList ,
oldPalletDetailList , newPalletDetailList ) ;
/ / 获取发货通知单创建人邮箱
String creatorEmail = coDelMapper . queryByUserName ( notifyHeader . getCreateBy ( ) ) . getEmail ( ) ;
if ( StringUtils . isBlank ( creatorEmail ) ) {
log . warn ( "发货通知单创建人{}没有配置邮箱地址" , notifyHeader . getCreateBy ( ) ) ;
return ;
}
/ / 发送邮件
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 oldBoxList 计算前的箱子列表
* @param newBoxList 计算后的箱子列表
* @param oldPalletDetailList 计算前的装箱明细列表
* @param newPalletDetailList 计算后的装箱明细列表
* @return HTML格式的邮件内容
* @author AI Assistant
* @date 2024 - 10 - 09
* /
private String generatePackingComparisonEmailContent ( EcssCoDelNotifyHeaderData notifyHeader ,
List < Map > oldBoxList ,
List < Map > newBoxList ,
List < EcssCoDelPalletDetailData > oldPalletDetailList ,
List < EcssCoDelPalletDetailData > newPalletDetailList ) {
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: #f2f2f2; font-weight: bold; }" ) ;
emailContent . append ( ".changed { color: red; font-weight: bold; }" ) ;
emailContent . append ( ".section-title { color: #333; font-size: 16px; font-weight: bold; margin: 20px 0 10px 0; }" ) ;
emailContent . append ( "</style>" ) ;
emailContent . append ( "</head>" ) ;
emailContent . append ( "<body>" ) ;
/ / 邮件标题
emailContent . append ( "<h2>发货通知单一键装箱数据变更通知</h2>" ) ;
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 ( ) ) . append ( "</p>" ) ;
emailContent . append ( "<p><strong>操作时间:</strong>" ) . append ( DateUtils . format ( new Date ( ) , "yyyy-MM-dd HH:mm:ss" ) ) . append ( "</p>" ) ;
emailContent . append ( "<p><strong>操作类型:</strong><span class='changed'>一键装箱重新计算</span></p>" ) ;
/ / 箱子信息对比
emailContent . append ( "<div class='section-title'>箱子信息对比</div>" ) ;
emailContent . append ( generateBoxListComparisonTable ( oldBoxList , newBoxList ) ) ;
/ / 装箱明细对比
emailContent . append ( "<div class='section-title'>装箱明细对比</div>" ) ;
emailContent . append ( generatePalletDetailComparisonTable ( oldPalletDetailList , newPalletDetailList ) ) ;
emailContent . append ( "</body>" ) ;
emailContent . append ( "</html>" ) ;
return emailContent . toString ( ) ;
}
/ * *
* 生成箱子列表对比表格
*
* @param oldBoxList 计算前的箱子列表
* @param newBoxList 计算后的箱子列表
* @return HTML表格内容
* /
private String generateBoxListComparisonTable ( List < Map > oldBoxList , List < Map > newBoxList ) {
StringBuilder table = new StringBuilder ( ) ;
table . append ( "<table>" ) ;
table . append ( "<tr>" ) ;
table . append ( "<th>序号</th>" ) ;
table . append ( "<th>毛重(计算前)</th>" ) ;
table . append ( "<th>毛重(计算后)</th>" ) ;
table . append ( "<th>净重(计算前)</th>" ) ;
table . append ( "<th>净重(计算后)</th>" ) ;
table . append ( "<th>箱数(计算前)</th>" ) ;
table . append ( "<th>箱数(计算后)</th>" ) ;
table . append ( "</tr>" ) ;
/ / 创建映射以便对比
Map < Integer , Map > oldBoxMap = new HashMap < > ( ) ;
for ( Map box : oldBoxList ) {
Integer itemNo = ( Integer ) box . get ( "item_no" ) ;
oldBoxMap . put ( itemNo , box ) ;
}
Map < Integer , Map > newBoxMap = new HashMap < > ( ) ;
for ( Map box : newBoxList ) {
Integer itemNo = ( Integer ) box . get ( "item_no" ) ;
newBoxMap . put ( itemNo , box ) ;
}
/ / 获取所有序号
Set < Integer > allItemNos = new HashSet < > ( ) ;
allItemNos . addAll ( oldBoxMap . keySet ( ) ) ;
allItemNos . addAll ( newBoxMap . keySet ( ) ) ;
List < Integer > sortedItemNos = new ArrayList < > ( allItemNos ) ;
sortedItemNos . sort ( Integer : : compareTo ) ;
for ( Integer itemNo : sortedItemNos ) {
Map oldBox = oldBoxMap . get ( itemNo ) ;
Map newBox = newBoxMap . get ( itemNo ) ;
table . append ( "<tr>" ) ;
table . append ( "<td>" ) . append ( itemNo ) . append ( "</td>" ) ;
/ / 毛重对比
BigDecimal oldGrossWeight = oldBox ! = null ? ( BigDecimal ) oldBox . get ( "gross_weight" ) : BigDecimal . ZERO ;
BigDecimal newGrossWeight = newBox ! = null ? ( BigDecimal ) newBox . get ( "gross_weight" ) : BigDecimal . ZERO ;
table . append ( "<td>" ) . append ( formatDecimal ( oldGrossWeight ) ) . append ( "</td>" ) ;
if ( oldGrossWeight . compareTo ( newGrossWeight ) ! = 0 ) {
table . append ( "<td class='changed'>" ) . append ( formatDecimal ( newGrossWeight ) ) . append ( "</td>" ) ;
} else {
table . append ( "<td>" ) . append ( formatDecimal ( newGrossWeight ) ) . append ( "</td>" ) ;
}
/ / 净重对比
BigDecimal oldNetWeight = oldBox ! = null ? ( BigDecimal ) oldBox . get ( "net_weight" ) : BigDecimal . ZERO ;
BigDecimal newNetWeight = newBox ! = null ? ( BigDecimal ) newBox . get ( "net_weight" ) : BigDecimal . ZERO ;
table . append ( "<td>" ) . append ( formatDecimal ( oldNetWeight ) ) . append ( "</td>" ) ;
if ( oldNetWeight . compareTo ( newNetWeight ) ! = 0 ) {
table . append ( "<td class='changed'>" ) . append ( formatDecimal ( newNetWeight ) ) . append ( "</td>" ) ;
} else {
table . append ( "<td>" ) . append ( formatDecimal ( newNetWeight ) ) . append ( "</td>" ) ;
}
/ / 箱数对比
BigDecimal oldBoxQty = oldBox ! = null ? ( BigDecimal ) oldBox . get ( "box_qty" ) : BigDecimal . ZERO ;
BigDecimal newBoxQty = newBox ! = null ? ( BigDecimal ) newBox . get ( "box_qty" ) : BigDecimal . ZERO ;
table . append ( "<td>" ) . append ( formatDecimal ( oldBoxQty ) ) . append ( "</td>" ) ;
if ( oldBoxQty . compareTo ( newBoxQty ) ! = 0 ) {
table . append ( "<td class='changed'>" ) . append ( formatDecimal ( newBoxQty ) ) . append ( "</td>" ) ;
} else {
table . append ( "<td>" ) . append ( formatDecimal ( newBoxQty ) ) . append ( "</td>" ) ;
}
table . append ( "</tr>" ) ;
}
table . append ( "</table>" ) ;
return table . toString ( ) ;
}
/ * *
* 生成装箱明细对比表格
*
* @param oldPalletDetailList 计算前的装箱明细列表
* @param newPalletDetailList 计算后的装箱明细列表
* @return HTML表格内容
* /
private String generatePalletDetailComparisonTable ( List < EcssCoDelPalletDetailData > oldPalletDetailList ,
List < EcssCoDelPalletDetailData > newPalletDetailList ) {
StringBuilder table = new StringBuilder ( ) ;
table . append ( "<table>" ) ;
table . append ( "<tr>" ) ;
table . append ( "<th>序号</th>" ) ;
table . append ( "<th>项次</th>" ) ;
table . append ( "<th>物料号</th>" ) ;
table . append ( "<th>PN</th>" ) ;
table . append ( "<th>数量(计算前)</th>" ) ;
table . append ( "<th>数量(计算后)</th>" ) ;
table . append ( "<th>箱数(计算前)</th>" ) ;
table . append ( "<th>箱数(计算后)</th>" ) ;
table . append ( "<th>卷数(计算前)</th>" ) ;
table . append ( "<th>卷数(计算后)</th>" ) ;
table . append ( "</tr>" ) ;
/ / 创建映射以便对比 - 使用序号 + 项次作为唯一标识
Map < String , EcssCoDelPalletDetailData > oldDetailMap = new HashMap < > ( ) ;
for ( EcssCoDelPalletDetailData detail : oldPalletDetailList ) {
String key = detail . getSeqNo ( ) + "_" + detail . getItemNo ( ) ;
oldDetailMap . put ( key , detail ) ;
}
Map < String , EcssCoDelPalletDetailData > newDetailMap = new HashMap < > ( ) ;
for ( EcssCoDelPalletDetailData detail : newPalletDetailList ) {
String key = detail . getSeqNo ( ) + "_" + detail . getItemNo ( ) ;
newDetailMap . put ( key , detail ) ;
}
/ / 获取所有键值
Set < String > allKeys = new HashSet < > ( ) ;
allKeys . addAll ( oldDetailMap . keySet ( ) ) ;
allKeys . addAll ( newDetailMap . keySet ( ) ) ;
List < String > sortedKeys = new ArrayList < > ( allKeys ) ;
sortedKeys . sort ( ( a , b ) - > {
String [ ] aParts = a . split ( "_" ) ;
String [ ] bParts = b . split ( "_" ) ;
int seqCompare = Integer . compare ( Integer . parseInt ( aParts [ 0 ] ) , Integer . parseInt ( bParts [ 0 ] ) ) ;
if ( seqCompare ! = 0 ) return seqCompare ;
return Integer . compare ( Integer . parseInt ( aParts [ 1 ] ) , Integer . parseInt ( bParts [ 1 ] ) ) ;
} ) ;
for ( String key : sortedKeys ) {
EcssCoDelPalletDetailData oldDetail = oldDetailMap . get ( key ) ;
EcssCoDelPalletDetailData newDetail = newDetailMap . get ( key ) ;
String [ ] keyParts = key . split ( "_" ) ;
Integer seqNo = Integer . parseInt ( keyParts [ 0 ] ) ;
Integer itemNo = Integer . parseInt ( keyParts [ 1 ] ) ;
table . append ( "<tr>" ) ;
table . append ( "<td>" ) . append ( seqNo ) . append ( "</td>" ) ;
table . append ( "<td>" ) . append ( itemNo ) . append ( "</td>" ) ;
/ / 物料号和PN ( 取新数据或旧数据 )
EcssCoDelPalletDetailData referenceDetail = newDetail ! = null ? newDetail : oldDetail ;
table . append ( "<td>" ) . append ( referenceDetail . getPartNo ( ) ! = null ? referenceDetail . getPartNo ( ) : "" ) . append ( "</td>" ) ;
table . append ( "<td>" ) . append ( referenceDetail . getPn ( ) ! = null ? referenceDetail . getPn ( ) : "" ) . append ( "</td>" ) ;
/ / 数量对比
BigDecimal oldQty = oldDetail ! = null ? oldDetail . getQty ( ) : BigDecimal . ZERO ;
BigDecimal newQty = newDetail ! = null ? newDetail . getQty ( ) : BigDecimal . ZERO ;
table . append ( "<td>" ) . append ( formatDecimal ( oldQty ) ) . append ( "</td>" ) ;
if ( oldQty . compareTo ( newQty ) ! = 0 ) {
table . append ( "<td class='changed'>" ) . append ( formatDecimal ( newQty ) ) . append ( "</td>" ) ;
} else {
table . append ( "<td>" ) . append ( formatDecimal ( newQty ) ) . append ( "</td>" ) ;
}
/ / 箱数对比
BigDecimal oldBoxQty = oldDetail ! = null ? oldDetail . getBoxQty ( ) : BigDecimal . ZERO ;
BigDecimal newBoxQty = newDetail ! = null ? newDetail . getBoxQty ( ) : BigDecimal . ZERO ;
table . append ( "<td>" ) . append ( formatDecimal ( oldBoxQty ) ) . append ( "</td>" ) ;
if ( oldBoxQty . compareTo ( newBoxQty ) ! = 0 ) {
table . append ( "<td class='changed'>" ) . append ( formatDecimal ( newBoxQty ) ) . append ( "</td>" ) ;
} else {
table . append ( "<td>" ) . append ( formatDecimal ( newBoxQty ) ) . append ( "</td>" ) ;
}
/ / 卷数对比
BigDecimal oldRolls = oldDetail ! = null ? oldDetail . getRolls ( ) : BigDecimal . ZERO ;
BigDecimal newRolls = newDetail ! = null ? newDetail . getRolls ( ) : BigDecimal . ZERO ;
table . append ( "<td>" ) . append ( formatDecimal ( oldRolls ) ) . append ( "</td>" ) ;
if ( oldRolls . compareTo ( newRolls ) ! = 0 ) {
table . append ( "<td class='changed'>" ) . append ( formatDecimal ( newRolls ) ) . append ( "</td>" ) ;
} else {
table . append ( "<td>" ) . append ( formatDecimal ( newRolls ) ) . append ( "</td>" ) ;
}
table . append ( "</tr>" ) ;
}
table . append ( "</table>" ) ;
return table . toString ( ) ;
}
/ * *
* 格式化BigDecimal数值显示
*
* @param value 数值
* @return 格式化后的字符串
* /
private String formatDecimal ( BigDecimal value ) {
if ( value = = null ) {
return "0" ;
}
return value . stripTrailingZeros ( ) . toPlainString ( ) ;
}
/ * *
* 发送箱子变更通知邮件
*
* @param notifyHeader 发货通知单头数据
* @param oldBoxList 操作前的箱子列表
* @param operation 操作类型 ( 修改 / 删除 )
* @param boxData 操作的箱子数据
* @author AI Assistant
* @date 2024 - 10 - 09
* /
private void sendBoxChangeNotificationEmail ( EcssCoDelNotifyHeaderData notifyHeader ,
List < Map > oldBoxList ,
String operation ,
Map < String , Object > boxData ) {
try {
log . info ( "开始发送箱子{}通知邮件,发货通知单号:{}" , operation , notifyHeader . getDelNo ( ) ) ;
/ / 获取操作后的装箱数据
List < Map > newBoxList = coDelMapper . selectBoxList ( notifyHeader ) ;
/ / 生成对比邮件内容
String emailContent = generateBoxChangeEmailContent ( notifyHeader , oldBoxList , newBoxList , operation , boxData ) ;
/ / 获取发货通知单创建人邮箱
String creatorEmail = coDelMapper . queryByUserName ( notifyHeader . getCreateBy ( ) ) . getEmail ( ) ;
if ( StringUtils . isBlank ( creatorEmail ) ) {
log . warn ( "发货通知单创建人{}没有配置邮箱地址" , notifyHeader . getCreateBy ( ) ) ;
return ;
}
/ / 发送邮件
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 oldPalletDetailList 操作前的装箱明细列表
* @param operation 操作类型 ( 修改 / 删除 )
* @param detailData 操作的明细数据
* @author AI Assistant
* @date 2024 - 10 - 09
* /
private void sendDetailChangeNotificationEmail ( EcssCoDelNotifyHeaderData notifyHeader ,
List < EcssCoDelPalletDetailData > oldPalletDetailList ,
String operation ,
EcssCoDelPalletData detailData ) {
try {
log . info ( "开始发送箱明细{}通知邮件,发货通知单号:{}" , operation , notifyHeader . getDelNo ( ) ) ;
/ / 获取操作后的装箱数据
EcssCoDelPalletHeaderData queryData = new EcssCoDelPalletHeaderData ( ) ;
queryData . setSite ( detailData . getSite ( ) ) ;
queryData . setBuNo ( detailData . getBuNo ( ) ) ;
queryData . setDelNo ( detailData . getDelNo ( ) ) ;
List < EcssCoDelPalletDetailData > newPalletDetailList = coDelMapper . searchEcssCoDelPalletDetailData ( queryData ) ;
/ / 生成对比邮件内容
String emailContent = generateDetailChangeEmailContent ( notifyHeader , oldPalletDetailList , newPalletDetailList , operation , detailData ) ;
/ / 获取发货通知单创建人邮箱
String creatorEmail = coDelMapper . queryByUserName ( notifyHeader . getCreateBy ( ) ) . getEmail ( ) ;
if ( StringUtils . isBlank ( creatorEmail ) ) {
log . warn ( "发货通知单创建人{}没有配置邮箱地址" , notifyHeader . getCreateBy ( ) ) ;
return ;
}
/ / 发送邮件
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 operation 操作类型
* @param boxData 操作的箱子数据
* @return HTML格式的邮件内容
* /
private String generateBoxChangeEmailContent ( EcssCoDelNotifyHeaderData notifyHeader ,
List < Map > oldBoxList ,
List < Map > newBoxList ,
String operation ,
Map < String , Object > boxData ) {
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: #f2f2f2; font-weight: bold; }" ) ;
emailContent . append ( ".changed { color: red; font-weight: bold; }" ) ;
emailContent . append ( ".deleted { color: red; text-decoration: line-through; }" ) ;
emailContent . append ( ".section-title { color: #333; font-size: 16px; font-weight: bold; margin: 20px 0 10px 0; }" ) ;
emailContent . append ( "</style>" ) ;
emailContent . append ( "</head>" ) ;
emailContent . append ( "<body>" ) ;
/ / 邮件标题
emailContent . append ( "<h2>发货通知单箱子" ) . append ( operation ) . append ( "通知</h2>" ) ;
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 ( ) ) . append ( "</p>" ) ;
emailContent . append ( "<p><strong>操作时间:</strong>" ) . append ( DateUtils . format ( new Date ( ) , "yyyy-MM-dd HH:mm:ss" ) ) . append ( "</p>" ) ;
emailContent . append ( "<p><strong>操作类型:</strong><span class='changed'>" ) . append ( operation ) . append ( "箱子(序号:" ) . append ( boxData . get ( "item_no" ) ) . append ( ")</span></p>" ) ;
/ / 箱子信息对比
emailContent . append ( "<div class='section-title'>箱子信息对比</div>" ) ;
emailContent . append ( generateBoxListComparisonTable ( oldBoxList , newBoxList ) ) ;
emailContent . append ( "</body>" ) ;
emailContent . append ( "</html>" ) ;
return emailContent . toString ( ) ;
}
/ * *
* 生成箱明细变更邮件内容
*
* @param notifyHeader 发货通知单头数据
* @param oldPalletDetailList 操作前的装箱明细列表
* @param newPalletDetailList 操作后的装箱明细列表
* @param operation 操作类型
* @param detailData 操作的明细数据
* @return HTML格式的邮件内容
* /
private String generateDetailChangeEmailContent ( EcssCoDelNotifyHeaderData notifyHeader ,
List < EcssCoDelPalletDetailData > oldPalletDetailList ,
List < EcssCoDelPalletDetailData > newPalletDetailList ,
String operation ,
EcssCoDelPalletData detailData ) {
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: #f2f2f2; font-weight: bold; }" ) ;
emailContent . append ( ".changed { color: red; font-weight: bold; }" ) ;
emailContent . append ( ".deleted { color: red; text-decoration: line-through; }" ) ;
emailContent . append ( ".section-title { color: #333; font-size: 16px; font-weight: bold; margin: 20px 0 10px 0; }" ) ;
emailContent . append ( "</style>" ) ;
emailContent . append ( "</head>" ) ;
emailContent . append ( "<body>" ) ;
/ / 邮件标题
emailContent . append ( "<h2>发货通知单箱明细" ) . append ( operation ) . append ( "通知</h2>" ) ;
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 ( ) ) . append ( "</p>" ) ;
emailContent . append ( "<p><strong>操作时间:</strong>" ) . append ( DateUtils . format ( new Date ( ) , "yyyy-MM-dd HH:mm:ss" ) ) . append ( "</p>" ) ;
emailContent . append ( "<p><strong>操作类型:</strong><span class='changed'>" ) . append ( operation ) . append ( "箱明细(序号:" ) . append ( detailData . getSeqNo ( ) ) . append ( ",项次:" ) . append ( detailData . getItemNo ( ) ) . append ( ")</span></p>" ) ;
/ / 装箱明细对比
emailContent . append ( "<div class='section-title'>装箱明细对比</div>" ) ;
emailContent . append ( generatePalletDetailComparisonTable ( oldPalletDetailList , newPalletDetailList ) ) ;
emailContent . append ( "</body>" ) ;
emailContent . append ( "</html>" ) ;
return emailContent . toString ( ) ;
}
}