luofl
2025-03-13 4f97bdbaadcdc19df9dfb0971b930d799c4aeddc
迭代版本:2.28
25个文件已修改
2个文件已添加
964 ■■■■■ 已修改文件
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserClientFallbackFactory.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserClient.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-auth/src/main/resources/bootstrap.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-gateway/src/main/resources/bootstrap.yml 97 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AgentApplicationController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AppUserController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/UserCouponController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/VipCenterController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/AppUserService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/VipCenterService.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/AppUserServiceImpl.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/UserPointServiceImpl.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/VipCenterServiceImpl.java 483 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/WalletServiceImpl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/resources/bootstrap.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/UserPointMapper.xml 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/PayEvent.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/PayEventListener.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/CommissionServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/ShoppingCartServiceImpl.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/OrderExport.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/resources/bootstrap.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/OrderGoodMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/CouponInfoController.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/resources/bootstrap.yml 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserClientFallbackFactory.java
@@ -118,6 +118,11 @@
                R.fail("检查会员等级变更失败:" + cause.getMessage());
            }
            
            @Override
            public void vipConsumption(Long appUserId) {
                R.fail("检查会员等级变更失败:" + cause.getMessage());
            }
            @Override
            public void vipDemotion(Long appUserId) {
                R.fail("检查会员等级降级失败:" + cause.getMessage());
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserClient.java
@@ -109,6 +109,12 @@
     */
    @PostMapping("/app-user/vipUpgrade")
    void vipUpgrade(@RequestParam("appUserId") Long appUserId);
    /**
     * 消费后检查会员等级变更
     */
    @PostMapping("/app-user/vipConsumption")
    void vipConsumption(@RequestParam("appUserId") Long appUserId);
    
    
    /**
ruoyi-auth/src/main/resources/bootstrap.yml
@@ -55,13 +55,13 @@
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        group: DEFAULT_GROUP
ruoyi-gateway/src/main/resources/bootstrap.yml
@@ -1,8 +1,7 @@
server:
  port: 9000
  port: 9600
  tomcat:
    basedir: /mnt/tomcat
    max-swallow-size: 100MB
# Spring
spring:
  application:
@@ -10,6 +9,7 @@
    name: ruoyi-gateway
  main:
    allow-bean-definition-overriding: true
    allow-circular-references: true
  profiles:
    # 环境配置
#    active: dev
@@ -23,42 +23,25 @@
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        server-addr: 192.168.110.111/:8848
        service: ruoyi-gateway
        group: DEFAULT_GROUP
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        username:
        password:
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        server-addr: 192.168.110.111/:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        username:
        password:
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        name: ruoyi-gateway
        # 配置文件格式
        file-extension: yml
        # 共享配置
        shared-configs:
          - application.${spring.cloud.nacos.config.file-extension}
    sentinel:
      # 取消控制台懒加载
      eager: true
      transport:
        # 控制台地址
        dashboard: 127.0.0.1:8718
      # nacos配置持久化
      datasource:
        ds1:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: sentinel-ruoyi-gateway
            groupId: DEFAULT_GROUP
            username: nacos
            password: nacos
            data-type: json
            rule-type: gw-flow
---
spring:
  config:
@@ -69,41 +52,24 @@
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        service: ruoyi-gateway
        group: DEFAULT_GROUP
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        username: nacos
        password: nacos
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username:
        password:
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        username: nacos
        password: nacos
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username:
        password:
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        name: ruoyi-gateway
        # 配置文件格式
        file-extension: yml
        # 共享配置
        shared-configs:
          - application.${spring.cloud.nacos.config.file-extension}
    sentinel:
      # 取消控制台懒加载
      eager: true
      transport:
        # 控制台地址
        dashboard: 192.168.0.137:8718
      # nacos配置持久化
      datasource:
        ds1:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: sentinel-ruoyi-gateway
            groupId: DEFAULT_GROUP
            username: nacos
            password: nacos
            data-type: json
            rule-type: gw-flow
---
spring:
  config:
@@ -113,33 +79,18 @@
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        server-addr: 192.168.110.169:8848
        service: ruoyi-gateway
        group: DEFAULT_GROUP
        namespace: 96712c7a-480b-4f40-b783-39f00f3b33ce
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        server-addr: 192.168.110.169:8848
        namespace: 96712c7a-480b-4f40-b783-39f00f3b33ce
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        name: ruoyi-gateway
        # 配置文件格式
        file-extension: yml
        # 共享配置
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
    sentinel:
      # 取消控制台懒加载
      eager: true
      transport:
        # 控制台地址
        dashboard: 139.9.236.40:8718
      # nacos配置持久化
      datasource:
        ds1:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: sentinel-ruoyi-gateway
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: gw-flow
ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml
@@ -53,13 +53,13 @@
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        group: DEFAULT_GROUP
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AgentApplicationController.java
@@ -150,7 +150,7 @@
        }
        if (vipCenterService.checkReadyToBePartner(appUser.getId())){
        if (vipCenterService.isEligibleForGlobalPartner(appUser.getId())){
            return basePoint * i;
        }
        return 0;
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AppUserController.java
@@ -2,7 +2,6 @@
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -33,7 +32,6 @@
import com.ruoyi.other.api.domain.VipSetting;
import com.ruoyi.other.api.feignClient.ShopBalanceStatementClient;
import com.ruoyi.other.api.feignClient.ShopClient;
import com.ruoyi.other.api.feignClient.StoreClient;
import com.ruoyi.other.api.feignClient.VipSettingClient;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.feignClient.SysUserClient;
@@ -56,8 +54,6 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.ruoyi.common.core.constant.SecurityConstants.USER_APPLET_KEY;
/**
 * <p>
 * 前端控制器
@@ -77,8 +73,6 @@
    @Resource
    private AppUserService appUserService;
    @Resource
    private StoreClient storeClient;
    @Resource
    private UserCouponService userCouponService;
    @Resource
@@ -87,8 +81,6 @@
    private VipSettingClient vipSettingClient;
    @Resource
    private UserPointService userPointService;
    @Resource
    private VipSettingService vipSettingService;
    @Resource
    private AppUserMapper appUserMapper;
    @Resource
@@ -112,6 +104,9 @@
    @Resource
    private WeChatUtil weChatUtil;
    @Resource
    private IAppUserGiveawayTemporaryService appUserGiveawayTemporaryService;
    
    @Value("${file.upload.location}")
    private String filePath;
@@ -559,6 +554,11 @@
        } else {
            user.setIsSign(0);
        }
        List<AppUserGiveawayTemporary> temporaryList = appUserGiveawayTemporaryService.list(new LambdaQueryWrapper<AppUserGiveawayTemporary>()
                .eq(AppUserGiveawayTemporary::getAppUserId, userId));
        user.setLavePoint(temporaryList.stream().mapToInt(AppUserGiveawayTemporary::getTotalPoint).sum() + user.getTotalPoint());
        return R.ok(user);
    }
@@ -1316,6 +1316,10 @@
        appUserService.vipUpgrade(appUserId);
    }
    
    @PostMapping("/vipConsumption")
    public void vipConsumption(@RequestParam("appUserId") Long appUserId){
        appUserService.vipConsumption(appUserId);
    }
    
    /**
     * 检查会员降级
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/UserCouponController.java
@@ -75,7 +75,8 @@
    public R<Page<UserCoupon>> minelist(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @ApiParam("1未使用2已使用3已过期") Integer status) {
        Long userid = tokenService.getLoginUserApplet().getUserid();
        LambdaQueryChainWrapper<UserCoupon> chainWrapper = userCouponService.lambdaQuery()
                .eq(UserCoupon::getAppUserId, userid);
                .eq(UserCoupon::getAppUserId, userid)
                .isNotNull(UserCoupon::getCouponInfo);
        if(null != status && 1 == status){
            chainWrapper.isNull(UserCoupon::getUseTime).gt(UserCoupon::getEndTime, LocalDateTime.now());
        }
@@ -92,7 +93,7 @@
            CouponInfoVo vo = JSON.parseObject(couponInfo, CouponInfoVo.class);
//            BeanUtils.copyProperties(data,vo);
            //如果是商品券,将商品名称返回
            if (vo.getCouponType()==4){
            if (vo != null && vo.getCouponType()==4){
                List<String> goodNames = new ArrayList<>();
                if (vo.getForGoodIds().equals("-1")){
                    List<Goods> data1 = goodsClient.getAllGoods().getData();
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/VipCenterController.java
@@ -135,7 +135,7 @@
    @GetMapping("/check")
    @ApiOperation(value = "会员申请检查", tags = {"会员中心-小程序"})
    public R<Boolean> check(@ApiParam("4:准代理,5:代理,6:总代理,7:合伙人") @RequestParam Integer type) {
        return R.ok(vipCenterService.check(type));
        return R.ok(vipCenterService.checkEligibility(type));
    }
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/AppUserService.java
@@ -93,6 +93,12 @@
     * @param appUserId
     */
    void vipUpgrade(Long appUserId);
    /**
     * 消费后检查会员等级变更
     */
    void vipConsumption(Long appUserId);
    
    /**
     * 处理用户会员降级
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/VipCenterService.java
@@ -5,23 +5,23 @@
    /**
     * 校验准代理的申请条件
     */
    Boolean checkReadyToBeProxy(Long userId,Integer vipId);
    Boolean isEligibleForStorePartner(Long userId,Integer vipId);
    /**
     * 校验代理的申请条件
     */
    Boolean checkReadyToBeAgent(Long userId);
    Boolean isEligibleForCityPartner(Long userId);
    /**
     * 校验总代理的申请条件
     */
    Boolean checkReadyToBeTotalAgent(Long userId);
    Boolean isEligibleForNationalPartner(Long userId);
    /**
     * 校验合伙人的申请条件
     */
    Boolean checkReadyToBePartner(Long userId);
    Boolean isEligibleForGlobalPartner(Long userId);
    Boolean check(Integer type);
    Boolean checkEligibility(Integer type);
}
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/AppUserServiceImpl.java
@@ -22,18 +22,14 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.common.redis.annotation.DistributedLock;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.order.feignClient.OrderClient;
import com.ruoyi.other.api.domain.*;
import com.ruoyi.other.api.feignClient.*;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.feignClient.SysUserClient;
import com.ruoyi.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.core.util.UuidUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@@ -410,6 +406,7 @@
                    }
                    userCoupon.setStartTime(start);
                    userCoupon.setEndTime(end);
                    userCoupon.setCouponInfo(JSON.toJSONString(couponInfo));
                    userCouponService.save(userCoupon);
                }
            }
@@ -618,6 +615,130 @@
        }
    }
    
    public void vipConsumption(Long id){
        System.out.println("1111111111111111111111");
        AppUser appUser = this.getById(id);
        System.out.println("消费积分:"+ appUser.getShopPoint());
        System.out.println("返佣积分:"+ appUser.getSharePoint() );
        Integer vipId = appUser.getVipId();
        //钻石会员
        VipSetting vipSetting3 = vipSettingClient.getVipSetting(3).getData();
        //消费积分满足升级
        if(1 == vipSetting3.getVipLevelUpShopRole() && appUser.getShopPoint() >= vipSetting3.getVipLevelUpShop() && appUser.getVipId() < 3){
            appUser.setVipId(3);
            this.updateById(appUser);
            //添加等级变化记录
            UserChangeLog userChangeLog = new UserChangeLog();
            userChangeLog.setDelFlag(0);
            userChangeLog.setCreateTime(LocalDateTime.now());
            userChangeLog.setAppUserId(appUser.getId());
            userChangeLog.setBeforeVipId(vipId);
            userChangeLog.setAfterVipId(appUser.getVipId());
            userChangeLog.setChangeType(1);
            userChangeLogService.save(userChangeLog);
            return;
        }
        //返佣积分满足升级
        if(1 == vipSetting3.getVipLevelUpShareRole() && appUser.getSharePoint() >= vipSetting3.getVipLevelUpShare() && appUser.getVipId() < 3){
            appUser.setVipId(3);
            this.updateById(appUser);
            //添加等级变化记录
            UserChangeLog userChangeLog = new UserChangeLog();
            userChangeLog.setDelFlag(0);
            userChangeLog.setCreateTime(LocalDateTime.now());
            userChangeLog.setAppUserId(appUser.getId());
            userChangeLog.setBeforeVipId(vipId);
            userChangeLog.setAfterVipId(appUser.getVipId());
            userChangeLog.setChangeType(1);
            userChangeLogService.save(userChangeLog);
            return;
        }
        //下级人数满足升级
        Integer vipLevelUpNumRole = vipSetting3.getVipLevelUpNumRole();
        Integer vipDirectNum = vipSetting3.getVipDirectNum();
        Integer vipTeamNum = vipSetting3.getVipTeamNum();
        if(1 == vipLevelUpNumRole && appUser.getVipId() < 3){
            //查询直推用户达到X人或者团队人数达到X人后,可升级
            //直推用户数
            long count = this.count(new LambdaQueryWrapper<AppUser>().eq(AppUser::getDelFlag, 0).eq(AppUser::getStatus, 1).eq(AppUser::getInviteUserId, id));
            //团队用户数
            List<AppUser> subordinate = getSubordinate(id);
            if(vipDirectNum <= count || vipTeamNum <= subordinate.size()){
                appUser.setVipId(3);
                this.updateById(appUser);
                //添加等级变化记录
                UserChangeLog userChangeLog = new UserChangeLog();
                userChangeLog.setDelFlag(0);
                userChangeLog.setCreateTime(LocalDateTime.now());
                userChangeLog.setAppUserId(appUser.getId());
                userChangeLog.setBeforeVipId(vipId);
                userChangeLog.setAfterVipId(appUser.getVipId());
                userChangeLog.setChangeType(1);
                userChangeLogService.save(userChangeLog);
                return;
            }
        }
        //黄金会员
        VipSetting vipSetting2 = vipSettingClient.getVipSetting(2).getData();
        //消费积分满足升级
        if(1 == vipSetting2.getVipLevelUpShopRole() && appUser.getShopPoint() >= vipSetting2.getVipLevelUpShop() && appUser.getVipId() < 2){
            appUser.setVipId(2);
            this.updateById(appUser);
            //添加等级变化记录
            UserChangeLog userChangeLog = new UserChangeLog();
            userChangeLog.setDelFlag(0);
            userChangeLog.setCreateTime(LocalDateTime.now());
            userChangeLog.setAppUserId(appUser.getId());
            userChangeLog.setBeforeVipId(vipId);
            userChangeLog.setAfterVipId(appUser.getVipId());
            userChangeLog.setChangeType(1);
            userChangeLogService.save(userChangeLog);
            return;
        }
        //返佣积分满足升级
        if(1 == vipSetting2.getVipLevelUpShareRole() && appUser.getSharePoint() >= vipSetting2.getVipLevelUpShare() && appUser.getVipId() < 2){
            appUser.setVipId(2);
            this.updateById(appUser);
            //添加等级变化记录
            UserChangeLog userChangeLog = new UserChangeLog();
            userChangeLog.setDelFlag(0);
            userChangeLog.setCreateTime(LocalDateTime.now());
            userChangeLog.setAppUserId(appUser.getId());
            userChangeLog.setBeforeVipId(vipId);
            userChangeLog.setAfterVipId(appUser.getVipId());
            userChangeLog.setChangeType(1);
            userChangeLogService.save(userChangeLog);
            return;
        }
        //下级人数满足升级
        vipLevelUpNumRole = vipSetting2.getVipLevelUpNumRole();
        vipDirectNum = vipSetting2.getVipDirectNum();
        vipTeamNum = vipSetting2.getVipTeamNum();
        if(1 == vipLevelUpNumRole && appUser.getVipId() < 2){
            //查询直推用户达到X人或者团队人数达到X人后,可升级
            //直推用户数
            long count = this.count(new LambdaQueryWrapper<AppUser>().eq(AppUser::getDelFlag, 0).eq(AppUser::getStatus, 1).eq(AppUser::getInviteUserId, id));
            //团队用户数
            List<AppUser> subordinate = getSubordinate(id);
            if(vipDirectNum <= count || vipTeamNum <= subordinate.size()){
                appUser.setVipId(2);
                this.updateById(appUser);
                //添加等级变化记录
                UserChangeLog userChangeLog = new UserChangeLog();
                userChangeLog.setDelFlag(0);
                userChangeLog.setCreateTime(LocalDateTime.now());
                userChangeLog.setAppUserId(appUser.getId());
                userChangeLog.setBeforeVipId(vipId);
                userChangeLog.setAfterVipId(appUser.getVipId());
                userChangeLog.setChangeType(1);
                userChangeLogService.save(userChangeLog);
            }
        }
    }
    /**
     * 处理会员降级
     * @param appUserId
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/UserPointServiceImpl.java
@@ -71,7 +71,8 @@
    public UserPointVO getUserPoint(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        VipSetting vipSetting = vipSettingService.getVipSettingByUserId(userId);
        List<AppUserGiveawayTemporary> list = appUserGiveawayTemporaryService.list(new LambdaQueryWrapper<AppUserGiveawayTemporary>().eq(AppUserGiveawayTemporary::getAppUserId, userId));
        List<AppUserGiveawayTemporary> list = appUserGiveawayTemporaryService.list(new LambdaQueryWrapper<AppUserGiveawayTemporary>()
                .eq(AppUserGiveawayTemporary::getAppUserId, userId));
        int totalPoint = 0;
        int sharePoint = 0;
        int shopAchievementPoint = 0;
@@ -205,6 +206,16 @@
    @Override
    public UserPointStatistics getStatistics(UserPoint userPoint) {
        List<UserPoint> userPointList = this.baseMapper.selectUserPoint(userPoint);
        userPointList.forEach(item -> {
            int i = item.getHistoricalPoint() - item.getBalance();
            if (i>0){
                item.setVariablePoint(item.getVariablePoint() * -1);
            }else {
                item.setVariablePoint(item.getVariablePoint());
            }
        });
        Map<Integer, Integer> userBalanceMap = userPointList.stream()
                .collect(Collectors.groupingBy(
                        UserPoint::getType,
@@ -239,6 +250,15 @@
    @Override
    public IPage<UserPoint> getUserPointPage(Page<UserPoint> page, UserPoint userPoint) {
        return this.baseMapper.queryUserPointPage(page, userPoint);
        IPage<UserPoint> userPointIPage = this.baseMapper.queryUserPointPage(page, userPoint);
        userPointIPage.getRecords().forEach(item -> {
            int i = item.getHistoricalPoint() - item.getBalance();
            if (i>0){
                item.setVariablePoint(item.getVariablePoint() * -1);
            }else {
                item.setVariablePoint(item.getVariablePoint());
            }
        });
        return userPointIPage;
    }
}
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/VipCenterServiceImpl.java
@@ -4,7 +4,11 @@
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.account.api.model.AgentApplication;
import com.ruoyi.account.api.model.AppUser;
import com.ruoyi.account.mapper.AgentApplicationMapper;
import com.ruoyi.account.service.AgentApplicationService;
import com.ruoyi.account.service.AppUserService;
import com.ruoyi.account.service.VipCenterService;
import com.ruoyi.account.service.VipSettingService;
@@ -22,11 +26,10 @@
import com.ruoyi.other.api.feignClient.VipGoodClient;
import com.ruoyi.system.api.model.LoginUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
@Service
@@ -36,293 +39,271 @@
    @Resource
    private RemoteOrderGoodsClient remoteOrderGoodsClient;
    @Resource
    private VipGoodClient vipGoodClient;
    @Resource
    private VipSettingService vipSettingService;
    @Resource
    private ShopClient shopClient;
    @Resource
    private TokenService tokenService;
    @Resource
    private GoodsClient goodsClient;
    private AgentApplicationMapper agentApplicationMapper;
    // 钻石会员
    private static final int VIP_ID_DIAMOND = 3;
    // 门店合伙人
    private static final int VIP_ID_STORE_PARTNER = 4;
    // 城市合伙人
    private static final int VIP_ID_CITY_PARTNER = 5;
    // 全国合伙人
    private static final int VIP_ID_NATIONAL_PARTNER = 6;
    // 全球合伙人
    private static final int VIP_ID_GLOBAL_PARTNER = 7;
    @Override
    public Boolean checkReadyToBeProxy(Long userId,Integer vipId) {
    /**
     * 判断是否满足申请门店合伙人的条件
     * @param userId 用户ID
     * @param vipId 会员等级ID
     * @return 是否满足条件
     */
    public Boolean isEligibleForStorePartner(Long userId, Integer vipId) {
        AppUser appUser = appUserService.getById(userId);
        // 消费积分
        Integer shopPoint = appUser.getShopPoint();
        // 返佣积分
        Integer sharePoint = appUser.getSharePoint();
        // 准代理会员设置
        VipSetting vipSetting = vipSettingService.getVipSettingById(4);
        // 获取通过消费积分达成会员等级的开关
        Integer vipLevelUpShopRole = vipSetting.getVipLevelUpShopRole();
        // 获取指定购买商品
        boolean b = false;
        String[] split = vipSetting.getGoodIds().split(",");
        for (String s : split) {
            R<List<Order>> orderListByUserIdAndGoodsId = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(s));
            if (R.isSuccess(orderListByUserIdAndGoodsId)){
                List<Order> orderList = orderListByUserIdAndGoodsId.getData();
                if (orderList.size() > 0){
                    b = true;
                    break;
                }
            }
        }
        if (b && null != vipLevelUpShopRole && vipLevelUpShopRole == 1){
            // 消费积分阈值
            Integer vipLevelUpShop = vipSetting.getVipLevelUpShop();
            // 返佣积分阈值
            Integer vipLevelUpShare = vipSetting.getVipLevelUpShare();
            // 判断是否满足消费积分和返佣积分
            if (shopPoint.compareTo(vipLevelUpShop) >= 0 && sharePoint.compareTo(vipLevelUpShare) >= 0){
        VipSetting vipSetting = vipSettingService.getVipSettingById(VIP_ID_STORE_PARTNER);
        // 判断是否已经购买过指定商品
        if (hasPurchasedGoods(userId, vipSetting.getGoodIds())) {
                return true;
            }
        // 判断是否满足条件
        return meetsPointsAndDirectUsersCriteria(appUser, vipSetting);
        }
        Integer vipLevelUpNumRole = vipSetting.getVipLevelUpNumRole();
        if (b && null != vipLevelUpNumRole && vipLevelUpNumRole == 1){
            // 直推钻石用户数阈值
            Integer vipDirectNum = vipSetting.getVipDirectNum();
            // 获取用户直推钻石用户数量
            long userDiamondsCount = appUserService.count(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getInviteUserId, userId)
                    .eq(AppUser::getDelFlag, 0)
                    .eq(AppUser::getStatus, 1)
                    .gt(AppUser::getVipId, 2));
            // 判断是否满足直推钻石用户数量
            return userDiamondsCount >= vipDirectNum.longValue();
    /**
     * 判断是否满足申请城市合伙人的条件
     * @param userId 用户ID
     * @return 是否满足条件
     */
    public Boolean isEligibleForCityPartner(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        VipSetting vipSetting = vipSettingService.getVipSettingById(VIP_ID_CITY_PARTNER);
        if (hasPurchasedGoods(userId, vipSetting.getGoodIds())) {
            return true;
        }
        return meetsPointsAndDirectUsersCriteria(appUser, vipSetting);
    }
    /**
     * 判断是否满足申请全国合伙人的条件
     * @param userId 用户ID
     * @return 是否满足条件
     */
    public Boolean isEligibleForNationalPartner(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        VipSetting vipSetting = vipSettingService.getVipSettingById(VIP_ID_NATIONAL_PARTNER);
        // 判断是否已经购买过指定商品
        if (hasPurchasedGoods(userId, vipSetting.getGoodIds())) {
            return true;
        }
        if (vipSetting.getVipLevelUpProxyRole() == 1 && appUser.getVipId() == VIP_ID_CITY_PARTNER) {
            return true;
        }
        return meetsPointsAndDirectUsersCriteria(appUser, vipSetting);
    }
    /**
     * 判断是否满足申请全球合伙人的条件
     * @param userId 用户ID
     * @return 是否满足条件
     */
    public Boolean isEligibleForGlobalPartner(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        VipSetting vipSetting = vipSettingService.getVipSettingById(VIP_ID_GLOBAL_PARTNER);
        if (hasPurchasedGoods(userId, vipSetting.getGoodIds())) {
            return true;
        }
        return meetsPointsAndDirectUsersCriteria(appUser, vipSetting);
    }
    /**
     * 判断是否已经申请过
     * @param userId 用户ID
     * @param vipId 会员等级ID
     * @return 是否已经申请过
     */
    private boolean hasPendingApplication(Long userId, Integer vipId) {
        return agentApplicationMapper.selectCount(new QueryWrapper<AgentApplication>()
                .eq("app_user_id", userId)
                .eq("application_vip_id", vipId)
                .ne("status", 3)
                .eq("del_flag", 0)) > 0;
    }
    /**
     * 判断是否已经购买过指定商品
     * @param userId 用户ID
     * @param goodIds 商品ID列表
     * @return 是否已经购买过指定商品
     */
    private boolean hasPurchasedGoods(Long userId, String goodIds) {
        if (goodIds == null || goodIds.isEmpty()) {
        return false;
    }
        return Arrays.stream(goodIds.split(","))
                .anyMatch(goodId -> {
                    R<List<Order>> orderResponse = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(goodId));
                    return R.isSuccess(orderResponse) && !orderResponse.getData().isEmpty();
                });
    }
    @Override
    public Boolean checkReadyToBeAgent(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        // 消费积分
        Integer shopPoint = appUser.getShopPoint();
        // 返佣积分
        Integer sharePoint = appUser.getSharePoint();
        // 代理会员设置
        VipSetting vipSetting = vipSettingService.getVipSettingById(5);
        // 获取通过消费积分达成会员等级的开关
        Integer vipLevelUpShopRole = vipSetting.getVipLevelUpShopRole();
        boolean b = false;
        String[] split = vipSetting.getGoodIds().split(",");
        for (String s : split) {
            R<List<Order>> orderListByUserIdAndGoodsId = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(s));
            if (R.isSuccess(orderListByUserIdAndGoodsId)){
                List<Order> orderList = orderListByUserIdAndGoodsId.getData();
                if (orderList.size() > 0){
                    b = true;
                    break;
                }
            }
        }
        if (b && null != vipLevelUpShopRole && vipLevelUpShopRole == 1){
            // 消费积分阈值
            Integer vipLevelUpShop = vipSetting.getVipLevelUpShop();
            // 返佣积分阈值
            Integer vipLevelUpShare = vipSetting.getVipLevelUpShare();
            // 判断是否满足消费积分和返佣积分
            if (shopPoint.compareTo(vipLevelUpShop) >= 0 && sharePoint.compareTo(vipLevelUpShare) >= 0){
    /**
     * 判断是否满足条件
     * @param appUser 用户信息
     * @param vipSetting 会员设置
     * @return 是否满足条件
     */
    private boolean meetsPointsAndDirectUsersCriteria(AppUser appUser, VipSetting vipSetting) {
        // 满足消费积分和返佣积分
        if (vipSetting.getVipLevelUpShopRole() == 1) {
            if (appUser.getShopPoint() >= vipSetting.getVipLevelUpShop() &&
                    appUser.getSharePoint() >= vipSetting.getVipLevelUpShare()) {
                return true;
            }
        }
        Integer vipLevelUpNumRole = vipSetting.getVipLevelUpNumRole();
        if (b && null != vipLevelUpNumRole && vipLevelUpNumRole == 1){
            // 直推钻石用户数阈值
        long directDiamondUserCount = getDirectDiamondUserCount(appUser.getId()); // 直推钻石会员数量
        if (vipSetting.getId() < VIP_ID_NATIONAL_PARTNER){ // 门店合伙人、城市合伙人
            if (vipSetting.getVipLevelUpNumRole() == 1) {
                return directDiamondUserCount >= vipSetting.getVipDirectNum(); //直推钻石会员数量大于等于指定数量
            }
        }else if (vipSetting.getId() == VIP_ID_NATIONAL_PARTNER){ // 全国合伙人
            if (vipSetting.getVipLevelUpNumRole() == 1){
                List<AppUser> appUsers = appUserService.list(new LambdaQueryWrapper<AppUser>()
                        .eq(AppUser::getInviteUserId, appUser.getId())
                        .ge(AppUser::getVipId, VIP_ID_CITY_PARTNER)
                        .eq(AppUser::getDelFlag, 0));
                if (appUsers.size() >= vipSetting.getVipDirectNum()){ // 直推城市合伙人数量大于等于指定数量
                    List<Long> userIds = appUsers.stream().map(AppUser::getId).collect(Collectors.toList());
                    long directStorePartnerCount = getDirectStorePartnerCount(userIds);
                    return directStorePartnerCount >= vipSetting.getVipDirectVipNum(); // 城市合伙人下的门店合伙人数量大于等于指定数量
                }
            }
        }else if (vipSetting.getId() == VIP_ID_GLOBAL_PARTNER){ // 全球合伙人
            if (vipSetting.getVipLevelUpNumRole() == 1){
                // 城市合伙人用户数阈值
            Integer vipDirectNum = vipSetting.getVipDirectNum();
            // 获取用户直推钻石用户数量
            long userDiamondsCount = appUserService.count(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getInviteUserId, userId)
                    .eq(AppUser::getVipId, 3));
            // 判断是否满足直推钻石用户数量
            return userDiamondsCount >= vipDirectNum.longValue();
        }
        return false;
    }
    @Override
    public Boolean checkReadyToBeTotalAgent(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        // 获取总代会员设置
        VipSetting vipSetting = vipSettingService.getVipSettingById(6);
        // 获取指定购买商品
        boolean b = false;
        String[] split = vipSetting.getGoodIds().split(",");
        for (String s : split) {
            R<List<Order>> orderListByUserIdAndGoodsId = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(s));
            if (R.isSuccess(orderListByUserIdAndGoodsId)){
                List<Order> orderList = orderListByUserIdAndGoodsId.getData();
                if (orderList.size() > 0){
                    b = true;
                    break;
                }
            }
        }
        // 获取会员等级是否必须达到代理
        Integer vipLevelUpProxyRole = vipSetting.getVipLevelUpProxyRole();
        if (b && vipLevelUpProxyRole == 1 && appUser.getVipId() == 5){
            return true;
        }
        // 消费积分
        Integer shopPoint = appUser.getShopPoint();
        // 返佣积分
        Integer sharePoint = appUser.getSharePoint();
        // 获取通过消费积分达成会员等级的开关
        Integer vipLevelUpShopRole = vipSetting.getVipLevelUpShopRole();
        if (b && null != vipLevelUpShopRole && vipLevelUpShopRole == 1){
            // 消费积分阈值
            Integer vipLevelUpShop = vipSetting.getVipLevelUpShop();
            // 返佣积分阈值
            Integer vipLevelUpShare = vipSetting.getVipLevelUpShare();
            // 判断是否满足消费积分和返佣积分
            if (shopPoint.compareTo(vipLevelUpShop) >= 0 && sharePoint.compareTo(vipLevelUpShare) >= 0){
                return true;
            }
        }
        Integer vipLevelUpNumRole = vipSetting.getVipLevelUpNumRole();
        if (b && null != vipLevelUpNumRole && vipLevelUpNumRole == 1){
            // 直推代理用户数阈值
            Integer vipDirectNum = vipSetting.getVipDirectNum();
            // 准代理用户数阈值
                // 门店合伙人用户数阈值
            Integer vipDirectVipNum = vipSetting.getVipDirectVipNum();
            // 获取用户直推代理用户数量
            List<AppUser> userAgentList = appUserService.list(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getInviteUserId, userId)
                    .eq(AppUser::getVipId, 5));
            // 代理下的准代理数量
            List<Long> userQuasiAgent = userAgentList.stream().map(AppUser::getId).collect(Collectors.toList());
            long userQuasiAgentCount = 0;
            if(userQuasiAgent.size() > 0){
                userQuasiAgentCount = appUserService.count(new LambdaQueryWrapper<AppUser>()
                        .in(AppUser::getInviteUserId, userQuasiAgent)
                        .eq(AppUser::getVipId, 4));
            }
            // 判断是否满足直推代理用户数量和准代理数量
            return userAgentList.size() >= vipDirectNum && userQuasiAgentCount >= vipDirectVipNum.longValue();
        }
        return false;
    }
    @Override
    public Boolean checkReadyToBePartner(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        // 消费积分
        Integer shopPoint = appUser.getShopPoint();
        // 返佣积分
        Integer sharePoint = appUser.getSharePoint();
        // 合伙人会员设置
        VipSetting vipSetting = vipSettingService.getVipSettingById(7);
        // 获取指定购买商品
        boolean b = false;
        String[] split = vipSetting.getGoodIds().split(",");
        for (String s : split) {
            R<List<Order>> orderListByUserIdAndGoodsId = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(s));
            if (R.isSuccess(orderListByUserIdAndGoodsId)){
                List<Order> orderList = orderListByUserIdAndGoodsId.getData();
                if (orderList.size() > 0){
                    b = true;
                    break;
                }
            }
        }
        // 获取通过消费积分达成会员等级的开关
        Integer vipLevelUpShopRole = vipSetting.getVipLevelUpShopRole();
        if (b && null != vipLevelUpShopRole && vipLevelUpShopRole == 1){
            // 消费积分阈值
            Integer vipLevelUpShop = vipSetting.getVipLevelUpShop();
            // 返佣积分阈值
            Integer vipLevelUpShare = vipSetting.getVipLevelUpShare();
            // 判断是否满足消费积分和返佣积分
            if (shopPoint.compareTo(vipLevelUpShop) >= 0 && sharePoint.compareTo(vipLevelUpShare) >= 0){
                return true;
            }
        }
        Integer vipLevelUpNumRole = vipSetting.getVipLevelUpNumRole();
        if (b && null != vipLevelUpNumRole && vipLevelUpNumRole == 1){
            // 直推代理用户数阈值
            Integer vipDirectNum = vipSetting.getVipDirectNum();
            // 准代理用户数阈值
            Integer vipDirectVipNum = vipSetting.getVipDirectVipNum();
            // 总代用户数阈值
                // 全国合伙人用户数阈值
            Integer vipTeamVipNum = vipSetting.getVipTeamVipNum();
            // 获取开店数量阈值
                // 开店数量阈值
            Integer vipOpenShopNum = vipSetting.getVipOpenShopNum();
            // 获取直推用户有超过指定门店数量的用户
            List<Long> userShopList = appUserService.list(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getInviteUserId, userId))
                    .stream().map(AppUser::getId).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(userShopList)){
                R<List<Shop>> r = shopClient.getShopByUserIds(userShopList);
                List<Shop> shopList = r.getData();
                if (CollectionUtil.isNotEmpty(shopList)){
                    Map<Long, List<Shop>> shopUserMap = shopList.stream().collect(Collectors.groupingBy(Shop::getAppUserId));
                    // 查找 list 长度大于 3 的 key
                    Set<Long> shopUserIdSet = shopUserMap.entrySet().stream()
                            .filter(entry -> entry.getValue().size() >= vipOpenShopNum)
                            .map(Map.Entry::getKey)
                            .collect(Collectors.toSet());
                    // 获取用户直推总代理数量
                    List<AppUser> userTotalAgentList = appUserService.list(new LambdaQueryWrapper<AppUser>()
                            .in(AppUser::getId, shopUserIdSet)
                            .eq(AppUser::getVipId, 6));
                // 1.直推用户达到指定数量会员等级最低为城市合伙人
                List<AppUser> appUsers = appUserService.list(new LambdaQueryWrapper<AppUser>()
                        .eq(AppUser::getInviteUserId, appUser.getId())
                        .ge(AppUser::getVipId, VIP_ID_CITY_PARTNER)
                        .eq(AppUser::getDelFlag, 0));
                    // 获取用户直推代理用户数量
                    List<AppUser> userAgentList = appUserService.list(new LambdaQueryWrapper<AppUser>()
                            .in(AppUser::getId, userShopList)
                            .gt(AppUser::getVipId, 4));
                if (appUsers.size() >= vipDirectNum ){
                    // 2.城市合伙人下的门店合伙人数量达到指定人数
                    List<Long> userIds = appUsers.stream().map(AppUser::getId).collect(Collectors.toList());
                    long directStorePartnerCount = getDirectStorePartnerCount(userIds);
                    if (directStorePartnerCount >= vipDirectVipNum){
                    // 代理下的准代理数量
                    List<Long> userQuasiAgent = userAgentList.stream().map(AppUser::getId).collect(Collectors.toList());
                    long userQuasiAgentCount = 0;
                    if(userQuasiAgent.size() > 0){
                        userQuasiAgentCount = appUserService.count(new LambdaQueryWrapper<AppUser>()
                                .in(AppUser::getInviteUserId, userQuasiAgent)
                                .eq(AppUser::getVipId, 4));
                        // 3.直推用户达到指定数量会员等级最低为全国合伙人并且已经开了指定门店数量
                        List<AppUser> appUsers2 = appUserService.list(new LambdaQueryWrapper<AppUser>()
                                .eq(AppUser::getInviteUserId, appUser.getId())
                                .ge(AppUser::getVipId, VIP_ID_NATIONAL_PARTNER)
                                .eq(AppUser::getDelFlag, 0));
                        return appUsers2.size() >= vipTeamVipNum && appUsers2.size() >= vipOpenShopNum;
                    }
                    // 判断是否满足直推代理用户数量和准代理数量
                    return userTotalAgentList.size() >= vipTeamVipNum && userAgentList.size() >= vipDirectNum &&
                            userQuasiAgentCount >= vipDirectVipNum;
                }
                }
            }
        }
        return false;
    }
    @Override
    public Boolean check(Integer type) {
    /**
     * 获取指定用户直推钻石会员的数量
     */
    public long getDirectDiamondUserCount(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        if (appUser == null) {
            return 0;
        }
        return appUserService.count(new LambdaQueryWrapper<AppUser>()
                .eq(AppUser::getInviteUserId, appUser.getId())
                .eq(AppUser::getVipId, VIP_ID_DIAMOND));
    }
    /**
     * 获取指定用户下级门店合伙人的数量
     */
    public long getDirectStorePartnerCount(List<Long> userIds) {
        List<AppUser> allSubordinates = getAllSubordinates(userIds);
        return allSubordinates.stream()
                .filter(appUser -> appUser.getVipId().equals(VIP_ID_STORE_PARTNER))
                .count();
    }
    public List<AppUser> getAllSubordinates(List<Long> userIds) {
        List<AppUser> allSubordinates = new ArrayList<>();
        Set<Long> processedUsers = new HashSet<>(); // 用于避免重复添加用户
        // 遍历每个用户ID
        for (Long userId : userIds) {
            collectSubordinates(userId, allSubordinates, processedUsers);
        }
        return allSubordinates;
    }
    private void collectSubordinates(Long userId, List<AppUser> allSubordinates, Set<Long> processedUsers) {
        if (processedUsers.contains(userId)) {
            // 如果已经处理过该用户,则跳过,防止循环引用导致的无限递归
            return;
        }
        processedUsers.add(userId);
        List<AppUser> directChildren = appUserService.list(new LambdaQueryWrapper<AppUser>()
                .eq(AppUser::getInviteUserId, userId));
        for (AppUser child : directChildren) {
            if (!allSubordinates.contains(child)) { // 确保不添加重复的用户
                allSubordinates.add(child); // 添加直接下级
            }
            collectSubordinates(child.getId(), allSubordinates, processedUsers); // 递归添加间接下级
        }
    }
    public Boolean checkEligibility(Integer type) {
        LoginUser loginUser = tokenService.getLoginUserApplet();
        Long userid = loginUser.getUserid();
        if (type == 4){
            return checkReadyToBeProxy(userid, type);
        }else if (type == 5){
            return checkReadyToBeAgent(userid);
        }else if (type == 6){
            return checkReadyToBeTotalAgent(userid);
        }else if (type == 7){
            return checkReadyToBePartner(userid);
        }else {
        Long userId = loginUser.getUserid();
        switch (type) {
            case VIP_ID_STORE_PARTNER:
                return isEligibleForStorePartner(userId, type);
            case VIP_ID_CITY_PARTNER:
                return isEligibleForCityPartner(userId);
            case VIP_ID_NATIONAL_PARTNER:
                return isEligibleForNationalPartner(userId);
            case VIP_ID_GLOBAL_PARTNER:
                return isEligibleForGlobalPartner(userId);
            default:
            throw new ServiceException("参数错误");
        }
    }
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/WalletServiceImpl.java
@@ -15,6 +15,7 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
@Service
@@ -45,7 +46,7 @@
        
        List<AppUserGiveawayTemporary> list = appUserGiveawayTemporaryService.list(new LambdaQueryWrapper<AppUserGiveawayTemporary>().eq(AppUserGiveawayTemporary::getAppUserId, userId));
        BigDecimal commissionAmount = BigDecimal.ZERO;
        if(list.size() > 0){
        if(!list.isEmpty()){
            commissionAmount = list.stream().map(AppUserGiveawayTemporary::getTotalDistributionAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
@@ -58,13 +59,13 @@
        WalletVO walletVO = new WalletVO();
        BigDecimal balance = appUser.getBalance();
        walletVO.setCommissionAmount(appUser.getTotalDistributionAmount().add(commissionAmount).setScale(2, BigDecimal.ROUND_HALF_UP));
        walletVO.setCommissionAmount(appUser.getTotalDistributionAmount().add(commissionAmount).setScale(2, RoundingMode.HALF_UP));
        walletVO.setWithdrawalAmount(appUser.getWithdrawableAmount());
        walletVO.setWithdrawnAmount(appUser.getWithdrawnAmount().subtract(reduce));
        walletVO.setVipWithdrawalMinAmount(data.getVipWithdrawalMinAmount());
        walletVO.setTotalRechargeAmount(appUser.getTotalRechargeAmount());
        walletVO.setTotalRedPacketAmount(appUser.getTotalRedPacketAmount());
        walletVO.setTotalDistributionAmount(appUser.getTotalDistributionAmount());
        walletVO.setTotalDistributionAmount(appUser.getTotalDistributionAmount().add(commissionAmount).setScale(2, RoundingMode.HALF_UP));
        walletVO.setAuditAmount(reduce);
        walletVO.setBalance(balance);
        return walletVO;
ruoyi-service/ruoyi-account/src/main/resources/bootstrap.yml
@@ -54,13 +54,13 @@
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        group: DEFAULT_GROUP
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/UserPointMapper.xml
@@ -24,7 +24,9 @@
        tau.phone,
        tup.type,
        tup.create_time,
        tup.variable_point
        tup.variable_point,
        tup.historical_point,
        tup.balance
        FROM
        t_user_point tup
        LEFT JOIN t_app_user tau ON tup.app_user_id = tau.id
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/PayEvent.java
New file
@@ -0,0 +1,10 @@
package com.ruoyi.order.event;
import org.springframework.context.ApplicationEvent;
public class PayEvent extends ApplicationEvent {
    public PayEvent(Object source) {
        super(source);
    }
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/PayEventListener.java
New file
@@ -0,0 +1,33 @@
package com.ruoyi.order.event;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.account.api.feignClient.AppUserClient;
import com.ruoyi.account.api.model.AppUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@RequiredArgsConstructor
@Component
@Slf4j
public class PayEventListener {
    private final AppUserClient appUserClient;
    /**
     * 检查会员等级变更
     */
    @Async
    @EventListener(PayEvent.class)
    public void checkVipChange(PayEvent event) {
        String source = (String) event.getSource();
        System.out.println("11221212" + source);
        AppUser appUsers = JSONObject.parseObject(source, AppUser.class);
        appUserClient.vipConsumption(appUsers.getId());
    }
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/CommissionServiceImpl.java
@@ -1,31 +1,29 @@
package com.ruoyi.order.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.account.api.feignClient.*;
import com.ruoyi.account.api.feignClient.AppUserClient;
import com.ruoyi.account.api.feignClient.AppUserGiveawayTemporaryClient;
import com.ruoyi.account.api.feignClient.BalanceChangeRecordClient;
import com.ruoyi.account.api.feignClient.UserPointClient;
import com.ruoyi.account.api.model.*;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.order.model.Order;
import com.ruoyi.order.model.OrderGood;
import com.ruoyi.order.service.CommissionService;
import com.ruoyi.order.service.OrderGoodService;
import com.ruoyi.order.service.OrderService;
import com.ruoyi.other.api.domain.*;
import com.ruoyi.other.api.feignClient.*;
import com.ruoyi.order.model.Order;
import com.ruoyi.order.model.OrderGood;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/ShoppingCartServiceImpl.java
@@ -14,6 +14,7 @@
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.order.event.PayEvent;
import com.ruoyi.order.mapper.ShoppingCartMapper;
import com.ruoyi.order.model.Order;
import com.ruoyi.order.model.OrderBalancePayment;
@@ -31,6 +32,7 @@
import com.ruoyi.other.api.vo.GetGoodsShopByGoodsIds;
import com.ruoyi.other.api.vo.GetSeckillActivityInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@@ -108,12 +110,6 @@
    private CommissionService commissionService;
    @Resource
    private VipSettingClient vipSettingClient;
    @Resource
    private UserChangeLogClient userChangeLogClient;
    @Resource
    private PointSettingClient pointSettingClient;
    
    @Resource
@@ -121,6 +117,9 @@
    
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private ApplicationEventPublisher applicationEventPublisher;
    
    
    
@@ -1167,7 +1166,7 @@
                appUser.setLastShopTime(LocalDateTime.now());
                appUserClient.editAppUserById(appUser);
                //变更等级
                appUserClient.vipUpgrade(appUser.getId());
                applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
                //修改订支付状态
                order.setPayStatus(2);
                //自提
@@ -1272,7 +1271,7 @@
            appUser.setLastShopTime(LocalDateTime.now());
            appUserClient.editAppUserById(appUser);
            //变更等级
            appUserClient.vipUpgrade(appUser.getId());
            applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
            //构建余额明细变动记录
            BalanceChangeRecord balanceChangeRecord = new BalanceChangeRecord();
            balanceChangeRecord.setAppUserId(appUser.getId());
@@ -1355,7 +1354,7 @@
            appUser.setLastShopTime(LocalDateTime.now());
            appUserClient.editAppUserById(appUser);
            //变更等级
            appUserClient.vipUpgrade(appUser.getId());
            applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
            //积分支付不返佣
@@ -1513,7 +1512,7 @@
        appUser.setLastShopTime(LocalDateTime.now());
        appUserClient.editAppUserById(appUser);
        //变更等级
        appUserClient.vipUpgrade(appUser.getId());
        applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
        //修改订支付状态
        order.setPayStatus(2);
        //自提
@@ -1597,7 +1596,7 @@
        appUser.setLastShopTime(LocalDateTime.now());
        appUserClient.editAppUserById(appUser);
        //变更等级
        appUserClient.vipUpgrade(appUser.getId());
        applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
        //修改订支付状态
        order.setPayStatus(2);
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/OrderExport.java
@@ -27,6 +27,12 @@
    private String orderType;
    /**
     * 配送方式
     */
    @Excel(name = "配送方式", readConverterExp = "1=快递,2=自提")
    private String distributionMode;
    /**
     * 收货地址
     */
    @Excel(name = "收货地址")
ruoyi-service/ruoyi-order/src/main/resources/bootstrap.yml
@@ -54,13 +54,13 @@
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        group: DEFAULT_GROUP
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/OrderGoodMapper.xml
@@ -8,6 +8,6 @@
        FROM
            t_order_good og
                LEFT JOIN t_order o ON og.order_id = o.id
        WHERE og.goods_id = #{goodsId} and o.app_user_id = #{userId}
        WHERE og.goods_id = #{goodsId} and o.app_user_id = #{userId} and o.order_status != 5 and o.order_status != 6
    </select>
</mapper>
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml
@@ -101,12 +101,14 @@
    </select>
    <select id="getOrderStatistics" resultType="com.ruoyi.order.vo.OrderStatistics">
        SELECT
            SUM( CASE WHEN tor.order_status!=5 THEN 1 ELSE 0 END ) as total,
            SUM( CASE WHEN tor.order_type = 1 and tor.order_status!=5 THEN 1 ELSE 0 END ) as serviceTotal,
            SUM( CASE WHEN tor.order_type = 2 and tor.order_status!=5 THEN 1 ELSE 0 END ) as singleTotal,
            SUM( CASE WHEN tor.order_status!=5 THEN tor.total_amount ELSE 0 END ) as totalMoney,
            SUM( CASE WHEN tor.order_type = 1 and tor.order_status!=5 THEN tor.total_amount ELSE 0 END ) as serviceTotalMoney,
            SUM( CASE WHEN tor.order_type = 2 and tor.order_status!=5 THEN tor.total_amount ELSE 0 END ) as singleTotalMoney
        coalesce(SUM( CASE WHEN tor.order_status!=5 THEN 1 ELSE 0 END ), 0) as total,
        coalesce(SUM( CASE WHEN tor.order_type = 1 and tor.order_status!=5 THEN 1 ELSE 0 END ),0) as serviceTotal,
        coalesce(SUM( CASE WHEN tor.order_type = 2 and tor.order_status!=5 THEN 1 ELSE 0 END ),0) as singleTotal,
        coalesce(SUM( CASE WHEN tor.order_status!=5 THEN tor.total_amount ELSE 0 END ),0) as totalMoney,
        coalesce(SUM( CASE WHEN tor.order_type = 1 and tor.order_status!=5 THEN tor.total_amount ELSE 0 END ),0) as
        serviceTotalMoney,
        coalesce( SUM( CASE WHEN tor.order_type = 2 and tor.order_status!=5 THEN tor.total_amount ELSE 0 END ),0) as
        singleTotalMoney
        FROM
        t_order tor where 1 = 1 AND tor.del_flag = 0
        <if test="null != shopId">
@@ -160,6 +162,7 @@
            o.order_status,
            o.order_number,
            o.order_type,
            o.distribution_mode,
            o.address_Json,
            o.create_time,
            o.app_user_id,
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/CouponInfoController.java
@@ -162,9 +162,18 @@
        AppUser appUserById = appUserClient.getAppUserById(userid);
        LocalDateTime now = LocalDateTime.now();
        //查出全部可领取的优惠劵
        List<CouponInfo> list = couponInfoService.lambdaQuery().le(CouponInfo::getSendStartTime, now).ge(CouponInfo::getSendEndTime, now).eq(CouponInfo::getPersonType, 1).list();
        List<CouponInfo> list = couponInfoService.lambdaQuery()
                .le(CouponInfo::getSendStartTime, now)
                .ge(CouponInfo::getSendEndTime, now)
                .eq(CouponInfo::getPersonType, 1)
                .list();
        //查出指定人员可领取优惠券
        List<CouponInfo> list1 = couponInfoService.lambdaQuery().le(CouponInfo::getSendStartTime, now).ge(CouponInfo::getSendEndTime, now).eq(CouponInfo::getPersonType, 2).apply("FIND_IN_SET('" + appUserById.getId() + "', person_ids)").list();
        List<CouponInfo> list1 = couponInfoService.lambdaQuery()
                .le(CouponInfo::getSendStartTime, now)
                .ge(CouponInfo::getSendEndTime, now)
                .eq(CouponInfo::getPersonType, 2)
                .apply("FIND_IN_SET('" + appUserById.getId() + "', person_ids)")
                .list();
        //查出指定会员可领取优惠劵
        List<CouponInfo> list2 = couponInfoService.lambdaQuery().le(CouponInfo::getSendStartTime, now).ge(CouponInfo::getSendEndTime, now).eq(CouponInfo::getPersonType, 3).apply("FIND_IN_SET('" + appUserById.getVipId() + "', vip_ids)").list();
        List<CouponInfo> returnList = new ArrayList<>();
ruoyi-service/ruoyi-other/src/main/resources/bootstrap.yml
@@ -23,20 +23,20 @@
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
        server-addr: 192.168.110.111/:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        username:
        password:
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        server-addr: 192.168.110.111/:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        username:
        password:
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        username: nacos
        password: nacos
        # 配置文件格式
        file-extension: yml
        # 共享配置
@@ -54,15 +54,15 @@
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        username: nacos
        password: nacos
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username:
        password:
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        username: nacos
        password: nacos
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username:
        password:
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        # 配置文件格式