价保
This commit is contained in:
@@ -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; // 已付款订单
|
||||
|
||||
Reference in New Issue
Block a user