|
@@ -1,10 +1,113 @@
|
|
|
package com.fuint.common.service;
|
|
|
|
|
|
-import com.fuint.common.dto.ext.EmailDto;
|
|
|
-
|
|
|
-/**
|
|
|
- * 邮件发送服务
|
|
|
- */
|
|
|
-public interface EmailService {
|
|
|
- void sendAlertEmail(EmailDto emailDTO);
|
|
|
-}
|
|
|
+
|
|
|
+
|
|
|
+import com.fuint.common.dto.ext.ShopAlertInfo;
|
|
|
+import com.fuint.common.entity.Order;
|
|
|
+import com.fuint.common.entity.Shop;
|
|
|
+import com.fuint.repository.model.MtOrder;
|
|
|
+import com.fuint.repository.model.MtStore;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.mail.javamail.JavaMailSender;
|
|
|
+import org.springframework.mail.javamail.MimeMessageHelper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.mail.MessagingException;
|
|
|
+import javax.mail.internet.MimeMessage;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.text.DecimalFormat;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+@Slf4j
|
|
|
+public class EmailService {
|
|
|
+ private final JavaMailSender mailSender;
|
|
|
+ private final String from = "17633944959@163.com";
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 邮件聚合发送方法
|
|
|
+ * @param to
|
|
|
+ * @param alerts
|
|
|
+ */
|
|
|
+ public void sendAggregatedAlertEmail(String to, List<ShopAlertInfo> alerts) {
|
|
|
+ try {
|
|
|
+ MimeMessage message = mailSender.createMimeMessage();
|
|
|
+ MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
|
|
+
|
|
|
+ helper.setFrom(from);
|
|
|
+ helper.setTo(to);
|
|
|
+ helper.setSubject("【多店铺营业额预警】");
|
|
|
+
|
|
|
+ // 构建HTML表格内容
|
|
|
+ String htmlContent = buildAggregatedHtml(alerts);
|
|
|
+ helper.setText(htmlContent, true);
|
|
|
+
|
|
|
+ mailSender.send(message);
|
|
|
+ } catch (MessagingException e) {
|
|
|
+ log.error("聚合邮件发送失败: {}", to, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String buildAggregatedHtml(List<ShopAlertInfo> alerts) {
|
|
|
+// DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime类型
|
|
|
+ // 创建时间格式化器
|
|
|
+ SimpleDateFormat timeFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+ DecimalFormat df = new DecimalFormat("¥#,##0.00"); // 金额格式化
|
|
|
+
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.append("<h3 style='color: #dc3545;'>营业额预警明细</h3>");
|
|
|
+
|
|
|
+ alerts.forEach(info -> {
|
|
|
+ MtStore shop = info.getShop();
|
|
|
+ // 计算差额(阈值 - 实际销售额)
|
|
|
+ BigDecimal deficit = shop.getThreshold().subtract(info.getTotalSales());
|
|
|
+ List<MtOrder> orders = info.getOrders();
|
|
|
+ // 添加汇总统计
|
|
|
+ sb.append("<p style='color: #6c757d; margin-top: 10px;'>")
|
|
|
+ .append("总订单数:<strong>").append(orders.size()).append("</strong> 笔")
|
|
|
+ .append("</p>");
|
|
|
+
|
|
|
+ sb.append("<div style='margin-bottom: 30px; border: 1px solid #ddd; padding: 15px;'>")
|
|
|
+ .append("<h4 style='color: #0d6efd;'>").append(shop.getName()).append("</h4>")
|
|
|
+ .append("<p>目标阈值:<strong>").append(df.format(shop.getThreshold())).append("</strong></p>")
|
|
|
+ .append("<p>实际销售额:<strong style='color: red;'>").append(df.format(info.getTotalSales())).append("</strong></p>")
|
|
|
+ // 新增差额显示
|
|
|
+ .append("<p>差额:<strong style='color: red; border-bottom: 2px solid #ffcccc;'>")
|
|
|
+ .append(df.format(deficit))
|
|
|
+ .append("</strong></p>");
|
|
|
+
|
|
|
+ // 订单明细表格
|
|
|
+ if (!info.getOrders().isEmpty()) {
|
|
|
+ sb.append("<table style='width: 100%; border-collapse: collapse; margin-top: 10px;'>")
|
|
|
+ .append("<tr style='background-color: #f8f9fa;'>")
|
|
|
+ .append("<th style='padding: 8px; border: 1px solid #dee2e6;'>订单号</th>")
|
|
|
+ .append("<th style='padding: 8px; border: 1px solid #dee2e6;'>金额</th>")
|
|
|
+ .append("<th style='padding: 8px; border: 1px solid #dee2e6;'>时间</th>")
|
|
|
+ .append("</tr>");
|
|
|
+
|
|
|
+ info.getOrders().forEach(order -> {
|
|
|
+ sb.append("<tr>")
|
|
|
+ .append("<td style='padding: 8px; border: 1px solid #dee2e6;'>").append(order.getId()).append("</td>")
|
|
|
+ .append("<td style='padding: 8px; border: 1px solid #dee2e6;'>").append(df.format(order.getAmount())).append("</td>")
|
|
|
+ .append("<td style='padding: 8px; border: 1px solid #dee2e6;'>")
|
|
|
+ .append(timeFormatter.format(order.getCreateTime()))
|
|
|
+ .append("</td></tr>");
|
|
|
+ });
|
|
|
+
|
|
|
+ sb.append("</table>");
|
|
|
+ } else {
|
|
|
+ sb.append("<p style='color: #6c757d; margin-top: 10px;'>无当日订单记录</p>");
|
|
|
+ }
|
|
|
+ sb.append("</div>");
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ return sb.toString();
|
|
|
+ }
|
|
|
+}
|