|
@@ -0,0 +1,292 @@
|
|
|
+package cn.newfeifan.mall.module.distri.service.ordercalc;
|
|
|
+
|
|
|
+import cn.newfeifan.mall.framework.common.util.json.JsonUtils;
|
|
|
+import cn.newfeifan.mall.module.distri.controller.admin.duser.vo.DuserSaveReqVO;
|
|
|
+import cn.newfeifan.mall.module.distri.controller.admin.integral.vo.IntegralSaveReqVO;
|
|
|
+import cn.newfeifan.mall.module.distri.controller.admin.ptprofit.vo.PtProfitSaveReqVO;
|
|
|
+import cn.newfeifan.mall.module.distri.controller.admin.ptprofitlog.vo.PtProfitLogSaveReqVO;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.integral.IntegralDO;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.orderpercentage.OrderPercentageDO;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.ptprofit.PtProfitDO;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.sharepath.SharePathDO;
|
|
|
+import cn.newfeifan.mall.module.distri.enums.CaclEnum;
|
|
|
+import cn.newfeifan.mall.module.distri.mq.message.order.DistriOrderMessage;
|
|
|
+import cn.newfeifan.mall.module.distri.service.duser.DuserService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.integral.IntegralService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.orderpercentage.OrderPercentageService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.ptprofit.PtProfitService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.ptprofitlog.PtProfitLogService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.sharepath.SharePathService;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.validation.annotation.Validated;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+import cn.newfeifan.mall.module.distri.controller.admin.ordercalc.vo.*;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.ordercalc.OrderCalcDO;
|
|
|
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
|
|
|
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
|
|
|
+
|
|
|
+import cn.newfeifan.mall.module.distri.dal.mysql.ordercalc.OrderCalcMapper;
|
|
|
+
|
|
|
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
+import static cn.newfeifan.mall.module.distri.constant.DistriConstants.PERCENT;
|
|
|
+import static cn.newfeifan.mall.module.distri.constant.DistriConstants.THREE;
|
|
|
+import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 订单产生数据计算 Service 实现类
|
|
|
+ *
|
|
|
+ * @author 非繁人
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Validated
|
|
|
+public class OrderCalcServiceImpl implements OrderCalcService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private OrderCalcMapper orderCalcMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private PtProfitService ptProfitService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private PtProfitLogService ptProfitLogService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private SharePathService sharePathService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private OrderPercentageService orderPercentageService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private DuserService duserService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private IntegralService integralService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Long createOrderCalc(OrderCalcSaveReqVO createReqVO) {
|
|
|
+ // 插入
|
|
|
+ OrderCalcDO orderCalc = BeanUtils.toBean(createReqVO, OrderCalcDO.class);
|
|
|
+ orderCalcMapper.insert(orderCalc);
|
|
|
+ // 返回
|
|
|
+ return orderCalc.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateOrderCalc(OrderCalcSaveReqVO updateReqVO) {
|
|
|
+ // 校验存在
|
|
|
+ validateOrderCalcExists(updateReqVO.getId());
|
|
|
+ // 更新
|
|
|
+ OrderCalcDO updateObj = BeanUtils.toBean(updateReqVO, OrderCalcDO.class);
|
|
|
+ orderCalcMapper.updateById(updateObj);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void deleteOrderCalc(Long id) {
|
|
|
+ // 校验存在
|
|
|
+ validateOrderCalcExists(id);
|
|
|
+ // 删除
|
|
|
+ orderCalcMapper.deleteById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateOrderCalcExists(Long id) {
|
|
|
+ if (orderCalcMapper.selectById(id) == null) {
|
|
|
+ throw exception(ORDER_CALC_NOT_EXISTS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public OrderCalcDO getOrderCalc(Long id) {
|
|
|
+ return orderCalcMapper.selectById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public PageResult<OrderCalcDO> getOrderCalcPage(OrderCalcPageReqVO pageReqVO) {
|
|
|
+ return orderCalcMapper.selectPage(pageReqVO);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void calc(List<DistriOrderMessage> tradeOrderDO) {
|
|
|
+
|
|
|
+ // 获取到当前订单的所有人
|
|
|
+ List<Long> userId = tradeOrderDO.stream().map(DistriOrderMessage::getUserId).collect(Collectors.toList());
|
|
|
+ // 判断当前下单的人员是否有进入营销模块用户表, 如果没有的话, 需要初始化
|
|
|
+ duserService.hasUserAndCreat(userId);
|
|
|
+ // 判断当前下单人是否有有上级, 如果没有, 创建直推人关系
|
|
|
+ sharePathService.createSharePathByUserId(userId);
|
|
|
+
|
|
|
+ OrderPercentageDO orderPercentageDO = orderPercentageService.queryStatus();
|
|
|
+ // 当前计算百分比模板
|
|
|
+ String percentTemplate = JsonUtils.toJsonString(orderPercentageDO);
|
|
|
+
|
|
|
+ calc(tradeOrderDO, orderPercentageDO, percentTemplate);
|
|
|
+
|
|
|
+ // todo 计算当天用户的碰撞
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void calc(List<DistriOrderMessage> tradeOrderDO, OrderPercentageDO orderPercentageDO, String percentTemplate) {
|
|
|
+ // 每个订单收益
|
|
|
+ List<OrderCalcSaveReqVO> saveList = new ArrayList<>();
|
|
|
+ // 平台收益
|
|
|
+ List<PtProfitSaveReqVO> ptProfitSaveReqVOS = new ArrayList<>();
|
|
|
+ // 平台收益日志
|
|
|
+ List<PtProfitLogSaveReqVO> ptProfitLogSaveReqVOS = new ArrayList<>();
|
|
|
+ // 修改用户钱包
|
|
|
+ List<IntegralSaveReqVO> integralSaveReqVOS = new ArrayList<>();
|
|
|
+
|
|
|
+ // todo 修改用户身价 如何从订单中获取身价?
|
|
|
+ List<DuserSaveReqVO> duserSaveReqVOS = new ArrayList<>();
|
|
|
+
|
|
|
+ PtProfitDO ptProfitDO = ptProfitService.getPtProfit();
|
|
|
+ tradeOrderDO.forEach(k -> {
|
|
|
+
|
|
|
+ BigDecimal price = new BigDecimal(String.valueOf(k.getPrice()));
|
|
|
+ BigDecimal costPrice = new BigDecimal(String.valueOf(k.getCostPrice()));
|
|
|
+ BigDecimal productCount = new BigDecimal(String.valueOf(k.getProductCount()));
|
|
|
+
|
|
|
+ // 计算
|
|
|
+ // 计算利润: (价格 - 成本价格) * 产品数量
|
|
|
+// Integer profit = (k.getPrice() - k.getCostPrice()) * k.getProductCount();
|
|
|
+
|
|
|
+ BigDecimal profit = price.subtract(costPrice).multiply(productCount);
|
|
|
+
|
|
|
+ // 计算毛利: 利润 * 0.38
|
|
|
+ BigDecimal grossProfit = profit.multiply(new BigDecimal(String.valueOf(orderPercentageDO.getGrossProfitPerc()))).setScale(4, RoundingMode.DOWN);
|
|
|
+
|
|
|
+ // 计算推荐人额度: 毛利 * 0.35
|
|
|
+ BigDecimal ancestorQuota = grossProfit.multiply(new BigDecimal(orderPercentageDO.getGrossProfitUserQuotaPerc())).setScale(4, RoundingMode.DOWN);
|
|
|
+
|
|
|
+ // 计算直推人额度: 毛利 * 0.35
|
|
|
+ BigDecimal descendantQuota = grossProfit.multiply(new BigDecimal(orderPercentageDO.getGrossProfitAncestorQuotaPerc())).setScale(4, RoundingMode.DOWN);
|
|
|
+
|
|
|
+ // 计算合赢奖: 毛利 * 0.08
|
|
|
+ BigDecimal bonusQuota = grossProfit.multiply(new BigDecimal(orderPercentageDO.getGrossProfitBonusQuotaPerc())).setScale(4, RoundingMode.DOWN);
|
|
|
+
|
|
|
+ // 计算平台收益: 毛利 * 0.22
|
|
|
+ BigDecimal platformQuota = grossProfit.multiply(new BigDecimal(orderPercentageDO.getGrossProfitPlatformQuotaPerc())).setScale(4, RoundingMode.DOWN);
|
|
|
+
|
|
|
+ // 计算当前下单人的毛利的三倍
|
|
|
+ BigDecimal highQuota = grossProfit.multiply(new BigDecimal("3")).setScale(4, RoundingMode.DOWN);
|
|
|
+
|
|
|
+ // 乘以 10000 并转换为整数
|
|
|
+ int grossProfitInt = grossProfit.multiply(new BigDecimal("10000")).setScale(0, RoundingMode.DOWN).intValueExact();
|
|
|
+ int ancestorQuotaInt = ancestorQuota.multiply(new BigDecimal("10000")).setScale(0, RoundingMode.DOWN).intValueExact();
|
|
|
+ int descendantQuotaInt = descendantQuota.multiply(new BigDecimal("10000")).setScale(0, RoundingMode.DOWN).intValueExact();
|
|
|
+ int bonusQuotaInt = bonusQuota.multiply(new BigDecimal("10000")).setScale(0, RoundingMode.DOWN).intValueExact();
|
|
|
+ int platformQuotaInt = platformQuota.multiply(new BigDecimal("10000")).setScale(0, RoundingMode.DOWN).intValueExact();
|
|
|
+ int highQuotaInt = highQuota.multiply(new BigDecimal("10000")).setScale(0, RoundingMode.DOWN).intValueExact();
|
|
|
+
|
|
|
+
|
|
|
+ // 获取当前下单人关系
|
|
|
+ SharePathDO sharePath = getSharePath(k.getUserId());
|
|
|
+ // 如果sharePath为空, 则说明没有直推人关系
|
|
|
+ IntegralDO integralDOAncestor = integralService.selectByUser(sharePath.getAncestor());
|
|
|
+ IntegralDO integralDO = integralService.selectByUser(sharePath.getDescendant());
|
|
|
+
|
|
|
+ // ========== 汇总计算 =================
|
|
|
+ addCaclDo(percentTemplate, saveList, k, grossProfitInt, ancestorQuotaInt, descendantQuotaInt, bonusQuotaInt, platformQuotaInt);
|
|
|
+ // ========== 修改用户钱包 =================
|
|
|
+ changeUserWallet(integralSaveReqVOS, integralDO, integralDOAncestor, ancestorQuotaInt, descendantQuotaInt, highQuotaInt);
|
|
|
+ // ========== 修改平台信息 =================
|
|
|
+ // 每个订单计算的过程
|
|
|
+ // 增加平台收益
|
|
|
+ // 平台服务费
|
|
|
+
|
|
|
+ BigDecimal ptGrossAdd = new BigDecimal(ptProfitDO.getPtGrossAdd());
|
|
|
+ BigDecimal ptAdd = new BigDecimal(ptProfitDO.getPtAdd());
|
|
|
+ BigDecimal ptTotalAdd = new BigDecimal(ptProfitDO.getPtTotalAdd());
|
|
|
+ BigDecimal bonusQuotaPerc = new BigDecimal(orderPercentageDO.getGrossProfitPerc());
|
|
|
+
|
|
|
+ // 计算平台收益:毛利润减去合赢奖百分比后的金额
|
|
|
+ BigDecimal one = BigDecimal.ONE;
|
|
|
+ BigDecimal grossProfitAfterBonus = grossProfit.multiply(one.subtract(bonusQuotaPerc));
|
|
|
+ BigDecimal newPtAdd = ptAdd.add(grossProfitAfterBonus);
|
|
|
+ BigDecimal newPtGrossAdd = ptGrossAdd.add(platformQuota);
|
|
|
+
|
|
|
+ // 计算平台总收益
|
|
|
+ BigDecimal newPtTotal = ptTotalAdd.add(newPtGrossAdd).add(newPtAdd);
|
|
|
+
|
|
|
+ // 换成整数
|
|
|
+ int ptGrossAddInt = newPtGrossAdd.intValue();
|
|
|
+ int ptAddInt = newPtAdd.intValue();
|
|
|
+ int ptTotalInt = newPtTotal.intValue();
|
|
|
+
|
|
|
+ PtProfitSaveReqVO ptProfitSaveReqVO = PtProfitSaveReqVO.builder().ptAdd(ptAddInt).ptGrossAdd(ptGrossAddInt).ptTotalAdd(ptTotalInt).build();
|
|
|
+ ptProfitSaveReqVOS.add(ptProfitSaveReqVO);
|
|
|
+ // ========== 增加日志记录 =================
|
|
|
+
|
|
|
+ // 平台记录
|
|
|
+ PtProfitLogSaveReqVO ptGrossAddLog = PtProfitLogSaveReqVO.builder().orderId(k.getOrderId()).profitStatus(CaclEnum.PLATFORM_SERVICE_FEE.getType()).orderNo(k.getNo()).amount(platformQuotaInt).afterAmount(ptProfitSaveReqVO.getPtGrossAdd()).percentTemplate(percentTemplate).build();
|
|
|
+
|
|
|
+ PtProfitLogSaveReqVO ptAddLog = PtProfitLogSaveReqVO.builder().orderId(k.getOrderId()).profitStatus(CaclEnum.PLATFORM_REVENUE.getType()).orderNo(k.getNo()).amount(grossProfitAfterBonus.intValue()).afterAmount(ptProfitSaveReqVO.getPtAdd()).percentTemplate(percentTemplate).build();
|
|
|
+
|
|
|
+
|
|
|
+ // 推荐人记录
|
|
|
+ PtProfitLogSaveReqVO tjrLog = PtProfitLogSaveReqVO.builder().orderId(k.getOrderId()).profitStatus(CaclEnum.RECOMMENDED_PERSON_QUOTA.getType()).orderNo(k.getNo()).userId(sharePath.getAncestor()).amount(ancestorQuotaInt).afterAmount(integralDOAncestor.getCurrentQuota() + ancestorQuotaInt).percentTemplate(percentTemplate).build();
|
|
|
+
|
|
|
+
|
|
|
+ // 直推人记录
|
|
|
+ PtProfitLogSaveReqVO ztrLog = PtProfitLogSaveReqVO.builder().orderId(k.getOrderId()).profitStatus(CaclEnum.DIRECT_REFERRAL_QUOTA.getType()).orderNo(k.getNo()).userId(sharePath.getDescendant()).amount(descendantQuotaInt).afterAmount(integralDO.getCurrentQuota() + descendantQuotaInt).percentTemplate(percentTemplate).build();
|
|
|
+ PtProfitLogSaveReqVO highQuotaLog = PtProfitLogSaveReqVO.builder().orderId(k.getOrderId()).profitStatus(CaclEnum.HIGH_QUOTA.getType()).orderNo(k.getNo()).userId(sharePath.getDescendant()).amount(highQuotaInt).afterAmount(integralDO.getHighQuota() + highQuotaInt).percentTemplate(percentTemplate).build();
|
|
|
+
|
|
|
+ // 合赢奖记录
|
|
|
+ PtProfitLogSaveReqVO hyjLog = PtProfitLogSaveReqVO.builder().orderId(k.getOrderId()).profitStatus(CaclEnum.TOGETHER_AWARD.getType()).orderNo(k.getNo()).amount(bonusQuotaInt).afterAmount(0).percentTemplate(percentTemplate).build();
|
|
|
+
|
|
|
+
|
|
|
+ ptProfitLogSaveReqVOS.add(ptGrossAddLog);
|
|
|
+ ptProfitLogSaveReqVOS.add(ptAddLog);
|
|
|
+ ptProfitLogSaveReqVOS.add(tjrLog);
|
|
|
+ ptProfitLogSaveReqVOS.add(ztrLog);
|
|
|
+ ptProfitLogSaveReqVOS.add(hyjLog);
|
|
|
+ ptProfitLogSaveReqVOS.add(highQuotaLog);
|
|
|
+
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ // 将信息存储到数据库中
|
|
|
+ orderCalcMapper.insertBatch(BeanUtils.toBean(saveList, OrderCalcDO.class));
|
|
|
+ ptProfitService.saveBatch(ptProfitSaveReqVOS);
|
|
|
+ ptProfitLogService.saveBatch(ptProfitLogSaveReqVOS);
|
|
|
+ integralService.updateBatch(integralSaveReqVOS);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void addCaclDo(String percentTemplate, List<OrderCalcSaveReqVO> saveList, DistriOrderMessage k, Integer grossProfit, Integer ancestorQuota, Integer descendantQuota, Integer bonusQuota, Integer platformQuota) {
|
|
|
+ OrderCalcSaveReqVO orderCalcSaveReqVO = OrderCalcSaveReqVO.builder().userId(k.getUserId()).orderNo(k.getNo()).cost(k.getCostPrice()).price(k.getPrice()).grossProfit(grossProfit).grossProfitUserQuota(ancestorQuota).grossProfitAncestorQuota(descendantQuota).grossProfitBonusQuota(bonusQuota).grossProfitPlatformQuota(platformQuota).percentTemplate(percentTemplate).build();
|
|
|
+ saveList.add(orderCalcSaveReqVO);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void changeUserWallet(List<IntegralSaveReqVO> integralSaveReqVOS, IntegralDO integralDO, IntegralDO integralDOAncestor, Integer ancestorQuota, Integer descendantQuota, Integer highQuota) {
|
|
|
+ // 修改用户钱包
|
|
|
+ // 增加直推人额度
|
|
|
+ integralDO.setHighQuota(integralDO.getHighQuota() + highQuota);
|
|
|
+ integralDO.setCurrentQuota(integralDO.getCurrentQuota() + descendantQuota);
|
|
|
+
|
|
|
+ // 增加推荐人额度
|
|
|
+ integralDOAncestor.setCurrentQuota(integralDO.getCurrentQuota() + ancestorQuota);
|
|
|
+
|
|
|
+ integralSaveReqVOS.add(BeanUtils.toBean(integralDO, IntegralSaveReqVO.class));
|
|
|
+ integralSaveReqVOS.add(BeanUtils.toBean(integralDOAncestor, IntegralSaveReqVO.class));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 获取当前订单的下单人的直推关系
|
|
|
+ public SharePathDO getSharePath(Long userId) {
|
|
|
+
|
|
|
+ return sharePathService.getSharePathByDescendant(userId);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|