This commit is contained in:
2025-10-27 23:59:28 +08:00
parent b7a730c640
commit 66c9dad849
3 changed files with 232 additions and 4 deletions

View File

@@ -18,9 +18,15 @@ public class ProductJdConfig extends BaseEntity
/** 京东链接 */
private String jdUrl;
/** 佣金 */
/** 佣金(旧字段,保留兼容) */
private BigDecimal commission;
/** 佣金(收取) - 从客户收取的佣金 */
private BigDecimal commissionReceive;
/** 佣金(支付) - 支付给下单人的佣金 */
private BigDecimal commissionPay;
public ProductJdConfig() {
}
@@ -54,12 +60,30 @@ public class ProductJdConfig extends BaseEntity
this.commission = commission;
}
public BigDecimal getCommissionReceive() {
return commissionReceive;
}
public void setCommissionReceive(BigDecimal commissionReceive) {
this.commissionReceive = commissionReceive;
}
public BigDecimal getCommissionPay() {
return commissionPay;
}
public void setCommissionPay(BigDecimal commissionPay) {
this.commissionPay = commissionPay;
}
@Override
public String toString() {
return "ProductJdConfig{" +
"productModel='" + productModel + '\'' +
", jdUrl='" + jdUrl + '\'' +
", commission=" + commission +
", commissionReceive=" + commissionReceive +
", commissionPay=" + commissionPay +
'}';
}
}

View File

@@ -344,12 +344,17 @@ public class InstructionServiceImpl implements IInstructionService {
singlePayment = Math.round(singlePayment * 100.0) / 100.0;
singleRebate = Math.round(singleRebate * 100.0) / 100.0;
// 从Redis获取佣金
// 从Redis获取佣金(收取)
double commission = 0.0;
try {
com.ruoyi.jarvis.domain.ProductJdConfig config = productJdConfigService.selectProductJdConfigByModel(model);
if (config != null && config.getCommission() != null) {
commission = config.getCommission().doubleValue();
if (config != null) {
// 优先使用新的佣金收取字段如果没有则使用旧的commission字段
if (config.getCommissionReceive() != null) {
commission = config.getCommissionReceive().doubleValue();
} else if (config.getCommission() != null) {
commission = config.getCommission().doubleValue();
}
}
} catch (Exception ex) {
// 如果获取失败佣金为0
@@ -399,6 +404,174 @@ public class InstructionServiceImpl implements IInstructionService {
}
}
// ==================== 追加:按下单人分组统计 ====================
outputs.add("\n━━━━━━━ 按下单人统计 ━━━━━━━");
// 按下单人分组(过滤掉拍错退款)
Map<String, List<JDOrder>> byBuyer = filtered.stream()
.filter(o -> o.getStatus() == null || !"拍错退款".equals(o.getStatus()))
.filter(o -> o.getBuyer() != null && !o.getBuyer().isEmpty())
.collect(Collectors.groupingBy(JDOrder::getBuyer));
List<Map.Entry<String, List<JDOrder>>> buyerEntries = new ArrayList<>(byBuyer.entrySet());
buyerEntries.sort(Comparator.comparing(en -> en.getKey() == null ? "" : en.getKey()));
for (Map.Entry<String, List<JDOrder>> e : buyerEntries) {
String buyer = e.getKey() != null ? e.getKey() : "未提供";
List<JDOrder> orders = e.getValue();
Map<String, Long> byModel = orders.stream()
.collect(Collectors.groupingBy(JDOrder::getModelNumber, Collectors.counting()));
int totalCount = 0;
StringBuilder summary = new StringBuilder();
List<Map.Entry<String, Long>> modelEntries = new ArrayList<>(byModel.entrySet());
modelEntries.sort(Comparator.comparing(en -> en.getKey() == null ? "" : en.getKey()));
// 记录该下单人每个型号的最高单价订单
Map<String, JDOrder> buyerMaxPriceOrders = new HashMap<>();
Map<String, Integer> buyerModelCounts = new HashMap<>();
for (Map.Entry<String, Long> em : modelEntries) {
int c = em.getValue().intValue();
totalCount += c;
String model = em.getKey() != null ? em.getKey() : "未知";
summary.append("型号:").append(model).append(" 数量:").append(c).append("\n");
buyerModelCounts.put(model, c);
// 找到该型号价格最高的订单
for (JDOrder order : orders) {
if (model.equals(order.getModelNumber())) {
JDOrder currentMax = buyerMaxPriceOrders.get(model);
if (currentMax == null ||
(order.getPaymentAmount() != null &&
(currentMax.getPaymentAmount() == null ||
order.getPaymentAmount() > currentMax.getPaymentAmount()))) {
buyerMaxPriceOrders.put(model, order);
}
}
}
}
summary.append("总计:").append(totalCount).append("\n详情");
List<JDOrder> sorted = orders.stream()
.sorted(Comparator.comparing(JDOrder::getRemark, Comparator.nullsFirst(String::compareTo)))
.collect(Collectors.toList());
StringBuilder detail = new StringBuilder();
int idx = 0;
for (JDOrder o : sorted) {
if ("拍错退款".equals(o.getStatus())) continue;
idx++;
detail.append("\n").append(idx).append(" ────────────\n")
.append("单:").append(o.getRemark() != null ? o.getRemark() : "未提供").append("\n")
.append("备注:").append(o.getStatus() != null ? o.getStatus() : " ").append("\n")
.append("型号:").append(o.getModelNumber() != null ? o.getModelNumber() : "未提供").append("\n")
.append("地址:").append(o.getAddress() != null ? o.getAddress() : "未提供").append("\n")
.append("物流链接:\n").append(o.getLogisticsLink() != null ? o.getLogisticsLink() : "");
}
// 订单详情
StringBuilder infoSingle = new StringBuilder();
infoSingle.append("下单人:").append(buyer).append("\n").append(summary).append(detail).append("\n");
outputs.add(infoSingle.toString().trim());
// 算钱文本(使用佣金支付)
if (!buyerModelCounts.isEmpty()) {
StringBuilder priceText = new StringBuilder();
priceText.append("下单人:").append(buyer).append("\n");
// 先输出型号和数量
List<Map.Entry<String, Integer>> sortedEntries = buyerModelCounts.entrySet().stream()
.sorted(Comparator.comparing(Map.Entry::getKey))
.collect(Collectors.toList());
for (Map.Entry<String, Integer> entry : sortedEntries) {
String model = entry.getKey();
int count = entry.getValue();
priceText.append("型号:").append(model).append(" 数量:").append(count).append("\n");
}
priceText.append("\n");
// 输出金额计算(使用佣金支付字段)
double grandTotal = 0.0;
StringBuilder calculationLines = new StringBuilder();
List<Double> totalPricesList = new ArrayList<>();
for (Map.Entry<String, Integer> entry : sortedEntries) {
String model = entry.getKey();
int count = entry.getValue();
// 获取该型号最高价格的订单
JDOrder maxPriceOrder = buyerMaxPriceOrders.get(model);
double singlePayment = 0.0;
double singleRebate = 0.0;
if (maxPriceOrder != null) {
singlePayment = maxPriceOrder.getPaymentAmount() != null ? maxPriceOrder.getPaymentAmount() : 0.0;
singleRebate = maxPriceOrder.getRebateAmount() != null ? maxPriceOrder.getRebateAmount() : 0.0;
}
singlePayment = Math.round(singlePayment * 100.0) / 100.0;
singleRebate = Math.round(singleRebate * 100.0) / 100.0;
// 从Redis获取佣金支付- 支付给下单人的佣金
double commissionPay = 0.0;
try {
com.ruoyi.jarvis.domain.ProductJdConfig config = productJdConfigService.selectProductJdConfigByModel(model);
if (config != null) {
// 优先使用新的佣金支付字段如果没有则使用旧的commission字段
if (config.getCommissionPay() != null) {
commissionPay = config.getCommissionPay().doubleValue();
} else if (config.getCommission() != null) {
commissionPay = config.getCommission().doubleValue();
}
}
} catch (Exception ex) {
// 如果获取失败佣金为0
}
// 计算净价(单台价格 - 返现 + 佣金支付)
double netPrice = singlePayment - singleRebate + commissionPay;
netPrice = Math.round(netPrice * 100.0) / 100.0;
// 计算总价
double totalPrice = netPrice * count;
totalPrice = Math.round(totalPrice * 100.0) / 100.0;
totalPricesList.add(totalPrice);
grandTotal += totalPrice;
// 格式:单台价格-返现+佣金=净价×数量=总价
if (count == 1) {
calculationLines.append(String.format("%.2f-%.2f+%.2f=%.2f\n",
singlePayment, singleRebate, commissionPay, totalPrice));
} else {
calculationLines.append(String.format("%.2f-%.2f+%.2f=%.2f×%d=%.2f\n",
singlePayment, singleRebate, commissionPay, netPrice, count, totalPrice));
}
}
priceText.append(calculationLines);
// 输出汇总
if (sortedEntries.size() > 1) {
priceText.append("\n");
for (int i = 0; i < totalPricesList.size(); i++) {
if (i > 0) {
priceText.append("+");
}
priceText.append(String.format("%.2f", totalPricesList.get(i)));
}
grandTotal = Math.round(grandTotal * 100.0) / 100.0;
priceText.append(String.format("=%.2f", grandTotal));
}
outputs.add(priceText.toString().trim());
}
}
// ==================== 按下单人统计结束 ====================
return outputs.isEmpty() ? Collections.singletonList("无数据") : outputs;
}
@@ -862,6 +1035,8 @@ private String handleTF(String input) {
order.setLogisticsLink(extractFirstUrl(fields.getOrDefault("物流链接", "")));
order.setOrderId(fields.getOrDefault("订单号", null));
order.setBuyer(fields.getOrDefault("下单人", null));
// 默认参与统计
order.setIsCountEnabled(1);
try {
String dateStr = fields.getOrDefault("", "").split(" ")[0];
java.text.SimpleDateFormat sdf2 = new java.text.SimpleDateFormat("yyyy-MM-dd");

View File

@@ -81,6 +81,8 @@ public class ProductJdConfigServiceImpl implements IProductJdConfigService
ProductJdConfig config = new ProductJdConfig();
config.setProductModel((String) map.get("productModel"));
config.setJdUrl((String) map.get("jdUrl"));
// 处理旧的佣金字段(兼容)
Object commissionObj = map.get("commission");
if (commissionObj != null) {
if (commissionObj instanceof BigDecimal) {
@@ -91,6 +93,31 @@ public class ProductJdConfigServiceImpl implements IProductJdConfigService
config.setCommission(new BigDecimal(commissionObj.toString()));
}
}
// 处理佣金(收取)
Object commissionReceiveObj = map.get("commissionReceive");
if (commissionReceiveObj != null) {
if (commissionReceiveObj instanceof BigDecimal) {
config.setCommissionReceive((BigDecimal) commissionReceiveObj);
} else if (commissionReceiveObj instanceof Number) {
config.setCommissionReceive(new BigDecimal(commissionReceiveObj.toString()));
} else {
config.setCommissionReceive(new BigDecimal(commissionReceiveObj.toString()));
}
}
// 处理佣金(支付)
Object commissionPayObj = map.get("commissionPay");
if (commissionPayObj != null) {
if (commissionPayObj instanceof BigDecimal) {
config.setCommissionPay((BigDecimal) commissionPayObj);
} else if (commissionPayObj instanceof Number) {
config.setCommissionPay(new BigDecimal(commissionPayObj.toString()));
} else {
config.setCommissionPay(new BigDecimal(commissionPayObj.toString()));
}
}
return config;
}
return null;
@@ -124,6 +151,8 @@ public class ProductJdConfigServiceImpl implements IProductJdConfigService
map.put("productModel", productJdConfig.getProductModel());
map.put("jdUrl", productJdConfig.getJdUrl());
map.put("commission", productJdConfig.getCommission() != null ? productJdConfig.getCommission() : BigDecimal.ZERO);
map.put("commissionReceive", productJdConfig.getCommissionReceive() != null ? productJdConfig.getCommissionReceive() : BigDecimal.ZERO);
map.put("commissionPay", productJdConfig.getCommissionPay() != null ? productJdConfig.getCommissionPay() : BigDecimal.ZERO);
redisCache.setCacheMap(PRODUCT_JD_CONFIG_KEY + productJdConfig.getProductModel(), map);
return 1;
}