Commit 9856e179741730ff185212da37d60dc89efe5372

Authored by owen
1 parent e9fd3777

分销:根据商品,计算推广员可以得到的佣金

yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
@@ -137,4 +137,14 @@ public class ProductSpuRespDTO { @@ -137,4 +137,14 @@ public class ProductSpuRespDTO {
137 */ 137 */
138 private Integer clickCount; 138 private Integer clickCount;
139 139
  140 +
  141 + // ========== 分销相关字段 =========
  142 +
  143 + /**
  144 + * 分销类型
  145 + *
  146 + * false - 默认
  147 + * true - 自行设置
  148 + */
  149 + private Boolean subCommissionType;
140 } 150 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java
@@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBroke @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBroke
9 import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert; 9 import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
10 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO; 10 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
11 import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; 11 import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
12 -import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;  
13 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
14 import io.swagger.v3.oas.annotations.tags.Tag; 13 import io.swagger.v3.oas.annotations.tags.Tag;
15 import lombok.extern.slf4j.Slf4j; 14 import lombok.extern.slf4j.Slf4j;
@@ -32,8 +31,6 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLogi @@ -32,8 +31,6 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLogi
32 @Slf4j 31 @Slf4j
33 public class AppBrokerageRecordController { 32 public class AppBrokerageRecordController {
34 @Resource 33 @Resource
35 - private BrokerageUserService brokerageUserService;  
36 - @Resource  
37 private BrokerageRecordService brokerageRecordService; 34 private BrokerageRecordService brokerageRecordService;
38 35
39 @GetMapping("/page") 36 @GetMapping("/page")
@@ -45,15 +42,10 @@ public class AppBrokerageRecordController { @@ -45,15 +42,10 @@ public class AppBrokerageRecordController {
45 return success(BrokerageRecordConvert.INSTANCE.convertPage02(pageResult)); 42 return success(BrokerageRecordConvert.INSTANCE.convertPage02(pageResult));
46 } 43 }
47 44
48 - // TODO @疯狂:这里还有一个漏网之鱼~  
49 @GetMapping("/get-product-brokerage-price") 45 @GetMapping("/get-product-brokerage-price")
50 @Operation(summary = "获得商品的分销金额") 46 @Operation(summary = "获得商品的分销金额")
51 public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) { 47 public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) {
52 - AppBrokerageProductPriceRespVO respVO = new AppBrokerageProductPriceRespVO();  
53 - respVO.setEnabled(brokerageUserService.getUserBrokerageEnabled(getLoginUserId()));  
54 - respVO.setBrokerageMinPrice(1);  
55 - respVO.setBrokerageMaxPrice(2);  
56 - return success(respVO); 48 + return success(brokerageRecordService.calculateProductBrokeragePrice(spuId, getLoginUserId()));
57 } 49 }
58 50
59 } 51 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
1 package cn.iocoder.yudao.module.trade.convert.order; 1 package cn.iocoder.yudao.module.trade.convert.order;
2 2
  3 +import cn.hutool.core.util.BooleanUtil;
3 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
@@ -14,6 +15,7 @@ import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDT @@ -14,6 +15,7 @@ import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDT
14 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; 15 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
15 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; 16 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
16 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 17 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
  18 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
17 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; 19 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
18 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; 20 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
19 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; 21 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
@@ -266,11 +268,16 @@ public interface TradeOrderConvert { @@ -266,11 +268,16 @@ public interface TradeOrderConvert {
266 268
267 TradeOrderDO convert(TradeOrderRemarkReqVO reqVO); 269 TradeOrderDO convert(TradeOrderRemarkReqVO reqVO);
268 270
269 - default BrokerageAddReqBO convert(MemberUserRespDTO user, TradeOrderItemDO item, ProductSkuRespDTO sku) {  
270 - return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())).setSourceUserId(item.getUserId()) 271 + default BrokerageAddReqBO convert(MemberUserRespDTO user, TradeOrderItemDO item,
  272 + ProductSpuRespDTO spu, ProductSkuRespDTO sku) {
  273 + BrokerageAddReqBO bo = new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())).setSourceUserId(item.getUserId())
271 .setBasePrice(item.getPayPrice() * item.getCount()) 274 .setBasePrice(item.getPayPrice() * item.getCount())
272 .setTitle(StrUtil.format("{}成功购买{}", user.getNickname(), item.getSpuName())) 275 .setTitle(StrUtil.format("{}成功购买{}", user.getNickname(), item.getSpuName()))
273 - .setFirstFixedPrice(sku.getFirstBrokeragePrice()).setSecondFixedPrice(sku.getSecondBrokeragePrice()); 276 + .setFirstFixedPrice(0).setSecondFixedPrice(0);
  277 + if (BooleanUtil.isTrue(spu.getSubCommissionType())) {
  278 + bo.setFirstFixedPrice(sku.getFirstBrokeragePrice()).setSecondFixedPrice(sku.getSecondBrokeragePrice());
  279 + }
  280 + return bo;
274 } 281 }
275 282
276 TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO); 283 TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO);
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordService.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.service.brokerage; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.service.brokerage;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO; 4 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
  5 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO;
5 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO; 6 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO;
6 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO; 7 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO;
7 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO; 8 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
@@ -110,4 +111,12 @@ public interface BrokerageRecordService { @@ -110,4 +111,12 @@ public interface BrokerageRecordService {
110 */ 111 */
111 Integer getUserRankByPrice(Long userId, LocalDateTime[] times); 112 Integer getUserRankByPrice(Long userId, LocalDateTime[] times);
112 113
  114 + /**
  115 + * 计算商品被购买后,推广员可以得到的佣金
  116 + *
  117 + * @param spuId 商品编号
  118 + * @param userId 用户编号
  119 + * @return 用户佣金
  120 + */
  121 + AppBrokerageProductPriceRespVO calculateProductBrokeragePrice(Long spuId, Long userId);
113 } 122 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImpl.java
1 package cn.iocoder.yudao.module.trade.service.brokerage; 1 package cn.iocoder.yudao.module.trade.service.brokerage;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.collection.ListUtil;
4 import cn.hutool.core.util.ArrayUtil; 5 import cn.hutool.core.util.ArrayUtil;
5 import cn.hutool.core.util.BooleanUtil; 6 import cn.hutool.core.util.BooleanUtil;
6 import cn.hutool.core.util.ObjectUtil; 7 import cn.hutool.core.util.ObjectUtil;
@@ -9,7 +10,12 @@ import cn.hutool.extra.spring.SpringUtil; @@ -9,7 +10,12 @@ import cn.hutool.extra.spring.SpringUtil;
9 import cn.iocoder.yudao.framework.common.pojo.PageResult; 10 import cn.iocoder.yudao.framework.common.pojo.PageResult;
10 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 11 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
11 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; 12 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
  13 +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
  14 +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
  15 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  16 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
12 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO; 17 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
  18 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO;
13 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO; 19 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO;
14 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO; 20 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO;
15 import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert; 21 import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
@@ -36,6 +42,9 @@ import java.util.Objects; @@ -36,6 +42,9 @@ import java.util.Objects;
36 import java.util.Optional; 42 import java.util.Optional;
37 43
38 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 44 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  45 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue;
  46 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMinValue;
  47 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
39 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_WITHDRAW_USER_BALANCE_NOT_ENOUGH; 48 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_WITHDRAW_USER_BALANCE_NOT_ENOUGH;
40 49
41 /** 50 /**
@@ -55,6 +64,11 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { @@ -55,6 +64,11 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
55 @Resource 64 @Resource
56 private BrokerageUserService brokerageUserService; 65 private BrokerageUserService brokerageUserService;
57 66
  67 + @Resource
  68 + private ProductSpuApi productSpuApi;
  69 + @Resource
  70 + private ProductSkuApi productSkuApi;
  71 +
58 @Override 72 @Override
59 public BrokerageRecordDO getBrokerageRecord(Integer id) { 73 public BrokerageRecordDO getBrokerageRecord(Integer id) {
60 return brokerageRecordMapper.selectById(id); 74 return brokerageRecordMapper.selectById(id);
@@ -293,6 +307,50 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { @@ -293,6 +307,50 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
293 return true; 307 return true;
294 } 308 }
295 309
  310 + @Override
  311 + public AppBrokerageProductPriceRespVO calculateProductBrokeragePrice(Long spuId, Long userId) {
  312 + // 1. 构建默认的返回值
  313 + AppBrokerageProductPriceRespVO respVO = new AppBrokerageProductPriceRespVO().setEnabled(false)
  314 + .setBrokerageMinPrice(0).setBrokerageMaxPrice(0);
  315 +
  316 + // 2.1 校验分销功能是否开启
  317 + TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
  318 + if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) {
  319 + return respVO;
  320 + }
  321 +
  322 + // 2.2 校验用户是否有分销资格
  323 + respVO.setEnabled(brokerageUserService.getUserBrokerageEnabled(getLoginUserId()));
  324 + if (!BooleanUtil.isTrue(respVO.getEnabled())) {
  325 + return respVO;
  326 + }
  327 +
  328 + Integer fixedMinPrice = 0;
  329 + Integer fixedMaxPrice = 0;
  330 + Integer spuMinPrice = 0;
  331 + Integer spuMaxPrice = 0;
  332 + // 2.3 校验商品是否存在
  333 + ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
  334 + if (spu == null) {
  335 + return respVO;
  336 + }
  337 +
  338 + List<ProductSkuRespDTO> skuList = productSkuApi.getSkuListBySpuId(ListUtil.of(spuId));
  339 + if (BooleanUtil.isTrue(spu.getSubCommissionType())) {
  340 + // 3.1 商品单独分佣模式
  341 + fixedMinPrice = getMinValue(skuList, ProductSkuRespDTO::getFirstBrokeragePrice);
  342 + fixedMaxPrice = getMaxValue(skuList, ProductSkuRespDTO::getFirstBrokeragePrice);
  343 + } else {
  344 + // 3.2 全局分佣模式(根据商品价格比例计算)
  345 + spuMinPrice = getMinValue(skuList, ProductSkuRespDTO::getPrice);
  346 + spuMaxPrice = getMaxValue(skuList, ProductSkuRespDTO::getPrice);
  347 + }
  348 +
  349 + respVO.setBrokerageMinPrice(calculatePrice(spuMinPrice, tradeConfig.getBrokerageFirstPercent(), fixedMinPrice));
  350 + respVO.setBrokerageMaxPrice(calculatePrice(spuMaxPrice, tradeConfig.getBrokerageFirstPercent(), fixedMaxPrice));
  351 + return respVO;
  352 + }
  353 +
296 /** 354 /**
297 * 获得自身的代理对象,解决 AOP 生效问题 355 * 获得自身的代理对象,解决 AOP 生效问题
298 * 356 *
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
@@ -849,7 +849,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -849,7 +849,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
849 // 每一个订单项,都会去生成分销记录 849 // 每一个订单项,都会去生成分销记录
850 List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); 850 List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(orderId);
851 List<BrokerageAddReqBO> addList = convertList(orderItems, 851 List<BrokerageAddReqBO> addList = convertList(orderItems,
852 - item -> TradeOrderConvert.INSTANCE.convert(user, item, productSkuApi.getSku(item.getSkuId()))); 852 + item -> TradeOrderConvert.INSTANCE.convert(user, item,
  853 + productSpuApi.getSpu(item.getSpuId()), productSkuApi.getSku(item.getSkuId())));
853 brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList); 854 brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList);
854 } 855 }
855 856