diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertRoundController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertRoundController.java index 0961f610e..f4cace9c9 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertRoundController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertRoundController.java @@ -48,13 +48,6 @@ public class AdvertRoundController extends XktBaseController { return R.ok(advertRoundService.create(BeanUtil.toBean(createVO, AdRoundStoreCreateDTO.class))); } - @PreAuthorize("@ss.hasAnyRoles('admin,general_admin,store')||@ss.hasSupplierSubRole()") - @ApiOperation(value = "获取推广位数据及右侧 已订购推广位 列表", httpMethod = "GET", response = R.class) - @GetMapping(value = "/{advertId}/{storeId}/{showType}") - public R getStoreAdInfo(@PathVariable("advertId") Long advertId, @PathVariable("storeId") Long storeId, @PathVariable("showType") Integer showType) { - return R.ok(BeanUtil.toBean(advertRoundService.getStoreAdInfo(storeId, advertId, showType), AdRoundStoreResVO.class)); - } - @PreAuthorize("@ss.hasAnyRoles('admin,general_admin,store')||@ss.hasSupplierSubRole()") @ApiOperation(value = "获取当前推广所有轮次", httpMethod = "GET", response = R.class) @GetMapping(value = "/rounds/{storeId}/{typeId}") diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertRoundService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertRoundService.java index def315de8..c88d1d6f8 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertRoundService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertRoundService.java @@ -14,16 +14,6 @@ import java.util.List; */ public interface IAdvertRoundService { - /** - * 根据广告ID获取推广轮次列表,并返回当前档口在这些推广轮次的数据 - * - * @param storeId 档口ID - * @param advertId 广告ID - * @param showType 时间范围 位置枚举 - * @return AdRoundPlayStoreResDTO - */ - AdRoundStoreResDTO getStoreAdInfo(Long storeId, Long advertId, Integer showType); - /** * 档口购买推广营销 * diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertRoundServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertRoundServiceImpl.java index 59f964032..30a5c9618 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertRoundServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertRoundServiceImpl.java @@ -511,149 +511,6 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { } - /** - * 根据广告ID获取推广轮次列表,并返回当前档口在这些推广轮次的数据 - * - * @param storeId 档口ID - * @param advertId 广告ID - * @param showType 显示类型 时间范围 位置枚举 - * @return AdRoundPlayStoreResDTO - */ - @Override - @Transactional(readOnly = true) - public AdRoundStoreResDTO getStoreAdInfo(final Long storeId, final Long advertId, final Integer showType) { - // 用户是否为档口管理者或子账户 - if (!SecurityUtils.isAdmin() && !SecurityUtils.isStoreManagerOrSub(storeId)) { - throw new ServiceException("当前用户非档口管理者或子账号,无权限操作!", HttpStatus.ERROR); - } - final LocalTime now = LocalTime.now(); - // 当前时间 是否在 晚上22:00:00 到 晚上23:59:59之间 决定 biddingStatus 和 biddingTempStatus 用那一个字段 - boolean tenClockAfter = now.isAfter(LocalTime.of(22, 0, 0)) && now.isBefore(LocalTime.of(23, 59, 59)); - // 当天 - final Date voucherDate = java.sql.Date.valueOf(LocalDate.now()); - // 获取当前所有 正在投放 和 待投放的推广轮次 - List allRoundList = this.advertRoundMapper.selectList(new LambdaQueryWrapper() - .eq(AdvertRound::getDelFlag, Constants.UNDELETED) - .in(AdvertRound::getLaunchStatus, Arrays.asList(AdLaunchStatus.LAUNCHING.getValue(), AdLaunchStatus.UN_LAUNCH.getValue()))); - if (CollectionUtils.isEmpty(allRoundList)) { - return AdRoundStoreResDTO.builder().build(); - } - // 当前 档口 在所有 待投放 及 投放中 的推广轮次竞价失败记录 - List allRecordList = this.advertRoundRecordMapper.selectList(new LambdaQueryWrapper() - .eq(AdvertRoundRecord::getDelFlag, Constants.UNDELETED).eq(AdvertRoundRecord::getStoreId, storeId) - .in(AdvertRoundRecord::getAdvertRoundId, allRoundList.stream().map(AdvertRound::getId).collect(Collectors.toList()))); - AdRoundStoreResDTO roundResDTO = AdRoundStoreResDTO.builder() - // 获取档口 已抢购推广位 - .boughtRoundList(this.getStoreBoughtRecordList(allRoundList, allRecordList, storeId, voucherDate, tenClockAfter)) - .build(); - // 筛选当前 推广位 正在投放 及 待投放的推广轮次 - List advertRoundList = allRoundList.stream().filter(x -> Objects.equals(x.getAdvertId(), advertId)).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(advertRoundList)) { - return roundResDTO; - } - // 第一轮结束投放时间 - final Date firstRoundEndTime = advertRoundList.stream().filter(x -> x.getRoundId().equals(AdRoundType.PLAY_ROUND.getValue())) - .max(Comparator.comparing(AdvertRound::getEndTime)) - .orElseThrow(() -> new ServiceException("获取推广结束时间失败,请联系客服!", HttpStatus.ERROR)).getEndTime(); - // 如果当前非第一轮最后一天,则展示前3轮;如果当前是第一轮最后一天,则展示第2到第4轮。 - advertRoundList = voucherDate.before(firstRoundEndTime) - ? advertRoundList.stream().filter(x -> !Objects.equals(x.getRoundId(), AdRoundType.FOURTH_ROUND.getValue())).collect(Collectors.toList()) - : advertRoundList.stream().filter(x -> !Objects.equals(x.getRoundId(), AdRoundType.PLAY_ROUND.getValue())).collect(Collectors.toList()); - // 如果投放类型是:时间范围,则只需要返回每一轮的开始时间和结束时间;如果投放类型是:位置枚举,则需要返回每一个位置的详细情况 - if (Objects.equals(showType, AdShowType.TIME_RANGE.getValue())) { - // 有档口购买的所有轮次 - Set roundIdSet = advertRoundList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPayPrice())).map(AdvertRound::getRoundId).collect(Collectors.toSet()); - // 当前档口购买的轮次 - Set boughtIdSet = advertRoundList.stream().filter(x -> Objects.equals(x.getStoreId(), storeId)).map(AdvertRound::getRoundId).collect(Collectors.toSet()); - // 当前档口未购买的轮次 - roundIdSet.removeAll(boughtIdSet); - // 构建当前round基础数据 - List rangeDTOList = advertRoundList.stream().map(x -> new AdRoundStoreResDTO.ADRSRoundTimeRangeDTO() - .setAdvertId(x.getAdvertId()).setRoundId(x.getRoundId()).setSymbol(x.getSymbol()).setStartTime(x.getStartTime()).setEndTime(x.getEndTime()) - .setStartWeekDay(getDayOfWeek(x.getStartTime())).setEndWeekDay(getDayOfWeek(x.getEndTime())).setStartPrice(x.getStartPrice()) - .setDurationDay(calculateDurationDay(x.getStartTime(), x.getEndTime(), Boolean.TRUE))) - .distinct().collect(Collectors.toList()); - // 当前档口购买的推广轮次 - Map boughtRoundMap = advertRoundList.stream().filter(x -> Objects.equals(x.getStoreId(), storeId)) - .collect(Collectors.toMap(AdvertRound::getRoundId, Function.identity())); - // 未购买的推广轮次记录 - Map unBoughtRoundMap = CollectionUtils.isEmpty(roundIdSet) ? new HashMap<>() - : allRecordList.stream().filter(x -> Objects.equals(x.getAdvertId(), advertId) - && Objects.equals(x.getVoucherDate(), voucherDate) && roundIdSet.contains(x.getRoundId())) - .collect(Collectors.toMap(AdvertRoundRecord::getRoundId, Function.identity(), - BinaryOperator.maxBy(Comparator.comparing(AdvertRoundRecord::getId)))); - - final Date date = new Date(); - // 当前最近的播放轮次 - final Integer minRoundId = advertRoundList.stream().min(Comparator.comparing(AdvertRound::getRoundId)) - .orElseThrow(() -> new ServiceException("当前播放轮次不存在!请联系客服", HttpStatus.ERROR)).getRoundId(); - // 设置当前档口在推广轮次中的数据详情 - rangeDTOList.forEach(x -> { - // 只有播放轮才按照时间计算折扣价 - if (Objects.equals(x.getRoundId(), AdRoundType.PLAY_ROUND.getValue())) { - // 根据当前日期与截止日期的占比修改推广价格 - final BigDecimal curStartPrice = BigDecimal.valueOf(calculateDurationDay(date, x.getEndTime(), Boolean.TRUE)) - .divide(BigDecimal.valueOf(x.getDurationDay()), 10, RoundingMode.DOWN).multiply(x.getStartPrice()) - .setScale(0, RoundingMode.DOWN); - x.setStartPrice(curStartPrice); - } - // 已购买推广位轮次 - final AdvertRound boughtRound = boughtRoundMap.get(x.getRoundId()); - if (ObjectUtils.isNotEmpty(boughtRound) && ObjectUtils.isNotEmpty(boughtRound.getBiddingStatus())) { - // 如果是最近的播放轮次,且当前时间在 晚上10:00:01 之后到 当天23:59:59 都显示 biddingTempStatus 字段 - x.setBiddingStatus(tenClockAfter && Objects.equals(x.getRoundId(), minRoundId) ? boughtRound.getBiddingTempStatus() : boughtRound.getBiddingStatus()); - x.setBiddingStatusName(AdBiddingStatus.of(boughtRound.getBiddingStatus()).getLabel()); - } - // 未购买推广位轮次 - final AdvertRoundRecord unBought = unBoughtRoundMap.get(x.getRoundId()); - if (ObjectUtils.isNotEmpty(unBought)) { - x.setBiddingStatus(unBought.getBiddingStatus()); - x.setBiddingStatusName(AdBiddingStatus.of(unBought.getBiddingStatus()).getLabel()); - } - }); - return roundResDTO.setTimeRangeList(rangeDTOList); - // 位置枚举 - } else { - // 单纯的位置枚举 只展示一轮,主要用于:首页商品推广、下载竞价推广 - Integer minRoundId = advertRoundList.stream().min(Comparator.comparing(AdvertRound::getRoundId)).orElseThrow(() -> new ServiceException("当前播放轮次不存在!请联系客服", HttpStatus.ERROR)).getRoundId(); - // 找到roundId最小的播放轮列表 - List minRoundList = advertRoundList.stream().filter(x -> Objects.equals(x.getRoundId(), minRoundId)).collect(Collectors.toList()); - // 当前轮次所有的位置 - List positionList = minRoundList.stream().map(AdvertRound::getPosition).collect(Collectors.toList()); - // 当前轮次已购买的位置 - final List boughtPositionList = minRoundList.stream().filter(x -> Objects.equals(x.getStoreId(), storeId)).map(AdvertRound::getPosition).collect(Collectors.toList()); - // 该轮次 剩下的未购买的位置 - positionList.removeAll(boughtPositionList); - - Map unBoughtRecordMap = CollectionUtils.isEmpty(positionList) ? new HashMap<>() - : allRecordList.stream().filter(x -> Objects.equals(x.getAdvertId(), advertId) && Objects.equals(x.getVoucherDate(), voucherDate) - && positionList.contains(x.getPosition()) && Objects.equals(x.getRoundId(), minRoundId)).collect(Collectors.toMap(AdvertRoundRecord::getPosition, Function.identity(), - // 从unBoughtRecordList中取出每个位置最大createTime的数据,仅取一条 - BinaryOperator.maxBy(Comparator.comparing(AdvertRoundRecord::getCreateTime)))); - - List positionDTOList = minRoundList.stream().map(x -> { - // 当前轮次有购买记录 - if (Objects.equals(x.getStoreId(), storeId)) { - // 晚上10:00:01 之后到 当天23:59:59 都显示 biddingTempStatus 字段 - final Integer biddingStatus = tenClockAfter ? x.getBiddingTempStatus() : x.getBiddingStatus(); - return BeanUtil.toBean(x, AdRoundStoreResDTO.ADRSRoundPositionDTO.class).setBiddingStatus(biddingStatus) - .setBiddingStatusName(AdBiddingStatus.of(biddingStatus).getLabel()); - } - // 其它轮次有购买记录 - if (ObjectUtils.isNotEmpty(unBoughtRecordMap.get(x.getPosition()))) { - return BeanUtil.toBean(unBoughtRecordMap.get(x.getPosition()), AdRoundStoreResDTO.ADRSRoundPositionDTO.class) - .setBiddingStatusName(AdBiddingStatus.of(unBoughtRecordMap.get(x.getPosition()).getBiddingStatus()).getLabel()) - // 需要展示当前推广位置 最高的价格 - .setPayPrice(x.getPayPrice()); - } - // 其它轮次没有购买轮次 - return BeanUtil.toBean(x, AdRoundStoreResDTO.ADRSRoundPositionDTO.class).setBiddingStatus(null); - }).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()); - return roundResDTO.setPositionList(positionDTOList); - } - } - - /** * 档口购买推广营销 * 主要是两个场景:1. 某个广告位(advert_id)某个轮次(round_id)按照出价(pay_price)决定能否购买。[eg: A B C D E] @@ -1202,87 +1059,6 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { return (int) start.until(end, ChronoUnit.DAYS) + (isContainToday ? 1 : 0); } - /** - * 获取当前档口 已抢购推广位 - * - * @param allRoundList 所有的推广 - * @param allRecordList 所有竞价失败的推广 - * @param storeId 档口ID - * @param voucherDate 单据日期 - * @param tenClockAfter 是否是10点后 - * @return - */ - private List getStoreBoughtRecordList(List allRoundList, List allRecordList, - Long storeId, Date voucherDate, boolean tenClockAfter) { - // 按照advertId进行分组,取最小的roundId列表 - Map> minRoundIdMap = allRoundList.stream().collect(Collectors.groupingBy(AdvertRound::getAdvertId, - Collectors.mapping(AdvertRound::getRoundId, Collectors.minBy(Comparator.comparing(Integer::intValue))))); - // 最小的roundId列表 - List roundIdList = minRoundIdMap.values().stream().filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); - // 筛选档口 所有的 已购买 推广位数据 - List boughtRoundList = allRoundList.stream().filter(x -> Objects.equals(x.getStoreId(), storeId)) - .map(x -> { - // 如果是最近的播放轮次,且当前时间在 晚上10:00:01 之后到 当天23:59:59 都显示 biddingTempStatus 字段 - final Integer biddingStatus = tenClockAfter && roundIdList.contains(x.getRoundId()) ? x.getBiddingTempStatus() : x.getBiddingStatus(); - return BeanUtil.toBean(x, AdRoundStoreResDTO.ADRSRoundRecordDTO.class).setBiddingStatus(biddingStatus) - .setBiddingStatusName(AdBiddingStatus.of(biddingStatus).getLabel()) - .setTypeName(AdType.of(x.getTypeId()).getLabel()) - // 如果是时间范围则不返回position - .setPosition(Objects.equals(x.getShowType(), AdShowType.TIME_RANGE.getValue()) ? null : x.getPosition()); - }) - .collect(Collectors.toList()); - // showType 为 时间范围的 每一轮最高的出价map - Map timeRangeRoundMaxPriceMap = allRoundList.stream() - .filter(x -> Objects.equals(x.getShowType(), AdShowType.TIME_RANGE.getValue())) - .filter(x -> ObjectUtils.isNotEmpty(x.getPayPrice())) - .collect(Collectors - .groupingBy(AdvertRound::getRoundId, Collectors - .mapping(AdvertRound::getPayPrice, Collectors.reducing(BigDecimal.ZERO, BigDecimal::max)))); - // showType 为 位置枚举的 每一个位置最高出价的 map - Map positionEnumMaxPriceMap = allRoundList.stream() - .filter(x -> Objects.equals(x.getShowType(), AdShowType.POSITION_ENUM.getValue())) - .filter(x -> ObjectUtils.isNotEmpty(x.getPayPrice())) - .collect(Collectors.toMap(AdvertRound::getId, AdvertRound::getPayPrice)); - // 已购买的 时间范围播放轮次 的roundId列表 - final List boughtTimeRangeRoundIdList = boughtRoundList.stream().filter(x -> Objects.equals(x.getShowType(), AdShowType.TIME_RANGE.getValue())) - .map(AdRoundStoreResDTO.ADRSRoundRecordDTO::getRoundId).collect(Collectors.toList()); - // 已购买的 位置枚举 的 advertRoundId 列表 - final List boughtPositionAdvertRoundIdList = boughtRoundList.stream().filter(x -> Objects.equals(x.getShowType(), AdShowType.POSITION_ENUM.getValue())) - .map(AdRoundStoreResDTO.ADRSRoundRecordDTO::getAdvertRoundId).collect(Collectors.toList()); - // 购买失败的 时间范围播放轮次的 列表 - Map unBoughtTimeRangeMap = allRecordList.stream() - .filter(x -> Objects.equals(x.getShowType(), AdShowType.TIME_RANGE.getValue())) - .filter(x -> !boughtTimeRangeRoundIdList.contains(x.getRoundId())) - .filter(x -> Objects.equals(x.getVoucherDate(), voucherDate)) - .collect(Collectors.toMap(AdvertRoundRecord::getRoundId, Function.identity(), - BinaryOperator.maxBy(Comparator.comparingLong(AdvertRoundRecord::getId)))); - // 购买失败的 位置枚举播放轮次的 列表 - Map unBoughtPositionMap = allRecordList.stream() - .filter(x -> Objects.equals(x.getShowType(), AdShowType.POSITION_ENUM.getValue())) - .filter(x -> !boughtPositionAdvertRoundIdList.contains(x.getAdvertRoundId())) - .filter(x -> Objects.equals(x.getVoucherDate(), voucherDate)) - .collect(Collectors.toMap(AdvertRoundRecord::getAdvertRoundId, Function.identity(), - BinaryOperator.maxBy(Comparator.comparingLong(AdvertRoundRecord::getId)))); - if (MapUtils.isNotEmpty(unBoughtTimeRangeMap)) { - unBoughtTimeRangeMap.forEach((roundId, record) -> { - boughtRoundList.add(BeanUtil.toBean(record, AdRoundStoreResDTO.ADRSRoundRecordDTO.class).setPosition(null) - .setTypeName(AdType.of(record.getTypeId()).getLabel()) - .setBiddingStatusName(AdBiddingStatus.of(record.getBiddingStatus()).getLabel() - + ",最新出价:" + timeRangeRoundMaxPriceMap.get(record.getRoundId()))); - }); - } - if (MapUtils.isNotEmpty(unBoughtPositionMap)) { - unBoughtPositionMap.forEach((advertRoundId, record) -> { - boughtRoundList.add(BeanUtil.toBean(record, AdRoundStoreResDTO.ADRSRoundRecordDTO.class) - .setTypeName(AdType.of(record.getTypeId()).getLabel()) - .setBiddingStatusName(AdBiddingStatus.of(record.getBiddingStatus()).getLabel() - + ",最新出价:" + positionEnumMaxPriceMap.get(record.getAdvertRoundId())) - ); - }); - } - return boughtRoundList; - } - /** * 购买人手机号中国部分用*号代替 *