TradeAuctionService.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. package com.izouma.nineth.service;
  2. import com.izouma.nineth.config.GeneralProperties;
  3. import com.izouma.nineth.config.RedisKeys;
  4. import com.izouma.nineth.domain.TradeAuction;
  5. import com.izouma.nineth.domain.TradeAuctionOrder;
  6. import com.izouma.nineth.domain.TradeAuctionRecord;
  7. import com.izouma.nineth.dto.PageQuery;
  8. import com.izouma.nineth.enums.AuctionOrderStatus;
  9. import com.izouma.nineth.enums.TradeAuctionStatus;
  10. import com.izouma.nineth.exception.BusinessException;
  11. import com.izouma.nineth.repo.TradeAuctionOrderRepo;
  12. import com.izouma.nineth.repo.TradeAuctionRepo;
  13. import com.izouma.nineth.utils.JpaUtils;
  14. import com.izouma.nineth.utils.ObjUtils;
  15. import lombok.AllArgsConstructor;
  16. import lombok.extern.slf4j.Slf4j;
  17. import org.apache.rocketmq.spring.core.RocketMQTemplate;
  18. import org.springframework.data.domain.Page;
  19. import org.springframework.data.redis.core.BoundValueOperations;
  20. import org.springframework.data.redis.core.RedisTemplate;
  21. import org.springframework.scheduling.annotation.Scheduled;
  22. import org.springframework.stereotype.Service;
  23. import java.math.BigDecimal;
  24. import java.math.RoundingMode;
  25. import java.security.PrivateKey;
  26. import java.time.LocalDate;
  27. import java.time.LocalDateTime;
  28. import java.util.ArrayList;
  29. import java.util.List;
  30. import java.util.Optional;
  31. import java.util.concurrent.TimeUnit;
  32. @Service
  33. @AllArgsConstructor
  34. @Slf4j
  35. public class TradeAuctionService {
  36. private TradeAuctionRepo tradeAuctionRepo;
  37. private RedisTemplate<String, Object> redisTemplate;
  38. private RocketMQTemplate rocketMQTemplate;
  39. private GeneralProperties generalProperties;
  40. private TradeAuctionOrderRepo tradeAuctionOrderRepo;
  41. private SysConfigService sysConfigService;
  42. public Page<TradeAuction> all(PageQuery pageQuery) {
  43. return tradeAuctionRepo
  44. .findAll(JpaUtils.toSpecification(pageQuery, TradeAuction.class), JpaUtils.toPageRequest(pageQuery));
  45. }
  46. public TradeAuction save(TradeAuction record) {
  47. if (record.getId() != null) {
  48. TradeAuction orig = tradeAuctionRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
  49. ObjUtils.merge(orig, record);
  50. return tradeAuctionRepo.save(orig);
  51. }
  52. // if (record.getAuctionType() == 1) {
  53. // record.setStartTime(LocalDate.now().atTime(8, 0));
  54. // } else if (record.getAuctionType() == 2) {
  55. // record.setStartTime(LocalDate.now().atTime(11, 0));
  56. // } else {
  57. // throw new BusinessException("未填写时间码");
  58. // }
  59. if (record.getStartTime().getHour() != 20 & record.getStartTime().getHour() != 11) {
  60. throw new BusinessException("开始时间不是11点或20点,请修改!");
  61. }
  62. record.setCurrentEndTime(record.getStartTime().plusHours(24));
  63. record.setIncreasePer(6);
  64. record.setRoyalties(10);
  65. record.setCurrentStartTime(record.getStartTime());
  66. record.setCurrentPrice(record.getPrice());
  67. record.setStatus(TradeAuctionStatus.WAITING);
  68. BigDecimal result = record.getCurrentPrice().multiply(BigDecimal.valueOf(record.getIncreasePer()))
  69. .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
  70. record.setNextPrice(result.add(record.getPrice()));
  71. record.setEarning(record.getNextPrice().subtract(record.getPrice()));
  72. record.setFixedPrice(record.getPrice().multiply(BigDecimal.valueOf(150))
  73. .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
  74. BigDecimal serviceCharge = (BigDecimal.valueOf(0.03).multiply(record.getNextPrice()))
  75. .add(record.getCurrentPrice().subtract(record.getPrice()));
  76. // record.setEarning(result.subtract(record.getPrice()));
  77. record.setCommission(serviceCharge);
  78. record.setStock(1L);
  79. record.setSale(0L);
  80. return tradeAuctionRepo.save(record);
  81. }
  82. // public void transfer(Long id) {
  83. // TradeAuctionRecord tradeAuctionRecord = new TradeAuctionRecord();
  84. // TradeAuction tradeAuction = tradeAuctionRepo.findById(id).orElseThrow(new BusinessException("暂无"));
  85. // tradeAuction.setStatus(TradeAuctionStatus.WAITING);
  86. // increaseSale(tr)
  87. // }
  88. public synchronized Long increaseStock(Long id, int number) {
  89. BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.AUCTION_STOCK + id);
  90. if (ops.get() == null) {
  91. Boolean success = ops.setIfAbsent(Optional.ofNullable(tradeAuctionRepo.getStock(id))
  92. .orElse(0), 7, TimeUnit.DAYS);
  93. log.info("创建redis库存:{}", success);
  94. }
  95. Long stock = ops.increment(number);
  96. redisTemplate.opsForHash().increment(RedisKeys.UPDATE_STOCK, id.toString(), 1);
  97. return stock;
  98. }
  99. public synchronized Integer getStock(Long id) {
  100. BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.AUCTION_STOCK + id);
  101. Integer stock = (Integer) ops.get();
  102. if (stock == null) {
  103. Boolean success = ops.setIfAbsent(Optional.ofNullable(tradeAuctionRepo.getStock(id))
  104. .orElse(0), 7, TimeUnit.DAYS);
  105. log.info("创建redis库存:{}", success);
  106. return (Integer) ops.get();
  107. } else {
  108. return stock;
  109. }
  110. }
  111. public synchronized Long decreaseStock(Long id, int number) {
  112. return increaseStock(id, -number);
  113. }
  114. public synchronized Long increaseSale(Long id, int number) {
  115. BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.COLLECTION_SALE + id);
  116. if (ops.get() == null) {
  117. Boolean success = ops.setIfAbsent(Optional.ofNullable(tradeAuctionRepo.getSale(id))
  118. .orElse(0), 7, TimeUnit.DAYS);
  119. log.info("创建redis销量:{}", success);
  120. }
  121. Long sale = ops.increment(number);
  122. redisTemplate.opsForHash().increment(RedisKeys.UPDATE_SALE, id.toString(), 1);
  123. // rocketMQTemplate.convertAndSend(generalProperties.getUpdateSaleTopic(), id);
  124. return sale;
  125. }
  126. public synchronized Long decreaseSale(Long id, int number) {
  127. return increaseSale(id, -number);
  128. }
  129. // @Debounce(key = "#id", delay = 500)
  130. public void syncStock(Long id) {
  131. Integer stock = (Integer) redisTemplate.opsForValue().get(RedisKeys.COLLECTION_STOCK + id);
  132. if (stock != null) {
  133. log.info("同步库存信息{}", id);
  134. tradeAuctionRepo.updateStock(id, stock);
  135. // cacheService.clearCollection(id);
  136. }
  137. }
  138. // @Debounce(key = "#id", delay = 500)
  139. public void syncSale(Long id) {
  140. Integer sale = (Integer) redisTemplate.opsForValue().get(RedisKeys.COLLECTION_SALE + id);
  141. if (sale != null) {
  142. log.info("同步销量信息{}", id);
  143. tradeAuctionRepo.updateSale(id, sale);
  144. // cacheService.clearCollection(id);
  145. }
  146. }
  147. @Scheduled(fixedRate = 6000)
  148. public void batchStartAuction() {
  149. List<TradeAuctionStatus> tradeAuctionStatuses = new ArrayList<>();
  150. tradeAuctionStatuses.add(TradeAuctionStatus.WAITING);
  151. tradeAuctionStatuses.add(TradeAuctionStatus.NOTSTARTED);
  152. List<TradeAuction> tradeAuctions = tradeAuctionRepo
  153. .findByStatusInAndCurrentStartTimeBefore(tradeAuctionStatuses,
  154. LocalDateTime.now().plusSeconds(5));
  155. tradeAuctions.parallelStream().forEach(o -> {
  156. try {
  157. TradeAuction auction = tradeAuctionRepo.findById(o.getId())
  158. .orElseThrow(new BusinessException("订单不存在"));
  159. if (auction.getStatus() == TradeAuctionStatus.WAITING || auction
  160. .getStatus() == TradeAuctionStatus.NOTSTARTED) {
  161. start(auction);
  162. }
  163. } catch (Exception e) {
  164. log.error("取消易拍订单错误 " + o.getId(), e);
  165. }
  166. });
  167. }
  168. public void start(TradeAuction tradeAuction) {
  169. tradeAuction.setStatus(TradeAuctionStatus.ONGOING);
  170. tradeAuction.setStock(1L);
  171. tradeAuctionRepo.save(tradeAuction);
  172. increaseStock(tradeAuction.getId(), 1);
  173. }
  174. @Scheduled(fixedRate = 6000)
  175. public void batchPurchaseAuction() {
  176. List<TradeAuctionStatus> tradeAuctionStatuses = new ArrayList<>();
  177. tradeAuctionStatuses.add(TradeAuctionStatus.ONGOING);
  178. List<TradeAuction> tradeAuctions = tradeAuctionRepo
  179. .findByStatusInAndCurrentEndTimeBefore(tradeAuctionStatuses,
  180. LocalDateTime.now().plusSeconds(5));
  181. tradeAuctions.parallelStream().forEach(o -> {
  182. try {
  183. TradeAuction auction = tradeAuctionRepo.findById(o.getId())
  184. .orElseThrow(new BusinessException("订单不存在"));
  185. if (auction.getStatus() == TradeAuctionStatus.ONGOING) {
  186. purchase(auction);
  187. }
  188. } catch (Exception e) {
  189. log.error("取消易拍订单错误 " + o.getId(), e);
  190. }
  191. });
  192. }
  193. public void purchase(TradeAuction tradeAuction) {
  194. if (tradeAuction.getCurrentOrderId() == null) {
  195. pass(tradeAuction);
  196. } else {
  197. TradeAuctionOrder tradeAuctionOrder = tradeAuctionOrderRepo.findById(tradeAuction.getCurrentOrderId())
  198. .orElseThrow(new BusinessException("暂无"));
  199. tradeAuction.setStatus(TradeAuctionStatus.PURCHASED);
  200. tradeAuction.setPurchasedPrice(tradeAuction.getCurrentPrice());
  201. // int time = sysConfigService.getInt("auction_cancel_time");
  202. tradeAuction.setCurrentEndTime(LocalDateTime.now().plusHours(48));
  203. tradeAuctionRepo.save(tradeAuction);
  204. tradeAuctionOrder.setTradeAuctionStatus(tradeAuction.getStatus());
  205. tradeAuctionOrder.setCurrentPrice(tradeAuctionOrder.getPrice());
  206. tradeAuctionOrderRepo.save(tradeAuctionOrder);
  207. decreaseStock(tradeAuction.getId(), 1);
  208. }
  209. }
  210. @Scheduled(fixedRate = 6000)
  211. public void batchPassAuction() {
  212. List<TradeAuctionStatus> tradeAuctionStatuses = new ArrayList<>();
  213. tradeAuctionStatuses.add(TradeAuctionStatus.PURCHASED);
  214. List<TradeAuction> tradeAuctions = tradeAuctionRepo
  215. .findByStatusInAndCurrentEndTimeBefore(tradeAuctionStatuses,
  216. LocalDateTime.now().plusSeconds(5));
  217. tradeAuctions.parallelStream().forEach(o -> {
  218. try {
  219. TradeAuction auction = tradeAuctionRepo.findById(o.getId())
  220. .orElseThrow(new BusinessException("订单不存在"));
  221. if (auction.getStatus() == TradeAuctionStatus.PURCHASED) {
  222. pass(auction);
  223. }
  224. } catch (Exception e) {
  225. log.error("取消易拍订单错误 " + o.getId(), e);
  226. }
  227. });
  228. }
  229. public void pass(TradeAuction tradeAuction) {
  230. tradeAuction.setStatus(TradeAuctionStatus.PASS);
  231. tradeAuctionRepo.save(tradeAuction);
  232. if (tradeAuction.getCurrentOrderId() != null) {
  233. TradeAuctionOrder tradeAuctionOrder = tradeAuctionOrderRepo.findById(tradeAuction.getCurrentOrderId())
  234. .orElseThrow(new BusinessException("暂无订单"));
  235. tradeAuctionOrder.setStatus(AuctionOrderStatus.PASS);
  236. tradeAuctionOrder.setTradeAuctionStatus(tradeAuction.getStatus());
  237. tradeAuctionOrderRepo.save(tradeAuctionOrder);
  238. }
  239. decreaseStock(tradeAuction.getId(), 1);
  240. }
  241. }