|
|
@@ -0,0 +1,519 @@
|
|
|
+package com.izouma.nineth.service;
|
|
|
+
|
|
|
+import com.izouma.nineth.config.Constants;
|
|
|
+import com.izouma.nineth.config.RedisKeys;
|
|
|
+import com.izouma.nineth.domain.*;
|
|
|
+import com.izouma.nineth.dto.PageQuery;
|
|
|
+import com.izouma.nineth.enums.*;
|
|
|
+import com.izouma.nineth.exception.BusinessException;
|
|
|
+import com.izouma.nineth.repo.*;
|
|
|
+import com.izouma.nineth.service.sms.SmsService;
|
|
|
+import com.izouma.nineth.utils.JpaUtils;
|
|
|
+import com.izouma.nineth.utils.SecurityUtils;
|
|
|
+import com.izouma.nineth.utils.SnowflakeIdWorker;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.ObjectUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.context.annotation.Lazy;
|
|
|
+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 javax.persistence.Transient;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Optional;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class AuctionOrderService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AuctionOrderRepo auctionOrderRepo;
|
|
|
+ @Autowired
|
|
|
+ private SysConfigService sysConfigService;
|
|
|
+ @Autowired
|
|
|
+ private UserRepo userRepo;
|
|
|
+ @Autowired
|
|
|
+ private AssetService assetService;
|
|
|
+ @Autowired
|
|
|
+ private AuctionActivityRepo auctionActivityRepo;
|
|
|
+ @Autowired
|
|
|
+ private AuctionRecordRepo auctionRecordRepo;
|
|
|
+ @Autowired
|
|
|
+ private AssetRepo assetRepo;
|
|
|
+ @Autowired
|
|
|
+ private UserAddressRepo userAddressRepo;
|
|
|
+ @Autowired
|
|
|
+ private AuctionActivityService auctionActivityService;
|
|
|
+ @Autowired
|
|
|
+ private RedisTemplate<String, Object> redisTemplate;
|
|
|
+ @Autowired
|
|
|
+ private SnowflakeIdWorker snowflakeIdWorker;
|
|
|
+ @Autowired
|
|
|
+ private AuctionPassRecordRepo auctionPassRecordRepo;
|
|
|
+ @Lazy
|
|
|
+ @Autowired
|
|
|
+ private OrderPayService orderPayService;
|
|
|
+ @Autowired
|
|
|
+ private SmsService smsService;
|
|
|
+ @Autowired
|
|
|
+ private UserBalanceRepo userBalanceRepo;
|
|
|
+ @Autowired
|
|
|
+ private BalanceRecordRepo balanceRecordRepo;
|
|
|
+
|
|
|
+ public Page<AuctionOrder> all(PageQuery pageQuery) {
|
|
|
+ return auctionOrderRepo
|
|
|
+ .findAll(JpaUtils.toSpecification(pageQuery, AuctionOrder.class), JpaUtils.toPageRequest(pageQuery));
|
|
|
+ }
|
|
|
+
|
|
|
+ public AuctionOrder create(Long userId, Long auctionId, Long addressId, Long auctionRecordId, AuctionPaymentType type) {
|
|
|
+ User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
|
|
|
+
|
|
|
+ AuctionActivity auction = auctionActivityRepo.findById(auctionId)
|
|
|
+ .orElseThrow(new BusinessException("无拍卖信息"));
|
|
|
+
|
|
|
+ if (!auction.isOnShelf()) {
|
|
|
+ throw new BusinessException("拍卖已结束");
|
|
|
+ }
|
|
|
+
|
|
|
+ String status = (String) redisTemplate.opsForValue().get(RedisKeys.AUCTION_STATUS + auctionId);
|
|
|
+ if (status == null)
|
|
|
+ status = auction.getStatus().toString();
|
|
|
+ switch (AuctionStatus.valueOf(status)) {
|
|
|
+ case NOTSTARTED:
|
|
|
+ throw new BusinessException("拍卖还未开始");
|
|
|
+// case PURCHASED:
|
|
|
+// throw new BusinessException("拍卖成交中");
|
|
|
+ case PASS:
|
|
|
+ throw new BusinessException("已经流拍");
|
|
|
+ case FINISH:
|
|
|
+ throw new BusinessException("拍卖已结束");
|
|
|
+ case FIXED_PRICE_PURCHASED:
|
|
|
+ if (AuctionPaymentType.FIXED_PRICE.equals(type)) {
|
|
|
+ throw new BusinessException("一口价成交中");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (user.getId().equals(auction.getSellerId())) {
|
|
|
+ throw new BusinessException("不可自己出价自己");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (AuctionPaymentType.PURCHASE_PRICE.equals(type)) {
|
|
|
+ if (auction.getEndTime().isAfter(LocalDateTime.now())) {
|
|
|
+ throw new BusinessException("拍卖还未结束");
|
|
|
+ }
|
|
|
+ AuctionRecord record = auctionRecordRepo.findTopByAuctionIdAndUserIdOrderByIdDesc(auctionId, userId);
|
|
|
+ if (ObjectUtils.isEmpty(record) || !record.isPayDeposit()) {
|
|
|
+ throw new BusinessException("未支付保证金");
|
|
|
+ }
|
|
|
+ if (record.getBidderPrice().compareTo(auction.getPurchasePrice()) != 0) {
|
|
|
+ throw new BusinessException("与成交价不否");
|
|
|
+ }
|
|
|
+ int time = sysConfigService.getInt("auction_cancel_time");
|
|
|
+ if (LocalDateTime.now().isAfter(auction.getEndTime().plusMinutes(time))) {
|
|
|
+ throw new BusinessException("超过支付时长");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (auction.getEndTime().isBefore(LocalDateTime.now())) {
|
|
|
+ throw new BusinessException("拍卖已结束");
|
|
|
+ }
|
|
|
+ if (AuctionPaymentType.DEPOSIT.equals(type)) {
|
|
|
+ return this.createDeposit(user, auction);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ UserAddress userAddress = null;
|
|
|
+ if (addressId != null) {
|
|
|
+ userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ auctionActivityService.changeStatus(auctionId, AuctionPaymentType.FIXED_PRICE
|
|
|
+ .equals(type) ? AuctionStatus.FIXED_PRICE_PURCHASED : AuctionStatus.PURCHASED);
|
|
|
+
|
|
|
+ if (AuctionSource.TRANSFER.equals(auction.getSource())) {
|
|
|
+ Asset asset = assetRepo.findById(auction.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
|
|
|
+ asset.setStatus(AssetStatus.AUCTION_TRADING);
|
|
|
+ assetRepo.save(asset);
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal price = AuctionPaymentType.FIXED_PRICE.equals(type) ? auction.getFixedPrice() : auction
|
|
|
+ .getPurchasePrice();
|
|
|
+
|
|
|
+ AuctionOrder order = AuctionOrder.builder()
|
|
|
+ .id(snowflakeIdWorker.nextId())
|
|
|
+ .auctionId(auction.getId())
|
|
|
+ .userId(user.getId())
|
|
|
+ .nickname(user.getNickname())
|
|
|
+ .paymentType(type)
|
|
|
+ .name(auction.getName())
|
|
|
+ .pic(auction.getPic())
|
|
|
+ .serviceCharge(auction.getServiceCharge())
|
|
|
+ .royalties(auction.getRoyalties())
|
|
|
+ .source(auction.getSource())
|
|
|
+ .price(price)
|
|
|
+ .totalPrice(price)
|
|
|
+ .auctionRecordId(auctionRecordId)
|
|
|
+ .status(AuctionOrderStatus.NOT_PAID)
|
|
|
+ .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
|
|
|
+ .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone).orElse(null))
|
|
|
+ .address(Optional.ofNullable(userAddress).map(UserAddress::getDetail).orElse(null))
|
|
|
+ .build();
|
|
|
+
|
|
|
+ return auctionOrderRepo.save(order);
|
|
|
+ } catch (Exception e) {
|
|
|
+ auctionActivityService.changeStatus(auctionId, AuctionStatus.ONGOING);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public AuctionOrder createDeposit(User user, AuctionActivity auction) {
|
|
|
+ if (user.getId().equals(auction.getSellerId())) {
|
|
|
+ throw new BusinessException("不可自己出价自己的");
|
|
|
+ }
|
|
|
+
|
|
|
+ //保证金
|
|
|
+// BigDecimal deposit = sysConfigService.getBigDecimal("deposit");
|
|
|
+ AuctionOrder order = auctionOrderRepo
|
|
|
+ .findByUserIdAndAuctionIdAndPaymentTypeAndStatusIn(user.getId(), auction.getId(),
|
|
|
+ AuctionPaymentType.DEPOSIT, Arrays
|
|
|
+ .asList(AuctionOrderStatus.NOT_PAID, AuctionOrderStatus.FINISH));
|
|
|
+ if (ObjectUtils.isNotEmpty(order)) {
|
|
|
+ if (AuctionOrderStatus.FINISH.equals(order.getStatus())) {
|
|
|
+ throw new BusinessException("保证金已交过,无需再交");
|
|
|
+ }
|
|
|
+ throw new BusinessException("保证金未支付,取消后再重新出价");
|
|
|
+ }
|
|
|
+
|
|
|
+ AuctionRecord auctionRecord = AuctionRecord.builder()
|
|
|
+ .auctionId(auction.getId())
|
|
|
+ .type(AuctionRecordType.DEPOSIT)
|
|
|
+ .bidderPrice(auction.getDeposit())
|
|
|
+ .auctionPic(null)
|
|
|
+ .userId(SecurityUtils.getAuthenticatedUser().getId())
|
|
|
+ .avatar(SecurityUtils.getAuthenticatedUser().getAvatar())
|
|
|
+ .name(auction.getName())
|
|
|
+ .purchased(false)
|
|
|
+ .auctionType(auction.getAuctionType())
|
|
|
+ .build();
|
|
|
+ AuctionRecord record = auctionRecordRepo.save(auctionRecord);
|
|
|
+
|
|
|
+ order = AuctionOrder.builder()
|
|
|
+ .id(snowflakeIdWorker.nextId())
|
|
|
+ .auctionId(auction.getId())
|
|
|
+ .userId(user.getId())
|
|
|
+ .nickname(user.getNickname())
|
|
|
+ .paymentType(AuctionPaymentType.DEPOSIT)
|
|
|
+ .name(auction.getName())
|
|
|
+ .pic(auction.getPic())
|
|
|
+ .serviceCharge(auction.getServiceCharge())
|
|
|
+ .royalties(auction.getRoyalties())
|
|
|
+ .source(auction.getSource())
|
|
|
+ .price(auction.getDeposit())
|
|
|
+ .totalPrice(auction.getDeposit())
|
|
|
+ .auctionRecordId(record.getId())
|
|
|
+ .status(AuctionOrderStatus.NOT_PAID)
|
|
|
+ .build();
|
|
|
+
|
|
|
+
|
|
|
+ return auctionOrderRepo.save(order);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transient
|
|
|
+ public void notify(Long id, PayMethod payMethod, String transactionId) {
|
|
|
+ AuctionOrder order = auctionOrderRepo.findById(id).orElseThrow(new BusinessException("无记录"));
|
|
|
+ if (!order.getStatus().equals(AuctionOrderStatus.NOT_PAID)) {
|
|
|
+ throw new BusinessException("订单已处理");
|
|
|
+ }
|
|
|
+ AuctionActivity auction = auctionActivityRepo.findById(order.getAuctionId())
|
|
|
+ .orElseThrow(new BusinessException("无拍卖活动"));
|
|
|
+
|
|
|
+ if (auction.getAuctionType().equals(AuctionType.ENTITY)) {
|
|
|
+ order.setStatus(AuctionOrderStatus.DELIVERY);
|
|
|
+ } else {
|
|
|
+ order.setStatus(AuctionOrderStatus.FINISH);
|
|
|
+ }
|
|
|
+ order.setPayMethod(payMethod);
|
|
|
+ order.setTransactionId(transactionId);
|
|
|
+ order.setPayTime(LocalDateTime.now());
|
|
|
+ //存订单
|
|
|
+ auctionOrderRepo.save(order);
|
|
|
+
|
|
|
+ if (AuctionPaymentType.DEPOSIT.equals(order.getPaymentType())) {
|
|
|
+ //改出价记录表
|
|
|
+ AuctionRecord record = auctionRecordRepo.findById(order.getAuctionRecordId())
|
|
|
+ .orElseThrow(new BusinessException("无出价记录"));
|
|
|
+ record.setPayDeposit(true);
|
|
|
+ auctionRecordRepo.save(record);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //此拍卖结束
|
|
|
+ auctionActivityService.changeStatus(order.getAuctionId(), AuctionStatus.FINISH);
|
|
|
+
|
|
|
+ //修改买家和成交价
|
|
|
+ auction.setPurchaserId(order.getUserId());
|
|
|
+ auction.setPurchasePrice(order.getTotalPrice());
|
|
|
+ auctionActivityRepo.save(auction);
|
|
|
+
|
|
|
+ if (AuctionSource.TRANSFER.equals(order.getSource())) {
|
|
|
+ Asset asset = assetRepo.findById(auction.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
|
|
|
+ if (asset.isPublicShow()) {
|
|
|
+ //取消公开展示
|
|
|
+ assetService.cancelPublic(asset);
|
|
|
+ }
|
|
|
+ User user = userRepo.findById(order.getUserId()).orElseThrow(new BusinessException("无用户"));
|
|
|
+ //转让流程
|
|
|
+ assetService.transfer(asset, order.getTotalPrice(), user, TransferReason.AUCTION, order.getId());
|
|
|
+
|
|
|
+ // 发送短信提醒用户转让成功
|
|
|
+ if (asset.getUserId() != null) {
|
|
|
+ smsService.sellOut(userRepo.findPhoneById(asset.getUserId()));
|
|
|
+ }
|
|
|
+
|
|
|
+ //用户冲余额
|
|
|
+ UserBalance userBalance = userBalanceRepo.findByUserId(asset.getOwnerId())
|
|
|
+ .orElse(UserBalance.builder()
|
|
|
+ .balance(BigDecimal.ZERO)
|
|
|
+ .lastBalance(BigDecimal.ZERO)
|
|
|
+ .userId(asset.getOwnerId())
|
|
|
+ .build());
|
|
|
+
|
|
|
+ BigDecimal amount = order.getTotalPrice()
|
|
|
+ .multiply(BigDecimal.valueOf(100 - order.getRoyalties() - order.getServiceCharge()))
|
|
|
+ .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
|
|
|
+
|
|
|
+ userBalance.setLastBalance(userBalance.getBalance());
|
|
|
+ userBalance.setBalance(userBalance.getBalance().add(amount));
|
|
|
+ userBalanceRepo.save(userBalance);
|
|
|
+ log.info("拍卖冲用户余额{},¥{}", asset.getOwnerId(), amount);
|
|
|
+
|
|
|
+ balanceRecordRepo.save(BalanceRecord.builder()
|
|
|
+ .time(LocalDateTime.now())
|
|
|
+ .userId(asset.getOwnerId())
|
|
|
+ .orderId(order.getId())
|
|
|
+ .amount(amount)
|
|
|
+ .balance(userBalance.getBalance())
|
|
|
+ .lastBalance(userBalance.getLastBalance())
|
|
|
+ .type(BalanceType.SELL)
|
|
|
+ .build());
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //改出价记录表为竞得(一口价无出价表)
|
|
|
+ auctionRecordRepo.findById(order.getAuctionRecordId())
|
|
|
+ .ifPresent(record -> {
|
|
|
+ record.setPurchased(true);
|
|
|
+ auctionRecordRepo.save(record);
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ //退保证金
|
|
|
+ List<AuctionOrder> orders = auctionOrderRepo.findAllByAuctionIdAndPaymentTypeAndStatus(order.getAuctionId(),
|
|
|
+ AuctionPaymentType.DEPOSIT, AuctionOrderStatus.FINISH);
|
|
|
+ //退款
|
|
|
+ orders.forEach(this::refund);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void cancel(AuctionOrder order) {
|
|
|
+ if (!getOrderLock(order.getId())) {
|
|
|
+ log.error("订单取消失败 {}, redis锁了", order.getId());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean isRefund = false;
|
|
|
+ try {
|
|
|
+ AuctionActivity auction = auctionActivityRepo.findById(order.getAuctionId())
|
|
|
+ .orElseThrow(new BusinessException("无记录"));
|
|
|
+
|
|
|
+ if (AuctionPaymentType.PURCHASE_PRICE.equals(order.getPaymentType())) {
|
|
|
+ //如果是拍卖,需获取取消订单的时长
|
|
|
+ int time = sysConfigService.getInt("auction_cancel_time");
|
|
|
+ if (LocalDateTime.now().isAfter(auction.getEndTime().plusMinutes(time))) {
|
|
|
+ //超过支付时长
|
|
|
+ log.info("取消订单流拍:{}", auction.getId());
|
|
|
+ auctionActivityService.changeStatus(order.getAuctionId(), AuctionStatus.PASS);
|
|
|
+ //添加到流拍记录表里
|
|
|
+ auctionPassRecordRepo.save(AuctionPassRecord.builder()
|
|
|
+ .auctionId(auction.getId())
|
|
|
+ .userId(auction.getPurchaserId())
|
|
|
+ .purchasePrice(auction.getPurchasePrice())
|
|
|
+ .build());
|
|
|
+ //流拍不退自己的保证金
|
|
|
+ isRefund = true;
|
|
|
+
|
|
|
+ if (AuctionSource.TRANSFER.equals(order.getSource())) {
|
|
|
+ //改回资产状态
|
|
|
+ Asset asset = assetRepo.findById(auction.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
|
|
|
+ asset.setStatus(AssetStatus.NORMAL);
|
|
|
+ assetRepo.save(asset);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ } else if (AuctionPaymentType.DEPOSIT.equals(order.getPaymentType())) {
|
|
|
+ //删除出价记录
|
|
|
+ auctionRecordRepo.softDelete(order.getAuctionRecordId());
|
|
|
+ } else {
|
|
|
+ //拍卖是否结束
|
|
|
+ if (LocalDateTime.now().isBefore(auction.getEndTime())) {
|
|
|
+ //返回拍卖状态
|
|
|
+ auctionActivityService.changeStatus(order.getAuctionId(), AuctionStatus.ONGOING);
|
|
|
+ } else {
|
|
|
+ //最后一个出价的人得
|
|
|
+ auctionActivityService.changeStatus(order.getAuctionId(), AuctionStatus.PURCHASED);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ order.setStatus(AuctionOrderStatus.CANCELLED);
|
|
|
+ order.setCancelTime(LocalDateTime.now());
|
|
|
+ auctionOrderRepo.save(order);
|
|
|
+ log.info("取消订单{}", order.getId());
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("订单取消错误 orderId: " + order.getId(), e);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isRefund) {
|
|
|
+ //退其余保证金
|
|
|
+ List<AuctionOrder> orders = auctionOrderRepo
|
|
|
+ .findAllByAuctionIdAndPaymentTypeAndStatus(order.getAuctionId(),
|
|
|
+ AuctionPaymentType.DEPOSIT, AuctionOrderStatus.FINISH);
|
|
|
+ //退款
|
|
|
+ orders.stream()
|
|
|
+ .filter(o -> !order.getUserId().equals(o.getUserId()))
|
|
|
+ .forEach(this::refund);
|
|
|
+ }
|
|
|
+ releaseOrderLock(order.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 退款方法
|
|
|
+ *
|
|
|
+ * @param order 订单
|
|
|
+ */
|
|
|
+ private void refund(AuctionOrder order) {
|
|
|
+ log.info("退款拍卖保证金订单{}", order.getId());
|
|
|
+ PayMethod payMethod = order.getPayMethod();
|
|
|
+ if (PayMethod.ALIPAY == payMethod) {
|
|
|
+ if (StringUtils.length(order.getTransactionId()) == 28) {
|
|
|
+ payMethod = PayMethod.HMPAY;
|
|
|
+ } else if (StringUtils.length(order.getTransactionId()) == 30) {
|
|
|
+ payMethod = PayMethod.SANDPAY;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ switch (payMethod) {
|
|
|
+ case HMPAY:
|
|
|
+ orderPayService.refund(order.getId().toString(), order.getTransactionId(), order.getTotalPrice(), Constants.PayChannel.HM);
|
|
|
+ log.info("退款成功{}", order.getId());
|
|
|
+ break;
|
|
|
+ case SANDPAY:
|
|
|
+ orderPayService.refund(order.getId().toString(), order.getTransactionId(), order.getTotalPrice(), Constants.PayChannel.SAND);
|
|
|
+ log.info("退款成功{}", order.getId());
|
|
|
+ break;
|
|
|
+ case PAYEASE:
|
|
|
+ orderPayService.refund(order.getId().toString(), order.getTransactionId(), order.getTotalPrice(), Constants.PayChannel.PE);
|
|
|
+ log.info("退款成功{}", order.getId());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ order.setRefundTime(LocalDateTime.now());
|
|
|
+ order.setStatus(AuctionOrderStatus.REFUNDED);
|
|
|
+ auctionOrderRepo.save(order);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("拍卖保证金订单退款失败 {} ", order.getId(), e);
|
|
|
+ order.setRefundTime(LocalDateTime.now());
|
|
|
+ order.setStatus(AuctionOrderStatus.REFUNDING);
|
|
|
+ auctionOrderRepo.save(order);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean getOrderLock(Long orderId) {
|
|
|
+ BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.AUCTION_ORDER_LOCK + orderId);
|
|
|
+ Boolean flag = ops.setIfAbsent(1, 1, TimeUnit.DAYS);
|
|
|
+ return Boolean.TRUE.equals(flag);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void releaseOrderLock(Long orderId) {
|
|
|
+ redisTemplate.delete(RedisKeys.AUCTION_ORDER_LOCK + orderId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Scheduled(cron = "0 0/10 * * * ?")
|
|
|
+ public void passOverTimeAuction() {
|
|
|
+ List<AuctionActivity> purchased = auctionActivityRepo.findAllByStatus(AuctionStatus.PURCHASED);
|
|
|
+ if (purchased != null) {
|
|
|
+ int time = sysConfigService.getInt("auction_cancel_time");
|
|
|
+ purchased.forEach(act -> {
|
|
|
+ if (LocalDateTime.now().isAfter(act.getEndTime().plusMinutes(time))) {
|
|
|
+ List<AuctionOrder> auctionOrders = auctionOrderRepo.findAllByAuctionIdAndPaymentTypeAndStatus(act
|
|
|
+ .getId(), AuctionPaymentType.PURCHASE_PRICE, AuctionOrderStatus.NOT_PAID);
|
|
|
+// if (CollUtil.isNotEmpty(auctionOrders)) {
|
|
|
+ auctionOrders.forEach(this::cancel);
|
|
|
+// return;
|
|
|
+// }
|
|
|
+
|
|
|
+ auctionActivityService.changeStatus(act.getId(), AuctionStatus.PASS);
|
|
|
+ log.info("拍卖定时任务流拍{}", act.getId());
|
|
|
+
|
|
|
+ if (AuctionSource.TRANSFER.equals(act.getSource())) {
|
|
|
+ //改回资产状态
|
|
|
+ Asset asset = assetRepo.findById(act.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
|
|
|
+ asset.setStatus(AssetStatus.NORMAL);
|
|
|
+ assetRepo.save(asset);
|
|
|
+ }
|
|
|
+
|
|
|
+ //退其余保证金
|
|
|
+ List<AuctionOrder> orders = auctionOrderRepo
|
|
|
+ .findAllByAuctionIdAndPaymentTypeAndStatus(act.getId(),
|
|
|
+ AuctionPaymentType.DEPOSIT, AuctionOrderStatus.FINISH);
|
|
|
+ //退款
|
|
|
+ orders.stream()
|
|
|
+ .filter(o -> !act.getPurchaserId().equals(o.getUserId()))
|
|
|
+ .forEach(this::refund);
|
|
|
+
|
|
|
+ //添加到流拍记录表里
|
|
|
+ auctionPassRecordRepo.save(AuctionPassRecord.builder()
|
|
|
+ .auctionId(act.getId())
|
|
|
+ .userId(act.getPurchaserId())
|
|
|
+ .purchasePrice(act.getPurchasePrice())
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发货
|
|
|
+ *
|
|
|
+ * @param id 编号
|
|
|
+ * @param courierId 快递单号
|
|
|
+ */
|
|
|
+ public void dispatch(Long id, String courierId) {
|
|
|
+ AuctionOrder auctionOrder = auctionOrderRepo.findById(id).orElseThrow(new BusinessException("铸造订单不存在"));
|
|
|
+ auctionOrder.setStatus(AuctionOrderStatus.RECEIVE);
|
|
|
+ auctionOrder.setCourierId(courierId);
|
|
|
+ auctionOrderRepo.save(auctionOrder);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订单
|
|
|
+ *
|
|
|
+ * @param id 编号
|
|
|
+ */
|
|
|
+ public void finish(Long id) {
|
|
|
+ AuctionOrder auctionOrder = auctionOrderRepo.findById(id).orElseThrow(new BusinessException("铸造订单不存在"));
|
|
|
+ auctionOrder.setStatus(AuctionOrderStatus.FINISH);
|
|
|
+ auctionOrderRepo.save(auctionOrder);
|
|
|
+ }
|
|
|
+}
|