|
|
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|
|
|
import com.qs.serve.common.model.consts.SysConfigKey; |
|
|
|
import com.qs.serve.common.util.Assert; |
|
|
|
import com.qs.serve.common.util.CollectionUtil; |
|
|
|
import com.qs.serve.common.util.CopierUtil; |
|
|
|
import com.qs.serve.modules.bms.entity.BmsSubject; |
|
|
|
import com.qs.serve.modules.bms.entity.BmsSupplier; |
|
|
|
import com.qs.serve.modules.bms.service.BmsSupplierService; |
|
|
@ -14,6 +15,7 @@ import com.qs.serve.modules.tbs.common.util.TbsBudgetCostUtil; |
|
|
|
import com.qs.serve.modules.tbs.entity.*; |
|
|
|
import com.qs.serve.modules.tbs.entity.bo.TbsActivityBo; |
|
|
|
import com.qs.serve.modules.tbs.entity.dto.TbsBudgetCostResult; |
|
|
|
import com.qs.serve.modules.tbs.entity.vo.TbsBudgetMatchVo; |
|
|
|
import com.qs.serve.modules.tbs.entity.vo.TbsBudgetTableVo; |
|
|
|
import com.qs.serve.modules.tbs.mapper.TbsActivityGoodsMapper; |
|
|
|
import com.qs.serve.modules.tbs.mapper.TbsActivityMapper; |
|
|
@ -53,8 +55,7 @@ public class TbsActivityApplicationService { |
|
|
|
* @param activityBo |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
public TbsBudgetCostResult matchBudgetCostResult(Boolean throwEx, TbsActivityBo activityBo){ |
|
|
|
BmsSupplier supplier = supplierService.getById(activityBo.getSupplierId()); |
|
|
|
public TbsBudgetMatchVo matchBudgetCostResult(Boolean throwEx, TbsActivityBo activityBo){ |
|
|
|
//允许超出预算标识
|
|
|
|
boolean overspend = configService.getByKey(SysConfigKey.TbsBudgetOverspend).getConfigValue().equals("1"); |
|
|
|
//考核期有关的预算id,判断逻辑为活动需要允许在
|
|
|
@ -71,14 +72,6 @@ public class TbsActivityApplicationService { |
|
|
|
.collect(Collectors.groupingBy(TbsBudgetCostItem::getScheduleItemBudgetId)); |
|
|
|
List<TbsActivityGoods> activityGoodsList = activityService.buildActGoodsList(activityBo,null,null); |
|
|
|
//构建预算费用占用明细
|
|
|
|
Map<Long, BmsSubject> subjectMap = new HashMap<>(); |
|
|
|
List<TbsActivitySubject> activitySubjects = new ArrayList<>(); |
|
|
|
List<TbsActivityCenter> activityCenterList = new ArrayList<>(); |
|
|
|
Map<String, TbsCenterDto> centerDtoMap = new HashMap<>(); |
|
|
|
activityService.initSubjectAndCenter(activityBo,subjectMap,centerDtoMap,activitySubjects,activityCenterList,null,null); |
|
|
|
Map<String,BigDecimal> checkAmountMap = new HashMap<>(); |
|
|
|
List<TbsActivityCenterGoods> activityCenterGoodsList = new ArrayList<>(); |
|
|
|
activityService.initCenterGoods(activityBo,subjectMap,centerDtoMap,checkAmountMap,activityGoodsList,activityCenterGoodsList,null,new TbsActivity(),supplier); |
|
|
|
// 加载所有条件
|
|
|
|
List<TbsBudget> budgetList = new ArrayList<>(); |
|
|
|
if(budgetIds.size()>0){ |
|
|
@ -90,53 +83,77 @@ public class TbsActivityApplicationService { |
|
|
|
List<TbsBudget> noConditionBudgetList = new ArrayList<>(); |
|
|
|
boolean budgetNoCondition = this.loadConditionByBudgetsAndMatch(budgetList, noConditionBudgetList); |
|
|
|
//预算条件需包含活动条件, Map结构:活动id->满足的预算id列表
|
|
|
|
List<Long> activityAllowBudgetIds = this.buildActivityBudgetMap(activityCenterGoodsList, budgetList, noConditionBudgetList); |
|
|
|
List<Long> activityAllowBudgetIds = this.buildActivityBudgetMap(activityGoodsList, budgetList, noConditionBudgetList); |
|
|
|
//活动拦截
|
|
|
|
this.handleNoBudgetActivity(throwEx, overspend, budgetNoCondition,activityAllowBudgetIds); |
|
|
|
//统计当前活动前置项占用预算
|
|
|
|
Map<Long,BigDecimal> counterMap = new HashMap<>(); |
|
|
|
//匹配预算主要方法
|
|
|
|
final List<TbsActivityCenterGoods> actMatchList = new ArrayList<>(); |
|
|
|
final List<TbsActivityCenterGoods> actUnMatchList = new ArrayList<>(); |
|
|
|
for (TbsActivityCenterGoods activityCostItem : activityCenterGoodsList) { |
|
|
|
this.matchActivityMain(activityCostItem,throwEx, overspend, scheduleItemList, hisCostGroupByItemBudget, budgetList, |
|
|
|
noConditionBudgetList, counterMap, actMatchList, actUnMatchList,activityAllowBudgetIds); |
|
|
|
Map<Long,List<TbsScheduleItemBudget>> scheduleItemBudgetMap = scheduleItemList.stream() |
|
|
|
.collect(Collectors.groupingBy(TbsScheduleItemBudget::getBudgetId)); |
|
|
|
TbsBudgetMatchVo budgetMatchVo = new TbsBudgetMatchVo(); |
|
|
|
BigDecimal totalAllAmount = BigDecimal.ZERO; |
|
|
|
BigDecimal totalAllHisAmount = BigDecimal.ZERO; |
|
|
|
if(CollectionUtil.isNotEmpty(activityAllowBudgetIds)){ |
|
|
|
TbsBudget budget = null; |
|
|
|
List<TbsBudgetMatchVo.BudgetVo> matchVos = new ArrayList<>(); |
|
|
|
for (Long allowBudgetId : activityAllowBudgetIds) { |
|
|
|
for (TbsBudget budget2 : budgetList) { |
|
|
|
if(allowBudgetId.equals(budget2.getId())){ |
|
|
|
budget = budget2; |
|
|
|
} |
|
|
|
List<TbsBudgetCostItem> budgetMatchList = actMatchList.stream() |
|
|
|
.map(TbsActivityCenterGoods::toBudgetCostItem).collect(Collectors.toList()); |
|
|
|
List<TbsBudgetCostItem> budgetUnMatchList = actUnMatchList.stream() |
|
|
|
.map(TbsActivityCenterGoods::toBudgetCostItem).collect(Collectors.toList()); |
|
|
|
TbsBudgetCostResult result = new TbsBudgetCostResult(); |
|
|
|
result.setBudgetMatchList(budgetMatchList); |
|
|
|
result.setBudgetUnMatchList(budgetUnMatchList); |
|
|
|
return result; |
|
|
|
break; |
|
|
|
} |
|
|
|
if(budget!=null){ |
|
|
|
BigDecimal totalBudgetAmount = BigDecimal.ZERO; |
|
|
|
BigDecimal totalBudgetHisAmount = BigDecimal.ZERO; |
|
|
|
List<TbsScheduleItemBudget> itemBudgets = scheduleItemBudgetMap.get(budget.getId()); |
|
|
|
List<TbsBudgetMatchVo.ItemBudgetVo> itemBudgetVoList = new ArrayList<>(); |
|
|
|
for (TbsScheduleItemBudget itemBudget : itemBudgets) { |
|
|
|
List<TbsBudgetCostItem> hisCostItems = hisCostGroupByItemBudget.get(itemBudget.getId()); |
|
|
|
BigDecimal totalItemBudgetHis = TbsBudgetCostUtil.totalHisCost(hisCostItems); |
|
|
|
totalBudgetHisAmount = totalBudgetHisAmount.add(totalBudgetHisAmount); |
|
|
|
totalBudgetAmount = totalBudgetAmount.add(itemBudget.getBudgetAmount()); |
|
|
|
|
|
|
|
TbsBudgetMatchVo.ItemBudgetVo itemBudgetVo = CopierUtil.copy(itemBudget,new TbsBudgetMatchVo.ItemBudgetVo()); |
|
|
|
itemBudgetVo.setHisAmount(totalItemBudgetHis); |
|
|
|
itemBudgetVoList.add(itemBudgetVo); |
|
|
|
} |
|
|
|
TbsBudgetMatchVo.BudgetVo matchVo = CopierUtil.copy(budget,new TbsBudgetMatchVo.BudgetVo()); |
|
|
|
matchVo.setTotalAmount(totalBudgetAmount); |
|
|
|
matchVo.setTotalHisAmount(totalBudgetHisAmount); |
|
|
|
matchVo.setItemBudgetVoList(itemBudgetVoList); |
|
|
|
matchVos.add(matchVo); |
|
|
|
totalAllAmount = totalAllAmount.add(totalBudgetAmount); |
|
|
|
totalAllHisAmount = totalBudgetHisAmount.add(totalBudgetHisAmount); |
|
|
|
} |
|
|
|
} |
|
|
|
budgetMatchVo.setBudgetVoList(matchVos); |
|
|
|
budgetMatchVo.setUsedAmount(totalAllHisAmount); |
|
|
|
budgetMatchVo.setTotalAmount(totalAllAmount); |
|
|
|
} |
|
|
|
return budgetMatchVo; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 预算条件需包含活动条件, Map结构:活动id->满足的预算id列表 |
|
|
|
* @param centerGoodsList |
|
|
|
* @param activityGoodsList |
|
|
|
* @param budgetList |
|
|
|
* @param noConditionBudgetList |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
private List<Long> buildActivityBudgetMap(List<TbsActivityCenterGoods> centerGoodsList, |
|
|
|
private List<Long> buildActivityBudgetMap(List<TbsActivityGoods> activityGoodsList, |
|
|
|
List<TbsBudget> budgetList, |
|
|
|
List<TbsBudget> noConditionBudgetList) { |
|
|
|
List<Long> budgetIdsOfActivity = new ArrayList<>(); |
|
|
|
if(CollectionUtil.isEmpty(noConditionBudgetList)){ |
|
|
|
budgetIdsOfActivity.addAll(noConditionBudgetList.stream().map(TbsBudget::getId).collect(Collectors.toList())); |
|
|
|
} |
|
|
|
Map<String,List<TbsActivityCenterGoods>> activityCenterGoodsListMap = centerGoodsList.stream().collect(Collectors.groupingBy(a->a.getTargetType()+":"+a.getTargetId())); |
|
|
|
for (TbsBudget budget : budgetList) { |
|
|
|
if(budget.getConditionFlag().equals(1)){ |
|
|
|
List<TbsBudgetCondition> budgetConditionList = budget.getBudgetConditionList(); |
|
|
|
boolean hasNoMatch = false; |
|
|
|
for (String key : activityCenterGoodsListMap.keySet()) { |
|
|
|
List<TbsActivityCenterGoods> centerGoods = activityCenterGoodsListMap.get(key); |
|
|
|
TbsActivityCenterGoods activityCenterGoods = centerGoods.get(0); |
|
|
|
for (TbsActivityGoods activityGoods : activityGoodsList) { |
|
|
|
boolean matchGoods = false; |
|
|
|
for (TbsBudgetCondition budgetCondition : budgetConditionList) { |
|
|
|
if(activityCenterGoods.getTargetLevelPathIds().contains(budgetCondition.getTargetLevelPathIds())){ |
|
|
|
if(activityGoods.getTargetLevelPathIds().contains(budgetCondition.getTargetLevelPathIds())){ |
|
|
|
matchGoods = true; |
|
|
|
break; |
|
|
|
} |
|
|
@ -154,146 +171,6 @@ public class TbsActivityApplicationService { |
|
|
|
return budgetIdsOfActivity; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 匹配的主要方法 |
|
|
|
* @param activityCostItem 活动项 |
|
|
|
* @param throwEx 预算不够时抛出异常 |
|
|
|
* @param overspend 超值标识 |
|
|
|
* @param scheduleItemBudgets 时间区间条件 |
|
|
|
* @param hisCostGroupByItemBudget 历史费用组 |
|
|
|
* @param allBudgetList 所有预算 |
|
|
|
* @param noConditionBudgetList 没有条件的预算列表 |
|
|
|
* @param counterMap 历史预算占用 |
|
|
|
* @param actMatchList 匹配预算占用的费用(含超支预算) |
|
|
|
* @param actUnMatchList 没有匹配预算的费用 |
|
|
|
* @param allowBudgetIds 满足当前活动项的费用idMap |
|
|
|
*/ |
|
|
|
private void matchActivityMain(TbsActivityCenterGoods activityCostItem, |
|
|
|
Boolean throwEx, |
|
|
|
boolean overspend, |
|
|
|
List<TbsScheduleItemBudget> scheduleItemBudgets, |
|
|
|
Map<Long, List<TbsBudgetCostItem>> hisCostGroupByItemBudget, |
|
|
|
final List<TbsBudget> allBudgetList, |
|
|
|
List<TbsBudget> noConditionBudgetList, |
|
|
|
Map<Long, BigDecimal> counterMap, |
|
|
|
final List<TbsActivityCenterGoods> actMatchList, |
|
|
|
final List<TbsActivityCenterGoods> actUnMatchList, |
|
|
|
final List<Long> allowBudgetIds) { |
|
|
|
List<TbsBudget> budgetList = allBudgetList.stream().filter(obj->allowBudgetIds.contains(obj.getId())).collect(Collectors.toList()); |
|
|
|
//PS:排序规则:优先为时间条件,其次匹配品牌条件
|
|
|
|
//按品类条件,提取可用预算(列表已按小维度到大维度排列)
|
|
|
|
List<TbsBudget> currentItemBudgetList = this.filterMatchGoodsCondition(budgetList, activityCostItem); |
|
|
|
//关联无条件预算
|
|
|
|
currentItemBudgetList.addAll(noConditionBudgetList); |
|
|
|
//提取可用预算的考核期
|
|
|
|
List<TbsScheduleItemBudget> currentScheduleItemBudgets = new ArrayList<>(); |
|
|
|
for (TbsBudget budget : currentItemBudgetList) { |
|
|
|
for (TbsScheduleItemBudget scheduleItemBudget : scheduleItemBudgets) { |
|
|
|
if(scheduleItemBudget.getBudgetId().equals(budget.getId())){ |
|
|
|
currentScheduleItemBudgets.add(scheduleItemBudget); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
//检测是否有是否足够预算
|
|
|
|
BigDecimal goodsAmount = activityCostItem.getCenterGoodsAmount(); |
|
|
|
if(CollectionUtil.isNotEmpty(currentScheduleItemBudgets)){ |
|
|
|
boolean isMatch = false; |
|
|
|
for (TbsScheduleItemBudget itemBudget : currentScheduleItemBudgets) { |
|
|
|
//历史费用
|
|
|
|
BigDecimal totalUsed = TbsBudgetCostUtil.totalHisCost(hisCostGroupByItemBudget.get(itemBudget.getId())); |
|
|
|
//当前项费用
|
|
|
|
BigDecimal budgetAmount = itemBudget.getBudgetAmount(); |
|
|
|
//前置费用
|
|
|
|
BigDecimal lastAmount = counterMap.get(itemBudget.getId()); |
|
|
|
if(lastAmount==null){ |
|
|
|
lastAmount = BigDecimal.ZERO; |
|
|
|
} |
|
|
|
if(budgetAmount.subtract(lastAmount).subtract(totalUsed).compareTo(goodsAmount)>0){ |
|
|
|
activityCostItem.setBudgetId(itemBudget.getBudgetId()); |
|
|
|
activityCostItem.setScheduleId(itemBudget.getScheduleId()); |
|
|
|
activityCostItem.setScheduleItemId(itemBudget.getScheduleItemId()); |
|
|
|
activityCostItem.setScheduleItemBudgetId(itemBudget.getId()); |
|
|
|
isMatch = true; |
|
|
|
//记录当前费用使用考核期费用
|
|
|
|
lastAmount = lastAmount.add(goodsAmount); |
|
|
|
counterMap.put(itemBudget.getId(),lastAmount); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
//无匹配的预算
|
|
|
|
if(!isMatch){ |
|
|
|
if(overspend){ |
|
|
|
TbsScheduleItemBudget itemBudget = currentScheduleItemBudgets.get(0); |
|
|
|
activityCostItem.setBudgetId(itemBudget.getBudgetId()); |
|
|
|
activityCostItem.setScheduleId(itemBudget.getScheduleId()); |
|
|
|
activityCostItem.setScheduleItemId(itemBudget.getScheduleItemId()); |
|
|
|
activityCostItem.setScheduleItemBudgetId(itemBudget.getId()); |
|
|
|
//记录当前费用使用考核期费用
|
|
|
|
BigDecimal lastAmount = counterMap.get(itemBudget.getId()); |
|
|
|
if(lastAmount==null){ |
|
|
|
lastAmount = BigDecimal.ZERO; |
|
|
|
} |
|
|
|
lastAmount = lastAmount.add(goodsAmount); |
|
|
|
counterMap.put(itemBudget.getId(),lastAmount); |
|
|
|
}else if (throwEx){ |
|
|
|
Assert.throwEx("品类["+ activityCostItem.getTargetName()+"]预算不足"); |
|
|
|
} |
|
|
|
activityCostItem.setBudgetId(0L); |
|
|
|
activityCostItem.setScheduleId(0L); |
|
|
|
activityCostItem.setScheduleItemId(0L); |
|
|
|
activityCostItem.setScheduleItemBudgetId(0L); |
|
|
|
} |
|
|
|
actMatchList.add(activityCostItem); |
|
|
|
}else { |
|
|
|
if(throwEx){ |
|
|
|
Assert.throwEx("品类["+ activityCostItem.getTargetName()+"]无可用预算"); |
|
|
|
} |
|
|
|
if(overspend){ |
|
|
|
//添加到预算超支表
|
|
|
|
activityCostItem.setBudgetId(0L); |
|
|
|
activityCostItem.setScheduleId(0L); |
|
|
|
activityCostItem.setScheduleItemId(0L); |
|
|
|
activityCostItem.setScheduleItemBudgetId(0L); |
|
|
|
actUnMatchList.add(activityCostItem); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 按品类条件,提取可用预算 |
|
|
|
* @param budgetList |
|
|
|
* @param activityCostItem |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
@NotNull |
|
|
|
private List<TbsBudget> filterMatchGoodsCondition(List<TbsBudget> budgetList,TbsActivityCenterGoods activityCostItem) { |
|
|
|
String levelPath = activityCostItem.getTargetLevelPathIds(); |
|
|
|
Set<String> levelPathSet = new LinkedHashSet<>(); |
|
|
|
levelPathSet.add(levelPath); |
|
|
|
TbsBudgetCostUtil.buildPaths(levelPath,levelPathSet); |
|
|
|
List<TbsBudget> currentItemBudgetList = new ArrayList<>(); |
|
|
|
for (TbsBudget budget : budgetList) { |
|
|
|
if(budget.getConditionFlag().equals(1)){ |
|
|
|
List<TbsBudgetCondition> budgetConditionListByBudget = budget.getBudgetConditionList(); |
|
|
|
boolean unMatch = true; |
|
|
|
for (String conditionString : levelPathSet) { |
|
|
|
if(unMatch){ |
|
|
|
for (TbsBudgetCondition budgetCondition : budgetConditionListByBudget) { |
|
|
|
if(budgetCondition.getTargetLevelPathIds().contains(conditionString)){ |
|
|
|
currentItemBudgetList.add(budget); |
|
|
|
unMatch = false; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return currentItemBudgetList; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 1.加载所有的条件 |
|
|
|
* 2.匹配初无条件预算 |
|
|
|