|
|
@@ -2,6 +2,7 @@ package com.ruoyi.subsidy.service.impl;
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
import com.ruoyi.common.exception.ServiceException;
|
|
|
import com.ruoyi.common.utils.BeanCopyUtils;
|
|
|
import com.ruoyi.common.utils.MathUtils;
|
|
|
@@ -15,9 +16,13 @@ import com.ruoyi.onlineorder.domain.OnlineOrder;
|
|
|
import com.ruoyi.onlineorder.service.IOnlineOrderService;
|
|
|
import com.ruoyi.subsidy.domain.SubsidyCutIn;
|
|
|
import com.ruoyi.subsidy.domain.SubsidyMode;
|
|
|
+import com.ruoyi.subsidy.enums.SubsidyCancelType;
|
|
|
import com.ruoyi.subsidy.enums.SubsidyStatus;
|
|
|
import com.ruoyi.subsidy.service.ISubsidyCutInService;
|
|
|
import com.ruoyi.subsidy.service.ISubsidyModeService;
|
|
|
+import com.ruoyi.user.domain.bo.UserChangeBalanceBo;
|
|
|
+import com.ruoyi.user.enums.BalanceSourceType;
|
|
|
+import com.ruoyi.user.service.IUserService;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import org.springframework.context.annotation.Lazy;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
@@ -30,6 +35,7 @@ import com.ruoyi.subsidy.exception.SubsidyQueueExceptionEnum;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
import java.math.BigDecimal;
|
|
|
+import java.util.Date;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Collection;
|
|
|
@@ -47,7 +53,7 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
private final SubsidyQueueMapper baseMapper;
|
|
|
@Lazy
|
|
|
@Resource
|
|
|
- private ISubsidyModeService subsidyModeService;
|
|
|
+ private ISubsidyModeService subsidyModeService;
|
|
|
|
|
|
@Lazy
|
|
|
@Resource
|
|
|
@@ -57,6 +63,10 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
@Resource
|
|
|
private ISubsidyCutInService subsidyCutInService;
|
|
|
|
|
|
+ @Lazy
|
|
|
+ @Resource
|
|
|
+ private IUserService userService;
|
|
|
+
|
|
|
/**
|
|
|
* 查询补贴排队分页
|
|
|
*
|
|
|
@@ -101,7 +111,7 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
lqw.eq(bo.getSubsidyPoints() != null, SubsidyQueue::getSubsidyPoints, bo.getSubsidyPoints());
|
|
|
lqw.eq(bo.getSubsidyStatus() != null, SubsidyQueue::getSubsidyStatus, bo.getSubsidyStatus());
|
|
|
lqw.eq(bo.getCutIn() != null, SubsidyQueue::getCutIn, bo.getCutIn());
|
|
|
- lqw.eq(bo.getCancelled() != null, SubsidyQueue::getCancelled, bo.getCancelled());
|
|
|
+ lqw.eq(bo.getCancelled() != null, SubsidyQueue::getCancelled, bo.getCancelled());
|
|
|
lqw.eq(bo.getExchanged() != null, SubsidyQueue::getExchanged, bo.getExchanged());
|
|
|
lqw.eq(bo.getExchangePoints() != null, SubsidyQueue::getExchangePoints, bo.getExchangePoints());
|
|
|
lqw.eq(bo.getActualPointsAfterCancel() != null, SubsidyQueue::getActualPointsAfterCancel, bo.getActualPointsAfterCancel());
|
|
|
@@ -121,7 +131,7 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
* @return 补贴排队
|
|
|
*/
|
|
|
@Override
|
|
|
- public SubsidyQueueVo queryById(Long queueId){
|
|
|
+ public SubsidyQueueVo queryById(Long queueId) {
|
|
|
return baseMapper.selectVoById(queueId);
|
|
|
}
|
|
|
|
|
|
@@ -132,9 +142,9 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
* @return 补贴排队
|
|
|
*/
|
|
|
@Override
|
|
|
- public SubsidyQueue loadById(Long queueId, Boolean tw){
|
|
|
+ public SubsidyQueue loadById(Long queueId, Boolean tw) {
|
|
|
SubsidyQueue info = this.baseMapper.selectById(queueId);
|
|
|
- if(ObjectUtil.isEmpty(info) && tw){
|
|
|
+ if (ObjectUtil.isEmpty(info) && tw) {
|
|
|
throw new ServiceException(SubsidyQueueExceptionEnum.SubsidyQueue_IS_NOT_EXISTS);
|
|
|
}
|
|
|
return info;
|
|
|
@@ -176,7 +186,7 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
*
|
|
|
* @param entity 实体类数据
|
|
|
*/
|
|
|
- private void validEntityBeforeSave(SubsidyQueue entity){
|
|
|
+ private void validEntityBeforeSave(SubsidyQueue entity) {
|
|
|
//TODO 做一些数据校验,如唯一约束
|
|
|
}
|
|
|
|
|
|
@@ -188,7 +198,7 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
*/
|
|
|
@Override
|
|
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
|
|
- if(isValid){
|
|
|
+ if (isValid) {
|
|
|
//TODO 做一些业务上的校验,判断是否需要校验
|
|
|
}
|
|
|
return baseMapper.deleteBatchIds(ids) > 0;
|
|
|
@@ -202,6 +212,12 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取商家当前排队人数
|
|
|
+ *
|
|
|
+ * @param businessId 商家id
|
|
|
+ * @return 排队人数
|
|
|
+ */
|
|
|
@Override
|
|
|
public Long validQueueCountAndLock(Long businessId) {
|
|
|
return this.baseMapper.validQueueCountAndLock(businessId);
|
|
|
@@ -210,7 +226,7 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
@Override
|
|
|
public void createQueue(OnlineOrder order) {
|
|
|
SubsidyMode currentMode = subsidyModeService.loadCurrentMode(order.getBusinessId());
|
|
|
- // 商家让利金额
|
|
|
+ // 商家总供让利金额
|
|
|
BigDecimal shouldSubsidyAmount = MathUtils.setScale(order.getPayAmount().doubleValue() * currentMode.getSubsidyRatio().doubleValue() / 100);
|
|
|
// 有效的第一个插队补贴数据
|
|
|
SubsidyCutIn firstSubsidyCutIn = subsidyCutInService.validFirstSubsidyCutIn(order.getBusinessId());
|
|
|
@@ -218,43 +234,209 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
|
|
|
BigDecimal subsidyCutIn = BigDecimal.ZERO;
|
|
|
//排队补贴金额
|
|
|
BigDecimal subsidyQueue = BigDecimal.ZERO;
|
|
|
+
|
|
|
+ // 当前有效排队人数
|
|
|
+ Long validQueueCount = this.validQueueCountAndLock(order.getBusinessId());
|
|
|
+ // 当前插队有效排队人数
|
|
|
+ Long validCutinCount = subsidyCutInService.validQueueCountAndLock(order.getBusinessId());
|
|
|
+
|
|
|
// 存在第一个补贴插队数据
|
|
|
- if(ObjectUtil.isNotNull(firstSubsidyCutIn))
|
|
|
- {
|
|
|
- subsidyCutIn = MathUtils.setScale(shouldSubsidyAmount.doubleValue() * firstSubsidyCutIn.getCutInRatio().doubleValue()/100);
|
|
|
+ if (ObjectUtil.isNotNull(firstSubsidyCutIn)) {
|
|
|
+ subsidyCutIn = MathUtils.setScale(shouldSubsidyAmount.doubleValue() * firstSubsidyCutIn.getCutInRatio().doubleValue() / 100);
|
|
|
}
|
|
|
//排队补贴金额 = 补贴金额 - 补贴插队金额
|
|
|
- subsidyQueue = MathUtils.subtract(shouldSubsidyAmount, subsidyCutIn);
|
|
|
+ subsidyQueue = MathUtils.subtract(shouldSubsidyAmount, subsidyCutIn);
|
|
|
|
|
|
- // 消费者最高补贴
|
|
|
- BigDecimal amountSubsidy = MathUtils.setScale(order.getPayAmount().doubleValue()* currentMode.getAmountSubsidyRatio().doubleValue()/100);
|
|
|
+ // 当前消费者最高补贴
|
|
|
+ BigDecimal amountSubsidy = MathUtils.setScale(order.getPayAmount().doubleValue() * currentMode.getAmountSubsidyRatio().doubleValue() / 100);
|
|
|
// 排队第一名默认补贴金额
|
|
|
+ BigDecimal firstSubsidy = subsidyQueue;
|
|
|
|
|
|
- // 当前有效排队人数
|
|
|
- Long validQueueCount = this.validQueueCountAndLock(order.getBusinessId());
|
|
|
+ // 创建自己的排队已完成
|
|
|
+ createSelfQueueHandle(order, amountSubsidy, validQueueCount);
|
|
|
+ if (!currentMode.getSharedMode()) {
|
|
|
|
|
|
- // 排队第一名补贴金额
|
|
|
- BigDecimal firstSubsidy = subsidyQueue;
|
|
|
- if(!currentMode.getSharedMode())
|
|
|
- {
|
|
|
- //非均摊模式
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ //排队实际补贴(非均摊模式)
|
|
|
+ BigDecimal queueReturnAmount = queueActualSubsidyHandle(order.getBusinessId(), firstSubsidy);
|
|
|
+ // 如果实际补贴有盈余,商家的实际补贴金额 = 商家实际补贴金额 - 盈余
|
|
|
+ if (queueReturnAmount.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ shouldSubsidyAmount = MathUtils.subtract(shouldSubsidyAmount, queueReturnAmount);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
//均摊模式
|
|
|
- //排队第一名补贴金额
|
|
|
+ //排队第一名实际补贴金额
|
|
|
firstSubsidy = MathUtils.setScale(subsidyQueue.doubleValue() * currentMode.getFirstSubsidyRatio().doubleValue() / 100);
|
|
|
+ //排队实际补贴
|
|
|
+ BigDecimal queueReturnAmount = queueActualSubsidyHandle(order.getBusinessId(), firstSubsidy);
|
|
|
+ if (queueReturnAmount.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ shouldSubsidyAmount = MathUtils.subtract(shouldSubsidyAmount, queueReturnAmount);
|
|
|
+ }
|
|
|
+
|
|
|
//排队均摊补贴金额
|
|
|
- BigDecimal sharedSubsidy = MathUtils.subtract(subsidyQueue, firstSubsidy);
|
|
|
+ BigDecimal sharedSubsidy = MathUtils.subtract(subsidyQueue, firstSubsidy);
|
|
|
+ BigDecimal sharedSubsidyReturnAmount = sharedSubsidyHandle(order.getBusinessId(), sharedSubsidy);
|
|
|
+ if (sharedSubsidyReturnAmount.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ shouldSubsidyAmount = MathUtils.subtract(shouldSubsidyAmount, sharedSubsidyReturnAmount);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ if (ObjectUtil.isNotNull(firstSubsidyCutIn) && subsidyCutIn.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ BigDecimal returnAmount = subsidyCutInHandle(firstSubsidyCutIn, subsidyCutIn);
|
|
|
+ if (returnAmount.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ shouldSubsidyAmount = MathUtils.subtract(shouldSubsidyAmount, returnAmount);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if(ObjectUtil.isNotNull(firstSubsidyCutIn) && subsidyCutIn.compareTo(BigDecimal.ZERO)>0)
|
|
|
- {
|
|
|
+ // 有了商家的实际补贴金额,就可以计算商家当前这个订单的实际所得
|
|
|
+ // 实际所得 = 订单金额- 商家实际补贴金额(让利)- 平台服务费(5%)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private BigDecimal subsidyCutInHandle(SubsidyCutIn firstSubsidyCutIn, BigDecimal subsidyCutIn) {
|
|
|
+ return BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 均摊补贴金额
|
|
|
+ *
|
|
|
+ * @param businessId 商家id
|
|
|
+ * @param sharedSubsidy 排队均摊补贴金额
|
|
|
+ * @return 结余
|
|
|
+ */
|
|
|
+ private BigDecimal sharedSubsidyHandle(Long businessId, BigDecimal sharedSubsidy) {
|
|
|
+ return BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建自己的排队
|
|
|
+ *
|
|
|
+ * @param order
|
|
|
+ * @param amountSubsidy 当前消费者最高补贴
|
|
|
+ * @param validQueueCount 当前有效排队人数
|
|
|
+ */
|
|
|
+ private void createSelfQueueHandle(OnlineOrder order, BigDecimal amountSubsidy, Long validQueueCount) {
|
|
|
+ if (amountSubsidy.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ SubsidyQueueBo subsidyQueueBo = new SubsidyQueueBo();
|
|
|
+ subsidyQueueBo.setUserId(order.getUserId());
|
|
|
+ subsidyQueueBo.setUserMobile(order.getUserMobile());
|
|
|
+ subsidyQueueBo.setUserName(order.getUserName());
|
|
|
+ subsidyQueueBo.setOrderId(order.getOrderId());
|
|
|
+ subsidyQueueBo.setOrderNo(order.getOrderNo());
|
|
|
+ subsidyQueueBo.setCurrentBusinessId(order.getBusinessId());
|
|
|
+ subsidyQueueBo.setCurrentBusinessName(order.getBusinessName());
|
|
|
+ subsidyQueueBo.setOriginalBusinessId(order.getBusinessId());
|
|
|
+ subsidyQueueBo.setOriginalBusinessName(order.getBusinessName());
|
|
|
+ subsidyQueueBo.setPayAmount(order.getOrderAmount());
|
|
|
+ subsidyQueueBo.setShouldSubsidyAmount(amountSubsidy);
|
|
|
+ subsidyQueueBo.setActualSubsidyAmount(BigDecimal.ZERO);
|
|
|
+ subsidyQueueBo.setSubsidyPoints(order.getSendPoint());
|
|
|
+ subsidyQueueBo.setSubsidyStatus(SubsidyStatus.WAITING);
|
|
|
+ subsidyQueueBo.setCutIn(false);
|
|
|
+ subsidyQueueBo.setCancelled(false);
|
|
|
+ subsidyQueueBo.setExchanged(false);
|
|
|
+ subsidyQueueBo.setExchangePoints(BigDecimal.ONE);
|
|
|
+ subsidyQueueBo.setActualPointsAfterCancel(BigDecimal.ZERO);
|
|
|
+ subsidyQueueBo.setConsumeTime(order.getPayTime());
|
|
|
+ subsidyQueueBo.setCancelType(SubsidyCancelType.NO);
|
|
|
+ subsidyQueueBo.setQueueOrder(validQueueCount.intValue() + 1);
|
|
|
+ this.insertByBo(subsidyQueueBo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 排队实际补贴(非均摊模式)
|
|
|
+ *
|
|
|
+ * @param businessId 商家id
|
|
|
+ * @param firstSubsidy 排队第一名实际补贴金额
|
|
|
+ * @return 结余
|
|
|
+ */
|
|
|
+ private BigDecimal queueActualSubsidyHandle(Long businessId, BigDecimal firstSubsidy) {
|
|
|
+ while (true) {
|
|
|
+ if (firstSubsidy.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ return BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ SubsidyQueue firstQueue = this.validFirstQueue(businessId);
|
|
|
+ if (ObjectUtil.isNull(firstQueue)) {
|
|
|
+ return firstSubsidy;
|
|
|
+ }
|
|
|
+ //应补贴金额
|
|
|
+ BigDecimal shouldSubsidyAmount = firstQueue.getShouldSubsidyAmount();
|
|
|
+ //已补贴金额
|
|
|
+ BigDecimal actualSubsidyAmount = firstQueue.getActualSubsidyAmount();
|
|
|
+ //当前排队用户的剩余补贴金额
|
|
|
+ BigDecimal currentQueueSubsidyAmount = MathUtils.subtract(shouldSubsidyAmount, actualSubsidyAmount);
|
|
|
+ BigDecimal actualAddSubsidyAmount = BigDecimal.ZERO;
|
|
|
+ if (firstSubsidy.compareTo(currentQueueSubsidyAmount) >= 0) {
|
|
|
+ //如果超出了应补贴金额=====================//
|
|
|
+ //计算给下一个排队用户的补贴金额
|
|
|
+ firstSubsidy = MathUtils.subtract(firstSubsidy, currentQueueSubsidyAmount);
|
|
|
+ firstQueue.setActualSubsidyAmount(shouldSubsidyAmount);
|
|
|
+ firstQueue.setSubsidyStatus(SubsidyStatus.COMPLETE);
|
|
|
+ firstQueue.setQueueOrder(0);
|
|
|
+ firstQueue.setCompleteTime(new Date());
|
|
|
+ this.baseMapper.updateById(firstQueue);
|
|
|
+ actualAddSubsidyAmount = currentQueueSubsidyAmount;
|
|
|
+
|
|
|
+ validQueueOrderRearrange(businessId,firstQueue.getQueueId());
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //如果小于应补贴金额=====================//
|
|
|
+ actualAddSubsidyAmount = firstSubsidy;
|
|
|
+ firstSubsidy = BigDecimal.ZERO;
|
|
|
+ firstQueue.setActualSubsidyAmount(MathUtils.add(actualSubsidyAmount, firstSubsidy));
|
|
|
+ this.baseMapper.updateById(firstQueue);
|
|
|
+ }
|
|
|
+
|
|
|
+ //用户余额增加
|
|
|
+ userService.changeUserBalance(UserChangeBalanceBo.builder()
|
|
|
+ .userId(firstQueue.getUserId())
|
|
|
+ .entryValue(actualAddSubsidyAmount)
|
|
|
+ .isAdd(true)
|
|
|
+ .sourceType(BalanceSourceType.SUBSIDY)
|
|
|
+ .sourceId(firstQueue.getOrderId())
|
|
|
+ .sourceCode(firstQueue.getOrderNo())
|
|
|
+ .remark("消费排队补贴")
|
|
|
+ .build());
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 排队顺序重新排序
|
|
|
+ *
|
|
|
+ * @param businessId 商家id
|
|
|
+ * @param excludeQueueId 排队id
|
|
|
+ */
|
|
|
+ private void validQueueOrderRearrange(Long businessId, Long excludeQueueId) {
|
|
|
+ SubsidyQueue branchQueue = new SubsidyQueue();
|
|
|
+ branchQueue.setQueueOrder(branchQueue.getQueueOrder() - 1);
|
|
|
+
|
|
|
+ this.baseMapper.update(branchQueue, new LambdaUpdateWrapper<SubsidyQueue>()
|
|
|
+ .eq(SubsidyQueue::getCurrentBusinessId, businessId)
|
|
|
+ .eq(SubsidyQueue::getSubsidyStatus, SubsidyStatus.WAITING)
|
|
|
+ .ne(SubsidyQueue::getQueueId, excludeQueueId)
|
|
|
+ .orderByAsc(SubsidyQueue::getQueueOrder)
|
|
|
+ .set(SubsidyQueue::getQueueOrder, branchQueue.getQueueOrder())
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前商家的第一个有效的排队数据
|
|
|
+ *
|
|
|
+ * @param businessId 商家id
|
|
|
+ * @return 排队
|
|
|
+ */
|
|
|
+ private SubsidyQueue validFirstQueue(Long businessId) {
|
|
|
+ return this.baseMapper.selectOne(new LambdaQueryWrapper<SubsidyQueue>()
|
|
|
+ .eq(SubsidyQueue::getCurrentBusinessId, businessId)
|
|
|
+ .eq(SubsidyQueue::getSubsidyStatus, SubsidyStatus.WAITING)
|
|
|
+ .eq(SubsidyQueue::getCutIn, false)
|
|
|
+ .orderByAsc(SubsidyQueue::getQueueOrder)
|
|
|
+ .last("limit 1")
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
|
|
|
}
|