|
@@ -21,7 +21,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Lists;
|
|
|
import io.micrometer.core.instrument.util.NamedThreadFactory;
|
|
import io.micrometer.core.instrument.util.NamedThreadFactory;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
@@ -39,6 +38,11 @@ import java.util.concurrent.TimeUnit;
|
|
|
@Slf4j
|
|
@Slf4j
|
|
|
public class BidTask implements CacheMap {
|
|
public class BidTask implements CacheMap {
|
|
|
|
|
|
|
|
|
|
+ private static final String DEPOSIT_TYPE_LOT = "拍品";
|
|
|
|
|
+ private static final String DEPOSIT_TYPE_AUCTION = "拍卖会";
|
|
|
|
|
+ private static final Integer DEPOSIT_STATUS_WAITING_PAYMENT = 0;
|
|
|
|
|
+ private static final Integer DEPOSIT_STATUS_PAID = 1;
|
|
|
|
|
+
|
|
|
// region params
|
|
// region params
|
|
|
private static final ConcurrentHashMap<String, ConcurrentHashMap<String, Live>> liveCacheMap = new ConcurrentHashMap<>();
|
|
private static final ConcurrentHashMap<String, ConcurrentHashMap<String, Live>> liveCacheMap = new ConcurrentHashMap<>();
|
|
|
|
|
|
|
@@ -239,13 +243,17 @@ public class BidTask implements CacheMap {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
Lot lot = lotMapper.selectLotById(order.getLotId());
|
|
Lot lot = lotMapper.selectLotById(order.getLotId());
|
|
|
- if (Objects.isNull(lot) || Constants.LOT_STATUS_PASS.equals(lot.getStatus())) {
|
|
|
|
|
|
|
+ if (Objects.isNull(lot)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- lotMapper.updateLot(Lot.builder()
|
|
|
|
|
- .id(order.getLotId())
|
|
|
|
|
- .status(Constants.LOT_STATUS_PASS)
|
|
|
|
|
- .build());
|
|
|
|
|
|
|
+ if (!Constants.LOT_STATUS_PASS.equals(lot.getStatus())) {
|
|
|
|
|
+ lotMapper.updateLot(Lot.builder()
|
|
|
|
|
+ .id(order.getLotId())
|
|
|
|
|
+ .status(Constants.LOT_STATUS_PASS)
|
|
|
|
|
+ .build());
|
|
|
|
|
+ }
|
|
|
|
|
+ selectPendingDeposit(order.getUserId(), lot)
|
|
|
|
|
+ .forEach(deposit -> depositOrderService.reduceDeposit(deposit.getOrderNo()));
|
|
|
// appClient.notice(order.getLotId().toString(), "", "{}", "lot_auction", "");
|
|
// appClient.notice(order.getLotId().toString(), "", "{}", "lot_auction", "");
|
|
|
log.info("expire lot order marked pass, lotId={}, orderNo={}", order.getLotId(), order.getOrderNo());
|
|
log.info("expire lot order marked pass, lotId={}, orderNo={}", order.getLotId(), order.getOrderNo());
|
|
|
}
|
|
}
|
|
@@ -259,14 +267,19 @@ public class BidTask implements CacheMap {
|
|
|
if (CollectionUtils.isEmpty(paidOrders)) {
|
|
if (CollectionUtils.isEmpty(paidOrders)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- paidOrders.stream()
|
|
|
|
|
- .map(Order::getLotId)
|
|
|
|
|
- .filter(Objects::nonNull)
|
|
|
|
|
- .distinct()
|
|
|
|
|
- .forEach(lotId -> {
|
|
|
|
|
- lotMapper.updatePay(lotId, 1);
|
|
|
|
|
- log.info("paid lot order synced, lotId={}", lotId);
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ Set<Long> processedLotIds = new HashSet<>();
|
|
|
|
|
+ for (Order order : paidOrders) {
|
|
|
|
|
+ if (Objects.isNull(order) || Objects.isNull(order.getLotId()) || !processedLotIds.add(order.getLotId())) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ lotMapper.updatePay(order.getLotId(), 1);
|
|
|
|
|
+ Lot lot = lotMapper.selectLotById(order.getLotId());
|
|
|
|
|
+ if (isIndividualDeposit(lot) && isTerminalLot(lot)) {
|
|
|
|
|
+ selectPendingDeposit(order.getUserId(), lot)
|
|
|
|
|
+ .forEach(deposit -> depositOrderService.refundDepositOrder(deposit.getOrderNo()));
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("paid lot order synced, lotId={}", order.getLotId());
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -395,61 +408,138 @@ public class BidTask implements CacheMap {
|
|
|
//拍卖会结束发起退保证金,每五分钟执行一次
|
|
//拍卖会结束发起退保证金,每五分钟执行一次
|
|
|
@Scheduled(fixedRate = 1000*60*5)
|
|
@Scheduled(fixedRate = 1000*60*5)
|
|
|
public void depositOrderRefund(){
|
|
public void depositOrderRefund(){
|
|
|
- //查询已支付待退款的保证金订单
|
|
|
|
|
- DepositOrder depositOrder = new DepositOrder();
|
|
|
|
|
- depositOrder.setStatus(1);
|
|
|
|
|
- List<DepositOrder> depositOrderList = depositOrderService.selectDepositOrder(depositOrder);
|
|
|
|
|
- for (DepositOrder order : depositOrderList) {
|
|
|
|
|
- Integer userId = order.getUserId();
|
|
|
|
|
- //判断拍卖会是否已结束
|
|
|
|
|
- Auction auction = auctionService.selectAuctionById(order.getAuctionId());
|
|
|
|
|
- if (!Constants.GROUP_STATUS_FINISH.equals(auction.getStatus())){
|
|
|
|
|
- //如果拍卖会未结束,处理下一个保证金订单
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
+ DepositOrder pending = new DepositOrder();
|
|
|
|
|
+ pending.setStatus(DEPOSIT_STATUS_PAID);
|
|
|
|
|
+ List<DepositOrder> depositOrders = depositOrderService.selectDepositOrder(pending);
|
|
|
|
|
+ for (DepositOrder deposit : depositOrders) {
|
|
|
|
|
+ if (DEPOSIT_TYPE_LOT.equals(deposit.getDepositType())) {
|
|
|
|
|
+ settleIndividualDeposit(deposit);
|
|
|
|
|
+ } else if (DEPOSIT_TYPE_AUCTION.equals(deposit.getDepositType())) {
|
|
|
|
|
+ settleAuctionDeposit(deposit);
|
|
|
}
|
|
}
|
|
|
- if (StringUtils.equals("拍卖会",order.getDepositType())){
|
|
|
|
|
-
|
|
|
|
|
- //判断是否有未结束的未设置单独保证金的拍品
|
|
|
|
|
- List<Lot> lots = lotMapper.selectNotEndLotList(order.getAuctionId());
|
|
|
|
|
- if (!CollectionUtils.isEmpty(lots))
|
|
|
|
|
- continue;
|
|
|
|
|
- //拍卖会保证金,查询用户在该拍卖会下是否有非单独保证金的拍品中标未支付订单
|
|
|
|
|
- List<Order> orderList = orderService.getOrderListByUserAndAuction(order.getAuctionId(), userId);
|
|
|
|
|
- if (CollectionUtils.isEmpty(orderList)){
|
|
|
|
|
- //todo 没有待支付订单,或没中标,或已支付,执行退保证金操作
|
|
|
|
|
- depositOrderService.refundDepositOrder(order.getOrderNo());
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- //有待支付的订单列表,判断订单是否已过期,并更新订单记录表状态,
|
|
|
|
|
- for (Order order1 : orderList) {
|
|
|
|
|
- if (order1.getFlag()==2){
|
|
|
|
|
- //todo 订单待支付已过期,调用扣除保证金接口,更新订单记录表状态
|
|
|
|
|
- depositOrderService.reduceDeposit(order.getOrderNo());
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }else{
|
|
|
|
|
- Long lotId = order.getLotId();
|
|
|
|
|
- //查询拍品是否已结束,未结束则跳过
|
|
|
|
|
- Lot lot = lotMapper.selectLotById(lotId);
|
|
|
|
|
- if (StringUtils.equalsAny(lot.getStatus(), Constants.LOT_STATUS_WAITING, Constants.LOT_STATUS_STARTING, Constants.LOT_STATUS_BIDDING))
|
|
|
|
|
- continue;
|
|
|
|
|
-
|
|
|
|
|
- //已结束,查询用户是否有该拍品的订单,
|
|
|
|
|
- LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
- queryWrapper.eq(Order::getLotId,lotId).eq(Order::getUserId,order.getUserId());
|
|
|
|
|
- Order order1 = orderService.getOne(queryWrapper);
|
|
|
|
|
- if (order1==null){
|
|
|
|
|
- //todo 未中标,退拍品保证金
|
|
|
|
|
- depositOrderService.refundDepositOrder(order.getOrderNo());
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ timeoutUnpaidDepositOrders();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void timeoutUnpaidDepositOrders() {
|
|
|
|
|
+ DepositOrder waiting = new DepositOrder();
|
|
|
|
|
+ waiting.setStatus(DEPOSIT_STATUS_WAITING_PAYMENT);
|
|
|
|
|
+ List<DepositOrder> depositOrders = depositOrderService.selectDepositOrder(waiting);
|
|
|
|
|
+ for (DepositOrder deposit : depositOrders) {
|
|
|
|
|
+ if (DEPOSIT_TYPE_LOT.equals(deposit.getDepositType())) {
|
|
|
|
|
+ Lot lot = lotMapper.selectLotById(deposit.getLotId());
|
|
|
|
|
+ if (isTerminalLot(lot)) {
|
|
|
|
|
+ depositOrderService.timeoutDepositOrder(deposit.getOrderNo());
|
|
|
}
|
|
}
|
|
|
- if (order1.getFlag()==2){
|
|
|
|
|
- //todo 订单已过期 调用接口扣除保证金
|
|
|
|
|
- depositOrderService.reduceDeposit(order.getOrderNo());
|
|
|
|
|
|
|
+ } else if (DEPOSIT_TYPE_AUCTION.equals(deposit.getDepositType())) {
|
|
|
|
|
+ Auction auction = auctionService.selectAuctionById(deposit.getAuctionId());
|
|
|
|
|
+ if (Objects.nonNull(auction)
|
|
|
|
|
+ && Constants.GROUP_STATUS_FINISH.equals(auction.getStatus())
|
|
|
|
|
+ && CollectionUtils.isEmpty(lotMapper.selectNotEndLotList(deposit.getAuctionId()))) {
|
|
|
|
|
+ depositOrderService.timeoutDepositOrder(deposit.getOrderNo());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ private void settleIndividualDeposit(DepositOrder deposit) {
|
|
|
|
|
+ Lot lot = lotMapper.selectLotById(deposit.getLotId());
|
|
|
|
|
+ if (!isTerminalLot(lot)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ LambdaQueryWrapper<Order> query = new LambdaQueryWrapper<>();
|
|
|
|
|
+ query.eq(Order::getLotId, deposit.getLotId()).eq(Order::getUserId, deposit.getUserId());
|
|
|
|
|
+ Order winningOrder = orderService.getOne(query);
|
|
|
|
|
+ if (Objects.isNull(winningOrder)) {
|
|
|
|
|
+ if (!isWinningUser(deposit, lot)) {
|
|
|
|
|
+ depositOrderService.refundDepositOrder(deposit.getOrderNo());
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Objects.equals(lot.getPaid(), 1L)
|
|
|
|
|
+ || Constants.LOT_STATUS_CANCELLED.equals(lot.getStatus())) {
|
|
|
|
|
+ depositOrderService.refundDepositOrder(deposit.getOrderNo());
|
|
|
|
|
+ } else if (Constants.LOT_STATUS_PASS.equals(lot.getStatus())) {
|
|
|
|
|
+ depositOrderService.reduceDeposit(deposit.getOrderNo());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void settleAuctionDeposit(DepositOrder deposit) {
|
|
|
|
|
+ Auction auction = auctionService.selectAuctionById(deposit.getAuctionId());
|
|
|
|
|
+ if (Objects.isNull(auction) || !Constants.GROUP_STATUS_FINISH.equals(auction.getStatus())
|
|
|
|
|
+ || !CollectionUtils.isEmpty(lotMapper.selectNotEndLotList(deposit.getAuctionId()))) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ List<Order> winningOrders = orderService.getOrderListByUserAndAuction(deposit.getAuctionId(), deposit.getUserId());
|
|
|
|
|
+ if (hasWinningLotWithoutOrder(deposit, winningOrders)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (CollectionUtils.isEmpty(winningOrders)) {
|
|
|
|
|
+ depositOrderService.refundDepositOrder(deposit.getOrderNo());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (Order winningOrder : winningOrders) {
|
|
|
|
|
+ Lot lot = lotMapper.selectLotById(winningOrder.getLotId());
|
|
|
|
|
+ if (Objects.isNull(lot) || (!Constants.LOT_STATUS_PASS.equals(lot.getStatus())
|
|
|
|
|
+ && !Objects.equals(lot.getPaid(), 1L))) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Constants.LOT_STATUS_PASS.equals(lot.getStatus())) {
|
|
|
|
|
+ depositOrderService.reduceDeposit(deposit.getOrderNo());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ depositOrderService.refundDepositOrder(deposit.getOrderNo());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean hasWinningLotWithoutOrder(DepositOrder deposit, List<Order> winningOrders) {
|
|
|
|
|
+ List<Lot> auctionLots = lotMapper.selectLotByAucId(deposit.getAuctionId());
|
|
|
|
|
+ if (CollectionUtils.isEmpty(auctionLots)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ Set<Long> orderLotIds = new HashSet<>();
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(winningOrders)) {
|
|
|
|
|
+ winningOrders.stream()
|
|
|
|
|
+ .map(Order::getLotId)
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .forEach(orderLotIds::add);
|
|
|
|
|
+ }
|
|
|
|
|
+ return auctionLots.stream()
|
|
|
|
|
+ .filter(lot -> !isIndividualDeposit(lot))
|
|
|
|
|
+ .anyMatch(lot -> isWinningUser(deposit, lot) && !orderLotIds.contains(lot.getId()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean isWinningUser(DepositOrder deposit, Lot lot) {
|
|
|
|
|
+ return Objects.nonNull(deposit.getUserId()) && Objects.nonNull(lot)
|
|
|
|
|
+ && String.valueOf(deposit.getUserId()).equals(lot.getDealAccountId());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<DepositOrder> selectPendingDeposit(Long userId, Lot lot) {
|
|
|
|
|
+ if (Objects.isNull(userId) || Objects.isNull(lot)) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ DepositOrder condition = new DepositOrder();
|
|
|
|
|
+ condition.setUserId(userId.intValue());
|
|
|
|
|
+ condition.setStatus(DEPOSIT_STATUS_PAID);
|
|
|
|
|
+ if (isIndividualDeposit(lot)) {
|
|
|
|
|
+ condition.setDepositType(DEPOSIT_TYPE_LOT);
|
|
|
|
|
+ condition.setLotId(lot.getId());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ condition.setDepositType(DEPOSIT_TYPE_AUCTION);
|
|
|
|
|
+ condition.setAuctionId(lot.getAuctionId());
|
|
|
|
|
+ }
|
|
|
|
|
+ return depositOrderService.selectDepositOrder(condition);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean isIndividualDeposit(Lot lot) {
|
|
|
|
|
+ return Objects.nonNull(lot) && Objects.nonNull(lot.getDeposit());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean isTerminalLot(Lot lot) {
|
|
|
|
|
+ return Objects.nonNull(lot)
|
|
|
|
|
+ && (Constants.LOT_STATUS_SOLD.equals(lot.getStatus())
|
|
|
|
|
+ || Constants.LOT_STATUS_PASS.equals(lot.getStatus())
|
|
|
|
|
+ || Constants.LOT_STATUS_CANCELLED.equals(lot.getStatus()));
|
|
|
|
|
+ }
|
|
|
// endregion
|
|
// endregion
|
|
|
}
|
|
}
|