src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java
@@ -6,6 +6,12 @@ @Getter public enum DataDictionaryEnum { // 用户层级 MEMBER_LEVEL_ONE("MEMBER_LEVEL_CODE", "MEMBER_LEVEL_ONE"), MEMBER_LEVEL_TWO("MEMBER_LEVEL_CODE", "MEMBER_LEVEL_TWO"), // 用户佣金比例最小最大值 MEMBER_LEVEL_PERCENT_MIN("MEMBER_LEVEL_PERCENT_MIN", "MEMBER_LEVEL_PERCENT_MIN"), MEMBER_LEVEL_PERCENT_MAX("MEMBER_LEVEL_PERCENT_MAX", "MEMBER_LEVEL_PERCENT_MAX"), // 发票的通知回调路径 FP_CALLBACK_URL("FP_CALLBACK_URL", "FP_CALLBACK_URL"), //微信订阅模板ID, src/main/java/cc/mrbird/febs/common/enumerates/ScoreFlowTypeEnum.java
@@ -8,6 +8,7 @@ /** * */ LEVEL_PERK(4, "订单编号:{}的佣金"), PAY(1, "积分支付"), BUY(2, "购买商品获得积分"), src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java
@@ -88,6 +88,14 @@ return memberService.teamList(teamListDto); } @ApiOperation(value = "我的团队-更新用户层级和佣金比例") @PostMapping(value = "/levelUpdate") public FebsResponse levelUpdate(@RequestBody ApiLevelUpdateDto apiLevelUpdateDto) { return memberService.levelUpdate(apiLevelUpdateDto); } @ApiOperation(value = "资金流水列表") @ApiResponses({ src/main/java/cc/mrbird/febs/mall/dto/ApiLevelUpdateDto.java
New file @@ -0,0 +1,26 @@ package cc.mrbird.febs.mall.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.math.BigDecimal; @Data @ApiModel(value = "ApiLevelUpdateDto", description = "参数接收类") public class ApiLevelUpdateDto { @NotNull(message = "层级ID不能为空") @ApiModelProperty(value = "层级ID", example = "1") private Long levelId; @NotNull(message = "层级不能为空") @ApiModelProperty(value = "层级", example = "1") private Integer levelCode; @NotNull(message = "佣金比例不能为空") @ApiModelProperty(value = "佣金比例", example = "10") private BigDecimal levelPercent; } src/main/java/cc/mrbird/febs/mall/entity/MallMemberLevel.java
New file @@ -0,0 +1,20 @@ package cc.mrbird.febs.mall.entity; import cc.mrbird.febs.common.entity.BaseEntity; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.math.BigDecimal; @Data @TableName("mall_member_level") public class MallMemberLevel extends BaseEntity { private Long memberId; private Integer levelCode;//等级编码 private BigDecimal levelPercent;//佣金比例 } src/main/java/cc/mrbird/febs/mall/mapper/MallMemberLevelMapper.java
New file @@ -0,0 +1,7 @@ package cc.mrbird.febs.mall.mapper; import cc.mrbird.febs.mall.entity.MallMemberLevel; import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface MallMemberLevelMapper extends BaseMapper<MallMemberLevel> { } src/main/java/cc/mrbird/febs/mall/mapper/MallOrderInfoMapper.java
@@ -84,6 +84,12 @@ @SqlParser(filter = true) IPage<AdminGoodsStatisticsVo> getGoodsStatisticsInPage(Page<AdminGoodsStatisticsVo> page, @Param("record") MallOrderItem mallOrderItem); /** * * @param inviteId * @param type 1-查询自己 2-查询我的直推 * @return */ BigDecimal selectAmountOrTeamAmount(@Param("inviteId") String inviteId, @Param("type") Integer type); MallOrderInfo selectBypayOrderNo(@Param("payOrderNo")String payOrderNo); src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java
@@ -107,4 +107,6 @@ FebsResponse bindList(); FebsResponse bindResult(BindResultDto bindResultDto); FebsResponse levelUpdate(ApiLevelUpdateDto apiLevelUpdateDto); } src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsCategoryService.java
@@ -78,6 +78,7 @@ goodsCategory.setParentId(0L); goodsCategory.setIsRecommend(mallGoodsCategory.getIsRecommend()); } goodsCategory.setIndexNum(mallGoodsCategory.getIndexNum()); mallGoodsCategoryMapper.insert(goodsCategory); return new FebsResponse().success(); } src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
@@ -95,6 +95,7 @@ private final MallStoreMapper mallStoreMapper; private final MallStoreItemMapper mallStoreItemMapper; private final MallStoreMemberMapper mallStoreMemberMapper; private final MallMemberLevelMapper mallMemberLevelMapper; @Value("${spring.profiles.active}") @@ -379,12 +380,30 @@ MallMember mallMember = this.baseMapper.selectById(memberId); List<TeamListVo> list = this.baseMapper.selectTeamListByInviteId(mallMember.getInviteId()); if(CollUtil.isNotEmpty(list)){ for(TeamListVo teamListVo : list){ String levelName = ""; if(1 == teamListVo.getLevelCode()){ levelName = "一级"; }else if(2 == teamListVo.getLevelCode()){ levelName = "二级"; } teamListVo.setLevelName(levelName); } } QueryWrapper<MallMemberLevel> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("member_id",memberId); MallMemberLevel mallMemberLevel = mallMemberLevelMapper.selectOne(queryWrapper); MyTeamVo myTeamVo = new MyTeamVo(); myTeamVo.setLevelPercent(mallMemberLevel.getLevelPercent()); myTeamVo.setLevelCode(mallMemberLevel.getLevelCode()); myTeamVo.setTeam(list); myTeamVo.setMyAchieve(this.mallOrderInfoMapper.selectAmountOrTeamAmount(mallMember.getInviteId(), 1)); myTeamVo.setMyTeamAchieve(this.mallOrderInfoMapper.selectAmountOrTeamAmount(mallMember.getInviteId(), 2)); myTeamVo.setMyTeamCnt(this.baseMapper.selectAllChildAgentListByInviteId(mallMember.getInviteId()).size()); List<MallMember> mallMembers = this.baseMapper.selectChildAgentListByInviteId(mallMember.getInviteId()); myTeamVo.setMyTeamCnt(CollUtil.isEmpty(mallMembers) ? 0 : mallMembers.size()); return new FebsResponse().success().data(myTeamVo); } @@ -674,6 +693,12 @@ } } this.baseMapper.insert(mallMember); MallMemberLevel mallMemberLevel = new MallMemberLevel(); mallMemberLevel.setMemberId(mallMember.getId()); mallMemberLevel.setLevelCode(0); mallMemberLevel.setLevelPercent(BigDecimal.ZERO); mallMemberLevelMapper.insert(mallMemberLevel); mallMember = this.baseMapper.selectMemberByOpenId(openId); String inviteId = ShareCodeUtil.toSerialCode(mallMember.getId()); @@ -1307,6 +1332,52 @@ return new FebsResponse().success().data(data); } @Override public FebsResponse levelUpdate(ApiLevelUpdateDto apiLevelUpdateDto) { Long levelId = apiLevelUpdateDto.getLevelId(); MallMemberLevel mallMemberLevel = mallMemberLevelMapper.selectById(levelId); if(ObjectUtil.isEmpty(mallMemberLevel)){ throw new FebsException("记录不存在"); } DataDictionaryCustom memberLevelOneDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( DataDictionaryEnum.MEMBER_LEVEL_ONE.getType(), DataDictionaryEnum.MEMBER_LEVEL_ONE.getCode() ); if(Integer.parseInt(memberLevelOneDic.getValue()) != mallMemberLevel.getLevelCode()){ throw new FebsException(StrUtil.format("{}才能设置层级和佣金比例}", memberLevelOneDic.getDescription())); } DataDictionaryCustom memberLevelTwoDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( DataDictionaryEnum.MEMBER_LEVEL_TWO.getType(), DataDictionaryEnum.MEMBER_LEVEL_TWO.getCode() ); Integer levelCode = apiLevelUpdateDto.getLevelCode(); if(Integer.parseInt(memberLevelTwoDic.getValue()) != levelCode){ throw new FebsException(StrUtil.format("当前用户只能设置{}}", memberLevelTwoDic.getDescription())); } DataDictionaryCustom minPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( DataDictionaryEnum.MEMBER_LEVEL_PERCENT_MIN.getType(), DataDictionaryEnum.MEMBER_LEVEL_PERCENT_MIN.getCode() ); DataDictionaryCustom maxPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( DataDictionaryEnum.MEMBER_LEVEL_PERCENT_MAX.getType(), DataDictionaryEnum.MEMBER_LEVEL_PERCENT_MAX.getCode() ); BigDecimal minPercent = new BigDecimal(minPercentDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN); BigDecimal maxPercent = new BigDecimal(maxPercentDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN); BigDecimal levelPercent = apiLevelUpdateDto.getLevelPercent(); if(levelPercent.compareTo(minPercent) < 0 || levelPercent.compareTo(maxPercent) > 0){ throw new FebsException(StrUtil.format("佣金比例必须在{}和{}之间。", minPercent,maxPercent)); } mallMemberLevel.setLevelCode(levelCode); mallMemberLevel.setLevelPercent(levelPercent); mallMemberLevelMapper.updateById(mallMemberLevel); return new FebsResponse().success().message("操作成功"); } public static void main(String[] args) { Long userld = 173L; String shopAccount = "luohu"; src/main/java/cc/mrbird/febs/mall/vo/MyTeamVo.java
@@ -11,15 +11,21 @@ @ApiModel(value = "MyTeamVo", description = "我的团队返回参数类") public class MyTeamVo { @ApiModelProperty(value = "我的业绩") @ApiModelProperty(value = "个人业绩") private BigDecimal myAchieve; @ApiModelProperty(value = "我的团队业绩") @ApiModelProperty(value = "团队业绩") private BigDecimal myTeamAchieve; @ApiModelProperty(value = "团队数量") @ApiModelProperty(value = "团队总数") private int myTeamCnt; @ApiModelProperty(value = "层级编码 1-可以设置团队的佣金比例和层级 2-不能设置") private Integer levelCode; @ApiModelProperty(value = "佣金比例") private BigDecimal levelPercent; @ApiModelProperty(value = "团队列表") private List<TeamListVo> team; } src/main/java/cc/mrbird/febs/mall/vo/TeamListVo.java
@@ -19,45 +19,34 @@ @ApiModelProperty(value = "用户ID") private Long id; @ApiModelProperty(value = "邀请码") private String inviteId; @ApiModelProperty(value = "昵称") private String name; @ApiModelProperty(value = "等级ID") private Long levelId; @ApiModelProperty(value = "头像") private String avatar; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @ApiModelProperty(value = "注册时间") private Date createTime; @ApiModelProperty(value = "手机号") private String phone; @ApiModelProperty(value = "金额") private BigDecimal amount; @ApiModelProperty(value = "订单数量") private Integer orderCnt; @ApiModelProperty(value = "团队数量") private Integer cnt; @ApiModelProperty(value = "昵称") private String name; @ApiModelProperty(value = "注册时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createdTime; @ApiModelProperty(value = "是否当前用户 1-是") private Integer isCurrent; @ApiModelProperty(value = "手机号") private String phone; @ApiModelProperty(value = "竞猜积分") private BigDecimal prizeScore; @ApiModelProperty(value = "层级编码") private Integer levelCode; @ApiModelProperty(value = "用户等级") @ApiModelProperty(value = "层级") private String levelName; @ApiModelProperty(value = "自己下单数量") private Integer selfOrderCnt; @ApiModelProperty(value = "佣金比例") private BigDecimal levelPercent; @ApiModelProperty(value = "推荐人数") private Integer cnt; @ApiModelProperty(value = "消费金额") private BigDecimal amount; } src/main/java/cc/mrbird/febs/vip/service/impl/VipCommonServiceImpl.java
@@ -3,10 +3,8 @@ import cc.mrbird.febs.common.enumerates.FlowTypeEnum; import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum; import cc.mrbird.febs.common.enumerates.ScoreFlowTypeEnum; import cc.mrbird.febs.mall.entity.MallGoods; import cc.mrbird.febs.mall.entity.MallMember; import cc.mrbird.febs.mall.entity.MallOrderInfo; import cc.mrbird.febs.mall.entity.MallOrderItem; import cc.mrbird.febs.mall.entity.*; import cc.mrbird.febs.mall.mapper.MallMemberLevelMapper; import cc.mrbird.febs.mall.mapper.MallMemberMapper; import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; import cc.mrbird.febs.mall.service.IApiMallGoodsService; @@ -21,8 +19,10 @@ import cc.mrbird.febs.vip.service.IVipCommonService; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -50,6 +50,7 @@ private final MallVipConfigMapper mallVipConfigMapper; private final AgentProducer agentProducer; private final IApiMallGoodsService mallGoodsService; private final MallMemberLevelMapper mallMemberLevelMapper; @Override @Transactional(rollbackFor = Exception.class) @@ -58,60 +59,61 @@ if (mallOrderInfo == null) { return; } BigDecimal amount = mallOrderInfo.getAmount(); Long memberId = mallOrderInfo.getMemberId(); MallVipBenefits mallVipBenefits = mallVipConfigService.hasVipBenefits(memberId); MallMember member = mallMemberMapper.selectById(memberId); BigDecimal multiple = BigDecimal.ONE; String name = ""; if (mallVipBenefits != null) { multiple = mallVipBenefits.getScoreMultiple(); name = mallVipBenefits.getName(); /** * 一级返佣 */ String referrerId = member.getReferrerId(); if(StrUtil.isEmpty(referrerId)){ return; } MallMember mallMemberRef = mallMemberMapper.selectInfoByInviteId(referrerId); QueryWrapper<MallMemberLevel> mallMemberLevelQueryWrapper = new QueryWrapper<>(); mallMemberLevelQueryWrapper.eq("member_id",mallMemberRef.getId()); MallMemberLevel mallMemberLevelRef = mallMemberLevelMapper.selectOne(mallMemberLevelQueryWrapper); if(ObjectUtil.isNotEmpty(mallMemberLevelRef)){ BigDecimal levelPercent = mallMemberLevelRef.getLevelPercent(); BigDecimal refAmount = amount.multiply(levelPercent.multiply(new BigDecimal(0.01))).setScale(2, BigDecimal.ROUND_DOWN); mallMemberWalletService.addBalance(refAmount,mallMemberRef.getId()); mallMoneyFlowService.addMoneyFlow( mallMemberRef.getId(), refAmount, ScoreFlowTypeEnum.LEVEL_PERK.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.BALANCE.getValue(), StrUtil.format(ScoreFlowTypeEnum.LEVEL_PERK.getDesc(),mallOrderInfo.getOrderNo()), 2); } List<String> skuNames = mallOrderInfo.getItems().stream().map(MallOrderItem::getSkuName).collect(Collectors.toList()); double sum = mallOrderInfo.getItems().stream().map(MallOrderItem::getAmount).mapToDouble(BigDecimal::doubleValue).sum(); /** * 两级返佣 */ String referrerIdRef = mallMemberRef.getReferrerId(); if(StrUtil.isEmpty(referrerIdRef)){ return; } MallMember mallMemberRefTwo = mallMemberMapper.selectInfoByInviteId(referrerIdRef); QueryWrapper<MallMemberLevel> mallMemberLevelQueryWrapperTwo = new QueryWrapper<>(); mallMemberLevelQueryWrapperTwo.eq("member_id",mallMemberRefTwo.getId()); MallMemberLevel mallMemberLevelRefTwo = mallMemberLevelMapper.selectOne(mallMemberLevelQueryWrapperTwo); if(ObjectUtil.isNotEmpty(mallMemberLevelRefTwo)){ BigDecimal levelPercentTwo = mallMemberLevelRefTwo.getLevelPercent(); int score = multiple.multiply(BigDecimal.valueOf(sum)).intValue(); mallMoneyFlowService.addMoneyFlow(memberId, new BigDecimal(score), ScoreFlowTypeEnum.BUY.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), CollUtil.join(skuNames, ","), 2); mallMemberWalletService.add(new BigDecimal(score), memberId, "prizeScore"); List<Long> itemGoodsIds = mallOrderInfo.getItems().stream().map(MallOrderItem::getGoodsId).distinct().collect(Collectors.toList()); List<MallGoods> goodsList = mallGoodsService.listByIds(itemGoodsIds); Map<Long, MallGoods> goodsMap = goodsList.stream().collect(Collectors.toMap(MallGoods::getId, MallGoods -> MallGoods)); Map<Long, BigDecimal> recommendScoreMap = new HashMap<>(); mallOrderInfo.getItems().forEach(item -> { if (StrUtil.isNotBlank(item.getMemberInviteId()) && !member.getInviteId().equals(item.getMemberInviteId())) { MallGoods mallGoods = goodsMap.get(item.getGoodsId()); if (mallGoods.getStaticMulti() == null) { return; } BigDecimal multi = mallGoods.getStaticMulti().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); MallMember mallMember = mallMemberMapper.selectInfoByInviteId(item.getMemberInviteId()); if (mallMember == null) { return; } BigDecimal recommendScore = recommendScoreMap.get(mallMember.getId()); recommendScore = recommendScore == null ? BigDecimal.ZERO : recommendScore; recommendScore = recommendScore.add(item.getAmount().multiply(multi)); recommendScoreMap.put(mallMember.getId(), recommendScore); } }); recommendScoreMap.forEach((key, value) -> { if (value != null) { mallMoneyFlowService.addMoneyFlow(key, value, ScoreFlowTypeEnum.RECOMMEND.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), CollUtil.join(skuNames, ","), 2); mallMemberWalletService.add(value, key, "prizeScore"); } }); agentProducer.sendVipLevelUp(orderId); BigDecimal refAmountTwo = amount.multiply(levelPercentTwo.multiply(new BigDecimal(0.01))).setScale(2, BigDecimal.ROUND_DOWN); mallMemberWalletService.addBalance(refAmountTwo,mallMemberRefTwo.getId()); mallMoneyFlowService.addMoneyFlow( mallMemberRefTwo.getId(), refAmountTwo, ScoreFlowTypeEnum.LEVEL_PERK.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.BALANCE.getValue(), StrUtil.format(ScoreFlowTypeEnum.LEVEL_PERK.getDesc(),mallOrderInfo.getOrderNo()), 2); } } @Override src/main/resources/application-dev.yml
@@ -15,10 +15,10 @@ datasource: # 数据源-1,名称为 base base: username: db_blnka password: blnka!@#123 username: store_basic password: store_basic321 driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://121.37.162.173:3306/db_blnka?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 url: jdbc:mysql://120.27.238.55:3406/store_basic?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 redis: # Redis数据库索引(默认为 0) src/main/resources/application.yml
@@ -5,7 +5,7 @@ spring: profiles: active: test active: dev servlet: multipart: src/main/resources/mapper/modules/MallMemberMapper.xml
@@ -80,23 +80,23 @@ <select id="selectTeamListByInviteId" resultType="cc.mrbird.febs.mall.vo.TeamListVo"> select a.id, a.name, a.phone, a.invite_id, 2 isCurrent, a.created_time, a.avatar, (select count(1) from mall_order_info orderInfo where orderInfo.status in (2, 3, 4) and orderInfo.member_id=a.id) selfOrderCnt, a.name, a.created_time, a.phone, b.id levelId, b.level_code levelCode, b.level_percent levelPercent, (select sum(e.amount) from mall_order_info e inner join mall_member b on e.member_id=b.ID where e.status in (2, 3, 4) and e.order_type=1 and (b.invite_id=a.invite_id or b.referrer_id=a.invite_id)) amount, (select count(1) from mall_member e inner join mall_order_info b on e.id=b.member_id and b.status in (2, 3, 4) where find_in_set(a.invite_id, e.referrer_ids) or a.invite_id=e.invite_id) orderCnt, (select count(1) from mall_member x where find_in_set(a.invite_id, x.referrer_ids)) cnt inner join mall_member c on e.member_id = c.id where e.status = 4 and c.referrer_id = a.invite_id) amount, (select count(1) from mall_member x where x.referrer_id = a.invite_id) cnt from mall_member a left join mall_member_level b on a.id = b.member_id where a.referrer_id=#{inviteId} </select> src/main/resources/mapper/modules/MallOrderInfoMapper.xml
@@ -458,12 +458,12 @@ select IFNULL(sum(IFNULL(a.amount,0)),0) from mall_order_info a inner join mall_member b on a.member_id=b.ID <where> a.status in (2,3,4) a.status = 4 <if test="type == 1"> and b.invite_id=#{inviteId} </if> <if test="type == 2"> and FIND_IN_SET(#{inviteId},b.referrer_ids) and b.referrer_id=#{inviteId} </if> </where> </select> src/main/resources/templates/febs/views/modules/product/categoryAdd.html
@@ -72,6 +72,13 @@ <input type="radio" name="isRecommend" value="2" title="否" checked=""> </div> </div> <div class="layui-form-item"> <label class="layui-form-label febs-form-item-require">排序:</label> <div class="layui-input-block"> <input type="number" name="indexNum" lay-verify="indexNum" autocomplete="off" class="layui-input" > </div> </div> <div class="layui-form-item febs-hide"> <button class="layui-btn" lay-submit="" lay-filter="categary-add-form-submit" id="submit"></button> </div> src/main/resources/templates/febs/views/modules/product/categoryList.html
@@ -153,6 +153,7 @@ id: 'userTable', url: ctx + 'admin/goodsCategory/categoryList', cols: [[ {type: 'numbers'}, {field: 'name', title: '名称', minWidth: 150,align:'left'}, {field: 'parentName', title: '父级名称', minWidth: 150,align:'left'}, {field: 'image', title: '图片',