| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040 |
- 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());
- }
- Lot lot = live.getLot();
- lot.setProperties(null);
- 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) {
- UserInfo userInfo = UserUtils.getSimpleUserInfo();
- if (userInfo == null) {
- throw new ServiceException("璇峰厛鐧诲綍");
- }
- List<DepositOrder> depositOrders = selectPaidDepositOrders(userInfo.getId());
- List<Bid> userBidList = bidMapper.selectBidList(Bid.builder()
- .accountId(userInfo.getId().toString())
- .build());
- List<Lot> candidateLots = selectSelfCandidateLots(depositOrders, userBidList.stream()
- .map(Bid::getLotId)
- .filter(Objects::nonNull)
- .collect(Collectors.toSet()));
- Map<String, Live> cacheLive = new HashMap<>();
- candidateLots.stream()
- .map(Lot::getAuctionId)
- .filter(Objects::nonNull)
- .distinct()
- .forEach(auctionId -> {
- Map<String, Live> auctionLive = CloneUtils.clone(cacheMap.viewAuction(auctionId));
- if (!CollectionUtils.isEmpty(auctionLive)) {
- cacheLive.putAll(auctionLive);
- }
- });
- 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(null);
- }
- @Override
- public List<LotVO> selfWin(SelfVO selfVO) {
- return finishOrWin(1);
- }
- @Override
- public List<LotVO> selfList(SelfVO selfVO) {
- UserInfo userInfo = UserUtils.getSimpleUserInfo();
- if (userInfo == null) {
- throw new ServiceException("请先登录");
- }
- String userId = userInfo.getId().toString();
- List<DepositOrder> depositOrders = selectPaidDepositOrders(userInfo.getId());
- List<Bid> userBidList = bidMapper.selectBidList(Bid.builder()
- .accountId(userId)
- .build());
- Map<Long, List<Bid>> userBidMap = userBidList.stream()
- .filter(bid -> Objects.nonNull(bid.getLotId()))
- .collect(Collectors.groupingBy(Bid::getLotId));
- List<Lot> lotList = selectSelfCandidateLots(depositOrders, userBidMap.keySet());
- String type = StringUtils.isEmpty(selfVO.getType()) ? "all" : selfVO.getType();
- List<LotVO> result = new ArrayList<>();
- for (Lot lot : lotList) {
- List<Bid> userBids = userBidMap.getOrDefault(lot.getId(), Collections.emptyList());
- boolean hasUserBid = !CollectionUtils.isEmpty(userBids);
- boolean hasWinBid = hasUserBid && userBids.stream().anyMatch(bid -> Objects.equals(bid.getStatus(), 1));
- boolean hasDeposit = hasDepositQualification(lot, depositOrders);
- String selfStatus = resolveSelfStatus(lot, hasDeposit, hasUserBid, hasWinBid);
- if (matchSelfScene(type, selfStatus)) {
- result.add(buildSelfLotVo(lot, userBids, selfStatus));
- }
- }
- sortSelfLots(type, result);
- return result;
- }
- private List<DepositOrder> selectPaidDepositOrders(Integer userId) {
- return depositOrderMapper.selectList(new LambdaQueryWrapper<DepositOrder>()
- .eq(DepositOrder::getUserId, userId)
- .eq(DepositOrder::getStatus, 1));
- }
- private List<Lot> selectSelfCandidateLots(List<DepositOrder> depositOrders, Collection<Long> bidLotIds) {
- Map<Long, Lot> lotMap = new LinkedHashMap<>();
- if (!CollectionUtils.isEmpty(depositOrders)) {
- depositOrders.stream()
- .map(DepositOrder::getAuctionId)
- .filter(Objects::nonNull)
- .distinct()
- .forEach(auctionId -> addLots(lotMap, lotMapper.selectLotByAucId(auctionId)));
- }
- Set<Long> lotIds = new LinkedHashSet<>();
- if (!CollectionUtils.isEmpty(bidLotIds)) {
- lotIds.addAll(bidLotIds);
- }
- if (!CollectionUtils.isEmpty(depositOrders)) {
- depositOrders.stream()
- .map(DepositOrder::getLotId)
- .filter(Objects::nonNull)
- .forEach(lotIds::add);
- }
- if (!CollectionUtils.isEmpty(lotIds)) {
- addLots(lotMap, lotMapper.selectLotListByLotIds(new ArrayList<>(lotIds)));
- }
- return new ArrayList<>(lotMap.values());
- }
- private void addLots(Map<Long, Lot> lotMap, List<Lot> lots) {
- if (CollectionUtils.isEmpty(lots)) {
- return;
- }
- lots.stream()
- .filter(lot -> Objects.nonNull(lot.getId()))
- .forEach(lot -> lotMap.put(lot.getId(), lot));
- }
- 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 String resolveSelfStatus(Lot lot, boolean hasDeposit, boolean hasUserBid, boolean hasWinBid) {
- if (isWaitingLot(lot, hasDeposit)) {
- return "waiting";
- }
- if (isLiveLot(lot, hasDeposit, hasUserBid)) {
- return "live";
- }
- if (isWinLot(lot, hasWinBid)) {
- return "win";
- }
- if (isLoseLot(lot, hasUserBid, hasWinBid)) {
- return "lose";
- }
- return null;
- }
- private boolean matchSelfScene(String type, String selfStatus) {
- if (StringUtils.isEmpty(selfStatus)) {
- return false;
- }
- if ("all".equals(type)) {
- return true;
- }
- if ("lose".equals(type) || "pass".equals(type) || "finish".equals(type)) {
- return "lose".equals(selfStatus);
- }
- if ("win".equals(type)) {
- return "win".equals(selfStatus);
- }
- return type.equals(selfStatus);
- }
- 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 isWinLot(Lot lot, boolean hasWinBid) {
- return Constants.LOT_STATUS_SOLD.equals(lot.getStatus()) && hasWinBid;
- }
- 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, String selfStatus) {
- LotVO lotVO = new LotVO();
- BeanUtils.copyProperties(lot, lotVO);
- lotVO.setBids(userBids);
- TraditionRule rule = StringUtils.isEmpty(lot.getRuleContent())
- ? null
- : JSON.parseObject(lot.getRuleContent(), TraditionRule.class);
- lotVO.setStartPrice(Objects.isNull(rule) ? null : rule.getStartPrice());
- lotVO.setCurrentPrice(Objects.nonNull(lot.getLastPrice()) ? lot.getLastPrice() : null);
- lotVO.setSelfStatus(selfStatus);
- 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) || "win".equals(type)) {
- lots.sort(Comparator.comparing(Lot::getRealEndTime, Comparator.nullsLast(Date::compareTo)).reversed());
- return;
- }
- List<LotVO> waiting = lots.stream().filter(lot -> "waiting".equals(lot.getSelfStatus()))
- .sorted(Comparator.comparing(Lot::getStartTime, Comparator.nullsLast(Date::compareTo)))
- .collect(Collectors.toList());
- List<LotVO> live = lots.stream()
- .filter(lot -> "live".equals(lot.getSelfStatus()))
- .sorted(Comparator.comparing(Lot::getLastPriceTime, Comparator.nullsLast(Date::compareTo)).reversed())
- .collect(Collectors.toList());
- List<LotVO> lose = lots.stream()
- .filter(lot -> "lose".equals(lot.getSelfStatus()) || "win".equals(lot.getSelfStatus()))
- .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(Integer win) {
- String account = UserUtils.getSimpleUserInfo().getId().toString();
- List<LotVO> resultList = new ArrayList<>();
- List<Lot> lotList = lotMapper.selectLotFinishOrWin(win, account);
- 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);
- }
- }
|