diff --git a/src/main/java/com/gxwebsoft/glt/task/DealerOrderSettlement10584Task.java b/src/main/java/com/gxwebsoft/glt/task/DealerOrderSettlement10584Task.java index d83e9f1..59af8dc 100644 --- a/src/main/java/com/gxwebsoft/glt/task/DealerOrderSettlement10584Task.java +++ b/src/main/java/com/gxwebsoft/glt/task/DealerOrderSettlement10584Task.java @@ -48,6 +48,7 @@ public class DealerOrderSettlement10584Task { private static final BigDecimal RATE_0_03 = new BigDecimal("0.03"); private static final BigDecimal RATE_0_02 = new BigDecimal("0.02"); private static final BigDecimal RATE_0_01 = new BigDecimal("0.01"); + private static final BigDecimal TOTAL_DEALER_DIVIDEND_RATE = RATE_0_01; private static final int MAX_ORDERS_PER_RUN = 50; private static final int MAX_REFEREE_CHAIN_DEPTH = 20; @@ -95,6 +96,10 @@ public class DealerOrderSettlement10584Task { // Per-run caches to reduce DB chatter across orders. Map level1ParentCache = new HashMap<>(); Map shopRoleCache = new HashMap<>(); + Integer totalDealerUserId = findTotalDealerUserId(); + if (totalDealerUserId == null) { + log.warn("未找到总经销商账号,订单仍可结算但不会发放总经销商分润 - tenantId={}", TENANT_ID); + } log.info("租户{}待结算订单数: {}, orderNos(sample)={}", TENANT_ID, @@ -108,7 +113,7 @@ public class DealerOrderSettlement10584Task { if (!claimOrderToSettle(order.getOrderId())) { return; } - settleOneOrder(order, level1ParentCache, shopRoleCache); + settleOneOrder(order, level1ParentCache, shopRoleCache, totalDealerUserId); }); } catch (Exception e) { log.error("订单结算失败,将回滚本订单并在下次任务重试 - orderId={}, orderNo={}", order.getOrderId(), order.getOrderNo(), e); @@ -141,7 +146,12 @@ public class DealerOrderSettlement10584Task { ); } - private void settleOneOrder(ShopOrder order, Map level1ParentCache, Map shopRoleCache) { + private void settleOneOrder( + ShopOrder order, + Map level1ParentCache, + Map shopRoleCache, + Integer totalDealerUserId + ) { if (order.getUserId() == null || order.getOrderNo() == null) { throw new IllegalStateException("订单关键信息缺失,无法结算 - orderId=" + order.getOrderId()); } @@ -183,8 +193,11 @@ public class DealerOrderSettlement10584Task { // 2) 门店分红上级:从下单用户开始逐级向上找,命中 ShopDealerUser.type=1 的最近两级(直推门店/间推门店)。 ShopRoleCommission shopRoleCommission = settleShopRoleRefereeCommission(order, baseAmount, goodsQty, commissionConfig, level1ParentCache, shopRoleCache); - // 3) 写入分销订单记录(用于排查/统计;详细分佣以 ShopDealerCapital 为准) - createDealerOrderRecord(order, baseAmount, dealerRefereeCommission, shopRoleCommission); + // 3) 总经销商分润:固定比率,每个订单都分。 + TotalDealerCommission totalDealerCommission = settleTotalDealerCommission(order, baseAmount, goodsQty, totalDealerUserId); + + // 4) 写入分销订单记录(用于排查/统计;详细分佣以 ShopDealerCapital 为准) + createDealerOrderRecord(order, baseAmount, dealerRefereeCommission, shopRoleCommission, totalDealerCommission); log.info("订单结算完成 - orderId={}, orderNo={}, baseAmount={}", order.getOrderId(), order.getOrderNo(), baseAmount); } @@ -323,6 +336,40 @@ public class DealerOrderSettlement10584Task { return new ShopRoleCommission(shopRoleReferees.get(0), storeDirectMoney, shopRoleReferees.get(1), storeSimpleMoney); } + private TotalDealerCommission settleTotalDealerCommission( + ShopOrder order, + BigDecimal baseAmount, + int goodsQty, + Integer totalDealerUserId + ) { + if (totalDealerUserId == null) { + return TotalDealerCommission.empty(); + } + BigDecimal money = calcMoneyByCommissionType(baseAmount, TOTAL_DEALER_DIVIDEND_RATE, goodsQty, DIVIDEND_SCALE, 20); + log.info("总经销商分润发放 - orderNo={}, totalDealerUserId={}, rate={}, money={}", + order.getOrderNo(), totalDealerUserId, TOTAL_DEALER_DIVIDEND_RATE, money); + creditDealerCommission( + totalDealerUserId, + money, + order, + order.getUserId(), + buildCommissionComment("总经销商分润", 20, TOTAL_DEALER_DIVIDEND_RATE, goodsQty) + ); + return new TotalDealerCommission(totalDealerUserId, money); + } + + private Integer findTotalDealerUserId() { + ShopDealerUser dealerUser = shopDealerUserService.getOne( + new LambdaQueryWrapper() + .eq(ShopDealerUser::getTenantId, TENANT_ID) + .eq(ShopDealerUser::getType, 2) + .and(w -> w.eq(ShopDealerUser::getIsDelete, 0).or().isNull(ShopDealerUser::getIsDelete)) + .orderByAsc(ShopDealerUser::getId) + .last("limit 1") + ); + return dealerUser != null ? dealerUser.getUserId() : null; + } + /** * 门店分红规则: * - 门店角色为 ShopDealerUser.type=1; @@ -502,7 +549,8 @@ public class DealerOrderSettlement10584Task { ShopOrder order, BigDecimal baseAmount, DealerRefereeCommission dealerRefereeCommission, - ShopRoleCommission shopRoleCommission + ShopRoleCommission shopRoleCommission, + TotalDealerCommission totalDealerCommission ) { // 幂等:同一订单只写一条(依赖 order_no + tenant_id 作为业务唯一) ShopDealerOrder existed = shopDealerOrderService.getOne( @@ -580,20 +628,25 @@ public class DealerOrderSettlement10584Task { dealerOrder.setMonth(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"))); dealerOrder.setTenantId(TENANT_ID); - dealerOrder.setComments(buildCommissionTraceComment(dealerRefereeCommission, shopRoleCommission)); + dealerOrder.setComments(buildCommissionTraceComment(dealerRefereeCommission, shopRoleCommission, totalDealerCommission)); shopDealerOrderService.save(dealerOrder); log.info("写入ShopDealerOrder完成 - orderNo={}, firstUserId={}, secondUserId={}, firstDividendUser={}, secondDividendUser={}", order.getOrderNo(), dealerOrder.getFirstUserId(), dealerOrder.getSecondUserId(), dealerOrder.getFirstDividendUser(), dealerOrder.getSecondDividendUser()); } - private String buildCommissionTraceComment(DealerRefereeCommission dealerRefereeCommission, ShopRoleCommission shopRoleCommission) { + private String buildCommissionTraceComment( + DealerRefereeCommission dealerRefereeCommission, + ShopRoleCommission shopRoleCommission, + TotalDealerCommission totalDealerCommission + ) { // 轻量“过程”留痕,方便排查;详细分佣以 ShopDealerCapital 为准。 return "direct=" + dealerRefereeCommission.directDealerId + ":" + dealerRefereeCommission.directMoney + ",simple=" + dealerRefereeCommission.simpleDealerId + ":" + dealerRefereeCommission.simpleMoney + ",third=" + dealerRefereeCommission.thirdDealerId + ":" + dealerRefereeCommission.thirdMoney + ",dividend1=" + shopRoleCommission.storeDirectUserId + ":" + shopRoleCommission.storeDirectMoney - + ",dividend2=" + shopRoleCommission.storeSimpleUserId + ":" + shopRoleCommission.storeSimpleMoney; + + ",dividend2=" + shopRoleCommission.storeSimpleUserId + ":" + shopRoleCommission.storeSimpleMoney + + ",totalDealer=" + totalDealerCommission.userId + ":" + totalDealerCommission.money; } private BigDecimal getOrderBaseAmount(ShopOrder order) { @@ -805,4 +858,18 @@ public class DealerOrderSettlement10584Task { this.storeSimpleMoney = storeSimpleMoney != null ? storeSimpleMoney : BigDecimal.ZERO; } } + + private static class TotalDealerCommission { + private final Integer userId; + private final BigDecimal money; + + private static TotalDealerCommission empty() { + return new TotalDealerCommission(null, BigDecimal.ZERO); + } + + private TotalDealerCommission(Integer userId, BigDecimal money) { + this.userId = userId; + this.money = money != null ? money : BigDecimal.ZERO; + } + } }