src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java
@@ -171,6 +171,24 @@ } @Bean public DirectExchange saleLevelUp() { return new DirectExchange(RabbitQueueEnum.SALE_LEVEL_UP.getExchange()); } @Bean public Queue saleLevelUpQueue() { return new Queue(RabbitQueueEnum.SALE_LEVEL_UP.getQueue()); } @Bean public Binding saleLevelUpBind() { return BindingBuilder.bind(saleLevelUpQueue()).to(saleLevelUp()).with(RabbitQueueEnum.SALE_LEVEL_UP.getRoute()); } @Bean public DirectExchange activityOrderCheckExchange() { return new DirectExchange(RabbitQueueEnum.ACTIVITY_ORDER_ITEM_CHECK.getExchange()); src/main/java/cc/mrbird/febs/common/enumerates/FlowTypeEnum.java
@@ -15,11 +15,11 @@ */ BALANCE(1), /** * 积分 * 会员升级经验 */ SCORE(2), /** * 竞猜积分 * 积分 */ PRIZE_SCORE(3), /** src/main/java/cc/mrbird/febs/common/enumerates/ScoreFlowTypeEnum.java
@@ -8,9 +8,13 @@ /** * */ SALE_RECOMMEND(6, "好友下单获得佣金"), OTHER_RECOMMEND(5, "推荐下单获得积分"), MINE_RECOMMEND(4, "下单获得积分"), PAY(1, "积分支付"), BUY(2, "购买商品获得积分"), BUY(2, "购买商品,获得等级经验"), RECOMMEND(3, "推荐下单获得积分"); @@ -29,7 +33,6 @@ return scoreFlowTypeEnum.getDesc(); } } return ""; } src/main/java/cc/mrbird/febs/mall/controller/banner/ApiMallNewsController.java
@@ -23,7 +23,7 @@ @RestController @RequestMapping(value = "/api/news") @RequiredArgsConstructor @Api(value = "ApiMallNewsController", tags = "新闻接口类") @Api(value = "ApiMallNewsController", tags = "365轮播广告接口类") public class ApiMallNewsController { private final IApiMallNewsService newsService; src/main/java/cc/mrbird/febs/mall/controller/goods/AdminMallGoodsCategoryController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/AdminMallGoodsCategoryController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.goods; import cc.mrbird.febs.common.annotation.ControllerEndpoint; import cc.mrbird.febs.common.controller.BaseController; src/main/java/cc/mrbird/febs/mall/controller/goods/AdminMallGoodsController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/AdminMallGoodsController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.goods; import cc.mrbird.febs.common.annotation.ControllerEndpoint; src/main/java/cc/mrbird/febs/mall/controller/goods/ApiMallGoodsCategoryController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ApiMallGoodsCategoryController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.goods; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.mall.service.IApiMallGoodsCategoryService; @@ -24,7 +24,7 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/category") @Api(value = "ApiMallGoodsCategoryController", tags = "商品分类参数接收类") @Api(value = "ApiMallGoodsCategoryController", tags = "365商品分类") public class ApiMallGoodsCategoryController { private final IApiMallGoodsCategoryService mallGoodsCategoryService; src/main/java/cc/mrbird/febs/mall/controller/goods/ApiMallGoodsController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ApiMallGoodsController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.goods; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.mall.dto.ApiMallGoodsCommentDto; @@ -23,7 +23,7 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/goods") @Api(value = "ApiMallGoodsController", tags = "商城商品接口类") @Api(value = "ApiMallGoodsController", tags = "365商品") public class ApiMallGoodsController { private final IApiMallGoodsService mallGoodsService; src/main/java/cc/mrbird/febs/mall/controller/goods/ApiMemberCollectionController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ApiMemberCollectionController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.goods; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.mall.dto.AddCollectionDto; @@ -18,7 +18,7 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/collection") @Api(value = "ApiMemberCollectionController", tags = "收藏接口类") @Api(value = "ApiMemberCollectionController", tags = "365商品收藏") public class ApiMemberCollectionController { @Autowired src/main/java/cc/mrbird/febs/mall/controller/goods/ApiMemberFootprintController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ApiMemberFootprintController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.goods; import cc.mrbird.febs.common.entity.FebsResponse; @@ -23,7 +23,7 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/footprint") @Api(value = "ApiMemberFootprintController", tags = "足迹接口类") @Api(value = "ApiMemberFootprintController", tags = "365商品浏览足迹") public class ApiMemberFootprintController { @Autowired src/main/java/cc/mrbird/febs/mall/controller/goods/ViewMallGoodsCategoryController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ViewMallGoodsCategoryController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.goods; import cc.mrbird.febs.common.controller.BaseController; import cc.mrbird.febs.common.entity.FebsConstant; src/main/java/cc/mrbird/febs/mall/controller/goods/ViewMallGoodsController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ViewMallGoodsController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.goods; import cc.mrbird.febs.common.controller.BaseController; import cc.mrbird.febs.common.entity.FebsConstant; src/main/java/cc/mrbird/febs/mall/controller/member/ApiMallMemberController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.member; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.mall.dto.*; @@ -29,7 +29,7 @@ @RestController @RequestMapping(value = "/api/member") @RequiredArgsConstructor @Api(value = "ApiMallMemberController", tags = "商城用户接口类") @Api(value = "ApiMallMemberController", tags = "365用户操作") public class ApiMallMemberController { private final IApiMallMemberService memberService; src/main/java/cc/mrbird/febs/mall/controller/order/AdminMallOrderController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java @@ -1,15 +1,11 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.order; import cc.mrbird.febs.common.annotation.ControllerEndpoint; import cc.mrbird.febs.common.controller.BaseController; import cc.mrbird.febs.common.entity.DeptTree; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.common.entity.QueryRequest; import cc.mrbird.febs.common.enumerates.DataDictionaryEnum; import cc.mrbird.febs.common.enumerates.OrderDeliveryStateEnum; import cc.mrbird.febs.common.enumerates.OrderStatusEnum; import cc.mrbird.febs.common.exception.FebsException; import cc.mrbird.febs.common.utils.FebsUtil; import cc.mrbird.febs.common.utils.RedisUtils; import cc.mrbird.febs.common.utils.SpringContextHolder; import cc.mrbird.febs.common.utils.excl.ExcelSheetPO; @@ -19,17 +15,11 @@ import cc.mrbird.febs.mall.dto.*; import cc.mrbird.febs.mall.entity.*; import cc.mrbird.febs.mall.mapper.*; import cc.mrbird.febs.mall.service.IAdminMallGoodsService; import cc.mrbird.febs.mall.service.IAdminMallOrderService; import cc.mrbird.febs.mall.service.IApiMallTeamLeaderService; import cc.mrbird.febs.mall.service.MallInvoiceService; import cc.mrbird.febs.mall.vo.AdminAddAddressTreeVo; import cc.mrbird.febs.mall.vo.AdminMallOrderRefundAddressVo; import cc.mrbird.febs.pay.model.OrderStateDto; import cc.mrbird.febs.pay.service.IXcxPayService; import cc.mrbird.febs.pay.util.WechatConfigure; import cc.mrbird.febs.system.entity.Dept; import cc.mrbird.febs.system.entity.User; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; src/main/java/cc/mrbird/febs/mall/controller/order/ApiMallAddressInfoController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ApiMallAddressInfoController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.order; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.mall.conversion.MallAddressInfoConversion; @@ -28,7 +28,7 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/address") @Api(value = "ApiMallAddressInfoController", tags = "用户地址管理接口类") @Api(value = "ApiMallAddressInfoController", tags = "365订单地址") public class ApiMallAddressInfoController { private final IApiMallAddressInfoService mallAddressInfoService; src/main/java/cc/mrbird/febs/mall/controller/order/ApiMallInvoiceController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ApiMallInvoiceController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.order; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.mall.dto.ApiMallInvoiceDto; src/main/java/cc/mrbird/febs/mall/controller/order/ApiMallOrderController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ApiMallOrderController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.order; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.mall.dto.*; @@ -27,7 +27,7 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/order") @Api(value = "ApiMallOrderController", tags = "订单接口类") @Api(value = "ApiMallOrderController", tags = "365订单") public class ApiMallOrderController { private final IApiMallOrderInfoService mallOrderInfoService; src/main/java/cc/mrbird/febs/mall/controller/order/ApiMallShoppingCartController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ApiMallShoppingCartController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.order; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.mall.dto.AddCartDto; @@ -28,7 +28,7 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/cart") @Api(value = "ApiMallShoppingCartController", tags = "商城购物车接口请求类") @Api(value = "ApiMallShoppingCartController", tags = "365购物车") public class ApiMallShoppingCartController { private final IApiMallShoppingCartService mallShoppingCartService; src/main/java/cc/mrbird/febs/mall/controller/order/ViewMallOrderController.java
File was renamed from src/main/java/cc/mrbird/febs/mall/controller/ViewMallOrderController.java @@ -1,4 +1,4 @@ package cc.mrbird.febs.mall.controller; package cc.mrbird.febs.mall.controller.order; import cc.mrbird.febs.common.controller.BaseController; import cc.mrbird.febs.common.entity.FebsConstant; src/main/java/cc/mrbird/febs/mall/controller/signActivity/ApiScoreController.java
@@ -29,7 +29,7 @@ @CrossOrigin("*") @RequiredArgsConstructor @RequestMapping(value = "/api/score") @Api(value = "ApiScoreController", tags = "365签到接口类") @Api(value = "ApiScoreController", tags = "365签到") public class ApiScoreController { private final IScoreService scoreService; src/main/java/cc/mrbird/febs/mall/entity/MallAchieveRecord.java
@@ -16,9 +16,9 @@ public class MallAchieveRecord extends BaseEntity { private Long memberId; //业绩 private BigDecimal amount; //返佣 private BigDecimal costAmount; private Date achieveTime; src/main/java/cc/mrbird/febs/mall/entity/MallGoods.java
@@ -64,6 +64,9 @@ */ private BigDecimal staticProp; @TableField(exist = false) private BigDecimal staticPropPrice; /** * 是否多规则 1-是 2-否 */ src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java
@@ -25,6 +25,8 @@ private Date orderTime; private Date payTime; //支付积分 private BigDecimal scoreAmount; private BigDecimal amount; src/main/java/cc/mrbird/febs/mall/entity/MallOrderItem.java
@@ -3,6 +3,7 @@ import cc.mrbird.febs.common.entity.BaseEntity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; @@ -36,6 +37,8 @@ private Integer cnt; private BigDecimal price; //支付积分 private BigDecimal scoreAmount; private BigDecimal amount; @@ -58,4 +61,7 @@ @TableField(exist = false) private BigDecimal itemAmount; @TableField(exist = false) private BigDecimal itemScoreAmount; } src/main/java/cc/mrbird/febs/mall/service/impl/AgentServiceImpl.java
@@ -1,32 +1,17 @@ package cc.mrbird.febs.mall.service.impl; import cc.mrbird.febs.common.enumerates.AgentLevelEnum; import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum; import cc.mrbird.febs.common.utils.AppContants; import cc.mrbird.febs.mall.entity.AgentInfo; import cc.mrbird.febs.mall.entity.DataDictionaryCustom; import cc.mrbird.febs.mall.entity.MallMember; import cc.mrbird.febs.mall.entity.MallOrderInfo; import cc.mrbird.febs.mall.entity.*; import cc.mrbird.febs.mall.mapper.*; import cc.mrbird.febs.mall.service.IAgentService; import cc.mrbird.febs.mall.service.IApiMallMemberService; import cc.mrbird.febs.mall.service.IApiMallMemberWalletService; import cc.mrbird.febs.mall.service.IMallAchieveService; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import jdk.nashorn.internal.ir.IfNode; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author wzy @@ -39,116 +24,105 @@ private final DataDictionaryCustomMapper dataDictionaryCustomMapper; private final MallMemberMapper memberMapper; private final HappySaleLevelMapper happySaleLevelMapper; /** * 自动升级代理等级 * 根据会员的当前状态和业绩,自动为其升级到下一个代理等级 * @param memberId 会员ID,用于识别需要升级的会员 */ @Override @Transactional(rollbackFor = Exception.class) public void autoUpAgentLevel(Long memberId) { // 根据会员ID查询会员信息 MallMember member = memberMapper.selectById(memberId); if(StrUtil.isBlank(member.getReferrerIds())) { // 检查会员账户状态和类型,只有在启用状态和普通类型时才进行升级操作 if(MallMember.ACCOUNT_STATUS_ENABLE != member.getAccountStatus() || MallMember.ACCOUNT_TYPE_NORMAL != member.getAccountType() ){ return; } // 获取会员当前的店铺主人等级 Integer storeMaster = member.getStoreMaster(); // 下一个分销等级 storeMaster =storeMaster +1; // 根据新的店铺主人等级查询对应的快乐销售等级信息 HappySaleLevel happySaleLevel = happySaleLevelMapper.selectOne( new LambdaQueryWrapper<HappySaleLevel>() .eq(HappySaleLevel::getCode, storeMaster) ); // 如果没有找到对应的快乐销售等级信息,则记录日志并返回 if (happySaleLevel == null) { log.info("当前等级无下级"); return; } // 检查直推会员数量是否达到要求 if (!directMemberCnt(member, happySaleLevel.getDirectCnt())) { return; } List<String> ids = StrUtil.split(member.getReferrerIds(), ','); List<MallMember> parentMembers = memberMapper.selectByInviteIds(ids); for (MallMember parent : parentMembers) { // 未激活用户无法升级 if (AgentLevelEnum.ZERO_LEVEL.name().equals(member.getLevel())) { continue; } DataDictionaryCustom nextLevel = dataDictionaryCustomMapper.selectNextAgentLevelInfo(parent.getLevel()); if (nextLevel == null) { log.info("当前层级无下一级:{}", parent.getLevel()); continue; } AgentInfo agentInfo = JSONObject.parseObject(nextLevel.getValue(), AgentInfo.class); if (!directMemberCnt(parent, agentInfo)) { continue; } if (!agentCntFinish(parent, agentInfo)) { continue; } if (!teamIncome(parent, agentInfo)) { continue; } parent.setLevel(nextLevel.getCode()); memberMapper.updateById(parent); // 检查团队人数是否达到要求 if (!teamCntFinish(member, happySaleLevel.getTeamCnt())) { return; } // 检查团队业绩是否达到要求 if (!teamIncome(member, happySaleLevel.getTeamAmount())) { return; } // 更新会员的店铺主人等级 member.setStoreMaster(storeMaster); // 更新会员信息 memberMapper.updateById(member); } /** * 判断直推人数是否达标 * * @param member * @return */ private boolean directMemberCnt(MallMember member, AgentInfo agentInfo) { List<MallMember> childs = memberMapper.selectByRefererId(member.getInviteId()); if (CollUtil.isEmpty(childs)) { private boolean directMemberCnt(MallMember member, Integer directCnt) { List<MallMember> childList = memberMapper.selectByRefererId(member.getInviteId()); if (CollUtil.isEmpty(childList)) { return false; } if (childs.size() >= agentInfo.getDirectCnt()) { if (childList.size() >= directCnt) { return true; } log.info("用户:{}直推数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getLevel(), childs.size(), agentInfo.getLastAgentCnt()); log.info("用户:{}直推数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getStoreMaster(), childList.size(), directCnt); return false; } /** * 判断下级代理数量是否达标 * * @return * 判断团队数量是否达标 */ private boolean agentCntFinish(MallMember member, AgentInfo agentInfo) { if (agentInfo.getLastAgentCnt() == null || agentInfo.getLastAgentCnt() == 0) { return true; } private boolean teamCntFinish(MallMember member, Integer teamCnt) { // 直推用户 List<MallMember> directMember = memberMapper.selectByRefererId(member.getInviteId()); if (CollUtil.isEmpty(directMember)) { List<MallMember> teamMember = memberMapper.selectAllChildAgentListByInviteId(member.getInviteId()); if (CollUtil.isEmpty(teamMember)) { return false; } // 用户团队达到指定代理数量,且都不在同一条线 int i = 0; for (MallMember child : directMember) { List<MallMember> mallMembers = memberMapper.selectChildAgentList(child.getInviteId(), member.getLevel()); if (CollUtil.isNotEmpty(mallMembers)) { i++; } } if (i >= agentInfo.getLastAgentCnt()) { if (teamMember.size() >= teamCnt) { return true; } log.info("用户:{}代理数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getLevel(), i, agentInfo.getLastAgentCnt()); log.info("用户:{}团队数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getStoreMaster(), teamMember.size(), teamCnt); return false; } /** * 团队业绩是否达标 * * @param mallMember * @param agentInfo * @return */ private boolean teamIncome(MallMember member, AgentInfo agentInfo) { private boolean teamIncome(MallMember member, BigDecimal teamAmount) { BigDecimal totalIncome = memberMapper.selectAchieveByMemberId(member.getInviteId(), 2); BigDecimal targetIncome = agentInfo.getTeamIncome().multiply(new BigDecimal("10000")); if (totalIncome.compareTo(targetIncome) >= 0) { if(totalIncome.compareTo(teamAmount) >= 0){ return true; } log.info("用户:{}团队业绩未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getLevel(), totalIncome, targetIncome); log.info("用户:{}团队业绩未达标, 当前等级:{}, 当前业绩:{}, 目标业绩:{}", member.getPhone(), member.getStoreMaster(), totalIncome, teamAmount); return false; } src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
@@ -44,6 +44,7 @@ import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.stream.Collectors; @@ -56,6 +57,7 @@ @RequiredArgsConstructor public class ApiMallOrderInfoServiceImpl extends ServiceImpl<MallOrderInfoMapper, MallOrderInfo> implements IApiMallOrderInfoService { private final MallMemberWalletMapper mallMemberWalletMapper; private final MallGoodsMapper mallGoodsMapper; private final MallGoodsSkuMapper mallGoodsSkuMapper; private final MallAddressInfoMapper mallAddressInfoMapper; @@ -88,6 +90,7 @@ private final CouponGoodsMapper couponGoodsMapper; private final IMallVipConfigService mallVipConfigService; private final MallAchieveRecordMapper mallAchieveRecordMapper; @Override @Transactional(rollbackFor = Exception.class) @@ -121,6 +124,7 @@ this.baseMapper.insert(orderInfo); BigDecimal total = BigDecimal.ZERO; BigDecimal totalScoreAmount = BigDecimal.ZERO; /** * 根据传入的优惠卷ID和商品明细集合计算出每个商品获取的实际支付金额 */ @@ -138,6 +142,15 @@ } List<AddOrderItemDto> items = addOrderDto.getItems(); couponAmountMap = getCouponAmountMap(memberCouponId, items); } /** * 判断用户的积分是否足够 */ Map<Long, BigDecimal> scoreAmountMap = getScoreAmountMap(addOrderDto.getItems()); MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(memberId); //判断scoreAmountMap中的总积分数量是否大于用户的积分数量 if(scoreAmountMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(mallMemberWallet.getPrizeScore()) > 0){ throw new FebsException("您的积分不足"); } for (AddOrderItemDto item : addOrderDto.getItems()) { MallOrderItem orderItem = new MallOrderItem(); @@ -225,6 +238,7 @@ } } orderItem.setAmount(amount); orderItem.setScoreAmount(scoreAmountMap.get(item.getSkuId())); orderItem.setCnt(item.getCnt()); orderItem.setOrderId(orderInfo.getId()); orderItem.setPrice(sku.getPresentPrice()); @@ -246,6 +260,7 @@ orderItem.setCostPrice(sku.getCostPrice()); total = total.add(amount); totalScoreAmount = totalScoreAmount.add(scoreAmountMap.get(item.getSkuId())); //规格的库存销量 Integer skuResult = mallGoodsSkuMapper.upDateStockAndVolumeBySkuId(sku.getId(),item.getCnt()); if(1 != skuResult){ @@ -266,6 +281,7 @@ total = total.add(delivaryAmount); orderInfo.setAmount(total); orderInfo.setScoreAmount(totalScoreAmount); orderInfo.setAddressId(address.getId()); orderInfo.setName(address.getName()); orderInfo.setPhone(address.getPhone()); @@ -281,6 +297,39 @@ //过期时间修改成24小时 agentProducer.sendOrderCancelDelayMsg(orderInfo.getId(), 24 * 60 * 60 * 1000L); return orderInfo.getId(); } private Map<Long, BigDecimal> getScoreAmountMap(List<AddOrderItemDto> items) { Map<Long, BigDecimal> scoreAmountMap = new HashMap<>(); //全部skuIds Set<Long> skuIds = items.stream().map(AddOrderItemDto::getSkuId).collect(Collectors.toSet()); LambdaQueryWrapper<MallGoodsSku> mallGoodsSkuLambdaQueryWrapper = new LambdaQueryWrapper<>(); mallGoodsSkuLambdaQueryWrapper.in(MallGoodsSku::getId, skuIds); List<MallGoodsSku> skusAll = mallGoodsSkuMapper.selectList(mallGoodsSkuLambdaQueryWrapper); //全部goodsId Set<Long> goodsIdsAll = skusAll.stream().map(MallGoodsSku::getGoodsId).collect(Collectors.toSet()); LambdaQueryWrapper<MallGoods> mallGoodsLambdaQueryWrapper = new LambdaQueryWrapper<>(); mallGoodsLambdaQueryWrapper.in(MallGoods::getId, goodsIdsAll); List<MallGoods> goodsAll = mallGoodsMapper.selectList(mallGoodsLambdaQueryWrapper); //stream流操作goodsAll,返回一个Hashmap<id,MallGoods> Map<Long, MallGoods> goodsMap = goodsAll.stream().collect(Collectors.toMap(MallGoods::getId, mallGoods -> mallGoods)); for (AddOrderItemDto item : items) { Long skuId = item.getSkuId(); MallGoodsSku sku = skusAll.stream().filter(s -> s.getId().equals(skuId)).findFirst().orElse(null); if (ObjectUtil.isNotEmpty(sku)) { Long goodsId = sku.getGoodsId(); MallGoods mallGoods = goodsMap.get(goodsId); if (ObjectUtil.isNotEmpty(mallGoods)) { BigDecimal multi = mallGoods.getStaticProp().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_DOWN); //获取该商品该规格的积分 BigDecimal scoreAmount = sku.getOriginalPrice().multiply(multi).setScale(0, RoundingMode.HALF_DOWN); scoreAmountMap.put(skuId, scoreAmount); } } } return scoreAmountMap; } /** @@ -494,76 +543,109 @@ if (OrderStatusEnum.WAIT_PAY.getValue() != orderInfo.getStatus()) { throw new FebsException("订单状态不能支付"); } //先支付积分部分 if(orderInfo.getScoreAmount().compareTo(BigDecimal.ZERO) > 0){ balanceScorePay(orderInfo, payOrderDto.getTradePwd(), "prizeScore"); mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount().negate(), ScoreFlowTypeEnum.PAY.getValue(), orderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), null, 2); } String payResultStr = ""; String wxResultStr = ""; switch (payOrderDto.getType()) { case "1": BrandWCPayRequestData brandWCPayRequestData = null; try { brandWCPayRequestData = iXcxPayService.startPayment(orderInfo); } catch (Exception e) { throw new FebsException("支付失败"); } wxResultStr = JSONUtil.toJsonStr(brandWCPayRequestData); payResultStr = brandWCPayRequestData.getPrepay_id(); orderInfo.setPayMethod("微信支付"); break; case "2": if (StrUtil.isNotBlank(orderInfo.getPayOrderNo())) { payResultStr = orderInfo.getPayOrderNo(); } else { payResultStr = payService.aliPay(orderInfo); } if(orderInfo.getAmount().compareTo(BigDecimal.ZERO) <= 0){ orderInfo.setPayOrderNo(orderInfo.getOrderNo()); orderInfo.setPayMethod("积分支付"); orderInfo.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue()); orderInfo.setPayTime(new Date()); orderInfo.setPayResult("1"); payResultStr = orderInfo.getOrderNo(); }else{ switch (payOrderDto.getType()) { case "1": BrandWCPayRequestData brandWCPayRequestData = null; try { brandWCPayRequestData = iXcxPayService.startPayment(orderInfo); } catch (Exception e) { throw new FebsException("支付失败"); } wxResultStr = JSONUtil.toJsonStr(brandWCPayRequestData); payResultStr = brandWCPayRequestData.getPrepay_id(); orderInfo.setPayMethod("微信支付"); break; case "2": if (StrUtil.isNotBlank(orderInfo.getPayOrderNo())) { payResultStr = orderInfo.getPayOrderNo(); } else { payResultStr = payService.aliPay(orderInfo); } orderInfo.setPayOrderNo(payResultStr); orderInfo.setPayMethod("支付宝支付"); agentProducer.sendOrderReturn(orderInfo.getId()); break; case "3": payResultStr = balancePay(orderInfo, payOrderDto.getTradePwd(), "balance"); orderInfo.setPayOrderNo(payResultStr); orderInfo.setPayMethod("支付宝支付"); agentProducer.sendOrderReturn(orderInfo.getId()); break; case "3": payResultStr = balancePay(orderInfo, payOrderDto.getTradePwd(), "balance"); orderInfo.setPayOrderNo(orderInfo.getOrderNo()); orderInfo.setPayMethod("余额支付"); orderInfo.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue()); orderInfo.setPayTime(new Date()); orderInfo.setPayResult("1"); orderInfo.setDeliveryState(OrderDeliveryStateEnum.DELIVERY_WAIT.getValue()); orderInfo.setPayOrderNo(orderInfo.getOrderNo()); orderInfo.setPayMethod("余额支付"); orderInfo.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue()); orderInfo.setPayTime(new Date()); orderInfo.setPayResult("1"); orderInfo.setDeliveryState(OrderDeliveryStateEnum.DELIVERY_WAIT.getValue()); mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount().negate(), MoneyFlowTypeEnum.PAY.getValue(), orderInfo.getOrderNo(), FlowTypeEnum.BALANCE.getValue(),"余额支付",2); mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount().negate(), MoneyFlowTypeEnum.PAY.getValue(), orderInfo.getOrderNo(), FlowTypeEnum.BALANCE.getValue(),"余额支付",2); agentProducer.sendOrderCoupon(orderInfo.getId()); break; case "4": if (orderInfo.getOrderType() != 2) { throw new FebsException("非积分订单,无法使用积分支付"); } payResultStr = balancePay(orderInfo, payOrderDto.getTradePwd(), "prizeScore"); agentProducer.sendOrderCoupon(orderInfo.getId()); break; case "4": if (orderInfo.getOrderType() != 2) { throw new FebsException("非积分订单,无法使用积分支付"); } payResultStr = balancePay(orderInfo, payOrderDto.getTradePwd(), "prizeScore"); orderInfo.setPayOrderNo(orderInfo.getOrderNo()); orderInfo.setPayMethod("积分支付"); orderInfo.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue()); orderInfo.setPayTime(new Date()); orderInfo.setPayResult("1"); orderInfo.setPayOrderNo(orderInfo.getOrderNo()); orderInfo.setPayMethod("积分支付"); orderInfo.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue()); orderInfo.setPayTime(new Date()); orderInfo.setPayResult("1"); mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount().negate(), ScoreFlowTypeEnum.PAY.getValue(), orderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), null, 2); break; default: mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount().negate(), ScoreFlowTypeEnum.PAY.getValue(), orderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), null, 2); break; default: } } //订单支付成功产生一个提货码 String takeCode = ShareCodeUtil.toSerialCode(orderInfo.getId()); orderInfo.setTakeCode(takeCode); this.baseMapper.updateById(orderInfo); Map<String, Object> map = new HashMap<>(); map.put("orderInfo", payResultStr); map.put("orderNo", orderInfo.getOrderNo()); map.put("orderId", orderInfo.getId()); map.put("wxResultStr", wxResultStr); return map; } private String balanceScorePay(MallOrderInfo orderInfo, String tradePwd, String field) { if (StrUtil.isBlank(tradePwd)) { throw new FebsException("支付密码错误"); } MallMember mallMember = memberMapper.selectById(orderInfo.getMemberId()); if (StrUtil.isBlank(mallMember.getTradePassword())) { throw new FebsException("未设置支付密码"); } if (!SecureUtil.md5(tradePwd).equals(mallMember.getTradePassword())) { throw new FebsException("支付密码错误"); } int reduce = memberWalletService.reduce(orderInfo.getScoreAmount(), mallMember.getId(), field); if (reduce == 2) { throw new FebsException("积分不足"); } return orderInfo.getOrderNo(); } private String balancePay(MallOrderInfo orderInfo, String tradePwd, String field) { @@ -616,6 +698,7 @@ if(CollUtil.isNotEmpty(items)){ for(MallOrderItem mallOrderItem : items){ mallOrderItem.setItemAmount(mallOrderItemMapper.selectById(mallOrderItem.getId()).getAmount()); mallOrderItem.setScoreAmount(mallOrderItemMapper.selectById(mallOrderItem.getId()).getScoreAmount()); } } @@ -655,10 +738,6 @@ throw new FebsException("该状态不能确认收货"); } // if (orderInfo.getDeliveryState() != OrderDeliveryStateEnum.DELIVERY_FINISH.getValue()) { // throw new FebsException("还未送至自提点"); // } List<MallRefundEntity> mallRefundEntities = mallRefundMapper.selectByItemIdAndOrderIdAndState(null, orderInfo.getId(), 3); if(CollUtil.isNotEmpty(mallRefundEntities)){ throw new FebsException("请先处理退款商品"); @@ -669,34 +748,6 @@ this.baseMapper.updateById(orderInfo); agentProducer.sendGetScoreMsg(orderInfo.getId()); //生成一条团长提成记录 // Long orderInfoId = orderInfo.getId(); // List<MallOrderItem> mallOrderItemList = mallOrderItemMapper.selectListByOrderId(orderInfoId); // if(CollUtil.isNotEmpty(mallOrderItemList)){ // // MallTeamLeader mallTeamLeader = mallTeamLeaderMapper.selectLeaderByUniqueCode(orderInfo.getTakeUniqueCode()); // Integer profitSwitch = mallTeamLeader.getProfitSwitch()==null?2:mallTeamLeader.getProfitSwitch(); // BigDecimal bonusPercent =new BigDecimal(mallTeamLeader.getBonusPercent()==null?"0":mallTeamLeader.getBonusPercent()); // // if(1 == profitSwitch){ // for(MallOrderItem mallOrderItem : mallOrderItemList){ // Integer state = mallOrderItem.getState() == null ? 1 : mallOrderItem.getState(); // if(1 == state){ // MallLeaderAchieve mallLeaderAchieve = new MallLeaderAchieve(); // mallLeaderAchieve.setMemberId(orderInfo.getMemberId()); // mallLeaderAchieve.setOrderNo(orderInfo.getOrderNo()); // mallLeaderAchieve.setOrderItemId(mallOrderItem.getId()); // BigDecimal itemAmount = mallOrderItem.getAmount(); // mallLeaderAchieve.setAmount(itemAmount); // BigDecimal bigDecimal = bonusPercent.multiply(itemAmount).setScale(2, BigDecimal.ROUND_DOWN); // mallLeaderAchieve.setProfitAmount(bigDecimal); // mallLeaderAchieve.setUniqueCode(orderInfo.getTakeUniqueCode()); // mallLeaderAchieve.setState(MallLeaderAchieve.STATE_ONE); // mallLeaderAchieveMapper.insert(mallLeaderAchieve); // } // } // } // } } @Override @@ -1006,6 +1057,15 @@ if(CollUtil.isEmpty(items)){ return new FebsResponse().fail().message("请先挑选商品"); } /** * 判断用户的积分是否足够 */ Map<Long, BigDecimal> scoreAmountMap = getScoreAmountMap(apiCreateOrderVerifyDto.getItems()); MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(memberId); //判断scoreAmountMap中的总积分数量是否大于用户的积分数量 if(scoreAmountMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(mallMemberWallet.getPrizeScore()) > 0){ throw new FebsException("您的积分不足"); } for (AddOrderItemDto item : apiCreateOrderVerifyDto.getItems()) { MallGoodsSku sku = mallGoodsSkuMapper.selectSkuInfoById(item.getSkuId()); if (sku == null) { @@ -1035,6 +1095,8 @@ if (MallGoods.ISSALE_STATUS_DISABLED.equals(mallGoods.getIsSale())) { return new FebsResponse().fail().message(mallGoods.getGoodsName() + "已下架"); } //判断 } return new FebsResponse().success(); src/main/java/cc/mrbird/febs/mall/vo/MallGoodsDetailsVo.java
@@ -39,6 +39,9 @@ @ApiModelProperty(value = "原价") private String originalPrice; @ApiModelProperty(value = "积分价格") private String staticPropPrice; @ApiModelProperty(value = "现价") private String presentPrice; src/main/java/cc/mrbird/febs/mall/vo/MallGoodsListVo.java
@@ -32,6 +32,9 @@ @ApiModelProperty(value = "原价") private String originalPrice; @ApiModelProperty(value = "积分价格") private String staticPropPrice; @ApiModelProperty(value = "现价") private String presentPrice; src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java
@@ -37,6 +37,9 @@ @ApiModelProperty(value = "状态") private Integer status; @ApiModelProperty(value = "订单积分") private BigDecimal scoreAmount; @ApiModelProperty(value = "订单金额") private BigDecimal amount; src/main/java/cc/mrbird/febs/mall/vo/OrderItemVo.java
@@ -54,6 +54,9 @@ @ApiModelProperty(value = "1:正常 2:退款中3:已退") private Integer state; @ApiModelProperty(value = "订单积分") private BigDecimal itemScore; @ApiModelProperty(value = "支付金额") private BigDecimal itemAmount; } src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java
@@ -27,6 +27,9 @@ @ApiModelProperty(value = "状态 1-待支付 2-待发货 3-待收货 4-已完成 5-退款中 6-退款处理完成 7-已取消") private Integer status; //支付积分 @ApiModelProperty(value = "订单积分") private BigDecimal scoreAmount; @ApiModelProperty(value = "订单金额") private BigDecimal amount; src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java
@@ -16,4 +16,5 @@ public static final String GET_SCORE_MSG = "queue_get_score_msg"; public static final String VIP_LEVEL_UP = "queue_vip_level_up"; public static final String SALE_LEVEL_UP = "queue_sale_level_up"; } src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java
@@ -110,6 +110,16 @@ } } @RabbitListener(queues = QueueConstants.SALE_LEVEL_UP) public void saleLevelUp(Long orderId) { log.info("收到团长升级:{}", orderId); try { vipCommonService.saleLevelUp(orderId); } catch (Exception e) { log.error("团长升级消息异常", e); } } @RabbitListener(queues = QueueConstants.ACTIVITY_ORDER_ITEM_CHECK) public void checkActivityItem(Long orderId) { log.info("收到核销活动门票:{}", orderId); src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java
@@ -22,6 +22,8 @@ GET_SCORE_MSG("exchange_get_score_msg", "route_key_get_score_msg", QueueConstants.GET_SCORE_MSG), SALE_LEVEL_UP("exchange_sale_level_up", "route_key_sale_level_up", QueueConstants.SALE_LEVEL_UP), VIP_LEVEL_UP("exchange_vip_level_up", "route_key_vip_level_up", QueueConstants.VIP_LEVEL_UP); private String exchange; src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java
@@ -98,6 +98,13 @@ rabbitTemplate.convertAndSend(RabbitQueueEnum.VIP_LEVEL_UP.getExchange(), RabbitQueueEnum.VIP_LEVEL_UP.getRoute(), orderId, correlationData); } public void sendSaleLevelUp(Long orderId) { log.info("发送团长升级:{}", orderId); CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString()); rabbitTemplate.convertAndSend(RabbitQueueEnum.SALE_LEVEL_UP.getExchange(), RabbitQueueEnum.SALE_LEVEL_UP.getRoute(), orderId, correlationData); } public void sendCheckActivityItem(Long orderId) { log.info("核销活动门票:{}", orderId); src/main/java/cc/mrbird/febs/vip/service/IVipCommonService.java
@@ -5,4 +5,7 @@ void getScore(Long orderId); void levelUp(Long orderId); void saleLevelUp(Long orderId); } src/main/java/cc/mrbird/febs/vip/service/impl/VipCommonServiceImpl.java
@@ -2,13 +2,11 @@ import cc.mrbird.febs.common.enumerates.FlowTypeEnum; import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum; import cc.mrbird.febs.common.enumerates.OrderStatusEnum; 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.mapper.MallMemberMapper; import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; import cc.mrbird.febs.common.exception.FebsException; import cc.mrbird.febs.mall.entity.*; import cc.mrbird.febs.mall.mapper.*; import cc.mrbird.febs.mall.service.IApiMallGoodsService; import cc.mrbird.febs.mall.service.IApiMallMemberWalletService; import cc.mrbird.febs.mall.service.IApiMallOrderInfoService; @@ -21,6 +19,7 @@ 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 lombok.RequiredArgsConstructor; @@ -46,164 +45,369 @@ private final IMallVipConfigService mallVipConfigService; private final IMallMoneyFlowService mallMoneyFlowService; private final IApiMallMemberWalletService mallMemberWalletService; private final MallMemberWalletMapper mallMemberWalletMapper; private final MallMemberMapper mallMemberMapper; private final MallVipConfigMapper mallVipConfigMapper; private final AgentProducer agentProducer; private final IApiMallGoodsService mallGoodsService; private final HappyMemberLevelMapper happyMemberLevelMapper; private final HappySaleLevelMapper happySaleLevelMapper; private final MallAchieveRecordMapper mallAchieveRecordMapper; /** * 根据订单ID获取分数 * 此方法处理订单得分逻辑,包括直接购买得分、会员等级得分和推荐人得分 * * @param orderId 订单ID,用于查询订单详细信息 */ @Override @Transactional(rollbackFor = Exception.class) public void getScore(Long orderId) { // 根据订单ID查询订单详细信息 MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectOrderDetailsById(orderId); if (mallOrderInfo == null) { // 如果订单信息为空,则直接返回 return; } 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(); if (mallOrderInfo.getStatus() != OrderStatusEnum.FINISH.getValue()) { // 订单不是完成状态 return; } List<String> skuNames = mallOrderInfo.getItems().stream().map(MallOrderItem::getSkuName).collect(Collectors.toList()); double sum = mallOrderInfo.getItems().stream().map(MallOrderItem::getAmount).mapToDouble(BigDecimal::doubleValue).sum(); // 获取订单金额 BigDecimal amount = mallOrderInfo.getAmount(); if(BigDecimal.ZERO.compareTo(amount) >= 0){ // 如果订单金额小于等于0,则直接返回 return; } int score = multiple.multiply(BigDecimal.valueOf(sum)).intValue(); // 获取会员ID Long memberId = mallOrderInfo.getMemberId(); // 根据会员ID查询会员信息 MallMember member = mallMemberMapper.selectById(memberId); 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"); // 记录会员购买获得的经验 mallMoneyFlowService.addMoneyFlow( memberId, amount, ScoreFlowTypeEnum.BUY.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.SCORE.getValue(), ScoreFlowTypeEnum.BUY.getDesc(), 2 ); // 更新会员钱包中的分数 mallMemberWalletService.add(amount, memberId, "score"); 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)); // 下单自己获得积分,推荐人获得积分 //<memberId,积分数量>的map 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); Map<Long, Integer> recommendTypeScoreMap = new HashMap<>(); // 获取会员的董事等级代码 Integer director = member.getDirector(); // 查询与董事等级代码匹配的会员等级信息 LambdaQueryWrapper<HappyMemberLevel> happyMemberLevelLambdaQueryWrapper = new LambdaQueryWrapper<HappyMemberLevel>(); happyMemberLevelLambdaQueryWrapper.eq(HappyMemberLevel::getCode, director); happyMemberLevelLambdaQueryWrapper.last("limit 1"); HappyMemberLevel happyMemberLevel = happyMemberLevelMapper.selectOne(happyMemberLevelLambdaQueryWrapper); if(ObjectUtil.isNotEmpty(happyMemberLevel)){ // 计算自己获得的积分 BigDecimal minePercent = happyMemberLevel.getMinePercent(); BigDecimal mineScore = amount.multiply(minePercent.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_DOWN)).setScale(0, RoundingMode.HALF_DOWN); if(BigDecimal.ZERO.compareTo(mineScore) < 0){ recommendScoreMap.put(memberId, mineScore); recommendTypeScoreMap.put(memberId, ScoreFlowTypeEnum.MINE_RECOMMEND.getValue()); } }); // 计算推荐人获得的积分 if(StrUtil.isNotEmpty(member.getReferrerId())){ MallMember refMember = mallMemberMapper.selectInfoByInviteId(member.getReferrerId()); BigDecimal otherPercent = happyMemberLevel.getOtherPercent(); BigDecimal otherScore = amount.multiply(otherPercent.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_DOWN)).setScale(0, RoundingMode.HALF_DOWN); if(BigDecimal.ZERO.compareTo(otherScore) < 0){ recommendScoreMap.put(refMember.getId(), otherScore); recommendTypeScoreMap.put(memberId, ScoreFlowTypeEnum.OTHER_RECOMMEND.getValue()); } } } // 为推荐人和自己添加积分流动记录和更新钱包 recommendScoreMap.forEach((key, value) -> { if (value != null) { mallMoneyFlowService.addMoneyFlow(key, value, ScoreFlowTypeEnum.RECOMMEND.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), CollUtil.join(skuNames, ","), 2); mallMoneyFlowService.addMoneyFlow( key, value, recommendTypeScoreMap.get(key), mallOrderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), ScoreFlowTypeEnum.getDescByValue(recommendTypeScoreMap.get(key)), 2); mallMemberWalletService.add(value, key, "prizeScore"); } }); // 发送会员等级升级消息 agentProducer.sendVipLevelUp(orderId); } /** * 根据订单ID升级会员等级 * 当订单完成时,根据会员当前的经验值升级会员等级 * * @param orderId 订单ID */ @Override public void levelUp(Long orderId) { // 根据订单ID获取订单详细信息 MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectOrderDetailsById(orderId); // 如果订单信息为空,则直接返回 if (mallOrderInfo == null) { return; } // 如果订单状态不是完成状态,则直接返回 if (mallOrderInfo.getStatus() != OrderStatusEnum.FINISH.getValue()) { // 订单不是完成状态 return; } // 根据订单中的会员ID获取会员信息 MallMember member = mallMemberMapper.selectById(mallOrderInfo.getMemberId()); // 如果会员信息为空,则记录日志并返回 if (member == null) { log.info("会员不存在"); return; } MallVipConfig config = mallVipConfigMapper.selectVipConfigByCode(member.getLevel()); if (config == null) { log.info("会员等级配置不存在"); // 根据会员ID获取会员钱包信息 MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(member.getId()); // 如果会员钱包信息为空,则记录日志并返回 if (mallMemberWallet == null) { log.info("会员钱包不存在"); return; } //当前经验值 int score = mallMemberWallet.getScore().intValue(); // 查询当前经验值对应的会员等级 HappyMemberLevel happyMemberLevel = happyMemberLevelMapper.selectOne( new LambdaQueryWrapper<HappyMemberLevel>() .ge(HappyMemberLevel::getUpgradeScore, score) .orderByAsc(HappyMemberLevel::getCode) .last("limit 1") ); // 如果查询不到对应的会员等级,则记录日志并返回 if (happyMemberLevel == null) { log.info("会员等级不存在"); return; } // 获取当前会员等级代码 Integer code = happyMemberLevel.getCode(); // 如果当前会员等级与会员的导演等级相同,则直接返回 if(member.getDirector() == code){ return; } // LambdaQueryWrapper<MallVipConfig> configQuery = new LambdaQueryWrapper<>(); // configQuery.gt(MallVipConfig::getLevel, config.getLevel()) // .orderByAsc(MallVipConfig::getLevel) // .last("limit 1"); // MallVipConfig nextLevel = mallVipConfigMapper.selectOne(configQuery); // 更新会员的导演等级为当前会员等级代码 member.setDirector(code); // 更新会员信息 mallMemberMapper.updateById(member); List<MallVipConfig> configs = mallVipConfigMapper.selectVipConfigList(); String nextLevelCode = ""; for (MallVipConfig nextLevel : configs) { if (config.getLevel() >= nextLevel.getLevel()) { continue; } // 指定商品 if (nextLevel.getType() == 1) { boolean hasMatch = mallOrderInfo.getItems().stream().anyMatch(item -> { return item.getGoodsId().equals(nextLevel.getTargetId()); }); if (hasMatch) { nextLevelCode = nextLevel.getCode(); continue; } } // 时间区间内金额 if (nextLevel.getType() == 2) { Date endTime = DateUtil.endOfDay(new Date()); Date startTime = getStartTime(nextLevel.getValidType()); LambdaQueryWrapper<MallOrderInfo> query = new LambdaQueryWrapper<>(); query.ge(MallOrderInfo::getReceivingTime, startTime) .le(MallOrderInfo::getReceivingTime, endTime) .eq(MallOrderInfo::getStatus, 4) .eq(MallOrderInfo::getMemberId, member.getId()); List<MallOrderInfo> orderList = mallOrderInfoMapper.selectList(query); if (CollUtil.isEmpty(orderList)) { continue; } double totalAmount = orderList.stream().mapToDouble(item -> { return item.getAmount().doubleValue(); }).sum(); if (nextLevel.getAmount().compareTo(BigDecimal.valueOf(totalAmount)) <= 0) { nextLevelCode = nextLevel.getCode(); } } } if (StrUtil.isNotBlank(nextLevelCode)) { MallMember update = new MallMember(); update.setId(member.getId()); update.setLevel(nextLevelCode); update.setVipLevelTime(new Date()); mallMemberMapper.updateById(update); } // 发送分销等级升级消息 agentProducer.sendSaleLevelUp(orderId); } private Date getStartTime(String type) { Date date = new Date(); switch (type) { case "day" : return DateUtil.beginOfDay(date); case "month": return DateUtil.beginOfMonth(date); case "year": return DateUtil.beginOfYear(date); default: return date; /** * 升级销售级别时处理订单相关的逻辑 * * @param orderId 订单ID,用于识别和处理特定的订单 */ @Override public void saleLevelUp(Long orderId) { // 根据订单ID获取订单详细信息 MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectOrderDetailsById(orderId); // 如果订单信息为空,则直接返回 if (mallOrderInfo == null) { return; } // 如果订单状态不是完成状态,则直接返回 if (mallOrderInfo.getStatus() != OrderStatusEnum.FINISH.getValue()) { // 订单不是完成状态 return; } // 根据订单中的会员ID获取会员信息 MallMember member = mallMemberMapper.selectById(mallOrderInfo.getMemberId()); // 如果会员信息为空,则记录日志并返回 if (member == null) { log.info("会员不存在"); return; } // 如果会员的推荐人ID为空,则直接返回 if(StrUtil.isEmpty(member.getReferrerIds())){ return; } // 分割会员的推荐人ID String[] referrerIds = member.getReferrerIds().split(","); // 查询符合条件的团长会员 MallMember storeMasterMember = mallMemberMapper.selectOne( new LambdaQueryWrapper<MallMember>() .in(MallMember::getInviteId, referrerIds) .eq(MallMember::getAccountStatus, MallMember.ACCOUNT_STATUS_ENABLE) .eq(MallMember::getAccountType, MallMember.ACCOUNT_TYPE_NORMAL) .ne(MallMember::getStoreMaster, 0) .orderByAsc(MallMember::getStoreMaster) .last("limit 1") ); // 如果没有找到符合条件的团长,则记录日志并返回 if (storeMasterMember == null) { log.info("团长不存在"); return; } // 根据团长的等级代码查询团长等级信息 HappySaleLevel happySaleLevel = happySaleLevelMapper.selectOne( new LambdaQueryWrapper<HappySaleLevel>() .eq(HappySaleLevel::getCode, storeMasterMember.getStoreMaster()) ); // 如果团长等级信息不存在,则记录日志并返回 if (happySaleLevel == null) { log.info("团长等级不存在"); return; } // 计算返佣金额 BigDecimal divide = happySaleLevel.getReturnPercent().divide(new BigDecimal(100)); BigDecimal multiply = mallOrderInfo.getAmount().multiply(divide).setScale(2, RoundingMode.HALF_DOWN); // 如果返佣金额小于等于0,则直接返回 if(BigDecimal.ZERO.compareTo(multiply) >=0){ return; } // 如果返佣金额大于等于订单金额,则直接返回 if(multiply.compareTo(mallOrderInfo.getAmount()) >= 0){ return; } // 记录团长获得返佣 mallMoneyFlowService.addMoneyFlow( storeMasterMember.getId(), multiply, ScoreFlowTypeEnum.SALE_RECOMMEND.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.BALANCE.getValue(), ScoreFlowTypeEnum.SALE_RECOMMEND.getDesc(), 2 ); // 更新会员钱包中的余额 mallMemberWalletService.add(multiply, storeMasterMember.getId(), "balance"); MallAchieveRecord mallAchieveRecord = new MallAchieveRecord(); mallAchieveRecord.setMemberId(mallOrderInfo.getMemberId()); mallAchieveRecord.setAchieveTime(new Date()); mallAchieveRecord.setAmount(mallOrderInfo.getAmount()); mallAchieveRecord.setCostAmount(multiply); mallAchieveRecord.setOrderId(mallOrderInfo.getId()); mallAchieveRecord.setIsNormal(1); mallAchieveRecord.setPayTime(mallOrderInfo.getPayTime()); mallAchieveRecordMapper.insert(mallAchieveRecord); this.autoUpAgentLevel(storeMasterMember.getId()); } /** * 自动升级代理等级 * 根据会员的当前状态和业绩,自动为其升级到下一个代理等级 * @param memberId 会员ID,用于识别需要升级的会员 */ private void autoUpAgentLevel(Long memberId) { // 根据会员ID查询会员信息 MallMember member = mallMemberMapper.selectById(memberId); // 检查会员账户状态和类型,只有在启用状态和普通类型时才进行升级操作 if(MallMember.ACCOUNT_STATUS_ENABLE != member.getAccountStatus() || MallMember.ACCOUNT_TYPE_NORMAL != member.getAccountType() ){ return; } // 获取会员当前的店铺主人等级 Integer storeMaster = member.getStoreMaster(); // 下一个分销等级 storeMaster =storeMaster +1; // 根据新的店铺主人等级查询对应的快乐销售等级信息 HappySaleLevel happySaleLevel = happySaleLevelMapper.selectOne( new LambdaQueryWrapper<HappySaleLevel>() .eq(HappySaleLevel::getCode, storeMaster) ); // 如果没有找到对应的快乐销售等级信息,则记录日志并返回 if (happySaleLevel == null) { log.info("当前等级无下级"); return; } // 检查直推会员数量是否达到要求 if (!directMemberCnt(member, happySaleLevel.getDirectCnt())) { return; } // 检查团队人数是否达到要求 if (!teamCntFinish(member, happySaleLevel.getTeamCnt())) { return; } // 检查团队业绩是否达到要求 if (!teamIncome(member, happySaleLevel.getTeamAmount())) { return; } // 更新会员的店铺主人等级 member.setStoreMaster(storeMaster); // 更新会员信息 mallMemberMapper.updateById(member); } /** * 判断直推人数是否达标 */ private boolean directMemberCnt(MallMember member, Integer directCnt) { List<MallMember> childList = mallMemberMapper.selectByRefererId(member.getInviteId()); if (CollUtil.isEmpty(childList)) { return false; } if (childList.size() >= directCnt) { return true; } log.info("用户:{}直推数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getStoreMaster(), childList.size(), directCnt); return false; } /** * 判断团队数量是否达标 */ private boolean teamCntFinish(MallMember member, Integer teamCnt) { // 直推用户 List<MallMember> teamMember = mallMemberMapper.selectAllChildAgentListByInviteId(member.getInviteId()); if (CollUtil.isEmpty(teamMember)) { return false; } if (teamMember.size() >= teamCnt) { return true; } log.info("用户:{}团队数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getStoreMaster(), teamMember.size(), teamCnt); return false; } /** * 团队业绩是否达标 */ private boolean teamIncome(MallMember member, BigDecimal teamAmount) { BigDecimal totalIncome = mallMemberMapper.selectAchieveByMemberId(member.getInviteId(), 2); if(totalIncome.compareTo(teamAmount) >= 0){ return true; } log.info("用户:{}团队业绩未达标, 当前等级:{}, 当前业绩:{}, 目标业绩:{}", member.getPhone(), member.getStoreMaster(), totalIncome, teamAmount); return false; } } src/main/resources/mapper/modules/MallGoodsMapper.xml
@@ -13,6 +13,7 @@ <result property="goodsDetails" column="goods_details" /> <result property="isSale" column="is_sale" /> <result property="originalPrice" column="original_price" /> <result property="staticPropPrice" column="staticPropPrice" /> <result property="presentPrice" column="present_price" /> <result property="categoryId" column="category_id" /> <result property="volume" column="volume" /> @@ -66,6 +67,7 @@ c.stock sku_stock, c.sku_volume, c.original_price sku_original_price, a.original_price*a.static_prop staticPropPrice, c.present_price sku_present_price, c.style_id sku_style_id, c.goods_weight sku_goods_weight, @@ -90,6 +92,7 @@ a.thumb, a.unit, a.original_price, a.original_price*a.static_prop staticPropPrice, a.present_price, a.level_one_price, a.level_two_price, @@ -340,6 +343,7 @@ a.thumb, a.unit, a.original_price, a.original_price*a.static_prop staticPropPrice, a.present_price, a.score, a.is_hot, src/main/resources/mapper/modules/MallOrderInfoMapper.xml
@@ -108,6 +108,7 @@ <result column="member_id" property="memberId" /> <result column="order_time" property="orderTime" /> <result column="pay_time" property="payTime" /> <result column="score_amount" property="scoreAmount" /> <result column="amount" property="amount" /> <result column="pay_method" property="payMethod" /> <result column="pay_order_no" property="payOrderNo" /> @@ -356,6 +357,7 @@ <result column="member_id" property="memberId" /> <result column="order_time" property="orderTime" /> <result column="pay_time" property="payTime" /> <result column="score_amount" property="scoreAmount" /> <result column="amount" property="amount" /> <result column="pay_method" property="payMethod" /> <result column="pay_order_no" property="payOrderNo" /> src/main/resources/templates/febs/views/modules/goods/goodsAddNew.html
@@ -103,20 +103,22 @@ </div> </div> <div class="layui-form-item"> <label class="layui-form-label">推销员返积分比例(%)</label> <div class="layui-input-block"> <input type="text" name="staticMulti" placeholder="请输入推销员返积分比例" autocomplete="off" class="layui-input"> </div> </div> <!-- <div class="layui-form-item">--> <!-- <label class="layui-form-label">推销员返积分比例(%)</label>--> <!-- <div class="layui-input-block">--> <!-- <input type="text" name="staticMulti" placeholder="请输入推销员返积分比例" autocomplete="off" class="layui-input">--> <!-- </div>--> <!-- </div>--> <div class="layui-form-item febs-hide tc-set"> <label class="layui-form-label">静态占比(%)</label> <div class="layui-input-block"> <input type="text" name="staticProp" placeholder="请输入静态占比" autocomplete="off" class="layui-input"> <div class="layui-form-mid layui-word-aux">所有套餐静态占比相加应等于100%</div> </div> </div> <!-- <div class="layui-form-item febs-hide tc-set">--> <!-- <label class="layui-form-label">积分折扣(%)</label>--> <!-- <div class="layui-input-block">--> <!-- <input type="text" name="staticProp" placeholder="请输入积分折扣" autocomplete="off" class="layui-input">--> <!-- <div class="layui-form-mid layui-word-aux">折扣积分=售价*积分折扣(%)*积分换算比例</div>--> <!-- <div class="layui-form-mid layui-word-aux">不允许使用积分设置成:0%</div>--> <!-- <div class="layui-form-mid layui-word-aux">全部使用积分设置成:大于等于100%</div>--> <!-- </div>--> <!-- </div>--> </div> <div class="layui-tab-item"> @@ -238,6 +240,16 @@ <input type="text" name="costPrice" lay-verify="required" placeholder="" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">积分折扣(%)</label> <div class="layui-input-block"> <input type="text" name="staticProp" lay-verify="required" placeholder="请输入积分折扣" lay-reqText="请输入积分折扣" autocomplete="off" class="layui-input"> <div class="layui-form-mid layui-word-aux">折扣积分=原价 * 积分折扣(%)* 积分换算比例</div> <div class="layui-form-mid layui-word-aux">不允许使用积分设置成:0%</div> <div class="layui-form-mid layui-word-aux">全部使用积分设置成:大于等于100%</div> </div> </div> </div> <blockquote class="layui-elem-quote blue-border">运费设置</blockquote> <div class="layui-form-item"> @@ -374,7 +386,7 @@ upload = layui.upload, validate = layui.validate, element = layui.element; // form.verify(validate); form.render(); const E = window.wangEditor; const editor = new E('#toolbar-container', '#text-container'); // 传入两个元素 @@ -826,14 +838,14 @@ return false; }); form.on('select(goods-type-select)', function(data){ $('.tc-set').each(function() { if (data.value == 2) { $(this).show(); } else { $(this).hide(); } }) }); // form.on('select(goods-type-select)', function(data){ // $('.tc-set').each(function() { // if (data.value == 2) { // $(this).show(); // } else { // $(this).hide(); // } // }) // }); }); </script> src/main/resources/templates/febs/views/modules/goods/goodsUpdateNew.html
@@ -112,21 +112,21 @@ </div> </div> <div class="layui-form-item"> <label class="layui-form-label">推销员返积分比例(%)</label> <div class="layui-input-block"> <input type="text" name="staticMulti" placeholder="请输入推销员返积分比例" autocomplete="off" class="layui-input"> </div> </div> <!-- <div class="layui-form-item">--> <!-- <label class="layui-form-label">推销员返积分比例(%)</label>--> <!-- <div class="layui-input-block">--> <!-- <input type="text" name="staticMulti" placeholder="请输入推销员返积分比例" autocomplete="off" class="layui-input">--> <!-- </div>--> <!-- </div>--> <div class="layui-form-item febs-hide tc-set"> <label class="layui-form-label">静态占比(%)</label> <div class="layui-input-block"> <input type="text" name="staticProp" placeholder="请输入静态占比" autoComplete="off" class="layui-input"> <div class="layui-form-mid layui-word-aux">所有套餐静态占比相加应等于100%</div> </div> </div> <!-- <div class="layui-form-item febs-hide tc-set">--> <!-- <label class="layui-form-label">静态占比(%)</label>--> <!-- <div class="layui-input-block">--> <!-- <input type="text" name="staticProp" placeholder="请输入静态占比"--> <!-- autoComplete="off" class="layui-input">--> <!-- <div class="layui-form-mid layui-word-aux">所有套餐静态占比相加应等于100%</div>--> <!-- </div>--> <!-- </div>--> </div> <div class="layui-tab-item"> @@ -238,6 +238,16 @@ <input type="text" name="costPrice" lay-verify="required" placeholder="" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">积分折扣(%)</label> <div class="layui-input-block"> <input type="text" name="staticProp" lay-verify="required" placeholder="请输入积分折扣" lay-reqText="请输入积分折扣" autocomplete="off" class="layui-input"> <div class="layui-form-mid layui-word-aux">折扣积分=售价*积分折扣(%)*积分换算比例</div> <div class="layui-form-mid layui-word-aux">不允许使用积分设置成:0%</div> <div class="layui-form-mid layui-word-aux">全部使用积分设置成:大于等于100%</div> </div> </div> </div> <!-- <blockquote class="layui-elem-quote blue-border">代理价格</blockquote>--> <!-- <div class="layui-row layui-col-space10 layui-form-item">-->