|
|
@@ -2,13 +2,14 @@ package cn.hobbystocks.auc.service.impl;
|
|
|
|
|
|
import cn.hobbystocks.auc.cache.CacheMap;
|
|
|
import cn.hobbystocks.auc.common.constant.Constants;
|
|
|
-import cn.hobbystocks.auc.common.core.domain.AjaxResult;
|
|
|
import cn.hobbystocks.auc.common.core.redis.Locker;
|
|
|
import cn.hobbystocks.auc.common.core.redis.RedisCache;
|
|
|
import cn.hobbystocks.auc.common.core.text.Convert;
|
|
|
import cn.hobbystocks.auc.common.enums.LotStatusEnum;
|
|
|
import cn.hobbystocks.auc.common.enums.PubStatusEnum;
|
|
|
import cn.hobbystocks.auc.common.enums.RuleTypeEnum;
|
|
|
+import cn.hobbystocks.auc.common.exception.ServiceException;
|
|
|
+import cn.hobbystocks.auc.common.user.UserInfo;
|
|
|
import cn.hobbystocks.auc.common.user.UserUtils;
|
|
|
import cn.hobbystocks.auc.common.utils.CloneUtils;
|
|
|
import cn.hobbystocks.auc.common.utils.DateUtils;
|
|
|
@@ -28,6 +29,7 @@ import cn.hobbystocks.auc.handle.context.tradition.TraditionRule;
|
|
|
import cn.hobbystocks.auc.mapper.*;
|
|
|
import cn.hobbystocks.auc.request.LotQueryRequest;
|
|
|
import cn.hobbystocks.auc.request.LotRequest;
|
|
|
+import cn.hobbystocks.auc.response.LotDetailResponse;
|
|
|
import cn.hobbystocks.auc.response.LotFansResponse;
|
|
|
import cn.hobbystocks.auc.service.ILotService;
|
|
|
import cn.hobbystocks.auc.task.DynamicTaskService;
|
|
|
@@ -35,14 +37,12 @@ import cn.hobbystocks.auc.vo.LiveVO;
|
|
|
import cn.hobbystocks.auc.vo.LotVO;
|
|
|
import cn.hobbystocks.auc.vo.SelfVO;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
-import com.alibaba.fastjson.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.google.common.collect.Lists;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
@@ -50,6 +50,7 @@ import org.springframework.transaction.annotation.Isolation;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
@@ -87,6 +88,8 @@ public class LotServiceImpl extends ServiceImpl<LotMapper,Lot> implements ILotSe
|
|
|
private LotFansMapper lotFansMapper;
|
|
|
@Autowired
|
|
|
private SpuCategoryMapper spuCategoryMapper;
|
|
|
+ @Autowired
|
|
|
+ private DepositOrderMapper depositOrderMapper;
|
|
|
|
|
|
@Override
|
|
|
public Lot selectLotById(Long id) {
|
|
|
@@ -542,6 +545,122 @@ public class LotServiceImpl extends ServiceImpl<LotMapper,Lot> implements ILotSe
|
|
|
return finishOrWin(selfVO, 1);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public List<LotVO> selfList(SelfVO selfVO) {
|
|
|
+ UserInfo userInfo = UserUtils.getSimpleUserInfo();
|
|
|
+ if (userInfo == null) {
|
|
|
+ throw new ServiceException("请先登录");
|
|
|
+ }
|
|
|
+ String userId = userInfo.getId().toString();
|
|
|
+ List<Lot> lotList = lotMapper.selectLotByAucId(selfVO.getAuctionId());
|
|
|
+ List<DepositOrder> depositOrders = depositOrderMapper.selectList(new LambdaQueryWrapper<DepositOrder>()
|
|
|
+ .eq(DepositOrder::getUserId, userInfo.getId())
|
|
|
+ .eq(DepositOrder::getAuctionId, selfVO.getAuctionId())
|
|
|
+ .in(DepositOrder::getStatus, 1));
|
|
|
+
|
|
|
+ String type = StringUtils.isEmpty(selfVO.getType()) ? "all" : selfVO.getType();
|
|
|
+ List<LotVO> result = new ArrayList<>();
|
|
|
+ for (Lot lot : lotList) {
|
|
|
+ List<Bid> userBids = bidMapper.selectBidList(Bid.builder()
|
|
|
+ .lotId(lot.getId())
|
|
|
+ .accountId(userId)
|
|
|
+ .build());
|
|
|
+ boolean hasUserBid = !CollectionUtils.isEmpty(userBids);
|
|
|
+ boolean hasWinBid = hasUserBid && userBids.stream().anyMatch(bid -> Objects.equals(bid.getStatus(), 1));
|
|
|
+ boolean hasDeposit = hasDepositQualification(lot, depositOrders);
|
|
|
+
|
|
|
+ if (matchSelfScene(type, lot, hasDeposit, hasUserBid, hasWinBid)) {
|
|
|
+ result.add(buildSelfLotVo(lot, userBids));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sortSelfLots(type, result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean hasDepositQualification(Lot lot, List<DepositOrder> depositOrders) {
|
|
|
+ if (CollectionUtils.isEmpty(depositOrders)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(lot.getDeposit())) {
|
|
|
+ return depositOrders.stream().anyMatch(order -> Objects.equals(order.getLotId(), lot.getId()));
|
|
|
+ }
|
|
|
+ return depositOrders.stream().anyMatch(order -> Objects.equals(order.getAuctionId(), lot.getAuctionId()));
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean matchSelfScene(String type, Lot lot, boolean hasDeposit, boolean hasUserBid, boolean hasWinBid) {
|
|
|
+ if ("all".equals(type)) {
|
|
|
+ return isWaitingLot(lot, hasDeposit) || isLiveLot(lot, hasDeposit, hasUserBid) || isLoseLot(lot, hasUserBid, hasWinBid);
|
|
|
+ }
|
|
|
+ if ("waiting".equals(type)) {
|
|
|
+ return isWaitingLot(lot, hasDeposit);
|
|
|
+ }
|
|
|
+ if ("live".equals(type)) {
|
|
|
+ return isLiveLot(lot, hasDeposit, hasUserBid);
|
|
|
+ }
|
|
|
+ if ("lose".equals(type) || "pass".equals(type) || "finish".equals(type)) {
|
|
|
+ return isLoseLot(lot, hasUserBid, hasWinBid);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isWaitingLot(Lot lot, boolean hasDeposit) {
|
|
|
+ return Constants.LOT_STATUS_WAITING.equals(lot.getStatus()) && hasDeposit;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isLiveLot(Lot lot, boolean hasDeposit, boolean hasUserBid) {
|
|
|
+ return (Constants.LOT_STATUS_STARTING.equals(lot.getStatus()) || Constants.LOT_STATUS_BIDDING.equals(lot.getStatus()))
|
|
|
+ && (hasDeposit || hasUserBid);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isLoseLot(Lot lot, boolean hasUserBid, boolean hasWinBid) {
|
|
|
+ if (!hasUserBid) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (Constants.LOT_STATUS_PASS.equals(lot.getStatus())) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return Constants.LOT_STATUS_SOLD.equals(lot.getStatus()) && !hasWinBid;
|
|
|
+ }
|
|
|
+
|
|
|
+ private LotVO buildSelfLotVo(Lot lot, List<Bid> userBids) {
|
|
|
+ LotVO lotVO = new LotVO();
|
|
|
+ BeanUtils.copyProperties(lot, lotVO);
|
|
|
+ lotVO.setBids(userBids);
|
|
|
+ lotVO.setCurrentPrice(Objects.nonNull(lot.getLastPrice()) ? lot.getLastPrice() : null);
|
|
|
+ return SensitiveDataUtils.handleViewDataSafe(lotVO);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void sortSelfLots(String type, List<LotVO> lots) {
|
|
|
+ if ("waiting".equals(type)) {
|
|
|
+ lots.sort(Comparator.comparing(Lot::getStartTime, Comparator.nullsLast(Date::compareTo)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if ("live".equals(type)) {
|
|
|
+ lots.sort(Comparator.comparing(Lot::getLastPriceTime, Comparator.nullsLast(Date::compareTo)).reversed());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if ("lose".equals(type) || "pass".equals(type) || "finish".equals(type)) {
|
|
|
+ lots.sort(Comparator.comparing(Lot::getRealEndTime, Comparator.nullsLast(Date::compareTo)).reversed());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<LotVO> waiting = lots.stream().filter(lot -> Constants.LOT_STATUS_WAITING.equals(lot.getStatus()))
|
|
|
+ .sorted(Comparator.comparing(Lot::getStartTime, Comparator.nullsLast(Date::compareTo)))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ List<LotVO> live = lots.stream()
|
|
|
+ .filter(lot -> Constants.LOT_STATUS_STARTING.equals(lot.getStatus()) || Constants.LOT_STATUS_BIDDING.equals(lot.getStatus()))
|
|
|
+ .sorted(Comparator.comparing(Lot::getLastPriceTime, Comparator.nullsLast(Date::compareTo)).reversed())
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ List<LotVO> lose = lots.stream()
|
|
|
+ .filter(lot -> Constants.LOT_STATUS_PASS.equals(lot.getStatus()) || Constants.LOT_STATUS_SOLD.equals(lot.getStatus()))
|
|
|
+ .sorted(Comparator.comparing(Lot::getRealEndTime, Comparator.nullsLast(Date::compareTo)).reversed())
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ lots.clear();
|
|
|
+ lots.addAll(waiting);
|
|
|
+ lots.addAll(live);
|
|
|
+ lots.addAll(lose);
|
|
|
+ }
|
|
|
+
|
|
|
private List<LotVO> finishOrWin(SelfVO selfVO, Integer win) {
|
|
|
String account = UserUtils.getSimpleUserInfo().getId().toString();
|
|
|
List<LotVO> resultList = new ArrayList<>();
|
|
|
@@ -691,6 +810,85 @@ public class LotServiceImpl extends ServiceImpl<LotMapper,Lot> implements ILotSe
|
|
|
return lotFansResponses;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public LotDetailResponse queryLotDetail(Long lotId) {
|
|
|
+ Lot lot = lotMapper.selectLotById(lotId);
|
|
|
+ if (Objects.isNull(lot)) {
|
|
|
+ throw new ServiceException("未找到拍品数据");
|
|
|
+ }
|
|
|
+ Auction auction = auctionMapper.selectAuctionById(lot.getAuctionId());
|
|
|
+ if (Objects.isNull(auction)) {
|
|
|
+ throw new ServiceException("未找到拍卖会相关数据");
|
|
|
+ }
|
|
|
+ TraditionRule rule = StringUtils.isEmpty(lot.getRuleContent())
|
|
|
+ ? null
|
|
|
+ : JSON.parseObject(lot.getRuleContent(), TraditionRule.class);
|
|
|
+ BigDecimal startPrice = Objects.isNull(rule) ? null : rule.getStartPrice();
|
|
|
+ BigDecimal markupAmount = Objects.isNull(rule) ? null : rule.getDefaultOnceAddPrice();
|
|
|
+ Long depositAmount = lot.getDeposit();
|
|
|
+ String depositType = "LOT";
|
|
|
+ if (Objects.isNull(depositAmount)) {
|
|
|
+ depositAmount = auction.getDeposit();
|
|
|
+ depositType = "AUCTION";
|
|
|
+ }
|
|
|
+ LotDetailResponse response = new LotDetailResponse();
|
|
|
+ response.setLotId(lot.getId());
|
|
|
+ response.setAuctionId(lot.getAuctionId());
|
|
|
+ response.setName(lot.getName());
|
|
|
+ response.setAuctionName(auction.getName());
|
|
|
+ response.setImgs(lot.getImgs());
|
|
|
+ response.setCarouselImgs(lot.getCarouselImgs());
|
|
|
+ response.setStatus(lot.getStatus());
|
|
|
+ response.setStartTime(lot.getStartTime());
|
|
|
+ response.setEndTime(lot.getEndTime());
|
|
|
+ response.setRealEndTime(lot.getRealEndTime());
|
|
|
+ response.setStartPrice(startPrice);
|
|
|
+ response.setCurrentPrice(Objects.nonNull(lot.getLastPrice()) ? lot.getLastPrice() : startPrice);
|
|
|
+ response.setBidCount(lot.getBidCount());
|
|
|
+ response.setDepositAmount(depositAmount);
|
|
|
+ response.setDepositType(depositType);
|
|
|
+ response.setServiceTariff(lot.getServiceTariff());
|
|
|
+ response.setRuleType(lot.getRuleType());
|
|
|
+ response.setMarkupAmount(markupAmount);
|
|
|
+ response.setDetail(lot.getDetail());
|
|
|
+ response.setProperties(lot.getProperties());
|
|
|
+ response.setIsFans(Boolean.FALSE);
|
|
|
+ response.setHasDeposit(Boolean.FALSE);
|
|
|
+ response.setPayTimeLimit(lot.getPayTimeLimit());
|
|
|
+ if (Objects.equals("Waiting", lot.getStatus())) {
|
|
|
+ response.setTimestamp(lot.getStartTime().getTime() - System.currentTimeMillis());
|
|
|
+ } else if (Objects.equals("Bidding", lot.getStatus())) {
|
|
|
+ response.setTimestamp(lot.getEndTime().getTime() - System.currentTimeMillis());
|
|
|
+ }
|
|
|
+ //TODO 成交用户暂时无
|
|
|
+ fillUserFlags(lot, response, depositType);
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void fillUserFlags(Lot lot, LotDetailResponse response, String depositType) {
|
|
|
+ UserInfo userInfo = UserUtils.getSimpleUserInfo();
|
|
|
+ if (Objects.isNull(userInfo)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Long favoriteCount = lotFansMapper.selectCount(new LambdaQueryWrapper<LotFans>()
|
|
|
+ .eq(LotFans::getLotId, lot.getId())
|
|
|
+ .eq(LotFans::getUserId, userInfo.getId().longValue())
|
|
|
+ .eq(LotFans::getType, "user_like"));
|
|
|
+ response.setIsFans(favoriteCount > 0);
|
|
|
+
|
|
|
+ LambdaQueryWrapper<DepositOrder> depositQuery = new LambdaQueryWrapper<DepositOrder>()
|
|
|
+ .eq(DepositOrder::getUserId, userInfo.getId())
|
|
|
+ .in(DepositOrder::getStatus, 1);
|
|
|
+ if (Objects.equals("LOT", depositType)) {
|
|
|
+ depositQuery.eq(DepositOrder::getLotId, lot.getId());
|
|
|
+ } else {
|
|
|
+ depositQuery.eq(DepositOrder::getAuctionId, lot.getAuctionId());
|
|
|
+ }
|
|
|
+ Long depositCount = depositOrderMapper.selectCount(depositQuery);
|
|
|
+ response.setHasDeposit(depositCount > 0);
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public List<LotExportDTO> exportLotList(LotRequest request) {
|
|
|
|