VipFrontServiceImpl.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. package com.cyksj.service.vip.impl;
  2. import cn.hutool.core.date.DateTime;
  3. import cn.hutool.core.date.DateUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  6. import com.cyksj.common.constant.Constant;
  7. import com.cyksj.common.exception.BusinessRuntimeException;
  8. import com.cyksj.mapper.*;
  9. import com.cyksj.mapper.sys.SysConfigMapper;
  10. import com.cyksj.mapper.vip.VipGoodsSkuMapper;
  11. import com.cyksj.model.dto.VipDeductDto;
  12. import com.cyksj.model.entity.*;
  13. import com.cyksj.model.manage.views.GroupsRelationView;
  14. import com.cyksj.model.response.VipUserPageResp;
  15. import com.cyksj.service.user.UserBindRelationService;
  16. import com.cyksj.service.vip.VipFrontService;
  17. import com.ejlchina.searcher.BeanSearcher;
  18. import com.ejlchina.searcher.param.Operator;
  19. import com.ejlchina.searcher.util.MapUtils;
  20. import lombok.RequiredArgsConstructor;
  21. import lombok.extern.slf4j.Slf4j;
  22. import org.springframework.stereotype.Service;
  23. import java.math.BigDecimal;
  24. import java.math.RoundingMode;
  25. import java.util.*;
  26. import java.util.stream.Collectors;
  27. /**
  28. * 项目名: yhlxj2
  29. * 文件名: VipFrontServiceImpl
  30. * 创建者: JavaZou
  31. * 创建时间:2025/5/15 16:00
  32. */
  33. @Service
  34. @RequiredArgsConstructor
  35. @Slf4j
  36. public class VipFrontServiceImpl implements VipFrontService {
  37. private final SysConfigMapper sysConfigMapper;
  38. private final VipGoodsSkuMapper vipGoodsSkuMapper;
  39. private final UserBindRelationService userBindRelationService;
  40. private final BeanSearcher beanSearcher;
  41. private final GoodsDonSkuMapper skuMapper;
  42. private final ChatgptUserMapper chatgptUserMapper;
  43. private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;
  44. private final ClaudeUserMapper claudeUserMapper;
  45. private final OrderDonMapper orderDonMapper;
  46. private final GoodsDonSkuMapper goodsDonSkuMapper;
  47. @Override
  48. public void fillVipInfo(Long userId, VipUserPageResp vipUserPageResp) {
  49. SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.VIP_FEE_KEY).last("limit 1"));
  50. if (sysConfig != null && StrUtil.isNotBlank(sysConfig.getSysValue())) {
  51. vipUserPageResp.setVipFee(BigDecimal.valueOf(Integer.parseInt(sysConfig.getSysValue())));
  52. }
  53. if (userId == null) {
  54. return;
  55. }
  56. //可抵扣价格
  57. BigDecimal deductMoney = BigDecimal.ZERO;
  58. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  59. List<Long> vipSkuIds = vipGoodsSkuMapper.selectList(null).stream().map(VipGoodsSku::getSkuId).collect(Collectors.toList());
  60. //可有抵扣车票
  61. DateTime now = DateTime.now();
  62. //会员规格
  63. Set<Long> goodsIds = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class)
  64. .in(GoodsDonSku::getId, vipSkuIds)).stream().map(GoodsDonSku::getGoodsId).collect(Collectors.toSet());
  65. Number count = beanSearcher.searchCount(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getUserId, userIdList).op(Operator.InList).field(GroupsRelationView::getGoodsId, goodsIds).op(Operator.InList).field(GroupsRelationView::getExpiryTime, now).op(Operator.GreaterThan).build());
  66. //可抵扣车票
  67. if (count.intValue() > 0) {
  68. //处理vip抵扣金额
  69. VipDeductDto vipDeductDto = commonHandleVipDeductMoney(userIdList, goodsIds, 12);
  70. deductMoney = vipDeductDto.getDeductMoney();
  71. vipUserPageResp.setRelationUserViews(vipDeductDto.getRelationUserViews());
  72. }
  73. vipUserPageResp.setDeductMoney(deductMoney);
  74. }
  75. /**
  76. * 检查用户并获取订单抵扣金额
  77. */
  78. @Override
  79. public VipDeductDto checkAndGetOrderDeductMoney(Long userId, Integer months) {
  80. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  81. List<Long> vipSkuIds = vipGoodsSkuMapper.selectList(null).stream().map(VipGoodsSku::getSkuId).collect(Collectors.toList());
  82. //会员规格
  83. Set<Long> goodsIds = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class)
  84. .in(GoodsDonSku::getId, vipSkuIds)).stream().map(GoodsDonSku::getGoodsId).collect(Collectors.toSet());
  85. Number count = beanSearcher.searchCount(GroupsRelationView.class, MapUtils.builder()
  86. .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
  87. .field(GroupsRelationView::getGoodsId, goodsIds).op(Operator.InList)
  88. .field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
  89. .field(GroupsRelationView::getIsVip, false)
  90. .build());
  91. if (count.intValue() == 0) {
  92. throw BusinessRuntimeException.getInstance("暂无可抵扣AI车票");
  93. }
  94. VipDeductDto vipDeductDto = commonHandleVipDeductMoney(userIdList, goodsIds, months);
  95. return vipDeductDto;
  96. }
  97. private BigDecimal getVipMoney(Integer months) {
  98. SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.VIP_FEE_KEY).last("limit 1"));
  99. if (sysConfig == null || StrUtil.isEmpty(sysConfig.getSysValue())) {
  100. throw BusinessRuntimeException.getInstance("系统异常");
  101. }
  102. BigDecimal vipFee = BigDecimal.valueOf(Long.valueOf(sysConfig.getSysValue()));
  103. return vipFee.multiply(BigDecimal.valueOf(months));
  104. }
  105. /**
  106. * 统一处理vip抵扣金额
  107. */
  108. public VipDeductDto commonHandleVipDeductMoney(List<Long> userIdList, Set<Long> goodsIds, Integer months) {
  109. VipDeductDto vipDeductDto = new VipDeductDto();
  110. DateTime now = DateTime.now();
  111. List<Long> deductRelationIds = new ArrayList<>();
  112. BigDecimal deductMoney = BigDecimal.ZERO;
  113. BigDecimal vipMoney = getVipMoney(months);
  114. List<GroupsRelationView> relations = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
  115. .field(GroupsRelationView::getGoodsId, goodsIds).op(Operator.InList)
  116. .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
  117. .field(GroupsRelationView::getIsVip, false)
  118. .field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
  119. .orderBy(GroupsRelationView::getExpiryTime).desc()
  120. .build());
  121. Set<Long> deductGoodsIds = null;
  122. List<GroupsRelationView> deductRelations = null;
  123. for (GroupsRelationView relation : relations) {
  124. if (deductGoodsIds == null) {
  125. deductGoodsIds = new HashSet<>();
  126. }
  127. if (deductRelations == null) {
  128. deductRelations = new ArrayList<>();
  129. }
  130. Long goodsId = relation.getGoodsId();
  131. if (deductGoodsIds.contains(goodsId)) {
  132. continue;
  133. }
  134. Long skuId = relation.getSkuId();
  135. deductGoodsIds.add(goodsId);
  136. Long relationId = relation.getId();
  137. Date relationExpiryTime = relation.getExpiryTime();
  138. //GPT
  139. // if (goodsId == Constant.GPT_PLUS_GID) {
  140. // ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getRelationId, relationId).last("limit 1"));
  141. // if (chatgptUser != null) {
  142. // //获取抵扣金额
  143. // deductMoney = deductMoney.add(getFinalDeductMoney(relationId, relation.getSkuId(), chatgptUser.getRenewSkuId(), chatgptUser.getRenewOrderId(), chatgptUser.getRenewExpiryTime(), relation.getStartTime(), relationExpiryTime, now, userIdList));
  144. // }
  145. // } else if (goodsId == Constant.CLAUDE_PRO_GID) {
  146. // ClaudeUser claudeUser = claudeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeUser.class).eq(ClaudeUser::getRelationId, relationId).last("limit 1"));
  147. // if (claudeUser != null) {
  148. // //获取抵扣金额
  149. // deductMoney = deductMoney.add(getFinalDeductMoney(relationId, relation.getSkuId(), claudeUser.getRenewSkuId(), claudeUser.getRenewOrderId(), claudeUser.getRenewExpiryTime(), relation.getStartTime(), relationExpiryTime, now, userIdList));
  150. // }
  151. // } else {
  152. // //该车票抵扣金额
  153. // deductMoney = deductMoney.add(getDeductMoneyFromTicket(skuId, now, relation.getId(), relation.getStartTime(), relationExpiryTime));
  154. // }
  155. //该车票抵扣金额
  156. deductMoney = deductMoney.add(getDeductMoneyFromTicket(skuId, now, relation.getId(), relation.getStartTime(), relationExpiryTime));
  157. deductRelationIds.add(relationId);
  158. //可抵扣车票
  159. deductRelations.add(relation);
  160. //超出可抵扣的金额 直接返回
  161. if (deductMoney.compareTo(vipMoney) >= 0) {
  162. deductMoney = vipMoney;
  163. break;
  164. }
  165. }
  166. vipDeductDto.setDeductMoney(deductMoney);
  167. vipDeductDto.setDeductRelationIds(deductRelationIds);
  168. vipDeductDto.setRelationUserViews(deductRelations);
  169. return vipDeductDto;
  170. }
  171. /**
  172. * 获取最终抵扣金额
  173. */
  174. public BigDecimal getFinalDeductMoney(Long relationId, Long relationSkuId, Long renewSkuId, Long renewOrderId, Date renewExpiryTime, Date relationStartTime, Date relationExpiryTime, DateTime now, List<Long> userIdList) {
  175. BigDecimal deductMoney = BigDecimal.ZERO;
  176. //一个月当30天算单价 往上取整
  177. //续费规格
  178. if (renewSkuId != null) {
  179. OrderDon renewOrderDon = orderDonMapper.selectById(renewOrderId);
  180. GoodsDonSku sku = skuMapper.selectById(renewSkuId);
  181. Long betweenDay = DateUtil.betweenDay(now, renewExpiryTime, false) + 1;
  182. //当天购买的按规格原价抵扣
  183. if (now.toDateStr().equals(DateUtil.format(renewOrderDon.getCreatedTime(), "yyyy-MM-dd"))) {
  184. deductMoney = deductMoney.add(sku.getPrice());
  185. } else {
  186. BigDecimal single = sku.getPrice().divide(BigDecimal.valueOf(sku.getMonths()).multiply(BigDecimal.valueOf(30)), 0, RoundingMode.UP);
  187. //该车票抵扣金额
  188. BigDecimal renewDeductMoney = single.multiply(BigDecimal.valueOf(betweenDay));
  189. log.info("车票id:{}目前续费升级规格可抵扣的金额为:{}", relationId, renewDeductMoney);
  190. deductMoney = deductMoney.add(renewDeductMoney);
  191. }
  192. relationExpiryTime = DateUtil.offsetDay(relationExpiryTime, -betweenDay.intValue());
  193. //上一个续费升级规格
  194. List<OrderDon> orderDOns = orderDonRenewRecordMapper.getOtherRenewSkus(renewOrderId, relationId, userIdList);
  195. for (OrderDon orderDOn : orderDOns) {
  196. Long skuId = orderDOn.getSkuId();
  197. sku = skuMapper.selectById(skuId);
  198. BigDecimal upDeductMoney = sku.getPrice();
  199. log.info("车票id:{}目前次一级规格:{}可抵扣的金额为:{}", relationId, sku.getSpecVal(), upDeductMoney);
  200. deductMoney = deductMoney.add(upDeductMoney);
  201. if (sku.getDays() != null) {
  202. relationExpiryTime = DateUtil.offsetDay(relationExpiryTime, -sku.getDays());
  203. } else {
  204. relationExpiryTime = DateUtil.offsetMonth(relationExpiryTime, -sku.getMonths());
  205. }
  206. }
  207. }
  208. if (relationExpiryTime.after(DateTime.now())) {
  209. //该车票抵扣金额
  210. BigDecimal deductMoneyFromTicket = getDeductMoneyFromTicket(relationSkuId, now, relationId, relationStartTime, relationExpiryTime);
  211. deductMoney = deductMoney.add(deductMoneyFromTicket);
  212. }
  213. log.info("车票id:{}最终到期时间为:{}车票可返回 抵扣金额:{}", relationId, DateUtil.format(relationExpiryTime, "yyyy-MM-dd HH:mm:ss"), deductMoney);
  214. return deductMoney;
  215. }
  216. /**
  217. * 获取车票可抵扣金额
  218. */
  219. public BigDecimal getDeductMoneyFromTicket(Long skuId, DateTime now, Long relationId, Date relationStartTime, Date relationExpiryTime) {
  220. GoodsDonSku sku = skuMapper.selectById(skuId);
  221. BigDecimal single = sku.getPrice().divide(BigDecimal.valueOf(sku.getMonths()).multiply(BigDecimal.valueOf(30)), 0, RoundingMode.UP);
  222. Long betweenDay = DateUtil.betweenDay(now, relationExpiryTime, false) + 1;
  223. //当天购买的按规格原价抵扣
  224. if (now.toDateStr().equals(DateUtil.format(relationStartTime, "yyyy-MM-dd"))) {
  225. //并且没有续费 且未扣时长
  226. if (DateUtil.betweenDay(DateUtil.offsetMonth(relationStartTime, 1), relationExpiryTime, true) == 0) {
  227. return sku.getPrice();
  228. }
  229. }
  230. //该车票抵扣金额
  231. BigDecimal deductMoney = single.multiply(BigDecimal.valueOf(betweenDay));
  232. return deductMoney;
  233. }
  234. }