使用Gemini2.5 pro 优化我的定时任务(二)

使用Gemini2.5 pro 优化我的定时任务(二)

前言

公司最近有一个九维分红的需求,用户体系一共是从普通用户、一维会员、二维会员、三维会员、四维会员、五维会员、六维会员、七维会员、八维会员、九维会员。

用户直推上一个统计周期总佣金/(所有一度会员上一个统计周期直推总佣金+所有二度会员上一个统计周期直推总佣金+所有三度会员上一个统计周期直推总佣金+所有四度会员上一个统计周期直推总佣金+所有五度会员上一个统计周期直推总佣金+所有六度会员上一个统计周期直推总佣金+所有七度会员上一个统计周期直推总佣金+所有八度会员上一个统计周期直推总佣金+所有九度会员上一个统计周期直推总佣金+)】*(平台总佣金*9%)*10000=XXX活跃积分

分红奖励:每月25日结算上个月佣金(统计周期与结算时间自定义)

分红条件:以下两个条件同时满足

1、必须是(一度会员.....九度会员)

2、必须有自购订单(统计周期)

其中, 平台总佣金 = 用户直推上一个统计周期总佣金 + 普通会员总佣金 + 没有自购订单的一~~九度会员的总佣金;

第一版代码

java 复制代码
import com.alibaba.nacos.api.config.listener.Listener;
import com.alipay.api.domain.SealTabsVO;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Max;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 数字联盟九维分红定时任务
 */

@Component
public class NineDimsDiddCpsJob {

    @Resource
    private JtkSharingConfigService jtkSharingConfigService;

    @Resource
    private JtkOrdersService jtkOrdersService;

    @Resource
    private DtkTbOrderService dtkTbOrderService;

    @Resource
    private DtkPddOrderService pddOrderService;

    private final String WEEK = "WEEK";

    private final String MONTH = "MONTH";

    /** 活跃积分固定值 */
    private final BigDecimal FIXED_ACTIVE = new BigDecimal("10000");


    /** FIRST_LEVEL 一维会员 */
    private final Long FIRST_LEVEL = 2L;
    /** SECOND_LEVEL 二维会员 */
    private final Long SECOND_LEVEL = 3L;
    /** THIRD_LEVEL 三维会员 */
    private final Long THIRD_LEVEL = 4L;
    /** FOURTH_LEVEL 四维会员 */
    private final Long FOURTH_LEVEL = 5L;
    /** FIFTH_LEVEL 五维会员 */
    private final Long FIFTH_LEVEL = 6L;
    /** SIXTH_LEVEL 六维会员 */
    private final Long SIXTH_LEVEL = 7L;
    /** SEVENTH_LEVEL 七维会员 */
    private final Long SEVENTH_LEVEL = 8L;
    /** EIGHTH_LEVEL 八维会员 */
    private final Long EIGHTH_LEVEL = 9L;
    /** NINTH_LEVEL 九维会员 */
    private final Long NINTH_LEVEL = 10L;

    @XxlJob("NineDimsDiddCpsJob")
    public void execute() {
        XxlJobHelper.log("数字联盟九维分红开始执行!");
        // 获取配置信息,确定是按照周分配还是月分配
        JtkSharingConfigDO jtkSharingConfigData = jtkSharingConfigService.getJtkSharingConfigData();
        // 获取配置为空则返回,不进行分配
        if (jtkSharingConfigData.getId() == 0) {
            XxlJobHelper.log("数字联盟九维分红配置为空!不进行后续分配!");
            return;
        }
        String statisticalPeriod = jtkSharingConfigData.getStatisticalPeriod();
        XxlJobHelper.log("数字联盟九维分红配置信息为:" + jtkSharingConfigData);
        LocalDateTime startTime;
        LocalDateTime endTime;
        if (WEEK.equals(statisticalPeriod)) {
            // 获取上周周一起始时间到周日的时间
            startTime = LocalDateTimeUtils.getLastMondayStart(LocalDateTime.now());
            endTime = LocalDateTimeUtils.getLastSundayEnd(LocalDateTime.now());
        } else {
            // 获取上月起始时间到月末的时间
            startTime = LocalDateTimeUtils.beginOfMonth(LocalDateTime.now().minusMonths(1));
            endTime = LocalDateTimeUtils.endOfMonth(LocalDateTime.now().minusMonths(1));
        }

        // 通过时间间隔查询订单数据
        List<JtkOrdersDO> jtkOrdersDOS = jtkOrdersService.getJtkOrdersByTimeInterval(startTime, endTime);
        List<DtkTbOrderDO> dtkTbOrderDOS = dtkTbOrderService.getDtkOrdersByTimeInterval(startTime, endTime);
        List<DtkPddOrderDO> pddOrderDOS = pddOrderService.getPddOrdersByTimeInterval(startTime, endTime);

        if (jtkOrdersDOS.isEmpty() && dtkTbOrderDOS.isEmpty() && pddOrderDOS.isEmpty()) {
            XxlJobHelper.log("数字联盟所有订单订单数据为空!不进行后续分配!");
        }

        /** step #1 计算用户直推上一个统计周期总佣金 */
        BigDecimal dprTotalCommission = BigDecimal.ZERO;
        BigDecimal jtkOrderTotalCommission = BigDecimal.ZERO;
        BigDecimal dtkTBTotalCommission = BigDecimal.ZERO;
        BigDecimal pddTotalCommission = BigDecimal.ZERO;
        boolean isJtkOrderEmpty = jtkOrdersDOS.isEmpty();
        boolean isDtkTbOrderEmpty = dtkTbOrderDOS.isEmpty();
        boolean isPddOrderEmpty = pddOrderDOS.isEmpty();
        /** step ##1.1 计算聚推客总佣金 */
        if (!isJtkOrderEmpty) {
            // 获取用户直推上一个统计周期总佣金
            jtkOrderTotalCommission = jtkOrdersDOS.stream()
                    // 将流转换为Stream<BigDecimal>, 存储佣金值的流
                    .map(JtkOrdersDO::getJtkShareFee)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        XxlJobHelper.log("数字联盟聚推客订单分配总佣金为:" + jtkOrderTotalCommission);

        /** step ##1.2 计算聚推客淘宝订单总佣金 */
        if (!isDtkTbOrderEmpty) {
            dtkTBTotalCommission = dtkTbOrderDOS.stream()
                    // 将流转换为Stream<BigDecimal>, 存储佣金值的流
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        XxlJobHelper.log("数字联盟淘宝订单分配总佣金为:" + dtkTBTotalCommission);

        /** step ##1.3 获取拼多多订单总佣金 */
        if (!isPddOrderEmpty) {
            pddTotalCommission = pddOrderDOS.stream()
                    // 将流转换为Stream<BigDecimal>, 存储佣金值的流
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        XxlJobHelper.log("数字联盟拼多多订单分配总佣金为:" + pddTotalCommission);

        /** step ##1.4 获取平台总佣金 */
        dprTotalCommission = jtkOrderTotalCommission.add(dtkTBTotalCommission).add(pddTotalCommission);
        XxlJobHelper.log("数字联盟待分配订单总佣金为:" + dprTotalCommission);

        /** step #2 获取各维度用户直推总佣金 */
        /**
         * 序数词(表示顺序)
         * first(第 1),缩写:1st
         * second(第 2),缩写:2nd
         * third(第 3),缩写:3rd
         * fourth(第 4),缩写:4th
         * fifth(第 5),缩写:5th
         * sixth(第 6),缩写:6th
         * seventh(第 7),缩写:7th
         * eighth(第 8),缩写:8th
         * ninth(第 9),缩写:9th
         */
        /** step ##2.1 获取第一维度用户直推总佣金 */
        BigDecimal dprFirstTotalCommission = BigDecimal.ZERO;
        /** step ##2.2 获取第二维度用户直推总佣金 */
        BigDecimal dprSecondTotalCommission = BigDecimal.ZERO;
        /** step ##2.3 获取第三维度用户直推总佣金 */
        BigDecimal dprThirdTotalCommission = BigDecimal.ZERO;
        /** step ##2.4 获取第四维度用户直推总佣金 */
        BigDecimal dprFourthTotalCommission = BigDecimal.ZERO;
        /** step ##2.5 获取第五维度用户直推总佣金 */
        BigDecimal dprFifthTotalCommission = BigDecimal.ZERO;
        /** step ##2.6 获取第六维度用户直推总佣金 */
        BigDecimal dprSixthTotalCommission = BigDecimal.ZERO;
        /** step ##2.7 获取第七维度用户直推总佣金 */
        BigDecimal dprSeventhTotalCommission = BigDecimal.ZERO;
        /** step ##2.8 获取第八维度用户直推总佣金 */
        BigDecimal dprEighthTotalCommission = BigDecimal.ZERO;
        /** step ##2.9 获取第九维度用户直推总佣金 */
        BigDecimal dprNinthTotalCommission = BigDecimal.ZERO;

        if (!isJtkOrderEmpty) {
            // 获取用户直推上一个统计周期总佣金
            dprFirstTotalCommission = jtkOrdersDOS.stream()
                    .filter(jtkOrdersDO -> jtkOrdersDO.getDprLevel().equals(FIRST_LEVEL))
                    .map(JtkOrdersDO::getJtkShareFee)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            dprSecondTotalCommission = jtkOrdersDOS.stream()
                    .filter(jtkOrdersDO -> jtkOrdersDO.getDprLevel().equals(SECOND_LEVEL))
                    .map(JtkOrdersDO::getJtkShareFee)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            dprThirdTotalCommission = jtkOrdersDOS.stream()
                    .filter(jtkOrdersDO -> jtkOrdersDO.getDprLevel().equals(THIRD_LEVEL))
                    .map(JtkOrdersDO::getJtkShareFee)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            dprFourthTotalCommission = jtkOrdersDOS.stream()
                     .filter(jtkOrdersDO -> jtkOrdersDO.getDprLevel().equals(FOURTH_LEVEL))
                     .map(JtkOrdersDO::getJtkShareFee)
                     .reduce(BigDecimal.ZERO, BigDecimal::add);
            dprFifthTotalCommission = jtkOrdersDOS.stream()
                    .filter(jtkOrdersDO -> jtkOrdersDO.getDprLevel().equals(FIFTH_LEVEL))
                    .map(JtkOrdersDO::getJtkShareFee)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            dprSixthTotalCommission = jtkOrdersDOS.stream()
                    .filter(jtkOrdersDO -> jtkOrdersDO.getDprLevel().equals(SIXTH_LEVEL))
                    .map(JtkOrdersDO::getJtkShareFee)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            dprSeventhTotalCommission = jtkOrdersDOS.stream()
                    .filter(jtkOrdersDO -> jtkOrdersDO.getDprLevel().equals(SEVENTH_LEVEL))
                    .map(JtkOrdersDO::getJtkShareFee)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            dprEighthTotalCommission = jtkOrdersDOS.stream()
                    .filter(jtkOrdersDO -> jtkOrdersDO.getDprLevel().equals(EIGHTH_LEVEL))
                    .map(JtkOrdersDO::getJtkShareFee)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            dprNinthTotalCommission = jtkOrdersDOS.stream()
                    .filter(jtkOrdersDO -> jtkOrdersDO.getDprLevel().equals(NINTH_LEVEL))
                    .map(JtkOrdersDO::getJtkShareFee)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }

        if (!isDtkTbOrderEmpty) {
            dprFirstTotalCommission = dprFirstTotalCommission.add(dtkTbOrderDOS.stream()
                    .filter(dtkTbOrderDO -> dtkTbOrderDO.getDprLevel().equals(FIRST_LEVEL))
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprSecondTotalCommission = dprSecondTotalCommission.add(dtkTbOrderDOS.stream()
                    .filter(dtkTbOrderDO -> dtkTbOrderDO.getDprLevel().equals(SECOND_LEVEL))
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprThirdTotalCommission = dprThirdTotalCommission.add(dtkTbOrderDOS.stream()
                    .filter(dtkTbOrderDO -> dtkTbOrderDO.getDprLevel().equals(THIRD_LEVEL))
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprFourthTotalCommission = dprFourthTotalCommission.add(dtkTbOrderDOS.stream()
                    .filter(dtkTbOrderDO -> dtkTbOrderDO.getDprLevel().equals(FOURTH_LEVEL))
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprFifthTotalCommission = dprFifthTotalCommission.add(dtkTbOrderDOS.stream()
                    .filter(dtkTbOrderDO -> dtkTbOrderDO.getDprLevel().equals(FIFTH_LEVEL))
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprSixthTotalCommission = dprSixthTotalCommission.add(dtkTbOrderDOS.stream()
                    .filter(dtkTbOrderDO -> dtkTbOrderDO.getDprLevel().equals(SIXTH_LEVEL))
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprSeventhTotalCommission = dprSeventhTotalCommission.add(dtkTbOrderDOS.stream()
                    .filter(dtkTbOrderDO -> dtkTbOrderDO.getDprLevel().equals(SEVENTH_LEVEL))
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprEighthTotalCommission = dprEighthTotalCommission.add(dtkTbOrderDOS.stream()
                    .filter(dtkTbOrderDO -> dtkTbOrderDO.getDprLevel().equals(EIGHTH_LEVEL))
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprNinthTotalCommission = dprNinthTotalCommission.add(dtkTbOrderDOS.stream()
                    .filter(dtkTbOrderDO -> dtkTbOrderDO.getDprLevel().equals(NINTH_LEVEL))
                    .map(DtkTbOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));
        }

        if (!isPddOrderEmpty) {
            dprFirstTotalCommission = dprFirstTotalCommission.add(pddOrderDOS.stream()
                    .filter(pddOrderDO -> pddOrderDO.getDprLevel().equals(FIRST_LEVEL))
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprSecondTotalCommission = dprSecondTotalCommission.add(pddOrderDOS.stream()
                    .filter(pddOrderDO -> pddOrderDO.getDprLevel().equals(SECOND_LEVEL))
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprThirdTotalCommission = dprThirdTotalCommission.add(pddOrderDOS.stream()
                    .filter(pddOrderDO -> pddOrderDO.getDprLevel().equals(THIRD_LEVEL))
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprFourthTotalCommission = dprFourthTotalCommission.add(pddOrderDOS.stream()
                    .filter(pddOrderDO -> pddOrderDO.getDprLevel().equals(FOURTH_LEVEL))
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprFifthTotalCommission = dprFifthTotalCommission.add(pddOrderDOS.stream()
                    .filter(pddOrderDO -> pddOrderDO.getDprLevel().equals(FIFTH_LEVEL))
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprSixthTotalCommission = dprSixthTotalCommission.add(pddOrderDOS.stream()
                    .filter(pddOrderDO -> pddOrderDO.getDprLevel().equals(SIXTH_LEVEL))
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprSeventhTotalCommission = dprSeventhTotalCommission.add(pddOrderDOS.stream()
                    .filter(pddOrderDO -> pddOrderDO.getDprLevel().equals(SEVENTH_LEVEL))
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprEighthTotalCommission = dprEighthTotalCommission.add(pddOrderDOS.stream()
                    .filter(pddOrderDO -> pddOrderDO.getDprLevel().equals(EIGHTH_LEVEL))
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

            dprNinthTotalCommission = dprNinthTotalCommission.add(pddOrderDOS.stream()
                    .filter(pddOrderDO -> pddOrderDO.getDprLevel().equals(NINTH_LEVEL))
                    .map(DtkPddOrderDO::getPromotionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));

        }
        XxlJobHelper.log("数字联盟聚推客订单分配第一维度总佣金为:" + dprFirstTotalCommission);
        XxlJobHelper.log("数字联盟聚推客订单分配第二维度总佣金为:" + dprSecondTotalCommission);
        XxlJobHelper.log("数字联盟聚推客订单分配第三维度总佣金为:" + dprThirdTotalCommission);
        XxlJobHelper.log("数字联盟聚推客订单分配第四维度总佣金为:" + dprFourthTotalCommission);
        XxlJobHelper.log("数字联盟聚推客订单分配第五维度总佣金为:" + dprFifthTotalCommission);
        XxlJobHelper.log("数字联盟聚推客订单分配第六维度总佣金为:" + dprSixthTotalCommission);
        XxlJobHelper.log("数字联盟聚推客订单分配第七维度总佣金为:" + dprSeventhTotalCommission);
        XxlJobHelper.log("数字联盟聚推客订单分配第八维度总佣金为:" + dprEighthTotalCommission);
        XxlJobHelper.log("数字联盟聚推客订单分配第九维度总佣金为:" + dprNinthTotalCommission);

        /** step #3 获取各维度用户信息 */
        /** step ##3.1 一维用户的所有信息 */
        Set<Long> firstDprUids = extractSpecialDprUids(jtkOrdersDOS, FIRST_LEVEL);
        firstDprUids.addAll(extractSpecialDprUids(dtkTbOrderDOS, FIRST_LEVEL));
        firstDprUids.addAll(extractSpecialDprUids(pddOrderDOS, FIRST_LEVEL));
        XxlJobHelper.log("获取到一维用户总数为:" + firstDprUids.size());

        /** step ##3.2 二维用户的所有信息 */
        Set<Long> secondDprUids = extractSpecialDprUids(jtkOrdersDOS, SECOND_LEVEL);
        secondDprUids.addAll(extractSpecialDprUids(dtkTbOrderDOS, SECOND_LEVEL));
        secondDprUids.addAll(extractSpecialDprUids(pddOrderDOS, SECOND_LEVEL));
        XxlJobHelper.log("获取到二维用户总数为:" + secondDprUids.size());

        /** step ##3.3 三维用户的所有信息 */
        Set<Long> thirdDprUids = extractSpecialDprUids(jtkOrdersDOS, THIRD_LEVEL);
        thirdDprUids.addAll(extractSpecialDprUids(dtkTbOrderDOS, THIRD_LEVEL));
        thirdDprUids.addAll(extractSpecialDprUids(pddOrderDOS, THIRD_LEVEL));
        XxlJobHelper.log("获取到三维用户总数为:" + thirdDprUids.size());

        /** step ##3.4 四维用户的所有信息 */
        Set<Long> fourthDprUids = extractSpecialDprUids(jtkOrdersDOS, FOURTH_LEVEL);
        fourthDprUids.addAll(extractSpecialDprUids(dtkTbOrderDOS, FOURTH_LEVEL));
        fourthDprUids.addAll(extractSpecialDprUids(pddOrderDOS, FOURTH_LEVEL));
        XxlJobHelper.log("获取到四维用户总数为:" + fourthDprUids.size());

        /** step ##3.5 五维用户的所有信息 */
        Set<Long> fifthDprUids = extractSpecialDprUids(jtkOrdersDOS, FIFTH_LEVEL);
        fifthDprUids.addAll(extractSpecialDprUids(dtkTbOrderDOS, FIFTH_LEVEL));
        fifthDprUids.addAll(extractSpecialDprUids(pddOrderDOS, FIFTH_LEVEL));
        XxlJobHelper.log("获取到五维用户总数为:" + fifthDprUids.size());


        /** step ##3.6 六维用户的所有信息 */
        Set<Long> sixthDprUids = extractSpecialDprUids(jtkOrdersDOS, SIXTH_LEVEL);
        sixthDprUids.addAll(extractSpecialDprUids(dtkTbOrderDOS, SIXTH_LEVEL));
        sixthDprUids.addAll(extractSpecialDprUids(pddOrderDOS, SIXTH_LEVEL));
        XxlJobHelper.log("获取到六维用户总数为:" + sixthDprUids.size());

        /** step ##3.7 七维用户的所有信息 */
        Set<Long> seventhDprUids = extractSpecialDprUids(jtkOrdersDOS, SEVENTH_LEVEL);
        seventhDprUids.addAll(extractSpecialDprUids(dtkTbOrderDOS, SEVENTH_LEVEL));
        seventhDprUids.addAll(extractSpecialDprUids(pddOrderDOS, SEVENTH_LEVEL));
        XxlJobHelper.log("获取到七维用户总数为:" + seventhDprUids.size());

        /** step ##3.8 八维用户所有的信息 */
        Set<Long> eighthDprUids = extractSpecialDprUids(jtkOrdersDOS, EIGHTH_LEVEL);
        eighthDprUids.addAll(extractSpecialDprUids(dtkTbOrderDOS, EIGHTH_LEVEL));
        eighthDprUids.addAll(extractSpecialDprUids(pddOrderDOS, EIGHTH_LEVEL));
        XxlJobHelper.log("获取到八维用户总数为:" + eighthDprUids.size());

        /** step ##3.9 九维用户所有的信息 */
        Set<Long> ninthDprUids = extractSpecialDprUids(jtkOrdersDOS, NINTH_LEVEL);
        ninthDprUids.addAll(extractSpecialDprUids(dtkTbOrderDOS, NINTH_LEVEL));
        ninthDprUids.addAll(extractSpecialDprUids(pddOrderDOS, NINTH_LEVEL));
        XxlJobHelper.log("获取到九维用户总数为:" + ninthDprUids.size());


        /** step #4 计算各维度分配金额 */
        // 计算1-9维用户所有的直推金额
        BigDecimal dprAllLevelTotalCommission = dprFirstTotalCommission.add(dprSecondTotalCommission).add(dprThirdTotalCommission).add(dprFourthTotalCommission)
                .add(dprFifthTotalCommission).add(dprSixthTotalCommission).add(dprSeventhTotalCommission)
                .add(dprEighthTotalCommission).add(dprNinthTotalCommission);

        /** step ##4.1 计算一维到九维用户分配金额 */
        BigDecimal firstLevelTotalAllocate = dprTotalCommission.divide(dprAllLevelTotalCommission, 8, RoundingMode.DOWN)
                .multiply(jtkSharingConfigData.getDividendProp().get(FIRST_LEVEL))
                .multiply(FIXED_ACTIVE);
        /** step ##4.2 计算二维到九维用户分配金额 */
        BigDecimal secondLevelTotalAllocate = dprTotalCommission.divide(dprAllLevelTotalCommission.subtract(dprFirstTotalCommission), 8, RoundingMode.DOWN)
                .multiply(jtkSharingConfigData.getDividendProp().get(SECOND_LEVEL))
                .multiply(FIXED_ACTIVE);
        /** step ##4.3 获取三维到九维用户分配金额 */
        BigDecimal thirdLevelTotalAllocate = dprTotalCommission.divide(dprAllLevelTotalCommission.subtract(dprFirstTotalCommission.add(dprSecondTotalCommission)), 8, RoundingMode.DOWN)
                .multiply(jtkSharingConfigData.getDividendProp().get(THIRD_LEVEL))
                .multiply(FIXED_ACTIVE);
        /** step ##4.4 获取四级到九维用户分配金额 */
        BigDecimal fourthLevelTotalAllocate = dprTotalCommission.divide(dprAllLevelTotalCommission.subtract(dprFirstTotalCommission.add(dprSecondTotalCommission).add(dprThirdTotalCommission)), 8, RoundingMode.DOWN)
                .multiply(jtkSharingConfigData.getDividendProp().get(FOURTH_LEVEL))
                .multiply(FIXED_ACTIVE);
        /** step ##4.5 获取五级到九维用户分配金额 */
        BigDecimal fifthLevelTotalAllocate = dprTotalCommission.divide(dprAllLevelTotalCommission.subtract(dprFirstTotalCommission.add(dprSecondTotalCommission).add(dprThirdTotalCommission).add(dprFourthTotalCommission)), 8, RoundingMode.DOWN)
                .multiply(jtkSharingConfigData.getDividendProp().get(FIFTH_LEVEL))
                .multiply(FIXED_ACTIVE);
        /** step ##4.6 获取六级到九维用户分配金额 */
        BigDecimal sixthLevelTotalAllocate = dprTotalCommission.divide(dprAllLevelTotalCommission.subtract(dprFirstTotalCommission.add(dprSecondTotalCommission).add(dprThirdTotalCommission).add(dprFourthTotalCommission)).add(dprFifthTotalCommission), 8, RoundingMode.DOWN)
                 .multiply(jtkSharingConfigData.getDividendProp().get(SIXTH_LEVEL))
                 .multiply(FIXED_ACTIVE);
        /** step ##4.7 获取七级到九维用户分配金额 */
        BigDecimal seventhLevelTotalAllocate = dprTotalCommission.divide(dprSeventhTotalCommission.add(dprEighthTotalCommission).add(dprNinthTotalCommission), 8, RoundingMode.DOWN)
                .multiply(jtkSharingConfigData.getDividendProp().get(SEVENTH_LEVEL))
                .multiply(FIXED_ACTIVE);
        /** step ##4.8 获取八维到九维用户分配金额 */
        BigDecimal eightLevelTotalAllocate = dprTotalCommission.divide(dprEighthTotalCommission.add(dprNinthTotalCommission))
                .multiply(jtkSharingConfigData.getDividendProp().get(EIGHTH_LEVEL))
                .multiply(FIXED_ACTIVE);
        /** step ##4.9 获取九维用户分配金额 */
        BigDecimal ninthLevelTotalAllocate = dprTotalCommission.divide(dprNinthTotalCommission)
                .multiply(jtkSharingConfigData.getDividendProp().get(NINTH_LEVEL))
                .multiply(FIXED_ACTIVE);

        /** step ##5 获取用户平均分配金额 */
        /** step ##5.1 获取一维用户分配金额平均值 */
        BigDecimal firstLevelAllocateAvg = firstLevelTotalAllocate.divide(BigDecimal.valueOf(firstDprUids.size()), 8, RoundingMode.DOWN);
        /** step ###5.3 获取二维用户分配金额平均值 */
        BigDecimal secondLevelAllocateAvg = secondLevelTotalAllocate.divide(BigDecimal.valueOf(secondDprUids.size()), 8, RoundingMode.DOWN);
        /** step ##5.4 获取三维用户分配金额平均值 */
        BigDecimal thirdLevelAllocateAvg = thirdLevelTotalAllocate.divide(BigDecimal.valueOf(thirdDprUids.size()), 8, RoundingMode.DOWN);
        /** step ##5.5 获取四级用户分配金额平均值 */
        BigDecimal fourthLevelAllocateAvg = fourthLevelTotalAllocate.divide(BigDecimal.valueOf(fourthDprUids.size()), 8, RoundingMode.DOWN);
        /** step ##5.6 获取五级用户分配金额平均值 */
        BigDecimal fifthLevelAllocateAvg = fifthLevelTotalAllocate.divide(BigDecimal.valueOf(fifthDprUids.size()), 8, RoundingMode.DOWN);
        /** step ##5.7 获取六级用户分配金额平均值 */
        BigDecimal sixthLevelAllocateAvg = sixthLevelTotalAllocate.divide(BigDecimal.valueOf(sixthDprUids.size()), 8, RoundingMode.DOWN);
        /** step ##5.8 获取七级用户分配金额平均值 */
        BigDecimal seventhLevelAllocateAvg = seventhLevelTotalAllocate.divide(BigDecimal.valueOf(seventhDprUids.size()), 8, RoundingMode.DOWN);
        /** step ##5.9 获取八级用户分配金额平均值 */
        BigDecimal eightLevelAllocateAvg = eightLevelTotalAllocate.divide(BigDecimal.valueOf(eighthDprUids.size()), 8, RoundingMode.DOWN);
        /** step ##5.10 获取九级用户分配金额平均值 */
        BigDecimal ninthLevelAllocateAvg = ninthLevelTotalAllocate.divide(BigDecimal.valueOf(ninthDprUids.size()), 8, RoundingMode.DOWN);

        /** step ##6 执行各维度用户分配逻辑 */


    }

    private static Set<Long> extractSpecialDprUids(List<? extends OrderCommonData> orders, Long levelId) {
        // 1. 健壮性检查
        if (orders == null || orders.isEmpty()) {
            return Set.of();
        }
        // 2. [预处理] 高效提取所有非空sid
        Set<String> existingSids = orders.stream()
                .map(OrderCommonData::getSid) // 使用接口方法
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (existingSids.isEmpty()) {
            return Set.of();
        }
        // 3. [主处理] 使用Stream流处理,所有逻辑都通过接口方法调用
        return orders.stream()
                .filter(order -> Objects.equals(order.getDprLevel(), levelId))
                .filter(order -> order.getDprUid() != null)
                .filter(order -> existingSids.contains(String.valueOf(order.getDprUid())))
                .map(OrderCommonData::getDprUid)
                .collect(Collectors.toSet());

    }


}

Gemini建议

代码功能上是完整的,但存在一些可以显著优化的方面,主要集中在:

  1. 代码冗余和重复:大量逻辑(特别是佣金计算和用户ID提取)在9个维度之间重复,导致代码冗长且难以维护。
  2. 性能效率:对订单列表进行了多次全量遍历(stream()),在订单数量巨大时会造成不必要的性能开销。
  3. 可读性和可维护性:大量的独立变量(dprFirstTotalCommission, firstDprUids 等)使得逻辑跟踪困难。如果未来需要增加或修改维度(例如增加"十维"),需要修改的地方非常多。
  4. 健壮性:代码中存在多处除法运算(divide()),但没有处理除数为零的边界情况,可能导致 ArithmeticException 异常。同时,从配置Map中获取分红比例时,也没有检查key是否存在。

详细分析与优化建议

1. 问题:代码冗余与性能低下 (核心问题)

现状分析: 代码在 step #2 和 step #3 中,为了计算每个维度的总佣金和用户ID集合,对三个订单列表(jtkOrdersDOS, dtkTbOrderDOS, pddOrderDOS)进行了 9 * 3 = 27 次stream操作。这是一个非常大的性能瓶颈和代码冗余点。

优化策略 : 采用 "一次遍历,全面聚合" 的思想。

  1. 数据归一化:由于三种订单 DO 都实现了 OrderCommonData 接口,我们可以将它们合并成一个 List。
  2. 单次聚合 :只遍历这个合并后的列表一次,使用Java Stream的 Collectors.groupingBy,按 dprLevel(维度ID)进行分组。在分组的同时,使用下游收集器(Collectors.teeing 或自定义收集器)一次性完成两件事:
    • 计算该维度的总佣金。
    • 收集该维度的所有dprUid。

这样,我们只需要遍历一次订单数据,就能得到所有维度所需的核心信息。


2. 问题:可读性与可维护性差

现状分析:

  • 定义了从 FIRST_LEVEL 到 NINTH_LEVEL 9个 Long 型常量。
  • 定义了 dprFirstTotalCommission 到 dprNinthTotalCommission 9个 BigDecimal 变量。
  • 定义了 firstDprUids 到 ninthDprUids 9个 Set 变量。
  • 后续的计算逻辑(step #4, step #5)也是逐个对这些变量进行硬编码操作。

优化策略: 使用数据结构来管理维度数据,而不是独立的变量。

  • 使用 Map
    • Map<Long, BigDecimal> commissionByLevel:键是维度ID,值是该维度的总佣金。
    • Map<Long, Set> uidsByLevel:键是维度ID,值是该维度的用户ID集合。
  • 这样,后续的计算可以通过遍历Map来完成,代码更简洁、更具扩展性。例如,增加一个维度只需要在配置和常量定义中增加,计算逻辑无需改动。
3. 问题:健壮性不足

现状分析:

  • firstLevelTotalAllocate.divide(BigDecimal.valueOf(firstDprUids.size()), ...):如果 firstDprUids 为空,size() 为0,将抛出 ArithmeticException。
  • dprTotalCommission.divide(dprAllLevelTotalCommission, ...):如果总佣金为0,也会抛出异常。
  • jtkSharingConfigData.getDividendProp().get(FIRST_LEVEL):如果配置的Map中缺少某个维度的比例,会返回 null,导致后续 multiply 操作时抛出 NullPointerException。

优化策略: 在所有除法和Map取值操作前,进行严格的非空和非零检查。

4. 问题:复杂的计算逻辑

现状分析: 在 step #4 中,计算分红池的公式非常复杂,例如: dprAllLevelTotalCommission.subtract(dprFirstTotalCommission.add(dprSecondTotalCommission)) 这种链式减法难以阅读,且容易出错。

优化策略 : 可以预先计算一个 "累积佣金" 的Map。

  • Map<Long, BigDecimal> cumulativeCommissionByLevel: 键是维度ID,值是 从该维度到最高维度 的总佣金之和。
  • 这样,计算分母时,可以直接从这个Map中获取,使公式更清晰。

优化版代码亮点总结

  1. 高效聚合:使用 Stream.of().flatMap() 合并数据源,再通过 Collectors.groupingBy 和 Collectors.teeing 一次性完成所有维度的数据聚合,将几十次遍历优化为一次。
  2. 结构清晰:用 Map<Long, LevelAggregate> 等数据结构替代了大量离散的变量,代码逻辑更集中,易于理解。
  3. 高可维护性:维度信息由 List LEVELS 管理。未来增加"十维"时,只需修改此列表和相关配置即可,计算逻辑无需改动,遵循了"开闭原则"。
  4. 健壮性增强:在所有除法和Map取值操作前都增加了校验,避免了 ArithmeticException 和 NullPointerException,并打印了明确的日志。
  5. 逻辑简化:通过预计算累积佣金 (cumulativeCommission),简化了分红池的计算公式,使其更易读。
  6. 代码复用:将核心计算逻辑(计算分红池、计算人均)封装成独立的私有方法,主流程 execute 方法更加清晰。
  7. 辅助数据类:使用内部类 LevelAggregate 来承载聚合结果,使得数据传递和处理更加规范。

优化代码

java 复制代码
import com.alipay.api.domain.SealTabsVO;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Max;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 数字联盟九维分红定时任务
 */

@Component
public class NineDimsDiddCpsJob {

    @Resource
    private JtkSharingConfigService jtkSharingConfigService;

    @Resource
    private JtkOrdersService jtkOrdersService;

    @Resource
    private DtkTbOrderService dtkTbOrderService;

    @Resource
    private DtkPddOrderService pddOrderService;

    private final String WEEK = "WEEK";

    private final String MONTH = "MONTH";

    /** 活跃积分固定值 */
    private final BigDecimal FIXED_ACTIVE = new BigDecimal("10000");

    /** 九维等级Id 0-9对应一度会员-九度会员 */
    private static final List<Long> LEVELS = List.of(2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L);

    @XxlJob("NineDimsDiddCpsJob")
    public void execute() {
        XxlJobHelper.log("数字联盟九维分红开始执行!");
        /** step #1 获取配置信息,确定是按照周分配还是月分配 */
        JtkSharingConfigDO jtkSharingConfigData = jtkSharingConfigService.getJtkSharingConfigData();
        if (jtkSharingConfigData.getId() == 0) {
            XxlJobHelper.log("数字联盟九维分红配置为空!不进行后续分配!");
            return;
        }
        XxlJobHelper.log("数字联盟九维分红配置信息为:" + jtkSharingConfigData);

        LocalDateTime startTime;
        LocalDateTime endTime;
        String statisticalPeriod = jtkSharingConfigData.getStatisticalPeriod();
        /** step #2 获取查询订单的时间间隔 */
        if (WEEK.equals(statisticalPeriod)) {
            // 获取上周周一起始时间到周日的时间
            startTime = LocalDateTimeUtils.getLastMondayStart(LocalDateTime.now());
            endTime = LocalDateTimeUtils.getLastSundayEnd(LocalDateTime.now());
        } else {
            // 获取上月起始时间到月末的时间
            startTime = LocalDateTimeUtils.beginOfMonth(LocalDateTime.now().minusMonths(1));
            endTime = LocalDateTimeUtils.endOfMonth(LocalDateTime.now().minusMonths(1));
        }

        /** step #3 获取订单数据 */
        List<JtkOrdersDO> jtkOrdersDOS = jtkOrdersService.getJtkOrdersByTimeInterval(startTime, endTime);
        XxlJobHelper.log("数字联盟聚推客订单数据总数为:" + jtkOrdersDOS.size());
        List<DtkTbOrderDO> dtkTbOrderDOS = dtkTbOrderService.getDtkOrdersByTimeInterval(startTime, endTime);
        XxlJobHelper.log("数字联盟淘宝订单数据总数为:" + dtkTbOrderDOS.size());
        List<DtkPddOrderDO> pddOrderDOS = pddOrderService.getPddOrdersByTimeInterval(startTime, endTime);
        XxlJobHelper.log("数字联盟拼多多订单数据总数为:" + pddOrderDOS.size());

        /** step #4 数据归一化:合并所有订单源到一个列表 */
        List<OrderCommonData> allOrders  = Stream.of(jtkOrdersDOS, dtkTbOrderDOS, pddOrderDOS)
                .filter(list -> !list.isEmpty())
                .flatMap(List::stream)
                .collect(Collectors.toList());
        if (allOrders.isEmpty()) {
            XxlJobHelper.log("时间范围 [{} - {}] 内所有订单数据为空! 任务终止!", startTime, endTime);
            return;
        }
        /** step #5 一次遍历, 聚合所有维度的数据 */
        Map<Long, LevelAggregate> aggregatesByLevel = allOrders.stream()
                .collect(Collectors.groupingBy(
                        OrderCommonData::getDprLevel,
                        Collectors.teeing(
                                // 下游收集器1: 计算总佣金
                                Collectors.mapping(OrderCommonData::getPromotionAmount, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)),
                                // 下游收集器2: 收集有效用户ID
                                Collectors.mapping(OrderCommonData::getDprUid, Collectors.toSet()),
                                // 合并两个结果
                                LevelAggregate::new
                        )
                ));

        /** step 5.1 提取订单全量uid, 获取所有用户的自购订单 */
        Set<String> allSids = allOrders.stream()
                .map(OrderCommonData::getSid)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        aggregatesByLevel.forEach((leveId, aggregate) -> {
            Set<Long> filteredUids = aggregate.getUids().stream()
                    .filter(uid -> uid != null && allSids.contains(String.valueOf(uid)))
                    .collect(Collectors.toSet());
            aggregate.setUids(filteredUids);
            XxlJobHelper.log("维度 {}: 总佣金 = {}, 有效用户数 = {}", leveId, aggregate.getCommission(), filteredUids.size());
        });

        /** step #6 计算总待分配佣金 */
        BigDecimal totalCommissionToDistribute = aggregatesByLevel.values().stream()
                .map(LevelAggregate::getCommission)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        XxlJobHelper.log("待分配总佣金为: {}" + totalCommissionToDistribute);
        if (totalCommissionToDistribute.compareTo(BigDecimal.ZERO) <= 0) {
            XxlJobHelper.log("待分配总佣金为0, 任务终止!");
            return;
        }




    }

    /**
     * 计算每个维度的分红总额 (分红池)
     */
    private Map<Long, BigDecimal> calculateAllocationPools(Map<Long, LevelAggregate> aggregatesByLevel, BigDecimal totalCommission, Map<Long, BigDecimal> dividendProps) {
        Map<Long, BigDecimal> pools = new HashMap<>();
        // 预计算所有级别的累计佣金,用于后续分母计算
        // 降序排序便于后续计算
        Map<Long, BigDecimal> cumulativeComminssion = new TreeMap<Long, BigDecimal>(Comparator.reverseOrder());
        BigDecimal currentSum = BigDecimal.ZERO;
        for (long level = LEVELS.get(LEVELS.size() - 1); level >= LEVELS.get(0); level--) {
            // 仅处理在LEVELS中定义的级别
            if (!LEVELS.contains(level)) continue;
            LevelAggregate levelAggregate = aggregatesByLevel.get(level);
            if (levelAggregate != null) {
                currentSum = currentSum.add(levelAggregate.getCommission());
            }
            cumulativeComminssion.put(level, currentSum);
        }
        for (Long level : LEVELS) {
            BigDecimal dividendProp = dividendProps.get(level);
            // 分母: 从当前级别到最高级的总佣金
            BigDecimal denominator = cumulativeComminssion.get(level);
            // 健壮性检查
            if (dividendProp == null || dividendProp.compareTo(BigDecimal.ZERO) <= 0) {
                XxlJobHelper.log("警告: 维度 {} 的分红比例未配置或为0,跳过计算。", level);
                pools.put(level, BigDecimal.ZERO);
                continue;
            }
            if (denominator == null || denominator.compareTo(BigDecimal.ZERO) <= 0) {
                XxlJobHelper.log("警告: 维度 {} 及以上无分红佣金,分母为0,跳过计算。", level);
                pools.put(level, BigDecimal.ZERO);
                continue;
            }
            // 分红池 = 用户直推总佣金 / (当前级别到最高级别的总佣金) * 平台总佣金 * 分红比例 * 活跃积分
            BigDecimal poolAmount = currentSum
                    .divide(denominator, 8, RoundingMode.DOWN)
                    .multiply(dividendProp).divide(BigDecimal.valueOf(100))
                    .multiply(FIXED_ACTIVE);
            pools.put(level, poolAmount);
            XxlJobHelper.log("维度 {} 分红池计算: {} / {} * {} * {} = {}", level, totalCommission, denominator, dividendProp, FIXED_ACTIVE, poolAmount);
            XxlJobHelper.log("维度 {}: 分红池 = {}", level, poolAmount);
        }
        return pools;
    }

    /**
     * 计算每个维度的人均分红金额
     */
    private Map<Long, BigDecimal> calculateAverageDividends(Map<Long, BigDecimal> pools, Map<Long, LevelAggregate> aggregates) {
        Map<Long, BigDecimal> averages = new HashMap<>();
        for (Long level : LEVELS) {
            BigDecimal poolAmount = pools.getOrDefault(level, BigDecimal.ZERO);
            int userCount = aggregates.get(level) != null ? aggregates.get(level).getUids().size() : 0;
            if (poolAmount.compareTo(BigDecimal.ZERO) <= 0 || userCount == 0) {
                averages.put(level, BigDecimal.ZERO);
                continue;
            }
            BigDecimal avgAmount = poolAmount.divide(new BigDecimal(userCount), 9, RoundingMode.DOWN);
            averages.put(level, avgAmount);
        }
        return averages;
    }


    /**
     * 内部数据类,用于在一次收集中聚合维度的多个信息
     */
    @Data
    @AllArgsConstructor
    private static class LevelAggregate {
        private BigDecimal commission;
        private Set<Long> uids;
    }

}

最终版优化代码

java 复制代码
import com.alibaba.nacos.api.config.listener.Listener;
import com.alipay.api.domain.SealTabsVO;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Max;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 数字联盟九维分红定时任务
 */

@Component
public class NineDimsDiddCpsJob {

    @Resource
    private JtkSharingConfigService jtkSharingConfigService;

    @Resource
    private JtkOrdersService jtkOrdersService;

    @Resource
    private DtkTbOrderService dtkTbOrderService;

    @Resource
    private DtkPddOrderService pddOrderService;

    private final String WEEK = "WEEK";

    private final String MONTH = "MONTH";

    /** 活跃积分固定值 */
    private final BigDecimal FIXED_ACTIVE = new BigDecimal("10000");

    /** 九维等级Id 0-9对应一度会员-九度会员 */
    private static final List<Long> LEVELS = List.of(2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L);

    @XxlJob("NineDimsDiddCpsJob")
    public void execute() {
        XxlJobHelper.log("数字联盟九维分红开始执行!");
        /** step #1 获取配置信息,确定是按照周分配还是月分配 */
        JtkSharingConfigDO jtkSharingConfigData = jtkSharingConfigService.getJtkSharingConfigData();
        if (jtkSharingConfigData.getId() == 0) {
            XxlJobHelper.log("数字联盟九维分红配置为空!不进行后续分配!");
            return;
        }
        XxlJobHelper.log("数字联盟九维分红配置信息为:" + jtkSharingConfigData);

        LocalDateTime startTime;
        LocalDateTime endTime;
        String statisticalPeriod = jtkSharingConfigData.getStatisticalPeriod();
        /** step #2 获取查询订单的时间间隔 */
        if (WEEK.equals(statisticalPeriod)) {
            // 获取上周周一起始时间到周日的时间
            startTime = LocalDateTimeUtils.getLastMondayStart(LocalDateTime.now());
            endTime = LocalDateTimeUtils.getLastSundayEnd(LocalDateTime.now());
        } else {
            // 获取上月起始时间到月末的时间
            startTime = LocalDateTimeUtils.beginOfMonth(LocalDateTime.now().minusMonths(1));
            endTime = LocalDateTimeUtils.endOfMonth(LocalDateTime.now().minusMonths(1));
        }

        /** step #3 获取订单数据 */
        List<JtkOrdersDO> jtkOrdersDOS = jtkOrdersService.getJtkOrdersByTimeInterval(startTime, endTime);
        XxlJobHelper.log("数字联盟聚推客订单数据总数为:" + jtkOrdersDOS.size());
        List<DtkTbOrderDO> dtkTbOrderDOS = dtkTbOrderService.getDtkOrdersByTimeInterval(startTime, endTime);
        XxlJobHelper.log("数字联盟淘宝订单数据总数为:" + dtkTbOrderDOS.size());
        List<DtkPddOrderDO> pddOrderDOS = pddOrderService.getPddOrdersByTimeInterval(startTime, endTime);
        XxlJobHelper.log("数字联盟拼多多订单数据总数为:" + pddOrderDOS.size());

        /** step #4 数据归一化:合并所有订单源到一个列表 */
        List<OrderCommonData> allOrders  = Stream.of(jtkOrdersDOS, dtkTbOrderDOS, pddOrderDOS)
                .filter(list -> !list.isEmpty())
                .flatMap(List::stream)
                .collect(Collectors.toList());
        if (allOrders.isEmpty()) {
            XxlJobHelper.log("时间范围 [{} - {}] 内所有订单数据为空! 任务终止!", startTime, endTime);
            return;
        }
        /** step #5 一次遍历, 聚合所有维度的数据 */
        Map<Long, LevelAggregate> aggregatesByLevel = allOrders.stream()
                .collect(Collectors.groupingBy(
                        OrderCommonData::getDprLevel,
                        Collectors.teeing(
                                // 下游收集器1: 计算总佣金
                                Collectors.mapping(OrderCommonData::getPromotionAmount, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)),
                                // 下游收集器2: 收集有效用户ID
                                Collectors.mapping(OrderCommonData::getDprUid, Collectors.toSet()),
                                // 合并两个结果
                                LevelAggregate::new
                        )
                ));

        /** step 5.1 提取订单全量uid, 获取所有用户的自购订单 */
        Set<String> allSids = allOrders.stream()
                .map(OrderCommonData::getSid)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        aggregatesByLevel.forEach((leveId, aggregate) -> {
            Set<Long> filteredUids = aggregate.getUids().stream()
                    .filter(uid -> uid != null && allSids.contains(String.valueOf(uid)))
                    .collect(Collectors.toSet());
            aggregate.setUids(filteredUids);
            XxlJobHelper.log("维度 {}: 总佣金 = {}, 有效用户数 = {}", leveId, aggregate.getCommission(), filteredUids.size());
        });

        /** step #6 计算总待分配佣金 */
        BigDecimal totalCommissionToDistribute = aggregatesByLevel.values().stream()
                .map(LevelAggregate::getCommission)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        XxlJobHelper.log("待分配总佣金为: {}" , totalCommissionToDistribute);
        if (totalCommissionToDistribute.compareTo(BigDecimal.ZERO) <= 0) {
            XxlJobHelper.log("待分配总佣金为0, 任务终止!");
            return;
        }

        /** step #7 计算每个维度的分红总额 (分红池) */
        Map<Long, BigDecimal> allocationPools = calculateAllocationPools(aggregatesByLevel, totalCommissionToDistribute, jtkSharingConfigData.getDividendProp());
        /** step #8 计算每个维度的平均分红具体值 */
        Map<Long, BigDecimal> averageAllocations = calculateAverageDividends(allocationPools, aggregatesByLevel);

        /** step #9 执行分红逻辑 */
        averageAllocations.forEach((level, avgAmount) -> {
            if (avgAmount.compareTo(BigDecimal.ZERO) > 0) {
                Set<Long> uids = aggregatesByLevel.get(level).getUids();
                XxlJobHelper.log("执行第 {} 级会员分红, 共有 {} 个用户, 平均分红值为 {}", level, uids.size(), avgAmount);
                // 这里执行分红逻辑,进行批量处理
            }
        });
        XxlJobHelper.handleSuccess(LocalDate.now()+ " 数字联盟九维分红执行完毕!");
    }

    /**
     * 计算每个维度的分红总额 (分红池)
     */
    private Map<Long, BigDecimal> calculateAllocationPools(Map<Long, LevelAggregate> aggregatesByLevel, BigDecimal totalCommission, Map<Long, BigDecimal> dividendProps) {
        Map<Long, BigDecimal> pools = new HashMap<>();
        // 预计算所有级别的累计佣金,用于后续分母计算
        // 降序排序便于后续计算
        Map<Long, BigDecimal> cumulativeComminssion = new TreeMap<Long, BigDecimal>(Comparator.reverseOrder());
        BigDecimal currentSum = BigDecimal.ZERO;
        for (long level = LEVELS.get(LEVELS.size() - 1); level >= LEVELS.get(0); level--) {
            // 仅处理在LEVELS中定义的级别
            if (!LEVELS.contains(level)) continue;
            LevelAggregate levelAggregate = aggregatesByLevel.get(level);
            if (levelAggregate != null) {
                currentSum = currentSum.add(levelAggregate.getCommission());
            }
            cumulativeComminssion.put(level, currentSum);
        }
        for (Long level : LEVELS) {
            BigDecimal dividendProp = dividendProps.get(level);
            // 分母: 从当前级别到最高级的总佣金
            BigDecimal denominator = cumulativeComminssion.get(level);
            // 健壮性检查
            if (dividendProp == null || dividendProp.compareTo(BigDecimal.ZERO) <= 0) {
                XxlJobHelper.log("警告: 维度 {} 的分红比例未配置或为0,跳过计算。", level);
                pools.put(level, BigDecimal.ZERO);
                continue;
            }
            if (denominator == null || denominator.compareTo(BigDecimal.ZERO) <= 0) {
                XxlJobHelper.log("警告: 维度 {} 及以上无分红佣金,分母为0,跳过计算。", level);
                pools.put(level, BigDecimal.ZERO);
                continue;
            }
            // 分红池 = 用户直推总佣金 / (当前级别到最高级别的总佣金) * 平台总佣金 * 分红比例 * 活跃积分
            BigDecimal poolAmount = currentSum
                    .divide(denominator, 8, RoundingMode.DOWN)
                    .multiply(totalCommission)
                    .multiply(dividendProp).divide(BigDecimal.valueOf(100))
                    .multiply(FIXED_ACTIVE);
            pools.put(level, poolAmount);
            XxlJobHelper.log("维度 {} 分红池计算: {} / {} * {} * {} * {} = {}", level, currentSum, denominator, totalCommission, dividendProp.divide(BigDecimal.valueOf(100)), FIXED_ACTIVE, poolAmount);
            XxlJobHelper.log("维度 {}: 分红池 = {}", level, poolAmount);
        }
        return pools;
    }

    /**
     * 计算每个维度的人均分红金额
     */
    private Map<Long, BigDecimal> calculateAverageDividends(Map<Long, BigDecimal> pools, Map<Long, LevelAggregate> aggregates) {
        Map<Long, BigDecimal> averages = new HashMap<>();
        for (Long level : LEVELS) {
            BigDecimal poolAmount = pools.getOrDefault(level, BigDecimal.ZERO);
            int userCount = aggregates.get(level) != null ? aggregates.get(level).getUids().size() : 0;
            if (poolAmount.compareTo(BigDecimal.ZERO) <= 0 || userCount == 0) {
                averages.put(level, BigDecimal.ZERO);
                continue;
            }
            BigDecimal avgAmount = poolAmount.divide(new BigDecimal(userCount), 8, RoundingMode.DOWN);
            averages.put(level, avgAmount);
        }
        return averages;
    }


    /**
     * 内部数据类,用于在一次收集中聚合维度的多个信息
     */
    @Data
    @AllArgsConstructor
    private static class LevelAggregate {
        private BigDecimal commission;
        private Set<Long> uids;
    }

}

总结

  • 将重复的逻辑抽象成了数据结构(Map, List)。

  • 使用了一次遍历聚合(groupingBy + teeing)代替了多次循环。

  • 将复杂的计算逻辑封装到了独立的辅助方法中。

同时也要充分吸收Gemini的优化要点,包括如下:

  1. 高效聚合:使用 Stream.of().flatMap() 合并数据源,再通过 Collectors.groupingBy 和 Collectors.teeing 一次性完成所有维度的数据聚合,将几十次遍历优化为一次。
  2. 结构清晰:用 Map<Long, LevelAggregate> 等数据结构替代了大量离散的变量,代码逻辑更集中,易于理解。
  3. 高可维护性:维度信息由 List LEVELS 管理。未来增加"十维"时,只需修改此列表和相关配置即可,计算逻辑无需改动,遵循了"开闭原则"。
  4. 健壮性增强:在所有除法和Map取值操作前都增加了校验,避免了 ArithmeticException 和 NullPointerException,并打印了明确的日志。
  5. 逻辑简化:通过预计算累积佣金 (cumulativeCommission),简化了分红池的计算公式,使其更易读。
  6. 代码复用:将核心计算逻辑(计算分红池、计算人均)封装成独立的私有方法,主流程 execute 方法更加清晰。
  7. 辅助数据类:使用内部类 LevelAggregate 来承载聚合结果,使得数据传递和处理更加规范。
相关推荐
小莫分享42 分钟前
github 镜像节点
java
链上Sniper1 小时前
智能合约状态快照技术:实现 EVM 状态的快速同步与回滚
java·大数据·linux·运维·web3·区块链·智能合约
缘来是庄1 小时前
设计模式之建造者模式
java·设计模式·建造者模式
小湘西2 小时前
Apache HttpClient 的请求模型和 I/O 类型
java·http·apache
沃夫上校2 小时前
Feign调Post接口异常:Incomplete output stream
java·后端·微服务
LeeGe2 小时前
SpringAOP中@within和@annotation以及 @within和@target的区别
后端
一个平平无奇的Java小学生2 小时前
Spring Cloud Alibaba 微服务从入门到生产部署完整指南
后端
一个平平无奇的Java小学生2 小时前
Spring Cloud Alibaba 微服务实战指南
后端
q567315232 小时前
Java Selenium反爬虫技术方案
java·爬虫·selenium
张小洛2 小时前
Spring IOC容器核心阶段解密:★Bean实例化全流程深度剖析★
java·后端·spring·ioc容器·bean实例化