浏览代码

免推荐注册用户.加入用户游客身份,计算利润时需要加上条件分支,游客的直推奖和上级合赢奖要加入到游客收益中

Yangzw 2 月之前
父节点
当前提交
60f2916f9f
共有 22 个文件被更改,包括 262 次插入80 次删除
  1. 1 0
      feifan-module-distri/feifan-module-distri-api/src/main/java/cn/newfeifan/mall/module/distri/constant/DistriConstants.java
  2. 2 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofit/vo/PtProfitPageReqVO.java
  3. 4 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofit/vo/PtProfitRespVO.java
  4. 3 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofit/vo/PtProfitSaveReqVO.java
  5. 0 1
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofitlog/PtProfitLogController.java
  6. 3 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofitlog/vo/PtProfitLogPageReqVO.java
  7. 10 1
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/sharepath/SharePathController.java
  8. 4 1
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/dataobject/ptprofit/PtProfitDO.java
  9. 16 4
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/ptprofitlog/PtProfitLogMapper.java
  10. 8 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/sharepath/SharePathMapper.java
  11. 1 2
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/integral/IntegralServiceImpl.java
  12. 78 43
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/partitioncrash/PartitionCrashServiceImpl.java
  13. 1 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/ptprofitlog/PtProfitLogServiceImpl.java
  14. 13 4
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/sharepath/SharePathService.java
  15. 71 12
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/sharepath/SharePathServiceImpl.java
  16. 9 3
      feifan-module-distri/feifan-module-distri-biz/src/main/resources/mapper/sharepath/SharePathMapper.xml
  17. 1 1
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/mysql/spuapply/SpuApplyMapper.java
  18. 22 3
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateServiceImpl.java
  19. 3 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/admin/user/vo/MemberUserBaseVO.java
  20. 4 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/dataobject/user/MemberUserDO.java
  21. 4 4
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/sms/SmsCodeServiceImpl.java
  22. 4 1
      sql/mysql/建空库SQL/25_20241011.sql

+ 1 - 0
feifan-module-distri/feifan-module-distri-api/src/main/java/cn/newfeifan/mall/module/distri/constant/DistriConstants.java

@@ -11,6 +11,7 @@ public class DistriConstants {
     public static final Integer MILLION = 1000000;      //百万倍
     public static final Integer THREE = 3;
     public static final Long PT_ID = 1L;
+    public static final Long BOOS_ID = 2L;
 
     public static final Boolean IS_EFFECTIVE  = true;
 

+ 2 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofit/vo/PtProfitPageReqVO.java

@@ -30,4 +30,6 @@ public class PtProfitPageReqVO extends PageParam {
     @Schema(description = "利润")
     private Long profit;
 
+    @Schema(description = "游客收益")
+    private Long visitorEarnings;
 }

+ 4 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofit/vo/PtProfitRespVO.java

@@ -33,4 +33,8 @@ public class PtProfitRespVO {
     @Schema(description = "利润", requiredMode = Schema.RequiredMode.REQUIRED)
     @ExcelProperty("利润")
     private Long profit;
+
+    @Schema(description = "游客收益", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("游客收益")
+    private Long visitorEarnings;
 }

+ 3 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofit/vo/PtProfitSaveReqVO.java

@@ -25,4 +25,7 @@ public class PtProfitSaveReqVO {
 
     @Schema(description = "利润", requiredMode = Schema.RequiredMode.REQUIRED)
     private Long profit;
+
+    @Schema(description = "游客收益", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Long visitorEarnings;
 }

+ 0 - 1
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofitlog/PtProfitLogController.java

@@ -79,7 +79,6 @@ public class PtProfitLogController {
     @PreAuthorize("@ss.hasPermission('distri:pt-profit-log:query')")
     public CommonResult<PageResult<PtProfitLogRespVO>> getPtProfitLogPage(@Valid PtProfitLogPageReqVO pageReqVO) {
         PageResult<PtProfitLogRespVO> pageResult = ptProfitLogService.getPtProfitLogPage(pageReqVO);
-
         return success(pageResult);
     }
 

+ 3 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/ptprofitlog/vo/PtProfitLogPageReqVO.java

@@ -57,4 +57,7 @@ public class PtProfitLogPageReqVO extends PageParam {
     @Schema(description = "直推奖超出额度")
     private Long ancestorQuotaAmount;
 
+    @Schema(description = "游客收益")
+    private Boolean visitor;
+
 }

+ 10 - 1
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/sharepath/SharePathController.java

@@ -2,6 +2,7 @@ package cn.newfeifan.mall.module.distri.controller.admin.sharepath;
 
 import cn.newfeifan.mall.module.distri.dal.dataobject.duser.DuserDO;
 import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserRespVO;
+import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
@@ -47,7 +48,7 @@ public class SharePathController {
     @Operation(summary = "创建分销用户关系")
     @PreAuthorize("@ss.hasPermission('distri:share-path:create')")
     public CommonResult<Boolean> createSharePath(@Valid @RequestBody SharePathSaveReqVO createReqVO) {
-        sharePathService.createSharePathByUserId(createReqVO);
+        sharePathService.createSharePathByUserId(createReqVO, true);
         return success(true);
     }
 
@@ -150,4 +151,12 @@ public class SharePathController {
         TreeNode sharePath = sharePathService.getTreeByNameOrMobile(sharePathTreeReqVO);
         return success(sharePath);
     }
+
+    @PutMapping("/updateMemberUser")
+    @Operation(summary = "更新会员用户信息")
+    @PreAuthorize("@ss.hasPermission('member:user:update')")
+    public CommonResult<Boolean> updateUser(@Valid @RequestBody MemberUserUpdateReqVO updateReqVO) {
+        sharePathService.updateUser(updateReqVO);
+        return success(true);
+    }
 }

+ 4 - 1
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/dataobject/ptprofit/PtProfitDO.java

@@ -36,10 +36,13 @@ public class PtProfitDO extends BaseDO {
      * 平台总收益
      */
     private Long ptTotalAdd;
-
     /**
      * 利润
      */
     private Long profit;
+    /**
+     * 游客收益
+     */
+    private Long visitorEarnings;
 
 }

+ 16 - 4
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/ptprofitlog/PtProfitLogMapper.java

@@ -46,7 +46,7 @@ public interface PtProfitLogMapper extends BaseMapperX<PtProfitLogDO> {
                 COMMISSION_TRANSITION.getType()
         );
 
-        if(reqVO.getUserId().equals(PT_ID)){
+        if(reqVO.getUserId() != null && reqVO.getUserId().equals(PT_ID)){
             profitStatus = Arrays.asList(
                     PLATFORM_TOTAL_ADD.getType(),
                     PLATFORM_SERVICE_FEE.getType(),
@@ -71,11 +71,23 @@ public interface PtProfitLogMapper extends BaseMapperX<PtProfitLogDO> {
 //            reqVO.setUserId(null);
         }
 
-        return selectPage(reqVO, new LambdaQueryWrapperX<PtProfitLogDO>()
+        LambdaQueryWrapperX<PtProfitLogDO> queryWrapper = new LambdaQueryWrapperX<PtProfitLogDO>()
                 .eqIfPresent(PtProfitLogDO::getUserId, reqVO.getUserId())
-                .in(PtProfitLogDO::getProfitStatus, profitStatus)
                 .orderByDesc(PtProfitLogDO::getCreateTime)
-                .orderByDesc(PtProfitLogDO::getId)
+                .orderByDesc(PtProfitLogDO::getId);
+
+        if(reqVO.getVisitor() != null && reqVO.getVisitor()){
+            profitStatus = Arrays.asList(
+                    RECOMMENDED_PERSON_QUOTA.getType(),
+                    ORDER_REFUND_INTEGRAL_ANCESTER.getType(),
+                    SMALL_QUOTA_CRASH_SETTLE.getType()
+                    );
+            queryWrapper.in(PtProfitLogDO::getProfitStatus,profitStatus);
+            queryWrapper.isNull(PtProfitLogDO::getUserId);
+        } else {
+            queryWrapper.in(PtProfitLogDO::getProfitStatus, profitStatus);
+        }
+        return selectPage(reqVO, queryWrapper
         );
     }
 }

+ 8 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/sharepath/SharePathMapper.java

@@ -78,6 +78,14 @@ public interface SharePathMapper extends BaseMapperX<SharePathDO> {
                 .eq(SharePathDO::getDepth, 1)
         ).getAncestor();
     }
+
+    /**
+     * 根据是否为游客查询分享关系
+     * @param ancestor 上级id
+     * @param visitor 是否游客
+     * @return 分销关系
+     */
+    List<SharePathDO> selectListByVisitor(@Param("ancestor") Long ancestor, @Param("visitor") Boolean visitor);
 }
 
 

+ 1 - 2
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/integral/IntegralServiceImpl.java

@@ -284,8 +284,7 @@ public class IntegralServiceImpl implements IntegralService {
         }else if(effectRowNum<1){//如果钱包积分不足,不够抵扣
             success = false;
         } else if (effectRowNum>1) {
-//            success = false;
-            throw new RuntimeException("用户IO为"+userId+"的用户钱包不只一个!");
+            throw new RuntimeException("用户ID为"+userId+"的用户钱包不只一个!");
         }
 
         return success;

+ 78 - 43
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/partitioncrash/PartitionCrashServiceImpl.java

@@ -23,6 +23,8 @@ import cn.newfeifan.mall.module.distri.service.partitionbrothers.PartitionBrothe
 import cn.newfeifan.mall.module.distri.service.partitionson.PartitionSonService;
 import cn.newfeifan.mall.module.distri.service.ptprofit.PtProfitService;
 import cn.newfeifan.mall.module.distri.service.ptprofitlog.PtProfitLogService;
+import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
+import cn.newfeifan.mall.module.member.service.user.MemberUserService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
@@ -99,6 +101,8 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
 
     @Resource
     private DailyAwardRecordsService dailyAwardRecordsService;
+    @Resource
+    private MemberUserService memberUserService;
 
 
     @Override
@@ -171,10 +175,16 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
         List<PartitionBrothersSaveReqVO> partitionBrothersSaveReqVOS = new ArrayList<>();
         List<PartitionCrashSaveReqVO> partitionCrashSaveReqVOS = new ArrayList<>();
 
+        // 本来在下面,搬上来,因为游客收益要扣减
+        IntegralDO ptIntegralDO = integralService.selectByUser(PT_ID);
+
         duserDOS.forEach(k -> {
 
             // 获取当前用户的钱包
             IntegralDO integralDO = integralService.selectByUser(k.getUserId());
+            // 获取当前用户信息
+            MemberUserDO user = memberUserService.getUser(k.getUserId());
+
             // 获取当前父亲的钱包
             Long parent = sonAndParent.get(k.getUserId());
             IntegralDO parentIntegralDo = integralService.selectByUser(parent);
@@ -217,7 +227,7 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
                 sonBuilder.price(sonSumPrice);
 
                 // 获取当前用户的兄弟分区
-                List<OrderCalcDO> brothersOrderCalcDOS = sharePathService.selectBrothers(k.getUserId(), userId);
+                List<OrderCalcDO> brothersOrderCalcDOS = sharePathService.selectBrothers(k.getUserId(), userId, user);
                 if (brothersOrderCalcDOS.isEmpty()) {
                     // 插入空数据
                     brotherBuilder = addBrotherEmpty(brotherBuilder, k);
@@ -293,59 +303,84 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
                     integralDO.setAccumulatedQuota(integralDO.getAccumulatedQuota() + amount);
                     // 碰撞后的额度添加到日志中 增加日志模块
                     integralService.updateIntegral(BeanUtils.toBean(integralDO, IntegralSaveReqVO.class));
-                    Long logId = ptProfitLogService.addMessageFreeze(integralDO.getUserId(),integralDO.getUserId(), CaclEnum.SMALL_QUOTA_CRASH, amount,
+                    Long logId = ptProfitLogService.addMessageFreeze(integralDO.getUserId(), integralDO.getUserId(), CaclEnum.SMALL_QUOTA_CRASH, amount,
                             integralDO.getFreezeQuota(), JsonUtils.toJsonString(orderPercentageDO), ptReplenish, -amount, highQuota - amount);
 
                     //记录每日用户有合赢将的记录,后面用来结算的
-                    dailyAwardRecordsService.addDailyAwardRecords(integralDO.getUserId(),integralDO.getUserId(),amount, logId,ptReplenish);
+                    dailyAwardRecordsService.addDailyAwardRecords(integralDO.getUserId(), integralDO.getUserId(), amount, logId, ptReplenish);
+                }
+                if (!ptReplenish.equals(0L)) {
+                    calcIntegral(ptReplenish, integralDO.getUserId(), JsonUtils.toJsonString(orderPercentageDO));
                 }
 
-                //直推人的上级的本次添加积分
-                Long parentAmount = 0L;
-                //平台需要补回的收益(也可以理解为用户溢出)
-                Long parentPtReplenish = multiply.longValue();
-                //直推人的父级
-                if (multiply.longValue() != 0) {
-                    if (parentHighQuota.compareTo(0L) > 0) {
-                        if (parentHighQuota.compareTo(multiply.longValue()) > 0) {
-                            parentAmount = multiply.longValue();
-                            parentPtReplenish = 0L;
-                        } else {
-                            parentAmount = highQuota;
-                            parentPtReplenish = multiply.longValue() - highQuota;
+                // 获取计算后积分, Long为userId, Integer为碰撞后额度
+                HashMap<Long, Long> map = new HashMap<>();
+
+                // 当用户为游客的时候上级不参与合赢奖
+                if (!user.getVisitor()) {
+                    //直推人的上级的本次添加积分
+                    Long parentAmount = 0L;
+                    //平台需要补回的收益(也可以理解为用户溢出)
+                    Long parentPtReplenish = multiply.longValue();
+                    //直推人的父级
+                    if (multiply.longValue() != 0) {
+                        if (parentHighQuota.compareTo(0L) > 0) {
+                            if (parentHighQuota.compareTo(multiply.longValue()) > 0) {
+                                parentAmount = multiply.longValue();
+                                parentPtReplenish = 0L;
+                            } else {
+                                parentAmount = highQuota;
+                                parentPtReplenish = multiply.longValue() - highQuota;
+                            }
+                            addHighQuota(userHighQuotaMap, parentIntegralDo.getUserId(), parentAmount);
                         }
-                        addHighQuota(userHighQuotaMap, parentIntegralDo.getUserId(), parentAmount);
+                        // 减去最高额度
+                        parentIntegralDo.setHighQuota(parentIntegralDo.getHighQuota() - parentAmount);
+                        parentIntegralDo.setFreezeQuota(parentIntegralDo.getFreezeQuota() + parentAmount);
+
+                        parentIntegralDo.setAccumulatedQuota(parentIntegralDo.getAccumulatedQuota() + parentAmount);
+                        // 碰撞后的额度添加到日志中 增加日志模块
+                        integralService.updateIntegral(BeanUtils.toBean(parentIntegralDo, IntegralSaveReqVO.class));
+                        Long logId = ptProfitLogService.addMessageFreeze(parentIntegralDo.getUserId(), integralDO.getUserId(), CaclEnum.SMALL_QUOTA_CRASH, parentAmount,
+                                parentIntegralDo.getFreezeQuota(), JsonUtils.toJsonString(orderPercentageDO), parentPtReplenish, -parentAmount, parentHighQuota - parentAmount);
+
+                        //记录每日用户有合赢将的记录,后面用来结算的
+                        dailyAwardRecordsService.addDailyAwardRecords(parentIntegralDo.getUserId(), integralDO.getUserId(), parentAmount, logId, parentPtReplenish);
                     }
-                    // 减去最高额度
-                    parentIntegralDo.setHighQuota(parentIntegralDo.getHighQuota() - parentAmount);
-                    parentIntegralDo.setFreezeQuota(parentIntegralDo.getFreezeQuota() + parentAmount);
-
-                    parentIntegralDo.setAccumulatedQuota(parentIntegralDo.getAccumulatedQuota() + parentAmount);
-                    // 碰撞后的额度添加到日志中 增加日志模块
-                    integralService.updateIntegral(BeanUtils.toBean(parentIntegralDo, IntegralSaveReqVO.class));
-                    Long logId = ptProfitLogService.addMessageFreeze(parentIntegralDo.getUserId(),integralDO.getUserId(), CaclEnum.SMALL_QUOTA_CRASH, parentAmount,
-                            parentIntegralDo.getFreezeQuota(), JsonUtils.toJsonString(orderPercentageDO), parentPtReplenish, -parentAmount, parentHighQuota - parentAmount);
 
-                    //记录每日用户有合赢将的记录,后面用来结算的
-                    dailyAwardRecordsService.addDailyAwardRecords(parentIntegralDo.getUserId(),integralDO.getUserId(),parentAmount,logId,parentPtReplenish);
-                }
+                    if (!parentPtReplenish.equals(0L)) {
+                        calcIntegral(parentPtReplenish, parentIntegralDo.getUserId(), JsonUtils.toJsonString(orderPercentageDO));
+                    }
 
-                if (!ptReplenish.equals(0L)) {
-                    calcIntegral(ptReplenish, integralDO.getUserId(), JsonUtils.toJsonString(orderPercentageDO));
-                }
-                if (!parentPtReplenish.equals(0L)) {
-                    calcIntegral(parentPtReplenish, parentIntegralDo.getUserId(), JsonUtils.toJsonString(orderPercentageDO));
+                    if (!parentIntegralDo.getUserId().equals(PT_ID)) {
+                        map.put(parentIntegralDo.getUserId(), parentAmount);
+                    }
+                } else if (multiply.longValue() != 0) {
+                    // 如果当前用户是游客,将上级推荐将加入到游客收益中,不算入到翁总的合赢奖
+                    Long visitorEarnings = multiply.longValue();        //单笔收益
+
+                    // 获取平台的游客收益
+                    PtProfitDO ptProfit = ptProfitService.getPtProfit();
+                    ptProfit.setVisitorEarnings(ptProfit.getVisitorEarnings() + visitorEarnings);
+                    ptProfit.setPtGrossAdd(ptProfit.getPtGrossAdd() - visitorEarnings);
+                    ptProfitService.updatePtProfit(BeanUtils.toBean(ptProfit, PtProfitSaveReqVO.class));
+                    ptIntegralDO.setCurrentQuota(ptIntegralDO.getCurrentQuota() - visitorEarnings);
+
+                    ptProfitLogService.addMessage(parent, CaclEnum.AFTER_CRASH_CALC_PT_TOTAL_QUOTA
+                            , -visitorEarnings, ptProfit.getPtTotalAdd() - visitorEarnings, JsonUtils.toJsonString(orderPercentageDO), null, null, null);
+                    ptProfitLogService.addMessage(parent, CaclEnum.AFTER_CRASH_CALC_PT_TOTAL_GROSS_QUOTA
+                            , -visitorEarnings, ptProfit.getPtGrossAdd(), JsonUtils.toJsonString(orderPercentageDO), null, null, null);
+
+                    // 记录平台游客收益log
+                    ptProfitLogService.addMessage(k.getUserId(), null ,CaclEnum.SMALL_QUOTA_CRASH_SETTLE, visitorEarnings, ptProfit.getVisitorEarnings()
+                    , null, null, JsonUtils.toJsonString(orderPercentageDO),null, null);
                 }
 
-                // 获取计算后积分, Long为userId, Integer为碰撞后额度
-                HashMap<Long, Long> map = new HashMap<>();
                 // 如果为当前用户为平台,则不需要存入这个地方
                 if (!k.getUserId().equals(PT_ID)) {
                     map.put(k.getUserId(), amount);
                 }
-                if (!parentIntegralDo.getUserId().equals(PT_ID)) {
-                    map.put(parentIntegralDo.getUserId(), parentAmount);
-                }
+
                 afterCrashMap.add(map);
 
                 log.info(k.getNickName() + "用户合赢奖已经计算: 该用户合赢奖为: \t" +
@@ -368,7 +403,7 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
         // 计算平台积分
         // 获取当前平台的额度
         PtProfitDO ptProfit = ptProfitService.getPtProfit();
-        IntegralDO ptIntegralDO = integralService.selectByUser(PT_ID);
+
         // 遍历hashMap
         for (HashMap<Long, Long> longIntegerHashMap : afterCrashMap) {
             for (Map.Entry<Long, Long> entry : longIntegerHashMap.entrySet()) {
@@ -538,7 +573,7 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
     }
 
     // 获取昨天的编号
-    public PartitionCrashDO crashYesterdayNo(Long userId,Integer yesterday) {
+    public PartitionCrashDO crashYesterdayNo(Long userId, Integer yesterday) {
         LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT); // 今天的开始时间,即午夜12点
         LocalDateTime localDateTime = todayStart.minusDays(yesterday);
         String yesterdayString = "CRASH:" + userId + ":" + localDateTime;
@@ -549,8 +584,8 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
                 .apply("date(create_time) < date(now())")
         );
         //判断这个用户不是第一次碰撞并且没有查询到昨天的碰撞记录,有可能是昨天或者更早定时任务没有启动导致的,所以再往前查几天
-        if(!partitionCrashDOS.isEmpty() && partitionCrashDO == null){
-            return crashYesterdayNo(userId,++yesterday);
+        if (!partitionCrashDOS.isEmpty() && partitionCrashDO == null) {
+            return crashYesterdayNo(userId, ++yesterday);
         }
 //        return "CRASH:" + userId + ":" + "2024-06-20T00:00";
         return partitionCrashDO;

+ 1 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/ptprofitlog/PtProfitLogServiceImpl.java

@@ -88,6 +88,7 @@ public class PtProfitLogServiceImpl implements PtProfitLogService {
                     ptProfitLogRespVO.getProfitStatus().equals(CaclEnum.ORDER_PAY_INTEGRAL_ANCESTER.getType()) ||
                     ptProfitLogRespVO.getProfitStatus().equals(CaclEnum.ORDER_REFUND_INTEGRAL_ANCESTER.getType()) ||
                     ptProfitLogRespVO.getProfitStatus().equals(CaclEnum.MANUAL_RETURN_INTEGRAL.getType()) ||
+                    ptProfitLogRespVO.getProfitStatus().equals(CaclEnum.SMALL_QUOTA_CRASH_SETTLE.getType()) ||
                     ptProfitLogRespVO.getProfitStatus().equals(SMALL_QUOTA_CRASH.getType())) {
                 ptProfitLogRespVO.setUsername(memberUserService.getUser(ptProfitLogRespVO.getGenerateUserId()).getUsername());
             }

+ 13 - 4
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/sharepath/SharePathService.java

@@ -9,6 +9,8 @@ import cn.newfeifan.mall.module.distri.dal.dataobject.ordercalc.OrderCalcDO;
 import cn.newfeifan.mall.module.distri.dal.dataobject.sharepath.SharePathDO;
 import cn.newfeifan.mall.framework.common.pojo.PageResult;
 import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserRespVO;
+import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
+import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
 
 /**
  * 分销用户关系 Service 接口
@@ -17,7 +19,7 @@ import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserRespVO
  */
 public interface SharePathService {
 
-    void createSharePathByUserId(SharePathSaveReqVO createReqVO);
+    void createSharePathByUserId(SharePathSaveReqVO createReqVO,Boolean isNew);
 
     void createSharePathByUserId(List<Long> userIds);
 
@@ -83,12 +85,12 @@ public interface SharePathService {
     /**
      * 获取兄弟订单分区
      *
-     * @param userId 用户id
+     * @param userId  用户id
      * @param userId1 ids
+     * @param user 用户
      * @return 订单计算
      */
-    List<OrderCalcDO> selectBrothers(Long userId, List<Long> userId1);
-
+    List<OrderCalcDO> selectBrothers(Long userId, List<Long> userId1, MemberUserDO user);
 
     Long queryParentBySonUserId(Long userId);
 
@@ -103,4 +105,11 @@ public interface SharePathService {
     TreeNode getTreeByNameOrMobile(SharePathTreeReqVO sharePathTreeReqVO);
 
     MemberUserRespVO getMemberUser(Long userId);
+
+    /**
+     * 【管理员】更新会员用户
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateUser(MemberUserUpdateReqVO updateReqVO);
 }

+ 71 - 12
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/sharepath/SharePathServiceImpl.java

@@ -15,6 +15,7 @@ import cn.newfeifan.mall.module.distri.service.orderpercentage.OrderPercentageSe
 import cn.newfeifan.mall.module.distri.service.socialstatus.SocialStatusService;
 import cn.newfeifan.mall.module.distri.service.socialstatuschangelog.SocialStatusChangeLogService;
 import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserRespVO;
+import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
 import cn.newfeifan.mall.module.member.convert.user.MemberUserConvert;
 import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
 import cn.newfeifan.mall.module.member.service.user.MemberUserService;
@@ -25,6 +26,7 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import java.math.BigDecimal;
@@ -42,6 +44,7 @@ import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
 import cn.newfeifan.mall.module.distri.dal.mysql.sharepath.SharePathMapper;
 
 import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.module.distri.constant.DistriConstants.BOOS_ID;
 import static cn.newfeifan.mall.module.distri.constant.DistriConstants.PT_ID;
 import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.*;
 
@@ -81,7 +84,7 @@ public class SharePathServiceImpl implements SharePathService {
     private OrderPercentageService orderPercentageService;
 
     @Override
-    public void createSharePathByUserId(SharePathSaveReqVO createReqVO) {
+    public void createSharePathByUserId(SharePathSaveReqVO createReqVO, Boolean isNew) {
 
         // 如果直推人为空, 则直接结束
         if (createReqVO.getDescendant() == null) {
@@ -94,7 +97,7 @@ public class SharePathServiceImpl implements SharePathService {
             throw exception(HAS_PARENT);
         }
         if (createReqVO.getAncestor() == null) {
-            createReqVO.setAncestor(PT_ID);
+            createReqVO.setAncestor(BOOS_ID);
         }
         MemberUserDO ancestor = memberUserService.getUser(createReqVO.getAncestor());
         MemberUserDO descendant = memberUserService.getUser(createReqVO.getDescendant());
@@ -107,16 +110,19 @@ public class SharePathServiceImpl implements SharePathService {
         if (!Objects.equals(createReqVO.getDescendant(), PT_ID)) {
             sharePathMapper.addNode(
                     createReqVO.getAncestor(),
-                    ancestor.getName(),
+                    ancestor.getUsername(),
                     ancestor.getNickname(),
                     ancestor.getMobile(),
 
                     createReqVO.getDescendant(),
-                    descendant.getName(),
+                    descendant.getUsername(),
                     descendant.getNickname(),
                     descendant.getMobile());
         }
 
+        if (!isNew) {
+            return;
+        }
         OrderPercentageDO orderPercentageDO = orderPercentageMapper.selectList().get(0);
         duserService.updateDuserSocial(createReqVO.getAncestor(), Long.valueOf(orderPercentageDO.getRegisterAncestorSocialStatus()), SocialStatusEnum.REGISTER_ANCESTOR_SOCIAL.getStatus());
         socialStatusChangeLogService.createSocialStatusChangeLog(createReqVO.getAncestor(), Long.valueOf(orderPercentageDO.getRegisterAncestorSocialStatus()), createReqVO.getAncestor(), SocialStatusEnum.REGISTER_ANCESTOR_SOCIAL);
@@ -133,10 +139,10 @@ public class SharePathServiceImpl implements SharePathService {
             }
             // 如果是没有父亲, 将其推荐人设置为平台
             SharePathSaveReqVO build = SharePathSaveReqVO.builder()
-                    .ancestor(PT_ID)
+                    .ancestor(BOOS_ID)
                     .descendant(userId)
                     .build();
-            createSharePathByUserId(build);
+            createSharePathByUserId(build, true);
         }
     }
 
@@ -235,14 +241,17 @@ public class SharePathServiceImpl implements SharePathService {
                 .eq(SharePathDO::getDescendant, userId)
                 .eq(SharePathDO::getDepth, 1)
         );
-        if (sharePathDO != null) memberUserRespVO.setAncNickName(sharePathDO.getAncNickName());
+        if (sharePathDO != null) {
+            memberUserRespVO.setAncNickName(sharePathDO.getAncNickName());
+            memberUserRespVO.setRecommenderdId(sharePathDO.getAncestor());
+        }
 
         DuserDO duser = duserService.getDuserByUser(memberUserRespVO.getId());
         //没有这个用户直接就返回
         if (duser == null) return memberUserRespVO;
 
         IntegralDO integral = integralService.getIntegralByUserId(userId);
-        if (integral != null){
+        if (integral != null) {
             memberUserRespVO.setCurrentQuota(integral.getCurrentQuota());
             OrderPercentageDO orderPercentageDO = orderPercentageService.queryStatus();
             memberUserRespVO.setHighQuotaTotal(integral.getHighQuotaTotal() + new BigDecimal(orderPercentageDO.getBaseMaxQuota()).longValue());
@@ -257,6 +266,54 @@ public class SharePathServiceImpl implements SharePathService {
         return memberUserRespVO;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateUser(MemberUserUpdateReqVO updateReqVO) {
+        // 判断当前用户是否更新推荐人
+        Long ancestor = sharePathMapper.selectAncestorByDescendant(updateReqVO.getId());
+        if (!Objects.equals(updateReqVO.getRecommenderdId(), ancestor)) {
+            // 如果用户为游客,将清除游客标识
+            updateReqVO.setVisitor(false);
+
+            // 如果有更新的话,要清除原来的关系树
+            List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapper<SharePathDO>()
+                    .eq(SharePathDO::getAncestor, updateReqVO.getId()));
+            List<SharePathDO> sharePathDOS1;
+            List<SharePathDO> children = null;
+            if (!sharePathDOS.isEmpty()) {
+                sharePathDOS1 = sharePathMapper.selectList(new LambdaQueryWrapper<SharePathDO>()
+                        .in(SharePathDO::getDescendant, sharePathDOS.stream().map(SharePathDO::getDescendant).collect(Collectors.toList())));
+                children = sharePathMapper.selectList(new LambdaQueryWrapper<SharePathDO>()
+                        .in(SharePathDO::getDescendant, sharePathDOS.stream().map(SharePathDO::getDescendant).collect(Collectors.toList()))
+                        .eq(SharePathDO::getDepth, 1));
+                // 逻辑删除旧的关系树
+                sharePathMapper.deleteBatchIds(sharePathDOS1.stream().map(SharePathDO::getId).collect(Collectors.toList()));
+            }
+            sharePathMapper.delete(new LambdaQueryWrapper<SharePathDO>()
+                    .eq(SharePathDO::getDescendant, updateReqVO.getId()));
+
+            // 添加新的关系树
+            createSharePathByUserId(SharePathSaveReqVO.builder().ancestor(updateReqVO.getRecommenderdId()).descendant(updateReqVO.getId()).build(), false);
+
+            if (children != null && !children.isEmpty()) for (SharePathDO child : children) {
+                createSharePathByUserId(SharePathSaveReqVO.builder().ancestor(child.getAncestor()).descendant(child.getDescendant()).build(), false);
+            }
+
+        }
+
+        // 更新
+        memberUserService.updateUser(updateReqVO);
+    }
+
+    private void createSharePath(List<TreeNode> children) {
+        for (TreeNode child : children) {
+            createSharePathByUserId(SharePathSaveReqVO.builder().ancestor(child.getParentId()).descendant(child.getUserId()).build(), false);
+            if (child.getChildren() != null) {
+                createSharePath(child.getChildren());
+            }
+        }
+    }
+
     private Long getUserIdByNameOrMobile(String name, String mobile) {
         if (!StringUtils.isEmpty(name)) {
             List<DuserDO> duserDOS = duserService.getDuserByName(name);
@@ -355,7 +412,7 @@ public class SharePathServiceImpl implements SharePathService {
     }
 
     @Override
-    public List<OrderCalcDO> selectBrothers(Long userId, List<Long> userIds) {
+    public List<OrderCalcDO> selectBrothers(Long userId, List<Long> userIds, MemberUserDO user) {
         List<Long> sortedSiblings = new ArrayList<>();
         // 先查询出他的父亲
         List<SharePathDO> sharePathDO = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>().eq(SharePathDO::getDepth, 1).eq(SharePathDO::getDescendant, userId));
@@ -363,9 +420,11 @@ public class SharePathServiceImpl implements SharePathService {
             sortedSiblings = sharePathMapper.findLessSortedSiblings(userId);
         } else {
             // 再根据父亲查询他的所有儿子
-            List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>()
-                    .eq(SharePathDO::getDepth, 1)
-                    .eq(SharePathDO::getAncestor, sharePathDO.get(0).getAncestor()));
+//            List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>()
+//                    .eq(SharePathDO::getDepth, 1)
+//                    .eq(SharePathDO::getAncestor, sharePathDO.get(0).getAncestor()));
+            // 后续加了游客身份所以,查询的时候要隔离游客的兄弟分区和用户的兄弟分区
+            List<SharePathDO> sharePathDOS = sharePathMapper.selectListByVisitor(sharePathDO.get(0).getAncestor(), user.getVisitor());
             //最后再进行排序
             sortedSiblings = filterByDescendant(sharePathDOS, userId);
             // 查询兄弟的所有儿子

+ 9 - 3
feifan-module-distri/feifan-module-distri-biz/src/main/resources/mapper/sharepath/SharePathMapper.xml

@@ -25,9 +25,9 @@
                #{newDescendantMobile},
 
                depth + 1,
-               (SELECT IFNULL(MAX(sort), 0) + 1 FROM distri_share_path WHERE ancestor = #{parentId} AND depth = 1)
+               (SELECT IFNULL(MAX(sort), 0) + 1 FROM distri_share_path WHERE ancestor = #{parentId} AND depth = 1 and deleted = 0)
         FROM distri_share_path
-        WHERE descendant = #{parentId}
+        WHERE descendant = #{parentId} and deleted = 0
         UNION ALL
         SELECT #{parentId},
                #{parentName},
@@ -39,7 +39,7 @@
                #{newDescendantNickName},
                #{newDescendantMobile},
                1,
-               (SELECT IFNULL(MAX(sort), 0) + 1 FROM distri_share_path WHERE ancestor = #{parentId} AND depth = 1);
+               (SELECT IFNULL(MAX(sort), 0) + 1 FROM distri_share_path WHERE ancestor = #{parentId} AND depth = 1 and deleted = 0);
     </insert>
 
 
@@ -144,4 +144,10 @@
             current_depth <![CDATA[<=]]> #{maxDepth};
 
     </select>
+    <select id="selectListByVisitor"
+            resultType="cn.newfeifan.mall.module.distri.dal.dataobject.sharepath.SharePathDO">
+        select path.* from distri_share_path path
+                    left join member_user user on user.id = path.descendant
+                    where depth = 1 and ancestor = #{ancestor} and user.visitor = #{visitor} and path.deleted = 0
+    </select>
 </mapper>

+ 1 - 1
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/mysql/spuapply/SpuApplyMapper.java

@@ -64,7 +64,7 @@ public interface SpuApplyMapper extends BaseMapperX<SpuApplyDO> {
                 .eqIfPresent(SpuApplyDO::getCheckComment, reqVO.getCheckComment())
                 .orderByDesc(SpuApplyDO::getId);
 
-        if(reqVO.getCheckStatus().equals(1)){
+        if(reqVO.getCheckStatus() != null && reqVO.getCheckStatus().equals(1)){
             wrapper.ne(SpuApplyDO::getCheckStatus, 0);
         }else{
             wrapper.eq(SpuApplyDO::getCheckStatus, 0);

+ 22 - 3
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateServiceImpl.java

@@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.extra.spring.SpringUtil;
+import cn.hutool.json.JSONUtil;
 import cn.newfeifan.mall.framework.common.core.KeyValue;
 import cn.newfeifan.mall.framework.common.enums.UserTypeEnum;
 import cn.newfeifan.mall.framework.common.util.json.JsonUtils;
@@ -30,6 +31,7 @@ import cn.newfeifan.mall.module.distri.service.ptprofitlog.PtProfitLogService;
 import cn.newfeifan.mall.module.distri.service.sharepath.SharePathService;
 import cn.newfeifan.mall.module.member.api.address.MemberAddressApi;
 import cn.newfeifan.mall.module.member.api.address.dto.MemberAddressRespDTO;
+import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
 import cn.newfeifan.mall.module.member.service.user.MemberUserService;
 import cn.newfeifan.mall.module.pay.api.order.PayOrderApi;
 import cn.newfeifan.mall.module.pay.api.order.dto.PayOrderCreateReqDTO;
@@ -1129,6 +1131,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         //20240604 推荐人(上级用户ID)
         Long ancesterUserId = tradeOrderMapper.selectAncesterByMemberUserId(memberUserIdOfTradeOrder);
 
+        // 当前订单用户
+        MemberUserDO user = memberUserService.getUser(memberUserIdOfTradeOrder);
+
         for (TradeOrderDO tradeOrderDO : TradeOrderDOList) {
 
             Long tradeOrderId = tradeOrderDO.getId();
@@ -1234,8 +1239,22 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             //修改购物者本人获得的冻结积分
             integralService.updateUserIntegral(tradeOrderDO.getUserId(), tradeOrderDO.getUserId(), CaclEnum.ORDER_PAY_INTEGRAL_CONSUMER, 0L, totalFreezeAmount, tradeOrderId, OrderNum);
 
-            //修改推荐人(上级)获得的冻结积分
-            integralService.updateUserIntegral(tradeOrderDO.getUserId(), ancesterUserId, CaclEnum.ORDER_PAY_INTEGRAL_ANCESTER, 0L, totalAncestorFreezeAmount, tradeOrderId, OrderNum);
+            // 如果用户不是游客才会分配直推将,否者是计算到游客收益中的
+            if (!user.getVisitor()) {
+                //修改推荐人(上级)获得的冻结积分
+                integralService.updateUserIntegral(tradeOrderDO.getUserId(), ancesterUserId, CaclEnum.ORDER_PAY_INTEGRAL_ANCESTER, 0L, totalAncestorFreezeAmount, tradeOrderId, OrderNum);
+            } else {
+                // 游客收益
+                PtProfitDO ptProfitDO = ptProfitService.getPtProfit();
+
+                ptProfitDO.setVisitorEarnings(ptProfitDO.getVisitorEarnings() + totalAncestorFreezeAmount);
+                ptProfitDO.setPtTotalAdd(ptProfitDO.getPtTotalAdd() + totalAncestorFreezeAmount);
+                ptProfitService.updatePtProfit(cn.newfeifan.mall.framework.common.util.object.BeanUtils.toBean(ptProfitDO, PtProfitSaveReqVO.class));
+
+                // 记录日志
+                ptProfitLogService.addMessage(user.getId(), null, CaclEnum.RECOMMENDED_PERSON_QUOTA, totalAncestorFreezeAmount,
+                        ptProfitDO.getVisitorEarnings(), null, null, JSONUtil.toJsonStr(orderPercentageDO), tradeOrderId, OrderNum);
+            }
 
             //修改购物者本人获得的冻结峰值
             integralService.updateIntegralFreezeHighQuota(tradeOrderDO.getUserId(), tradeOrderDO.getUserId(), CaclEnum.ORDER_PAY_FREEZE_HIGH_QUOTA, totalFreezeHighQuota, tradeOrderId, OrderNum);
@@ -1245,7 +1264,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             // 发送给微信消息给系统用户待发货消息
             sentWcChatMessage(order);
 
-            // 发送给极光推送给系统用户发货消息
+            // 发送给极光推送给系统用户发货消息
             sentJPush(order);
         }
 

+ 3 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/admin/user/vo/MemberUserBaseVO.java

@@ -115,4 +115,7 @@ public class MemberUserBaseVO {
     @Schema(description = "是否代理商")
     private Boolean agent;
 
+    @Schema(description = "是否是游客 0:否 1:是")
+    private Boolean visitor;
+
 }

+ 4 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/dataobject/user/MemberUserDO.java

@@ -221,5 +221,9 @@ public class MemberUserDO extends TenantBaseDO {
      * 是否是代理商 0:否 1:是
      */
     private Boolean agent;
+    /**
+     * 是否是游客 0:否 1:是
+     */
+    private Boolean visitor;
 
 }

+ 4 - 4
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/sms/SmsCodeServiceImpl.java

@@ -73,10 +73,10 @@ public class SmsCodeServiceImpl implements SmsCodeService {
         // 校验是否可以发送验证码,不用筛选场景
         SmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, null, null);
         if (lastSmsCode != null) {
-            if (LocalDateTimeUtil.between(lastSmsCode.getCreateTime(), LocalDateTime.now()).toMillis()
-                    < smsCodeProperties.getSendFrequency().toMillis()) { // 发送过于频繁
-                throw exception(SMS_CODE_SEND_TOO_FAST);
-            }
+//            if (LocalDateTimeUtil.between(lastSmsCode.getCreateTime(), LocalDateTime.now()).toMillis()
+//                    < smsCodeProperties.getSendFrequency().toMillis()) { // 发送过于频繁
+//                throw exception(SMS_CODE_SEND_TOO_FAST);
+//            }
             if (isToday(lastSmsCode.getCreateTime()) && // 必须是今天,才能计算超过当天的上限
                     lastSmsCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。
                 throw exception(SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY);

+ 4 - 1
sql/mysql/建空库SQL/25_20241011.sql

@@ -25,4 +25,7 @@ ALTER TABLE distri_order_percentage
     ADD COLUMN `agent_quota` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '成为代理商所需金额';
 
 ALTER TABLE member_user
-    ADD COLUMN `agent` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否是代理商 0:否 1:是';
+    ADD COLUMN `agent` bit(1) DEFAULT b'0' COMMENT '是否是代理商 0:否 1:是';
+
+ALTER TABLE member_user
+    ADD COLUMN `visitor` bit(1) DEFAULT b'0' COMMENT '是否是游客 0:否 1:是';