| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060 |
- 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.PageUtils;
- 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());
- // 保存拍品分类关联
- saveLotCategoryRelation(lot);
- }, true);
- }
- private void saveLotCategoryRelation(Lot lot) {
- List<String> names = new ArrayList<>();
- if (StringUtils.isNotEmpty(lot.getCategory())) {
- names.add(lot.getCategory());
- }
- if (StringUtils.isNotEmpty(lot.getSubCategory())) {
- names.add(lot.getSubCategory());
- }
- if (!names.isEmpty()) {
- List<Long> categoryIds = spuCategoryMapper.selectCategoryIdsByNames(names);
- if (!CollectionUtils.isEmpty(categoryIds)) {
- spuCategoryMapper.deleteLotCategoryRelation(lot.getId());
- spuCategoryMapper.insertLotCategoryRelation(lot.getId(), categoryIds);
- }
- }
- }
- @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) {
- lots.sort(Comparator.comparing(Lot::getCreateTime, Comparator.nullsLast(Comparator.reverseOrder())));
- }
- 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());
- }
- IPage<Lot> lotIPage =new Page<>(request.getPageNum(),request.getPageSize());
- Lot lot = new Lot();
- if (!CollectionUtils.isEmpty(categoryIds)) {
- // 3. 查询拍品ID
- List<Long> lotIds = spuCategoryMapper.listLotIdsByCategoryIds(categoryIds);
- if (CollectionUtils.isEmpty(lotIds)) {
- return emptyLotFansResponsePage(request);
- }
- 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());
- PageUtils.startPage(request);
- List<Lot> diamondPositions = baseMapper.selectLotList(lotIPage, lot);
- return toLotFansResponsePage(diamondPositions);
- }
- private List<LotFansResponse> toLotFansResponsePage(List<Lot> lots) {
- List<LotFansResponse> responses = lots.stream()
- .map(LotConvert.INSTANCE::toLotFansResponse)
- .collect(Collectors.toList());
- if (lots instanceof com.github.pagehelper.Page) {
- com.github.pagehelper.Page<Lot> lotPage = (com.github.pagehelper.Page<Lot>) lots;
- com.github.pagehelper.Page<LotFansResponse> responsePage =
- new com.github.pagehelper.Page<>(lotPage.getPageNum(), lotPage.getPageSize());
- responsePage.setTotal(lotPage.getTotal());
- responsePage.addAll(responses);
- return responsePage;
- }
- return responses;
- }
- private List<LotFansResponse> emptyLotFansResponsePage(LotQueryRequest request) {
- int pageNum = Objects.isNull(request.getPageNum()) ? 1 : request.getPageNum();
- int pageSize = Objects.isNull(request.getPageSize()) ? 100 : request.getPageSize();
- com.github.pagehelper.Page<LotFansResponse> page = new com.github.pagehelper.Page<>(pageNum, pageSize);
- page.setTotal(0);
- return page;
- }
- @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("未找到拍卖会相关数据");
- }
- Date currentEndTime = lot.getEndTime();
- if (Objects.equals(Constants.LOT_STATUS_BIDDING, lot.getStatus())) {
- Live live = redisCache.getCacheMapValue(
- String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, lot.getAuctionId()),
- lot.getId().toString());
- if (Objects.nonNull(live) && Objects.nonNull(live.getCurrentEndTime())) {
- currentEndTime = new Date(live.getCurrentEndTime());
- }
- }
- 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();
- BigDecimal serviceTariff = lot.getServiceTariff();;
- String depositType = "LOT";
- if (Objects.isNull(depositAmount)) {
- depositAmount = auction.getDeposit();
- depositType = "AUCTION";
- serviceTariff = auction.getServiceTariff();
- }
- 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());
- response.setStartTime(lot.getStartTime());
- response.setEndTime(lot.getEndTime());
- response.setCurrentEndTime(currentEndTime);
- 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(serviceTariff);
- 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(lot.getStartTime())) {
- response.setTimestamp(lot.getStartTime().getTime() - System.currentTimeMillis());
- } else if (Objects.equals("Bidding", lot.getStatus()) && Objects.nonNull(currentEndTime)) {
- response.setTimestamp(currentEndTime.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::getDelFlag, 0)
- .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);
- }
- }
|