TradeAuctionOrderService.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. package com.izouma.nineth.service;
  2. import com.izouma.nineth.domain.*;
  3. import com.izouma.nineth.dto.PageQuery;
  4. import com.izouma.nineth.enums.*;
  5. import com.izouma.nineth.exception.BusinessException;
  6. import com.izouma.nineth.repo.CommissionRecordRepo;
  7. import com.izouma.nineth.repo.TradeAuctionOrderRepo;
  8. import com.izouma.nineth.repo.TradeAuctionRepo;
  9. import com.izouma.nineth.repo.UserRepo;
  10. import com.izouma.nineth.utils.JpaUtils;
  11. import lombok.AllArgsConstructor;
  12. import lombok.extern.slf4j.Slf4j;
  13. import org.apache.commons.lang3.StringUtils;
  14. import org.springframework.data.domain.Page;
  15. import org.springframework.scheduling.annotation.Scheduled;
  16. import org.springframework.stereotype.Service;
  17. import javax.transaction.Transactional;
  18. import java.math.BigDecimal;
  19. import java.math.RoundingMode;
  20. import java.time.LocalDateTime;
  21. import java.util.List;
  22. @Service
  23. @AllArgsConstructor
  24. @Slf4j
  25. public class TradeAuctionOrderService {
  26. private TradeAuctionOrderRepo tradeAuctionOrderRepo;
  27. private TradeAuctionService tradeAuctionService;
  28. private TradeAuctionRepo tradeAuctionRepo;
  29. private UserRepo userRepo;
  30. private UserBalanceService userBalanceService;
  31. private SysConfigService sysConfigService;
  32. private CommissionRecordRepo commissionRecordRepo;
  33. private static int orderCancelInterval = 210;
  34. public Page<TradeAuctionOrder> all(PageQuery pageQuery) {
  35. return tradeAuctionOrderRepo.findAll(JpaUtils.toSpecification(pageQuery, TradeAuctionOrder.class), JpaUtils
  36. .toPageRequest(pageQuery));
  37. }
  38. public TradeAuctionOrder create(Long auctionId, Long userId, BigDecimal price, AuctionPaymentType auctionPaymentType) {
  39. // if (tradeAuctionService.getStock(auctionId) < 1) {
  40. // throw new BusinessException("库存不足");
  41. // }
  42. TradeAuction tradeAuction = tradeAuctionRepo.findById(auctionId).orElseThrow(new BusinessException("未找到易拍活动"));
  43. User user = userRepo.findById(userId).orElseThrow(new BusinessException("暂无用户"));
  44. if (tradeAuction.getStock() < 1) {
  45. throw new BusinessException("库存不足");
  46. }
  47. if (tradeAuction.getCurrentOwnerId() != null & tradeAuction.getStatus() != TradeAuctionStatus.PURCHASED) {
  48. if (tradeAuction.getCurrentOwnerId().equals(userId)) {
  49. throw new BusinessException("不可竞价持有的易拍产品");
  50. }
  51. }
  52. if (LocalDateTime.now().compareTo(tradeAuction.getCurrentStartTime()) < 0) {
  53. throw new BusinessException("未到竞价时间");
  54. }
  55. if (!tradeAuction.getStatus().equals(TradeAuctionStatus.ONGOING) & !tradeAuction.getStatus()
  56. .equals(TradeAuctionStatus.PURCHASED)) {
  57. throw new BusinessException("易拍产品未处在竞价状态");
  58. }
  59. if (auctionPaymentType.equals(AuctionPaymentType.DEPOSIT)) {
  60. if (price.compareTo(tradeAuction.getNextPrice()) != 0) {
  61. throw new BusinessException("购买资格已经没有");
  62. }
  63. }
  64. tradeAuctionService.decreaseStock(auctionId, 1);
  65. BigDecimal serviceCharge = (BigDecimal.valueOf(3).multiply(tradeAuction.getNextPrice())
  66. .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP))
  67. .add(tradeAuction.getCurrentPrice().subtract(tradeAuction.getPrice()));
  68. if (auctionPaymentType.equals(AuctionPaymentType.PURCHASE_PRICE)) {
  69. price = tradeAuction.getPrice().subtract(tradeAuction.getCommission());
  70. }
  71. TradeAuctionOrder tradeAuctionOrder = TradeAuctionOrder.builder()
  72. .tradeAuctionId(tradeAuction.getId())
  73. .earnedPrice(price.subtract(tradeAuction.getPrice()))
  74. .serviceCharge(serviceCharge)
  75. .name(tradeAuction.getName())
  76. .nickname(user.getNickname())
  77. .paymentType(auctionPaymentType)
  78. .userId(user.getId())
  79. .originPrice(tradeAuction.getPrice())
  80. .currentPrice(tradeAuction.getCurrentPrice())
  81. .price(price)
  82. .paybackStatus(PaybackStatus.NOPASSED)
  83. .pic(tradeAuction.getPic())
  84. .source(AuctionSource.OFFICIAL)
  85. .status(AuctionOrderStatus.NOT_PAID)
  86. .purchasedPrice(tradeAuction.getCurrentPrice())
  87. .build();
  88. if (user.getInviteType() != null) {
  89. if (user.getInviteType().equals(InviteType.AUCTION)) {
  90. tradeAuctionOrder.setInvitor(Long.valueOf(user.getInviteCode()));
  91. }
  92. }
  93. tradeAuctionOrder = tradeAuctionOrderRepo.save(tradeAuctionOrder);
  94. //下订单减库存
  95. return tradeAuctionOrder;
  96. }
  97. @Transactional
  98. public void notify(Long orderId, String transactionId, PayMethod payMethod) {
  99. TradeAuctionOrder tradeAuctionOrder = tradeAuctionOrderRepo.findById(orderId)
  100. .orElseThrow(new BusinessException("未找到订单"));
  101. if (!tradeAuctionOrder.getStatus().equals(AuctionOrderStatus.NOT_PAID)) {
  102. throw new BusinessException("订单已经处理");
  103. }
  104. tradeAuctionOrder.setPayTime(LocalDateTime.now());
  105. tradeAuctionOrder.setPayMethod(payMethod);
  106. tradeAuctionOrder.setTransactionId(transactionId);
  107. tradeAuctionOrder.setStatus(AuctionOrderStatus.FINISH);
  108. TradeAuction tradeAuction = tradeAuctionRepo.findById(tradeAuctionOrder.getTradeAuctionId())
  109. .orElseThrow(new BusinessException("未找到该易拍活动"));
  110. if (tradeAuction.getCurrentOrderId() != null & !tradeAuctionOrder.getPaymentType()
  111. .equals(AuctionPaymentType.PURCHASE_PRICE)) {
  112. //将上次订单设为待补偿状态
  113. TradeAuctionOrder lastOrder = tradeAuctionOrderRepo.findById(tradeAuction.getCurrentOrderId())
  114. .orElseThrow(new BusinessException("暂无订单"));
  115. lastOrder.setPaybackStatus(PaybackStatus.PASSED);
  116. tradeAuctionOrderRepo.save(lastOrder);
  117. }
  118. tradeAuction.setCurrentOrderId(orderId);
  119. if (tradeAuctionOrder.getPaymentType().equals(AuctionPaymentType.FIXED_PRICE)) {
  120. tradeAuction.setCurrentPrice(tradeAuctionOrder.getCurrentPrice());
  121. tradeAuction.setCurrentOwner(tradeAuctionOrder.getNickname());
  122. tradeAuction.setCurrentOwnerId(tradeAuctionOrder.getUserId());
  123. tradeAuction.setStatus(TradeAuctionStatus.FIXED_PRICE_PURCHASED);
  124. } else if (tradeAuctionOrder.getPaymentType().equals(AuctionPaymentType.DEPOSIT)) {
  125. if (tradeAuction.getSale() == 29) {
  126. tradeAuction.setSale(30L);
  127. tradeAuction.setCurrentPrice(tradeAuctionOrder.getPrice());
  128. tradeAuction.setCurrentOwner(tradeAuctionOrder.getNickname());
  129. tradeAuction.setCurrentOwnerId(tradeAuctionOrder.getUserId());
  130. tradeAuctionService.purchase(tradeAuction);
  131. return;
  132. } else {
  133. BigDecimal result = tradeAuctionOrder.getPrice()
  134. .multiply(BigDecimal.valueOf(tradeAuction.getIncreasePer()))
  135. .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
  136. tradeAuction.setNextPrice(result.add(tradeAuctionOrder.getPrice()));
  137. tradeAuction.setEarning(tradeAuction.getNextPrice().subtract(tradeAuction.getPrice()));
  138. BigDecimal serviceCharge = (BigDecimal.valueOf(0.03).multiply(tradeAuction.getNextPrice()))
  139. .add(tradeAuctionOrder.getPrice().subtract(tradeAuction.getPrice()));
  140. tradeAuction.setCommission(serviceCharge);
  141. tradeAuction.setCurrentPrice(tradeAuctionOrder.getPrice());
  142. tradeAuction.setCurrentOwner(tradeAuctionOrder.getNickname());
  143. tradeAuction.setCurrentOwnerId(tradeAuctionOrder.getUserId());
  144. tradeAuction.setCurrentStartTime(LocalDateTime.now().plusMinutes(1));
  145. tradeAuction
  146. .setCurrentEndTime(tradeAuction.getCurrentStartTime().plusMinutes(tradeAuction.getMinutes())
  147. .plusMinutes(10));
  148. tradeAuction.setFixedPrice(tradeAuctionOrder.getPrice().multiply(BigDecimal.valueOf(150))
  149. .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
  150. tradeAuction.setStatus(TradeAuctionStatus.WAITING);
  151. }
  152. } else {
  153. tradeAuction.setCurrentPrice(tradeAuctionOrder.getCurrentPrice());
  154. tradeAuction.setCurrentOwner(tradeAuctionOrder.getNickname());
  155. tradeAuction.setCurrentOwnerId(tradeAuctionOrder.getUserId());
  156. tradeAuction.setStatus(TradeAuctionStatus.FINISH);
  157. finishLastOrder(tradeAuction.getCurrentOrderId());
  158. tradeAuctionOrder.setStatus(AuctionOrderStatus.AIR_DROP);
  159. }
  160. tradeAuctionOrder.setCurrentEndTime(LocalDateTime.now().plusMinutes(tradeAuction.getMinutes()).plusDays(1));
  161. tradeAuctionOrder.setCurrentPrice(tradeAuctionOrder.getPrice());
  162. tradeAuction.setStock(0L);
  163. tradeAuction.setSale(tradeAuction.getSale() + 1);
  164. tradeAuctionOrder.setTradeAuctionStatus(tradeAuction.getStatus());
  165. tradeAuctionOrderRepo.save(tradeAuctionOrder);
  166. tradeAuctionRepo.save(tradeAuction);
  167. tradeAuctionService.increaseSale(tradeAuction.getId(), 1);
  168. }
  169. public void finishLastOrder(Long lastOrderId) {
  170. TradeAuctionOrder tradeAuctionOrder = tradeAuctionOrderRepo.findById(lastOrderId)
  171. .orElseThrow(new BusinessException("暂无订单"));
  172. tradeAuctionOrder.setStatus(AuctionOrderStatus.PAID);
  173. tradeAuctionOrder.setPaybackStatus(PaybackStatus.PAYED);
  174. tradeAuctionOrderRepo.save(tradeAuctionOrder);
  175. }
  176. @Scheduled(fixedRate = 6000)
  177. public void batchCancelledAuctionOrder() {
  178. List<TradeAuctionOrder> orders = tradeAuctionOrderRepo
  179. .findByStatusAndCreatedAtBeforeAndDelFalse(AuctionOrderStatus.NOT_PAID,
  180. LocalDateTime.now().minusSeconds(orderCancelInterval));
  181. orders.parallelStream().forEach(o -> {
  182. try {
  183. TradeAuctionOrder order = tradeAuctionOrderRepo.findById(o.getId())
  184. .orElseThrow(new BusinessException("订单不存在"));
  185. if (order.getStatus() == AuctionOrderStatus.NOT_PAID) {
  186. cancel(order);
  187. }
  188. } catch (Exception e) {
  189. log.error("取消易拍订单错误 " + o.getId(), e);
  190. }
  191. });
  192. }
  193. public void cancel(TradeAuctionOrder order) {
  194. if (order.getStatus() != AuctionOrderStatus.NOT_PAID) {
  195. throw new BusinessException("当前订单状态无法取消[" + order.getStatus().name() + "]");
  196. }
  197. order.setStatus(AuctionOrderStatus.CANCELLED);
  198. order.setCancelTime(LocalDateTime.now());
  199. tradeAuctionService.increaseStock(order.getTradeAuctionId(), 1);
  200. tradeAuctionOrderRepo.save(order);
  201. }
  202. @Scheduled(fixedRate = 30000)
  203. public void batchPayEarning() {
  204. List<TradeAuctionOrder> tradeAuctionOrders = tradeAuctionOrderRepo.findByPaybackStatus(PaybackStatus.PASSED);
  205. tradeAuctionOrders.parallelStream().forEach(o -> {
  206. try {
  207. TradeAuctionOrder order = tradeAuctionOrderRepo.findById(o.getId())
  208. .orElseThrow(new BusinessException("订单不存在"));
  209. if (order.getPaybackStatus() == PaybackStatus.PASSED) {
  210. payEarning(order);
  211. }
  212. } catch (Exception e) {
  213. log.error("取消易拍订单错误 " + o.getId(), e);
  214. }
  215. });
  216. }
  217. private void payEarning(TradeAuctionOrder order) {
  218. if (!order.getPaymentType().equals(AuctionPaymentType.PURCHASE_PRICE)) {
  219. userBalanceService.addBalance(order.getUserId(), order.getEarnedPrice(), order.getId(), BalanceType.BONUS);
  220. order.setPaybackStatus(PaybackStatus.PAYED);
  221. tradeAuctionOrderRepo.save(order);
  222. }
  223. }
  224. public void commission(TradeAuctionOrder order, BigDecimal price) {
  225. if (order.getInvitor() != null) {
  226. userRepo.findById(order.getInvitor()).ifPresent(user -> {
  227. BigDecimal shareRatio = sysConfigService.getBigDecimal("auction_commission_rate");
  228. if (StringUtils.isNotBlank(user.getSettleAccountId()) &&
  229. shareRatio != null && shareRatio.compareTo(BigDecimal.ZERO) > 0) {
  230. commissionRecordRepo.save(CommissionRecord.builder()
  231. .orderId(order.getId())
  232. .collectionId(order.getTradeAuctionId())
  233. .name(order.getName())
  234. .totalPrice(price)
  235. .nickname(user.getNickname())
  236. .userId(user.getId())
  237. .shareRatio(user.getShareRatio())
  238. .phone(user.getPhone())
  239. .shareAmount(price.multiply(shareRatio)
  240. .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))
  241. .type(InviteType.AUCTION)
  242. .build());
  243. userBalanceService.addBalance(user.getId(), price.multiply(shareRatio)
  244. .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP), order
  245. .getId(), BalanceType.COMMISSION);
  246. }
  247. });
  248. }
  249. }
  250. }