| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949 |
- 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.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;
- import cn.hobbystocks.auc.common.utils.SensitiveDataUtils;
- import cn.hobbystocks.auc.common.utils.StringUtils;
- import cn.hobbystocks.auc.convert.LotConvert;
- import cn.hobbystocks.auc.domain.*;
- import cn.hobbystocks.auc.dto.LotExportDTO;
- import cn.hobbystocks.auc.event.ChangeEvent;
- import cn.hobbystocks.auc.event.EventPublisher;
- import cn.hobbystocks.auc.event.JPushEvent;
- import cn.hobbystocks.auc.event.StartBiddingEvent;
- import cn.hobbystocks.auc.handle.RuleHandlerHolder;
- import cn.hobbystocks.auc.handle.context.Live;
- import cn.hobbystocks.auc.handle.context.LiveContext;
- 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;
- 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.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;
- 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;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import java.util.stream.Collectors;
- @Service
- @Slf4j
- public class LotServiceImpl extends ServiceImpl<LotMapper,Lot> implements ILotService
- {
- @Autowired
- private LotMapper lotMapper;
- @Autowired
- private BidMapper bidMapper;
- @Autowired
- private Locker locker;
- @Autowired
- private RuleHandlerHolder ruleHandlerHolder;
- @Autowired
- private RedisCache redisCache;
- @Autowired
- private AuctionMapper auctionMapper;
- @Autowired
- public EventPublisher eventPublisher;
- @Autowired(required = false)
- private CacheMap cacheMap;
- @Autowired
- private DynamicTaskService dynamicTaskService;
- @Autowired
- private LotServiceImpl _thiz;
- @Autowired
- private LotGroupMapper lotGroupMapper;
- @Autowired
- private LotFansMapper lotFansMapper;
- @Autowired
- private SpuCategoryMapper spuCategoryMapper;
- @Autowired
- private DepositOrderMapper depositOrderMapper;
- @Override
- public Lot selectLotById(Long id) {
- return lotMapper.selectLotById(id);
- }
- @Override
- public LotGroup selectLotGroupById(Long id) {
- return lotGroupMapper.selectLotGroupById(id);
- }
- @Override
- public List<Lot> selectLotList(Lot lot) {
- IPage<Lot> lotIPage=new Page<>(lot.getPageNum(),lot.getPageSize());
- return lotMapper.selectLotList(lotIPage,lot);
- }
- @Override
- public List<Lot> selectBiddingLotByAucId(Long aucId) {
- return lotMapper.selectNotEndLotList(aucId);
- }
- @Override
- public List<Lot> selectLotByGroupIds(Long[] groupIds) {
- return null;
- }
- @Override
- public List<LotGroup> selectLotGroupList(LotGroup lotGroup) {
- return lotGroupMapper.selectLotGroupList(lotGroup);
- }
- @Override
- public void cancelLotGroup(Long id) {
- LotGroup dbLotGroup = lotGroupMapper.selectLotGroupById(id);
- dbLotGroup.setStatus(Constants.GROUP_STATUS_WAITING);
- dbLotGroup.setPubStatus(Constants.PUB_STATUS_NO_PUBLISHED);
- lotGroupMapper.updateLotGroup(dbLotGroup);
- }
- @Override
- public List<Lot> selectLotByGroupId(Long id) {
- return lotMapper.selectLotByGroupId(id);
- }
- @Override
- public List<LotGroup> canCreateLive(Long merchantId) {
- return lotGroupMapper.canCreateLive(merchantId);
- }
- @Override
- public List<LotGroup> findPubbedLotGroupByIds(Long[] lotGroupIds,Long merchantId) {
- return lotGroupMapper.findPubbedLotGroupByLotIds(lotGroupIds,merchantId);
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public Long party(LotGroup lotGroup) {
- AtomicLong result = new AtomicLong(0);
- locker.tryLock(String.format(Constants.REDIS_GROUP_LOCK_LOT_TEMPLATE, lotGroup.getId()), () -> {
- LotGroup dbLotGroup = lotGroupMapper.selectLotGroupById(lotGroup.getId());
- Lot currLot = lotMapper.selectLotById(dbLotGroup.getNextLotId());
- Lot nextLot = new Lot();
- BeanUtils.copyProperties(dbLotGroup, nextLot, "id");
- nextLot.setStatus(Constants.LOT_STATUS_WAITING);
- nextLot.setStartTime(null);
- nextLot.setCreateTime(new Date());
- nextLot.setUpdateTime(null);
- nextLot.setPubTime(new Date());
- nextLot.setPubStatus(Constants.PUB_STATUS_PUBLISHED);
- nextLot.setGroupId(lotGroup.getId());
- nextLot.setAuctionId(2L);
- String name = currLot.getName();
- int i = name.lastIndexOf("#");
- if (i > 0 && i != name.length() -1) {
- String numStr = name.substring(i + 1);
- String nextNum = "";
- try {
- long l = Long.parseLong(numStr);
- nextNum = "#" + (l + 1);
- }catch (Exception ignored) {}
- nextLot.setName(nextLot.getName() + nextNum);
- }
- lotMapper.updateLot(
- Lot.builder()
- .id(currLot.getId())
- .startTime(new Date())
- .build());
- currLot.setStartTime(new Date());
- long l = Objects.isNull(dbLotGroup.getFinishNum()) ? 0 : dbLotGroup.getFinishNum();
- if (l >= dbLotGroup.getNum()) {
- throw new RuntimeException("商品库存已经用完");
- }else if (l<dbLotGroup.getNum()-1){
- lotMapper.insertLot(nextLot);
- }
- lotGroupMapper.updateLotGroup(LotGroup.builder()
- .id(lotGroup.getId())
- .lotId(currLot.getId())
- .nextLotId(nextLot.getId())
- .finishNum(Objects.isNull(dbLotGroup.getFinishNum()) ? 0 : dbLotGroup.getFinishNum() + 1)
- .status(Constants.LOT_STATUS_STARTING)
- .build()
- );
- pubLot(currLot);
- result.set(currLot.getId());
- eventPublisher.publishStartBiddingEvent(new StartBiddingEvent(dbLotGroup.getId()));
- }, true, "开启失败,请重试!");
- return result.get();
- }
- @Override
- public List<LotGroup> findStartingGroupByLotIds(Long[] lotIds) {
- return lotGroupMapper.findStartingGroupByIds(lotIds);
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public void updateExpire(LotFans fans) {
- lotFansMapper.updateLotFans(
- LotFans.builder()
- .id(fans.getId())
- .type("pay_expire")
- .expire(DateUtils.addDays(DateUtils.toDate(fans.getCreateTime()), 1))
- .build());
- lotMapper.updateLot(Lot.builder().id(fans.getLotId()).status(Constants.LOT_STATUS_PASS).build());
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public void updateSoldAndPaid(LotFans fans, Long groupId) {
- lotFansMapper.deleteLotFansById(fans.getId());
- lotMapper.updatePay(fans.getLotId(), 1);
- lotGroupMapper.addSold(groupId);
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public void handleEndLotGroup(LotGroup lotGroup, String status) {
- LotGroup dbLotGroup = lotGroupMapper.selectLotGroupById(lotGroup.getId());
- lotGroupMapper.updateLotGroupSold(dbLotGroup.getId());
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public int insertLot(Lot lot) {
- lot.setCreateTime(DateUtils.getNowDate());
- int result = lotMapper.insertLot(lot);
- dynamicTask(lot);
- return result;
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public int insertLotGroup(LotGroup lotGroup) {
- final int i = lotGroupMapper.insertLotGroup(lotGroup);
- Lot lot = new Lot();
- BeanUtils.copyProperties(lotGroup, lot, "id");
- lot.setStatus(Constants.LOT_STATUS_WAITING);
- lot.setStartTime(null);
- lot.setCreateTime(new Date());
- lot.setUpdateTime(null);
- lot.setPubTime(new Date());
- lot.setPubStatus(Constants.PUB_STATUS_PUBLISHED);
- lot.setGroupId(lotGroup.getId());
- lot.setNum(1L);
- lot.setName(lot.getName() + "#1");
- lotMapper.insertLot(lot);
- lotGroupMapper.updateLotGroup(LotGroup.builder().id(lotGroup.getId()).nextLotId(lot.getId()).build());
- return i;
- }
- @Override
- public int updateLot(Lot lot) {
- lot.setUpdateTime(DateUtils.getNowDate());
- return lotMapper.updateLot(lot);
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public int updateLotGroup(LotGroup lotGroup) {
- LotGroup dbLotGroup = lotGroupMapper.selectLotGroupById(lotGroup.getId());
- if (Objects.nonNull(lotGroup.getNum()) && dbLotGroup.getNum() > lotGroup.getNum()) {
- int count = lotMapper.selectLotByGroupId(lotGroup.getId()).size() - 1;
- if (count > lotGroup.getNum()) {
- throw new RuntimeException("数量不合法");
- }
- }
- lotGroup.setUpdateTime(DateUtils.getNowDate());
- int result = lotGroupMapper.updateLotGroup(lotGroup);
- dbLotGroup = lotGroupMapper.selectLotGroupById(lotGroup.getId());
- Lot lot = lotMapper.selectLotById(dbLotGroup.getNextLotId());
- if (Constants.LOT_STATUS_WAITING.equals(lot.getStatus())) {
- String name = lot.getName();
- String nextNum = "";
- int i = name.lastIndexOf("#");
- if (i > 0 && i != name.length() -1) {
- String numStr = name.substring(i + 1);
- try {
- long l = Long.parseLong(numStr);
- nextNum = "#" + l;
- }catch (Exception ignored) {}
- }
- BeanUtils.copyProperties(dbLotGroup, lot, "id","createTime", "name");
- lot.setStatus(Constants.LOT_STATUS_WAITING);
- lot.setStartTime(null);
- lot.setPubTime(new Date());
- lot.setPubStatus(Constants.PUB_STATUS_PUBLISHED);
- lot.setGroupId(lotGroup.getId());
- lot.setName(dbLotGroup.getName() + nextNum);
- updateLot(lot);
- }
- return result;
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public int updateLotGroup0(LotGroup lotGroup) {
- return lotGroupMapper.updateLotGroup(lotGroup);
- }
- @Override
- public int updateLotView(Lot lot) {
- lot.setUpdateTime(DateUtils.getNowDate());
- int result = lotMapper.updateLotView(lot);
- dynamicTask(lot);
- return result;
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public int updateLotEx(Lot lot) {
- lot.setUpdateTime(DateUtils.getNowDate());
- int result = lotMapper.updateLotEx(lot);
- dynamicTask(lot);
- return result;
- }
- @Override
- public List<Lot> selectBidding() {
- return lotMapper.selectBidding();
- }
- @Override
- public List<Lot> selectCancel() {
- return lotMapper.selectCancel();
- }
- @Override
- public int deleteLotByIds(String ids) {
- return lotMapper.deleteLotByIds(Convert.toLongArray(ids));
- }
- @Override
- public int deleteLotById(Long id) {
- return lotMapper.deleteLotById(id);
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public void pubLot(Lot lot) {
- locker.tryLock(String.format(Constants.REDIS_LOCK_LOT_TEMPLATE, lot.getId()), () ->{
- lot.setPubTime(new Date());
- lot.setPubStatus(Constants.PUB_STATUS_PUBLISHED);
- lot.setUpdateTime(new Date());
- lotMapper.updateLot(lot);
- //构建竞价拍卖上下文
- LiveContext liveContext = ruleHandlerHolder.pubLive(lot);
- if (liveContext.isLotUpdate()) {
- lotMapper.updateLot(lot);
- }
- redisCache.setCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, lot.getAuctionId()), lot.getId().toString(), liveContext.getLive());
- }, true);
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public void pubLots(Auction auction) {
- List<Lot> lots = lotMapper.selectLotByAucId(auction.getId());
- for (Lot lot : lots) {
- lot.setUpdateBy(auction.getUpdateBy());
- pubLot(lot);
- }
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public void insertLotAndPub(Lot lot) {
- insertLot(lot);
- pubLot(lot);
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public void updateLotAndPub(Lot lot) {
- updateLot(lot);
- pubLot(lot);
- }
- @Override
- public void removeLot(Lot lot) {
- Lot condition = new Lot();
- condition.setId(lot.getId());
- condition.setDelFlag(Constants.DEL_FLAG_DELETED);
- lotMapper.updateLot(condition);
- }
- @Override
- public void cancelLot(Lot lot) {
- lot.setUpdateTime(new Date());
- lot.setStatus(Constants.LOT_STATUS_CANCELLED);
- lot.setPubStatus(Constants.PUB_STATUS_NO_PUBLISHED);
- lotMapper.updateLot(lot);
- ruleHandlerHolder.cancelLot(lot);
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public void live(Live live) {
- live = redisCache.getCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, live.getLot().getAuctionId()), live.getLot().getId().toString());
- // 1秒的轮询 会存在失效数据 判断是否是失效数据
- if (Objects.isNull(live)) {
- //是失效数据
- return;
- }
- cacheMap.putLive(live);
- List<Bid> bidList = redisCache.getCacheList(String.format(Constants.REDIS_MAP_AUC_LOT_BID_TEMPLATE, live.getLot().getId()));
- // 创建当前 context
- LiveContext liveContext = LiveContext.builder()
- .live(live)
- .dbLot(Lot.builder()
- .id(live.getLot().getId())
- .auctionId(live.getLot().getAuctionId())
- .build())
- .bidList(bidList)
- .dbBid(getLastBid(bidList))
- .build();
- // 分析并设置当前状态
- ruleHandlerHolder.live(liveContext);
- // 更新当前状态 到数据库和缓存
- updateToRedisAndDb(liveContext);
- // 发送极光推送
- jPush(liveContext);
- }
- private void jPush(LiveContext liveContext) {
- Live live = liveContext.getLive();
- if (live.getCurrentEndTime() < (System.currentTimeMillis() + 1000 * 60 * 5)) {
- Long expire = redisCache.redisTemplate.getExpire(String.format(Constants.REDIS_LOCK_PUSH_LOT_TEMPLATE, live.getLot().getId()));
- if (Objects.isNull(expire) || expire < 0L) {
- eventPublisher.publishJPush(JPushEvent.builder().live(live).build());
- redisCache.setCacheObject(String.format(Constants.REDIS_LOCK_PUSH_LOT_TEMPLATE, live.getLot().getId()), "jPush", 10, TimeUnit.MINUTES);
- }
- }
- }
- private Bid getLastBid(List<Bid> bidList) {
- if (!CollectionUtils.isEmpty(bidList)) {
- return bidList.get(0);
- }
- return null;
- }
- private void updateToRedisAndDb(LiveContext liveContext) {
- Live live = liveContext.getLive();
- List<Bid> dataList = liveContext.getBidList();
- ChangeEvent changeEvent = new ChangeEvent(live);
- if (liveContext.isLotUpdate()) {
- liveContext.getDbLot().setUpdateTime(new Date());
- lotMapper.updateLot(liveContext.getDbLot());
- }
- if (liveContext.isBidUpdate()) {
- bidMapper.updateBid(liveContext.getDbBid());
- redisCache.setList(String.format(Constants.REDIS_MAP_AUC_LOT_BID_TEMPLATE, live.getLot().getId()), dataList);
- changeEvent.setBid(liveContext.getDbBid());
- }
- if (liveContext.isLiveUpdate()) {
- if (Constants.LOT_STATUS_SOLD.equals(live.getLot().getStatus()) ||
- Constants.LOT_STATUS_PASS.equals(live.getLot().getStatus())) {
- redisCache.delCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, live.getLot().getAuctionId()), live.getLot().getId().toString());
- redisCache.deleteObject(String.format(Constants.REDIS_MAP_AUC_LOT_BID_TEMPLATE, live.getLot().getId()));
- if (Constants.LOT_STATUS_SOLD.equals(live.getLot().getStatus())) {
- if(live.getBidId()==null){
- long bidid = bidMapper.getCurrentBid(live.getLot().getId());
- live.setBidId(bidid);
- }
- eventPublisher.publishSoldEvent(live, dataList);
- }
- eventPublisher.publishEndEvent(live);
- }else {
- redisCache.setCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, live.getLot().getAuctionId()), live.getLot().getId().toString(), live);
- }
- eventPublisher.publishChangeEvent(changeEvent);
- }
- }
- @Override
- public List<Lot> live(Long auctionId) {
- LambdaQueryWrapper<Lot> queryWrapper=new LambdaQueryWrapper<>();
- queryWrapper.eq(Lot::getAuctionId,auctionId).eq(Lot::getDelFlag,Constants.DEL_FLAG_NO_DELETE);
- return lotMapper.selectList(queryWrapper);
- }
- @Override
- public List<LiveVO> selfLive(SelfVO selfVO) {
- Map<String, Live> cacheLive = CloneUtils.clone(cacheMap.viewAuction(selfVO.getAuctionId()));
- return cacheLive.values().stream()
- .filter(live -> live.getAccountList().contains(UserUtils.getSimpleUserInfo().getId().toString()) &&
- Constants.LOT_STATUS_BIDDING.equals(live.getLot().getStatus()))
- .map(live -> {
- List<Bid> bidList = bidMapper.selectBidByLotId(live.getLot().getId());
- LiveVO liveVO = new LiveVO(live);
- if (!CollectionUtils.isEmpty(bidList)) {
- liveVO.setLastPriceTime(bidList.get(0).getCreateTime().getTime());
- }
- liveVO.setCurrUserBids(
- Objects.requireNonNull(bidList).stream()
- .filter(bid -> bid.getAccountId().equals(UserUtils.getSimpleUserInfo().getId().toString()))
- .collect(Collectors.toList())
- );
- return SensitiveDataUtils.handleViewDataSafe(liveVO);
- }).sorted(this::sort)
- .collect(Collectors.toList());
- }
- private int sort(LiveVO live1, LiveVO live2) {
- return (int)(live2.getLastPriceTime() - live1.getLastPriceTime());
- }
- @Override
- public List<LotVO> selfFinish(SelfVO selfVO) {
- return finishOrWin(selfVO, null);
- }
- @Override
- public List<LotVO> selfWin(SelfVO selfVO) {
- 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.getDepositType())
- && Objects.equals(order.getLotId(), lot.getId()));
- }
- return depositOrders.stream().anyMatch(order -> Objects.equals("拍卖会", order.getDepositType())
- && 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<>();
- List<Lot> lotList = lotMapper.selectLotByAucId(selfVO.getAuctionId());
- lotList.forEach(lot -> {
- if (Constants.LOT_STATUS_PASS.equals(lot.getStatus()) || Constants.LOT_STATUS_SOLD.equals(lot.getStatus())) {
- Bid condition = new Bid();
- condition.setLotId(lot.getId());
- condition.setAccountId(account);
- condition.setStatus(win);
- List<Bid> bids = bidMapper.selectBidList(condition);
- if (!CollectionUtils.isEmpty(bids)) {
- LotVO lotVO = new LotVO();
- BeanUtils.copyProperties(lot, lotVO);
- lotVO.setBids(bids);
- resultList.add(SensitiveDataUtils.handleViewDataSafe(lotVO));
- }
- }
- });
- return resultList;
- }
- @Override
- @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
- public void handleDelay(Long id) {
- Lot dbLot = lotMapper.selectLotById(id);
- Lot update = new Lot();
- BeanUtils.copyProperties(dbLot, update);
- update.setCreateBy("SYSTEM");
- update.setCreateTime(new Date());
- update.setPubStatus(Constants.PUB_STATUS_NO_PUBLISHED);
- update.setStatus(Constants.LOT_STATUS_WAITING);
- update.setDelFlag(Constants.DEL_FLAG_NO_DELETE);
- update.setStartTime(DateUtils.addDays(dbLot.getStartTime(), 1));
- update.setEndTime(DateUtils.addDays(dbLot.getEndTime(), 1));
- String name = update.getName();
- if (!StringUtils.isEmpty(name)) {
- Pattern pattern = Pattern.compile("第(\\d+)期");
- Matcher matcher = pattern.matcher(name);
- if (matcher.find()) {
- String group = matcher.group(0);
- String noStr = matcher.group(1);
- int no = (Integer.parseInt(noStr)) + 1;
- name = name.replace(group, "第" + no + "期");
- update.setName(name);
- }
- }
- lotMapper.insertLotClone(update);
- dbLot.setDelayPublish(null);
- lotMapper.updateLotView(dbLot);
- if (!Objects.equals(dbLot.getPubStatus(), Constants.PUB_STATUS_PUBLISHED)) {
- pubLot(dbLot);
- }
- dynamicTask(update);
- }
- @Override
- public void dynamicTasks() {
- lotMapper.dynamicLot().forEach(this::dynamicTask);
- }
- @Override
- public void dynamicTask(Lot lot) {
- //延时发布时间
- String delayPublish = lot.getDelayPublish();
- if (!StringUtils.isEmpty(delayPublish)) {
- dynamicTaskService.updateTask(lot.getId().toString(), DateUtils.getNextExecutionTime(delayPublish), () -> {
- _thiz.handleDelay(lot.getId());
- });
- }else {
- dynamicTaskService.removeTask(lot.getId().toString());
- }
- }
- @Override
- public List<Lot> selectLotListByAucId(Long aucId) {
- return getBaseMapper().selectLotByAucId(aucId);
- }
- @Override
- public void calculatorAndUpdateLotHot() {
- //查询正在竞价中的拍品
- List<Lot> lots = lotMapper.selectBidding();
- lots.forEach(lot -> {
- //计算出价权重
- double bidWeight = lot.getBidCount() * 0.5;
- //计算收藏权重
- LambdaQueryWrapper<LotFans> lotFansLambdaQueryWrapper = new LambdaQueryWrapper<>();
- Long lotFansCount = lotFansMapper.selectCount(lotFansLambdaQueryWrapper.eq(LotFans::getLotId, lot.getId()));
- double lotFansWeight = lotFansCount * 0.2;
- //计算时间权重,竞拍结束时间-当前时间=剩余时间
- Date endTime = lot.getEndTime();
- int timeWeight;
- Date date = new Date();
- Date date1 = DateUtils.addHours(date, 2);
- if (date1.after(endTime)){
- }
- //计算涨价幅度权重
- Long currentBid = bidMapper.getCurrentBid(lot.getId());
- });
- }
- @Override
- public List<Lot> selectBiddingLotList() {
- return getBaseMapper().selectBiddingLotList();
- }
- @Override
- public List<LotFansResponse> queryLotByCategory(LotQueryRequest request) {
- // 1. 构建最终要查询的分类ID
- List<Long> categoryIds = Lists.newArrayList();
- if (Objects.nonNull(request.getChildCategoryId())) {
- // 传了二级分类 → 直接用
- categoryIds.add(request.getChildCategoryId());
- } else if (Objects.nonNull(request.getMainCategoryId())) {
- // 只传一级 → 查询该一级下所有二级ID
- categoryIds = spuCategoryMapper.listChildByParentId(request.getMainCategoryId());
- }
- // 2. 没有分类 → 返回空
- if (CollectionUtils.isEmpty(categoryIds)) {
- return Lists.newArrayList();
- }
- // 3. 查询拍品ID
- List<Long> lotIds = spuCategoryMapper.listLotIdsByCategoryIds(categoryIds);
- if (CollectionUtils.isEmpty(lotIds)) {
- return Lists.newArrayList();
- }
- IPage<Lot> lotIPage =new Page<>(request.getPageNum(),request.getPageSize());
- Lot lot = new Lot();
- lot.setIds(lotIds);
- lot.setName(request.getName());
- lot.setPubStatus(request.getPubStatus());
- lot.setStatus(request.getStatus());
- lot.setStartTime(request.getStartTime());
- lot.setEndTime(request.getEndTime());
- lot.setRealEndTime(request.getRealEndTime());
- List<Lot> diamondPositions = baseMapper.selectLotList(lotIPage, lot);
- List<LotFansResponse> lotFansResponses = diamondPositions.stream().map(LotConvert.INSTANCE::toLotFansResponse).collect(Collectors.toList());
- 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.setAuctionDesc(auction.getDescription());
- response.setRuleContent(lot.getRuleContent());
- response.setAuctionImgs(auction.getImgs());
- response.setImgs(lot.getImgs());
- response.setCarouselImgs(lot.getCarouselImgs());
- response.setStatus(lot.getStatus());
- Date startTime = toBeijingTime(lot.getStartTime());
- Date endTime = toBeijingTime(lot.getEndTime());
- Date realEndTime = toBeijingTime(lot.getRealEndTime());
- response.setStartTime(startTime);
- response.setEndTime(endTime);
- response.setRealEndTime(realEndTime);
- 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()) && Objects.nonNull(startTime)) {
- response.setTimestamp(startTime.getTime() - System.currentTimeMillis());
- } else if (Objects.equals("Bidding", lot.getStatus()) && Objects.nonNull(endTime)) {
- response.setTimestamp(endTime.getTime() - System.currentTimeMillis());
- }
- //TODO 成交用户暂时无
- fillUserFlags(lot, response, depositType);
- return response;
- }
- private Date toBeijingTime(Date date) {
- return Objects.isNull(date) ? null : DateUtils.addHours(date, 8);
- }
- 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())
- .eq(DepositOrder::getDepositType, "拍品");
- } else {
- depositQuery.eq(DepositOrder::getAuctionId, lot.getAuctionId())
- .eq(DepositOrder::getDepositType, "拍卖会");
- }
- Long depositCount = depositOrderMapper.selectCount(depositQuery);
- response.setHasDeposit(depositCount > 0);
- }
- @Override
- public List<LotExportDTO> exportLotList(LotRequest request) {
- if (Objects.isNull(request.getPageNum()) && Objects.isNull(request.getPageSize())) {
- request.setPageNum(1);
- request.setPageSize(1000);
- }
- request.setDelFlag(Constants.DEL_FLAG_NO_DELETE);
- IPage<Lot> lotIPage=new Page<>(request.getPageNum(),request.getPageSize());
- List<Lot> lotList = lotMapper.selectLotList(lotIPage, request);
- List<LotExportDTO> lotExportDTOS = lotList.stream().map(l -> {
- LotExportDTO lotExportDTO = new LotExportDTO();
- lotExportDTO.setId(String.valueOf(l.getId()));
- lotExportDTO.setGoodsId(l.getGoodsId());
- lotExportDTO.setGoodsName(l.getGoodsName());
- lotExportDTO.setGoodsType(l.getGoodsType());
- lotExportDTO.setSort(String.valueOf(l.getSort()));
- lotExportDTO.setBidCount(String.valueOf(l.getBidCount()));
- lotExportDTO.setPubStatus(PubStatusEnum.of(l.getPubStatus()).getDesc());
- lotExportDTO.setStatus(LotStatusEnum.of(l.getStatus()).getDesc());
- lotExportDTO.setCreateTime(DateUtils.parseDateToStr(l.getCreateTime()));
- lotExportDTO.setStartTime(DateUtils.parseDateToStr(l.getStartTime()));
- lotExportDTO.setEndTime(DateUtils.parseDateToStr(l.getEndTime()));
- lotExportDTO.setDeposit(String.valueOf(l.getDeposit() == null ? 0 : l.getDeposit()));
- lotExportDTO.setServiceTariff(String.valueOf(l.getServiceTariff()));
- lotExportDTO.setRuleType(RuleTypeEnum.getByCode(l.getRuleType()).getDesc());
- // 起拍价
- if (StringUtils.isNotEmpty(l.getRuleContent())) {
- TraditionRule traditionRule = JSON.parseObject(l.getRuleContent(), TraditionRule.class);
- lotExportDTO.setLastPrice(String.valueOf(traditionRule.getStartPrice()));
- }
- return lotExportDTO;
- }).collect(Collectors.toList());
- return lotExportDTOS;
- }
- @Override
- public List<Lot> selectLotListByLotIds(List<Long> lotIds) {
- return baseMapper.selectLotListByLotIds(lotIds);
- }
- }
|