This commit is contained in:
Van0313
2025-05-16 23:43:57 +08:00
parent b6562ba7ec
commit d54bf5affb

View File

@@ -5,18 +5,20 @@ import cn.van.business.model.jd.OrderRow;
import cn.van.business.repository.OrderRowRepository;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.loggerger;
import org.slf4j.loggergerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -31,6 +33,7 @@ import static cn.van.business.util.WXUtil.*;
*/
@Service
public class OrderUtil {
private static final Logger logger = LoggerFactory.getLogger(OrderUtil.class);
@Autowired
private StringRedisTemplate redisTemplate;
@@ -48,82 +51,90 @@ public class OrderUtil {
*/
@Async("threadPoolTaskExecutor")
public void orderToWx(OrderRow orderRow, Boolean isAutoFlush) {
// 获取订单当前状态
Integer newValidCode = orderRow.getValidCode();
String oldValidCode = redisTemplate.opsForValue().get(ORDER_ROW_KEY + orderRow.getId());
// 价保
Double newProPriceAmount = orderRow.getProPriceAmount();
try {
// 获取订单当前状态
Integer newValidCode = orderRow.getValidCode();
String oldValidCode = getFromRedis(ORDER_ROW_KEY + orderRow.getId());
// 检查Redis中是否有旧的状态码没有的话赋予默认值
Integer lastValidCode = oldValidCode != null ? Integer.parseInt(oldValidCode) : -100;
// 先更新 Redis 状态,防止消息发送失败导致重复触发
redisTemplate.opsForValue().set(ORDER_ROW_KEY + orderRow.getId(), String.valueOf(orderRow.getValidCode()));
// 检查Redis中是否有旧的状态码没有的话赋予默认值
Integer lastValidCode = oldValidCode != null ? Integer.parseInt(oldValidCode) : -100;
// 订单变化:当 isAutoFlush == false 或状态确实有变化时,进行消息发送
if (!isAutoFlush || !lastValidCode.equals(newValidCode)) {
String content = getFormattedOrderInfo(orderRow);
String wxId = getWxidFromJdid(orderRow.getUnionId().toString());
// 订单变化
if (!isAutoFlush || !lastValidCode.equals(newValidCode)) {
// 当 isAutoFlush 为 false 或状态确实有变化时,进行消息发送
String content = getFormattedOrderInfo(orderRow);
String wxId = getWxidFromJdid(orderRow.getUnionId().toString());
if (Util.isNotEmpty(wxId)) {
wxUtil.sendTextMessage(wxId, content, 1, wxId, true);
// 加一个简短的今日订单统计
int[] param = {-1};
List<WXUtil.SuperAdmin> superAdmins = getSuperAdmins(wxId);
List<Long> unionIds = new ArrayList<>();
for (WXUtil.SuperAdmin superAdmin : superAdmins) {
String unionId = superAdmin.getUnionId();
unionIds.add(Long.valueOf(unionId));
if (Util.isNotEmpty(wxId)) {
wxUtil.sendTextMessage(wxId, content, 1, wxId, true);
// 发送今日统计信息
sendDailyStats(wxId);
}
List<OrderRow> orderRows = orderRowRepository.findByValidCodeNotInAndUnionIdIn(param, unionIds);
List<OrderRow> todayOrders = filterOrdersByDate(orderRows, 0);
// 分割统计每个京粉今天下单多少个订单,避免一天一个京粉下单太多
HashMap<String, List<OrderRow>> stringListHashMap = new HashMap<>();
List<OrderRow> cachedOrders = new ArrayList<>();
for (OrderRow todayOrder : todayOrders) {
String unionId = todayOrder.getUnionId().toString();
if (stringListHashMap.containsKey(unionId)) {
cachedOrders = stringListHashMap.get(unionId);
} else {
cachedOrders = new ArrayList<>();
}
cachedOrders.add(todayOrder);
stringListHashMap.put(unionId, cachedOrders);
}
// 只统计今天下单的京粉,因为有的京粉休息是不下单的
StringBuilder resultContent = new StringBuilder();
for (Map.Entry<String, List<OrderRow>> entry : stringListHashMap.entrySet()) {
String unionId = entry.getKey();
List<OrderRow> orderRows2 = entry.getValue();
OrderStats stats = calculateStats(orderRows2);
resultContent.append(buildStatsContent("京粉 : " + getRemarkFromJdid(unionId) , stats));
}
OrderStats orderStats = calculateStats(todayOrders);
wxUtil.sendTextMessage(wxId, buildStatsContent("今日总统计 : ", orderStats) + " \n 详 : \n ━━━━━━━━━━━━\n" + resultContent, 1, wxId, true);
}
}
// 更新 Redis 状态值
redisTemplate.opsForValue().set(ORDER_ROW_KEY + orderRow.getId(), String.valueOf(orderRow.getValidCode()));
if (!newProPriceAmount.equals(0.0)){
String oldProPriceAmount = redisTemplate.opsForValue().get(ORDER_ROW_JB_KEY + orderRow.getId());
if (Util.isNotEmpty(oldProPriceAmount)) {
if (!oldProPriceAmount.equals(newProPriceAmount.toString())) {
// 处理价保逻辑
BigDecimal newProPriceAmount = Optional.ofNullable(orderRow.getProPriceAmount()).map(BigDecimal::new).orElse(BigDecimal.ZERO);
if (BigDecimal.ZERO.compareTo(newProPriceAmount) < 0) {
String oldProPriceAmountStr = getFromRedis(ORDER_ROW_JB_KEY + orderRow.getId());
BigDecimal oldProPriceAmount = oldProPriceAmountStr == null ? BigDecimal.ZERO : new BigDecimal(oldProPriceAmountStr);
if (newProPriceAmount.compareTo(oldProPriceAmount) != 0) {
String wxId = getWxidFromJdid(orderRow.getUnionId().toString());
if (Util.isNotEmpty(wxId)) {
String content = getFormattedOrderInfo(orderRow);
wxUtil.sendTextMessage(wxId, "[Broken] [Broken] [Broken] 价保提醒 [Broken] [Broken] [Broken] " + newProPriceAmount + "\n" + content, 1, wxId, true);
String alertMsg = "[Broken][Broken][Broken] 价保提醒 [Broken][Broken][Broken] " + newProPriceAmount + "\n" + content;
wxUtil.sendTextMessage(wxId, alertMsg, 1, wxId, true);
}
}
}
// 不管价保与否都要写入redis
redisTemplate.opsForValue().set(ORDER_ROW_JB_KEY + orderRow.getId(), "0.0");
// 不管是否变动都写入 Redis用于下次比较
redisTemplate.opsForValue().set(ORDER_ROW_JB_KEY + orderRow.getId(), newProPriceAmount.toString());
}
} catch (Exception e) {
logger.error("处理订单微信通知失败: {}", e.getMessage(), e);
// 可加入重试机制或上报监控
}
}
private void sendDailyStats(String wxId) {
List<WXUtil.SuperAdmin> superAdmins = getSuperAdmins(wxId);
if (superAdmins.isEmpty()) return;
List<Long> unionIds = superAdmins.stream().map(admin -> Long.valueOf(admin.getUnionId())).collect(Collectors.toList());
List<OrderRow> orderRows = orderRowRepository.findByValidCodeNotInAndUnionIdIn(new int[]{-1}, unionIds);
List<OrderRow> todayOrders = filterOrdersByDate(orderRows, 0);
if (todayOrders.isEmpty()) return;
// 按照 unionId 分组统计
Map<String, List<OrderRow>> grouped = todayOrders.stream().collect(Collectors.groupingBy(o -> o.getUnionId().toString()));
StringBuilder resultContent = new StringBuilder();
for (Map.Entry<String, List<OrderRow>> entry : grouped.entrySet()) {
String unionId = entry.getKey();
OrderStats stats = calculateStats(entry.getValue());
resultContent.append(buildStatsContent("京粉 : " + getRemarkFromJdid(unionId), stats));
}
OrderStats totalStats = calculateStats(todayOrders);
String totalMsg = buildStatsContent("今日总统计 : ", totalStats) + " \n详:\n━━━━━━━━━━━━\n" + resultContent;
wxUtil.sendTextMessage(wxId, totalMsg, 1, wxId, true);
}
private String getFromRedis(String key) {
try {
return redisTemplate.opsForValue().get(key);
} catch (Exception e) {
logger.warn("Redis get 失败 key={}", key, e);
return null;
}
}
/**
@@ -136,8 +147,7 @@ public class OrderUtil {
String wxId = getWxidFromJdid(orderRowList.get(0).getUnionId().toString());
StringBuilder content = new StringBuilder();
content.append("批量订单:\n\r ").append("").append(orderRowList.size()).append("\r");
List<OrderRow> filterList = orderRowList.stream().filter(orderRow -> orderRow.getValidCode() != 2
&& orderRow.getValidCode() != 3).toList();
List<OrderRow> filterList = orderRowList.stream().filter(orderRow -> orderRow.getValidCode() != 2 && orderRow.getValidCode() != 3).toList();
content.append("移除 拆单或者取消 的订单, 共 ").append(filterList.size()).append("单: \n\r");
for (OrderRow orderRow : filterList) {
content.append("\r\n");
@@ -162,9 +172,7 @@ public class OrderUtil {
ValidCodeConverter converter = new ValidCodeConverter();
Long unionId = orderRow.getUnionId();
String remarkFromJdid = getRemarkFromJdid(String.valueOf(unionId));
StringBuilder orderInfo = new StringBuilder()
.append(" ").append(getEmjoy(orderRow.getValidCode())).append(" ")
.append(converter.getCodeDescription(orderRow.getValidCode())).append("\r");
StringBuilder orderInfo = new StringBuilder().append(" ").append(getEmjoy(orderRow.getValidCode())).append(" ").append(converter.getCodeDescription(orderRow.getValidCode())).append("\r");
//if (oldValidCode != -100 && !oldValidCode.equals(orderRow.getValidCode())) {
// orderInfo.insert(0, "从 " + getEmjoy(oldValidCode) + " "
@@ -175,21 +183,13 @@ public class OrderUtil {
orderInfo
//+ "订单+sku" + orderRow.getId() + "\r"
.append("京粉:").append(remarkFromJdid).append("\r")
.append("订单:").append(orderRow.getOrderId()).append(" (")
.append(orderRow.getPlus() == 1 ? "plus" : "非plus").append(")\r")
.append("名称:").append(orderRow.getSkuName()).append("\r").append("\r")
.append("京粉:").append(remarkFromJdid).append("\r").append("订单:").append(orderRow.getOrderId()).append(" (").append(orderRow.getPlus() == 1 ? "plus" : "非plus").append(")\r").append("名称:").append(orderRow.getSkuName()).append("\r").append("\r")
//+ "商品单价:" + orderRow.getPrice() + "\r"
//+ "商品数量:" + orderRow.getSkuNum() + "\r"
//+ "商品总价:" + (orderRow.getPrice() * orderRow.getSkuNum()) + "\r"
.append("计佣金额:").append(orderRow.getEstimateCosPrice()).append("\r")
//+ "金额:" + orderRow.getActualCosPrice() + "\r"
.append("比例:").append(orderRow.getCommissionRate()).append("\r")
.append("[Packet] 佣金:").append(orderRow.getEstimateFee()).append("\r")
.append("下单:").append(formatter.format(orderRow.getOrderTime())).append("\r")
.append("完成:").append(orderRow.getFinishTime() != null
? formatter.format(orderRow.getFinishTime())
: "未完成");
.append("比例:").append(orderRow.getCommissionRate()).append("\r").append("[Packet] 佣金:").append(orderRow.getEstimateFee()).append("\r").append("下单:").append(formatter.format(orderRow.getOrderTime())).append("\r").append("完成:").append(orderRow.getFinishTime() != null ? formatter.format(orderRow.getFinishTime()) : "未完成");
return orderInfo.toString();
}
@@ -235,12 +235,11 @@ public class OrderUtil {
//}
return "订单:" + orderRow.getOrderId() + " (" + (orderRow.getPlus() == 1 ? "plus" : "非plus") + ")\r"
+"走的京粉:"+ remarkFromJdid + "\r"
return "订单:" + orderRow.getOrderId() + " (" + (orderRow.getPlus() == 1 ? "plus" : "非plus") + ")\r" + "走的京粉:" + remarkFromJdid + "\r"
+"状态:" + (converter.getCodeDescription(orderRow.getValidCode())) + "\r"
+ "状态:" + (converter.getCodeDescription(orderRow.getValidCode())) + "\r"
+ "标题:" + orderRow.getSkuName() + "\r\n"+ "\r\n"
+ "标题:" + orderRow.getSkuName() + "\r\n" + "\r\n"
//+ "商品单价:" + orderRow.getPrice() + "\r"
//+ "商品数量:" + orderRow.getSkuNum() + "\r"
//+ "商品总价:" + (orderRow.getPrice() * orderRow.getSkuNum()) + "\r"
@@ -250,15 +249,14 @@ public class OrderUtil {
//+ "比例:" + orderRow.getCommissionRate() + "\r"
+ "佣金:" + orderRow.getEstimateFee() + "\r\n"
+ "下单:" + formatter.format(orderRow.getOrderTime()) + "\r"
+ "完成:" + (orderRow.getFinishTime() != null ? formatter.format(orderRow.getFinishTime()) : "未完成") + "\r";
+ "下单:" + formatter.format(orderRow.getOrderTime()) + "\r" + "完成:" + (orderRow.getFinishTime() != null ? formatter.format(orderRow.getFinishTime()) : "未完成") + "\r";
}
/**
* JDUtil拷贝的方法避免循环注入
* */
*/
private List<OrderRow> filterOrdersByDate(List<OrderRow> orderRows, int daysBack) {
private List<OrderRow> filterOrdersByDate(List<OrderRow> orderRows, int daysBack) {
LocalDate now = LocalDate.now();
return orderRows.stream().filter(order -> {
@@ -269,7 +267,8 @@ public class OrderUtil {
return !orderDate.isBefore(now.minusDays(daysBack)) && !orderDate.isAfter(now);
}).collect(Collectors.toList());
}
private OrderStats calculateStats(List<OrderRow> orders) {
private OrderStats calculateStats(List<OrderRow> orders) {
long paid = orders.stream().filter(o -> o.getValidCode() == 16).count();
long pending = orders.stream().filter(o -> o.getValidCode() == 15).count();
long canceled = orders.stream().filter(o -> o.getValidCode() != 16 && o.getValidCode() != 17).count();
@@ -277,6 +276,7 @@ public class OrderUtil {
return new OrderStats(orders.size(), orders.size() - canceled, paid, orders.stream().filter(o -> o.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum(), pending, orders.stream().filter(o -> o.getValidCode() == 15).mapToDouble(OrderRow::getEstimateFee).sum(), canceled, completed, orders.stream().filter(o -> o.getValidCode() == 17).mapToDouble(OrderRow::getEstimateFee).sum(), getStreamForWeiGui(orders).count(), getStreamForWeiGui(orders).mapToDouble(o -> o.getEstimateCosPrice() * o.getCommissionRate() * 0.01).sum());
}
private String buildStatsContent(String title, OrderStats stats) {
StringBuilder content = new StringBuilder();
content//[爱心][Wow][Packet][Party][Broken][心碎][亲亲][色]
@@ -289,6 +289,7 @@ public class OrderUtil {
.append("[Packet] 待付款佣金:").append(String.format("%.2f", stats.getPendingCommission())).append("\n").append("━━━━━━━━━━━━\n");
return content.toString();
}
private Stream<OrderRow> getStreamForWeiGui(List<OrderRow> todayOrders) {
return todayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 13 || orderRow.getValidCode() == 25 || orderRow.getValidCode() == 26 || orderRow.getValidCode() == 27 || orderRow.getValidCode() == 28 || orderRow.getValidCode() == 29);
}
@@ -296,8 +297,7 @@ public class OrderUtil {
// 统计指标DTO
@Getter
@AllArgsConstructor
static
class OrderStats {
static class OrderStats {
private long totalOrders; // 总订单数
private long validOrders; // 有效订单数(不含取消)
private long paidOrders; // 已付款订单