Browse Source

feat: 活动发货金额计算返利

master
Yen 2 months ago
parent
commit
2bcc6ff223
  1. 32
      cms-modules/cms-policy/cms-policy-api/src/main/java/com/qs/serve/modules/tzc/entity/dto/TzcRebateCalculateDTO.java
  2. 45
      cms-modules/cms-policy/cms-policy-api/src/main/java/com/qs/serve/modules/tzc/entity/dto/TzcRebateLevelAmountDTO.java
  3. 28
      cms-modules/cms-system/src/main/java/com/qs/serve/modules/tzc/service/TzcRebateApplication4CostService.java
  4. 26
      cms-modules/cms-system/src/main/java/com/qs/serve/modules/tzc/service/TzcRebateApplication4VerificationService.java
  5. 115
      cms-modules/cms-system/src/main/java/com/qs/serve/modules/tzc/service/impl/TzcRebateApplication4CostServiceImpl.java
  6. 82
      cms-modules/cms-system/src/main/java/com/qs/serve/modules/tzc/service/impl/TzcRebateApplication4VerificationServiceImpl.java

32
cms-modules/cms-policy/cms-policy-api/src/main/java/com/qs/serve/modules/tzc/entity/dto/TzcRebateCalculateDTO.java

@ -0,0 +1,32 @@
package com.qs.serve.modules.tzc.entity.dto;
import com.qs.serve.modules.tzc.entity.TzcRebateLevels;
import lombok.Data;
import java.util.List;
/**
*
* @author YenHex
* @since 2025/5/7
*/
@Data
public class TzcRebateCalculateDTO {
/**
* 当前条件命中的最大级坎级
*/
private TzcRebateLevels maxLevels;
/**
* 同期或不同期的所有坎级
*/
private List<TzcRebateLevels> samePeriodLevelList;
/**
* 通过配置叠加的坎级包含参数及初始的返利金额
* 初始的返利金额还要过滤一次不能超过金额上限
*/
private List<TzcRebateLevelAmountDTO> levelAmountList;
}

45
cms-modules/cms-policy/cms-policy-api/src/main/java/com/qs/serve/modules/tzc/entity/dto/TzcRebateLevelAmountDTO.java

@ -0,0 +1,45 @@
package com.qs.serve.modules.tzc.entity.dto;
import com.qs.serve.modules.tzc.entity.TzcRebateLevels;
import com.qs.serve.modules.tzc.entity.TzcRebateLevelsArgument;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* @author YenHex
* @since 2025/5/7
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class TzcRebateLevelAmountDTO extends TzcRebateLevels {
/**
* 坎级返利金额(最终结果)
*/
private BigDecimal returnAmt;
/**
* 最大返利金额
*/
private BigDecimal maxReturn;
/**
* 已经核销金额
*/
private BigDecimal verificationAmt;
/**
* 计算所得的返利金额(非最终结果)
*/
private BigDecimal levelReturnAmt;
/**
* 坎级的返利参数
*/
@NotNull
private TzcRebateLevelsArgument argument;
}

28
cms-modules/cms-system/src/main/java/com/qs/serve/modules/tzc/service/TzcRebateApplication4CostService.java

@ -1,8 +1,9 @@
package com.qs.serve.modules.tzc.service;
import com.qs.serve.modules.tzc.consts.TzcArgTypes;
import com.qs.serve.modules.tzc.entity.*;
import com.qs.serve.modules.tzc.entity.bo.TzcRebateParam;
import com.qs.serve.modules.tzc.entity.vo.TzcRebateVo;
import com.qs.serve.modules.tzc.entity.dto.TzcRebateCalculateDTO;
import com.qs.serve.modules.tzc.entity.dto.TzcRebateLevelAmountDTO;
import java.math.BigDecimal;
import java.util.List;
@ -35,16 +36,31 @@ public interface TzcRebateApplication4CostService {
List<TzcRebateCenter> centerList,
List<TzcRebateLevels> levelsList);
/**
* 获取最高命中返利坎级的信息
* 获取最高命中返利坎级的信息及坎级列表
* @param dispatchAmt 当前客户的发货金额
* @param sameDispatchAmt 同期发货金额
* @param rebatePeriodId 返利期间id
* @return
*/
TzcRebateLevels getHitRebateMaxLevel(BigDecimal dispatchAmt,
BigDecimal sameDispatchAmt,
Long rebatePeriodId);
TzcRebateCalculateDTO getHitRebateMaxLevel(BigDecimal dispatchAmt,
BigDecimal sameDispatchAmt,
Long rebatePeriodId);
/**
* 计算坎级返利
* @param dto 计算DTO
* @param dispatchAmt
* @param sameDispatchAmt
* @param argType 参数类型用于区分
* @return
*/
List<TzcRebateLevelAmountDTO> calculateRebate(TzcRebateCalculateDTO dto,
BigDecimal dispatchAmt,
BigDecimal sameDispatchAmt,
TzcArgTypes argType);
}

26
cms-modules/cms-system/src/main/java/com/qs/serve/modules/tzc/service/TzcRebateApplication4VerificationService.java

@ -0,0 +1,26 @@
package com.qs.serve.modules.tzc.service;
import com.qs.serve.modules.tzc.consts.TzcArgTypes;
import com.qs.serve.modules.tzc.entity.*;
import com.qs.serve.modules.tzc.entity.dto.TzcRebateCalculateDTO;
import java.math.BigDecimal;
import java.util.List;
/**
* 返利信息 服务接口
* @author YenHex
* @date 2025-04-15
*/
public interface TzcRebateApplication4VerificationService {
/**
* 获取活动返利金额
* @param activityId
* @param dispatchAmt
* @return
*/
TzcRebateCalculateDTO getActivityRebateAmount(Long activityId,BigDecimal dispatchAmt);
}

115
cms-modules/cms-system/src/main/java/com/qs/serve/modules/tzc/service/impl/TzcRebateApplication4CostServiceImpl.java

@ -2,7 +2,7 @@ package com.qs.serve.modules.tzc.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qs.serve.common.exception.Assert;
import com.qs.serve.common.utils.CopierUtil;
import com.qs.serve.modules.tbs.common.TbsActivityState;
import com.qs.serve.modules.tbs.common.TbsCostApplyState;
import com.qs.serve.modules.tbs.entity.*;
@ -10,6 +10,8 @@ import com.qs.serve.modules.tbs.mapper.TbsActivityMapper;
import com.qs.serve.modules.tbs.service.*;
import com.qs.serve.modules.tzc.consts.TzcArgTypes;
import com.qs.serve.modules.tzc.entity.*;
import com.qs.serve.modules.tzc.entity.dto.TzcRebateCalculateDTO;
import com.qs.serve.modules.tzc.entity.dto.TzcRebateLevelAmountDTO;
import com.qs.serve.modules.tzc.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -329,7 +331,10 @@ public class TzcRebateApplication4CostServiceImpl implements TzcRebateApplicatio
}
@Override
public TzcRebateLevels getHitRebateMaxLevel(BigDecimal dispatchAmt,BigDecimal sameDispatchAmt,Long rebatePeriodId) {
public TzcRebateCalculateDTO getHitRebateMaxLevel(BigDecimal dispatchAmt,
BigDecimal sameDispatchAmt,
Long rebatePeriodId) {
TzcRebateCalculateDTO dto = new TzcRebateCalculateDTO();
// 判断是否同期
int samePeriodFlag = sameDispatchAmt.compareTo(BigDecimal.ZERO)==0?0:1;
TzcRebatePeriod rebatePeriod = tzcRebatePeriodService.getById(rebatePeriodId);
@ -340,6 +345,7 @@ public class TzcRebateApplication4CostServiceImpl implements TzcRebateApplicatio
.eq(TzcRebateLevels::getSamePeriodFlag, samePeriodFlag)
.orderByDesc(TzcRebateLevels::getLevelNum)
);
dto.setSamePeriodLevelList(levelsList);
// 命中的最高坎级
for (TzcRebateLevels levels : levelsList) {
// 条件选择:0-百分比;1-固定金额
@ -357,21 +363,118 @@ public class TzcRebateApplication4CostServiceImpl implements TzcRebateApplicatio
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP)
)>=0;
if (!ok){
log.debug("命中坎级:"+levels.getLevelNum()+",条件比重:"+levels.getConditionRate()+"%");
log.debug("命中最高坎级:"+levels.getLevelNum()+",条件比重:"+levels.getConditionRate()+"%");
continue;
}
return levels;
dto.setMaxLevels(levels);
return dto;
}else if (levels.getConditionSelect().equals(1)){
// 发货金额大于坎级制定的固定金额
boolean ok = dispatchAmt.compareTo(levels.getConditionAmount())>=0;
if (!ok){
log.debug("命中坎级:"+levels.getLevelNum()+",条件固定金额:"+levels.getConditionAmount());
log.debug("命中最高坎级:"+levels.getLevelNum()+",条件固定金额:"+levels.getConditionAmount());
continue;
}
return levels;
dto.setMaxLevels(levels);
return dto;
}
}
return null;
}
@Override
public List<TzcRebateLevelAmountDTO> calculateRebate(TzcRebateCalculateDTO dto,
BigDecimal dispatchAmt,
BigDecimal sameDispatchAmt,
TzcArgTypes argType) {
if (dto==null){
log.debug("没有命中坎级");
return null;
}
TzcRebateLevels levels = dto.getMaxLevels();
List<TzcRebateLevels> allRebateLvList = dto.getSamePeriodLevelList();
TzcRebateLevelsConfig levelsConfig = tzcRebateLevelsConfigService.getOne(
new LambdaQueryWrapper<TzcRebateLevelsConfig>()
.eq(TzcRebateLevelsConfig::getRebateId, levels.getRebateId())
.eq(TzcRebateLevelsConfig::getLevelNum, levels.getLevelNum())
,false
);
String[] configArr;
if (levelsConfig==null){
log.warn("没有坎级配置:"+levels.getLevelNum()+";返利ID:"+levels.getRebateId());
configArr = new String[]{levels.getLevelNum()+""};
}else {
log.debug("读取坎级配置,坎级:"+levels.getLevelNum());
configArr = levelsConfig.getLevelConfigs();
}
// 获取命中的坎级
List<TzcRebateLevels> hitLevelsList = new ArrayList<>();
for (TzcRebateLevels lv : allRebateLvList) {
for (String levelNum : configArr) {
if (lv.getLevelNum().toString().equals(levelNum)){
hitLevelsList.add(lv);
break;
}
}
}
// 加载返利参数
List<Long> hitLevelsIds = hitLevelsList.stream().map(TzcRebateLevels::getId).collect(Collectors.toList());
List<TzcRebateLevelsArgument> argumentList = tzcRebateLevelsArgumentService.list(
new LambdaQueryWrapper<TzcRebateLevelsArgument>()
.eq(TzcRebateLevelsArgument::getRebateId, levels.getRebateId())
.in(TzcRebateLevelsArgument::getLevelId,hitLevelsIds)
);
Map<Long,List<TzcRebateLevelsArgument>> argumentListMap = argumentList.stream()
.collect(Collectors.groupingBy(TzcRebateLevelsArgument::getLevelId));
// 进行返利叠加
List<TzcRebateLevelAmountDTO> levelAmountDTOList = new ArrayList<>();
for (TzcRebateLevels rebateLevels : hitLevelsList) {
log.debug("读取坎级配置,坎级:"+rebateLevels.getLevelNum());
List<TzcRebateLevelsArgument> arguments = argumentListMap.get(rebateLevels.getId());
TzcRebateLevelsArgument currentArgument = null;
for (TzcRebateLevelsArgument argument : arguments) {
if (argument.getBusinessType().equals(argType.name())){
currentArgument = argument;
break;
}
}
if (currentArgument==null){
log.error("没有命中坎级参数:"+argType.name());
continue;
}
TzcRebateLevelAmountDTO rebateLevelsDTO = CopierUtil.copy(rebateLevels,new TzcRebateLevelAmountDTO());
rebateLevelsDTO.setArgument(currentArgument);
rebateLevelsDTO.setMaxReturn(currentArgument.getMaxReturn());
// 选择的策略:0-百分比;1-固定金额
if (currentArgument.getRateAmtFlag().equals(1)){
rebateLevelsDTO.setReturnAmt(currentArgument.getReturnFixed());
}else if (currentArgument.getRateAmtFlag().equals(0)){
//目标销量维度:0-总量;1-增量
if (currentArgument.getSumAddFlag().equals(0)){
BigDecimal rs = dispatchAmt.multiply(currentArgument.getReturnRate())
.divide(BigDecimal.valueOf(100),2,RoundingMode.HALF_UP);
rebateLevelsDTO.setReturnAmt(rs);
}else if (currentArgument.getSumAddFlag().equals(1)){
// 增量 = (发货金额 - 同比发货金额) * 返利比例 / 100
BigDecimal rs = dispatchAmt.subtract(sameDispatchAmt)
.multiply(currentArgument.getReturnRate())
.divide(BigDecimal.valueOf(100),2,RoundingMode.HALF_UP);
if (rs.compareTo(BigDecimal.ZERO)>0){
rebateLevelsDTO.setReturnAmt(rs);
}else {
rebateLevelsDTO.setReturnAmt(BigDecimal.ZERO);
log.warn("返利参数TzcRebateLevelsArgument-ID:{},返利金额小于0",currentArgument.getId());
}
}
}
// 记录坎级返利金额
rebateLevelsDTO.setLevelReturnAmt(rebateLevelsDTO.getReturnAmt());
levelAmountDTOList.add(rebateLevelsDTO);
}
return levelAmountDTOList;
}
}

82
cms-modules/cms-system/src/main/java/com/qs/serve/modules/tzc/service/impl/TzcRebateApplication4VerificationServiceImpl.java

@ -0,0 +1,82 @@
package com.qs.serve.modules.tzc.service.impl;
import com.qs.serve.modules.tbs.entity.TbsActivity;
import com.qs.serve.modules.tbs.mapper.TbsActivityMapper;
import com.qs.serve.modules.tbs.service.*;
import com.qs.serve.modules.tzc.consts.TzcArgTypes;
import com.qs.serve.modules.tzc.entity.TzcRebatePeriod;
import com.qs.serve.modules.tzc.entity.dto.TzcRebateCalculateDTO;
import com.qs.serve.modules.tzc.entity.dto.TzcRebateLevelAmountDTO;
import com.qs.serve.modules.tzc.service.*;
import com.qs.serve.modules.vtb.entity.VtbVerification;
import com.qs.serve.modules.vtb.mapper.VtbVerificationMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
/**
* @author YenHex
* @since 2025/5/7
*/
@Slf4j
@Service
@AllArgsConstructor
public class TzcRebateApplication4VerificationServiceImpl implements TzcRebateApplication4VerificationService {
private final TzcRebateApplication4CostService tzcRebateApplication4CostService;
private final VtbVerificationMapper vtbVerificationMapper;
private final TbsActivityMapper tbsActivityMapper;
private final TbsCostApplyService tbsCostApplyService;
private final TbsActivityService tbsActivityService;
private final TbsActivityCenterService tbsActivityCenterService;
private final TbsActivitySubjectService tbsActivitySubjectService;
private final TbsActivityGoodsService tbsActivityGoodsService;
private final TbsActivityCenterGoodsService tbsActivityCenterGoodsService;
private final TzcRebateService tzcRebateService;
private final TzcRebateSubjectService tzcRebateSubjectService;
private final TzcRebateCenterService tzcRebateCenterService;
private final TzcRebatePeriodService tzcRebatePeriodService;
private final TzcRebateLevelsArgumentService tzcRebateLevelsArgumentService;
private final TzcRebateGoodsService tzcRebateGoodsService;
private final TzcRebateLevelsConfigService tzcRebateLevelsConfigService;
private final TzcRebateLevelsService tzcRebateLevelsService;
@Override
public TzcRebateCalculateDTO getActivityRebateAmount(Long activityId, BigDecimal dispatchAmt) {
TbsActivity activity = tbsActivityMapper.selectById(activityId);
TzcRebatePeriod rebatePeriod = tzcRebatePeriodService.getById(activity.getRebatePeriodId());
BigDecimal sameDispatchAmt = rebatePeriod.getSamePeriodAmount();
// 获取最高命中的坎级
TzcRebateCalculateDTO calculateDTO = tzcRebateApplication4CostService.getHitRebateMaxLevel(
dispatchAmt, sameDispatchAmt, activity.getRebatePeriodId());
if (calculateDTO != null){
List<TzcRebateLevelAmountDTO> levelAmountList = tzcRebateApplication4CostService.calculateRebate(
calculateDTO,dispatchAmt, sameDispatchAmt, TzcArgTypes.LevelReturn);
// 计算已用的优惠
for (TzcRebateLevelAmountDTO amountDTO : levelAmountList) {
// 返利金额
BigDecimal returnAmt = amountDTO.getReturnAmt();
// 设置的最高返利金额
BigDecimal maxReturn = amountDTO.getMaxReturn();
// 已核销金额
BigDecimal verificationAmt = vtbVerificationMapper.totalActivityVerification(activityId+"");
// 剩余的可返利金额
BigDecimal surplusReturnAmt = maxReturn.subtract(verificationAmt);
if (returnAmt.compareTo(surplusReturnAmt) > 0){
amountDTO.setReturnAmt(surplusReturnAmt);
}
amountDTO.setVerificationAmt(verificationAmt);
}
calculateDTO.setLevelAmountList(levelAmountList);
}
return calculateDTO;
}
}
Loading…
Cancel
Save