package com.izouma.nineth.service; import com.izouma.nineth.config.GeneralProperties; import com.izouma.nineth.config.RedisKeys; import com.izouma.nineth.domain.TradeAuction; import com.izouma.nineth.domain.TradeAuctionOrder; import com.izouma.nineth.domain.TradeAuctionRecord; import com.izouma.nineth.dto.PageQuery; import com.izouma.nineth.enums.AuctionOrderStatus; import com.izouma.nineth.enums.TradeAuctionStatus; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.TradeAuctionOrderRepo; import com.izouma.nineth.repo.TradeAuctionRepo; import com.izouma.nineth.utils.JpaUtils; import com.izouma.nineth.utils.ObjUtils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.data.domain.Page; import org.springframework.data.redis.core.BoundValueOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.security.PrivateKey; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @Service @AllArgsConstructor @Slf4j public class TradeAuctionService { private TradeAuctionRepo tradeAuctionRepo; private RedisTemplate redisTemplate; private RocketMQTemplate rocketMQTemplate; private GeneralProperties generalProperties; private TradeAuctionOrderRepo tradeAuctionOrderRepo; public Page all(PageQuery pageQuery) { return tradeAuctionRepo .findAll(JpaUtils.toSpecification(pageQuery, TradeAuction.class), JpaUtils.toPageRequest(pageQuery)); } public TradeAuction save(TradeAuction record) { if (record.getId() != null) { TradeAuction orig = tradeAuctionRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录")); ObjUtils.merge(orig, record); return tradeAuctionRepo.save(orig); } record.setCurrentEndTime(record.getStartTime().plusDays(1)); record.setIncreasePer(6); record.setRoyalties(10); record.setCurrentStartTime(record.getStartTime()); record.setCurrentPrice(record.getPrice()); record.setStatus(TradeAuctionStatus.WAITING); BigDecimal result = record.getCurrentPrice().multiply(BigDecimal.valueOf(record.getIncreasePer())) .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP); record.setNextPrice(result.add(record.getPrice())); record.setEarning(record.getNextPrice().subtract(record.getPrice())); record.setFixedPrice(record.getPrice().multiply(BigDecimal.valueOf(150)) .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP)); BigDecimal serviceCharge = (BigDecimal.valueOf(0.03).multiply(record.getNextPrice())) .add(record.getCurrentPrice().subtract(record.getPrice())); // record.setEarning(result.subtract(record.getPrice())); record.setCommission(serviceCharge); record.setStock(1L); record.setSale(0L); return tradeAuctionRepo.save(record); } // public void transfer(Long id) { // TradeAuctionRecord tradeAuctionRecord = new TradeAuctionRecord(); // TradeAuction tradeAuction = tradeAuctionRepo.findById(id).orElseThrow(new BusinessException("暂无")); // tradeAuction.setStatus(TradeAuctionStatus.WAITING); // increaseSale(tr) // } public synchronized Long increaseStock(Long id, int number) { BoundValueOperations ops = redisTemplate.boundValueOps(RedisKeys.AUCTION_STOCK + id); if (ops.get() == null) { Boolean success = ops.setIfAbsent(Optional.ofNullable(tradeAuctionRepo.getStock(id)) .orElse(0), 7, TimeUnit.DAYS); log.info("创建redis库存:{}", success); } Long stock = ops.increment(number); rocketMQTemplate.convertAndSend(generalProperties.getUpdateStockTopic(), id); return stock; } public synchronized Integer getStock(Long id) { BoundValueOperations ops = redisTemplate.boundValueOps(RedisKeys.AUCTION_STOCK + id); Integer stock = (Integer) ops.get(); if (stock == null) { Boolean success = ops.setIfAbsent(Optional.ofNullable(tradeAuctionRepo.getStock(id)) .orElse(0), 7, TimeUnit.DAYS); log.info("创建redis库存:{}", success); return (Integer) ops.get(); } else { return stock; } } public synchronized Long decreaseStock(Long id, int number) { return increaseStock(id, -number); } public synchronized Long increaseSale(Long id, int number) { BoundValueOperations ops = redisTemplate.boundValueOps(RedisKeys.COLLECTION_SALE + id); if (ops.get() == null) { Boolean success = ops.setIfAbsent(Optional.ofNullable(tradeAuctionRepo.getSale(id)) .orElse(0), 7, TimeUnit.DAYS); log.info("创建redis销量:{}", success); } Long sale = ops.increment(number); redisTemplate.opsForHash().increment(RedisKeys.UPDATE_SALE, id.toString(), 1); // rocketMQTemplate.convertAndSend(generalProperties.getUpdateSaleTopic(), id); return sale; } public synchronized Long decreaseSale(Long id, int number) { return increaseSale(id, -number); } // @Debounce(key = "#id", delay = 500) public void syncStock(Long id) { Integer stock = (Integer) redisTemplate.opsForValue().get(RedisKeys.COLLECTION_STOCK + id); if (stock != null) { log.info("同步库存信息{}", id); tradeAuctionRepo.updateStock(id, stock); // cacheService.clearCollection(id); } } // @Debounce(key = "#id", delay = 500) public void syncSale(Long id) { Integer sale = (Integer) redisTemplate.opsForValue().get(RedisKeys.COLLECTION_SALE + id); if (sale != null) { log.info("同步销量信息{}", id); tradeAuctionRepo.updateSale(id, sale); // cacheService.clearCollection(id); } } @Scheduled(fixedRate = 6000) public void batchStartAuction() { List tradeAuctionStatuses = new ArrayList<>(); tradeAuctionStatuses.add(TradeAuctionStatus.WAITING); tradeAuctionStatuses.add(TradeAuctionStatus.NOTSTARTED); List tradeAuctions = tradeAuctionRepo .findByStatusInAndCurrentStartTimeBefore(tradeAuctionStatuses, LocalDateTime.now().plusMinutes(1)); tradeAuctions.parallelStream().forEach(o -> { try { TradeAuction auction = tradeAuctionRepo.findById(o.getId()) .orElseThrow(new BusinessException("订单不存在")); if (auction.getStatus() == TradeAuctionStatus.WAITING || auction .getStatus() == TradeAuctionStatus.NOTSTARTED) { start(auction); } } catch (Exception e) { log.error("取消易拍订单错误 " + o.getId(), e); } }); } public void start(TradeAuction tradeAuction) { tradeAuction.setStatus(TradeAuctionStatus.ONGOING); tradeAuctionRepo.save(tradeAuction); increaseStock(tradeAuction.getId(), 1); } @Scheduled(fixedRate = 6000) public void batchPurchaseAuction() { List tradeAuctionStatuses = new ArrayList<>(); tradeAuctionStatuses.add(TradeAuctionStatus.ONGOING); List tradeAuctions = tradeAuctionRepo .findByStatusInAndCurrentEndTimeBefore(tradeAuctionStatuses, LocalDateTime.now().plusMinutes(1)); tradeAuctions.parallelStream().forEach(o -> { try { TradeAuction auction = tradeAuctionRepo.findById(o.getId()) .orElseThrow(new BusinessException("订单不存在")); if (auction.getStatus() == TradeAuctionStatus.ONGOING) { purchase(auction); } } catch (Exception e) { log.error("取消易拍订单错误 " + o.getId(), e); } }); } public void purchase(TradeAuction tradeAuction) { tradeAuction.setStatus(TradeAuctionStatus.PURCHASED); tradeAuctionRepo.save(tradeAuction); decreaseStock(tradeAuction.getId(), 1); } @Scheduled(fixedRate = 6000) public void batchPassAuction() { List tradeAuctionStatuses = new ArrayList<>(); tradeAuctionStatuses.add(TradeAuctionStatus.PURCHASED); List tradeAuctions = tradeAuctionRepo .findByStatusInAndCurrentEndTimeBefore(tradeAuctionStatuses, LocalDateTime.now().plusMinutes(1)); tradeAuctions.parallelStream().forEach(o -> { try { TradeAuction auction = tradeAuctionRepo.findById(o.getId()) .orElseThrow(new BusinessException("订单不存在")); if (auction.getStatus() == TradeAuctionStatus.ONGOING) { pass(auction); } } catch (Exception e) { log.error("取消易拍订单错误 " + o.getId(), e); } }); } public void pass(TradeAuction tradeAuction) { tradeAuction.setStatus(TradeAuctionStatus.PASS); tradeAuctionRepo.save(tradeAuction); TradeAuctionOrder tradeAuctionOrder = tradeAuctionOrderRepo.findById(tradeAuction.getCurrentOrderId()) .orElseThrow(new BusinessException("暂无订单")); tradeAuctionOrder.setStatus(AuctionOrderStatus.PASS); tradeAuctionOrderRepo.save(tradeAuctionOrder); decreaseStock(tradeAuction.getId(), 1); } }