From e1e5135a1fa102e08f5172d9729168a6d69c4efb Mon Sep 17 00:00:00 2001 From: liujiang <569804566@qq.com> Date: Fri, 29 Aug 2025 20:25:38 +0800 Subject: [PATCH] =?UTF-8?q?master=EF=BC=9A=E6=8E=A8=E5=B9=BF=E8=90=A5?= =?UTF-8?q?=E9=94=80=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AdRoundTypeRoundBoughtResVO.java | 2 ++ .../vo/advertRound/AdRoundTypeRoundResVO.java | 2 ++ .../java/com/ruoyi/quartz/task/XktTask.java | 4 +-- sql/ry_20240629.sql | 2 +- .../AdRoundTypeRoundBoughtResDTO.java | 2 ++ .../advertRound/AdRoundTypeRoundResDTO.java | 2 ++ .../com/ruoyi/xkt/enums/AdBiddingStatus.java | 2 ++ .../impl/AdminAdvertRoundServiceImpl.java | 5 --- .../service/impl/AdvertRoundServiceImpl.java | 36 +++++++++++++------ 9 files changed, 39 insertions(+), 18 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundTypeRoundBoughtResVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundTypeRoundBoughtResVO.java index e5da93dd3..e338587d9 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundTypeRoundBoughtResVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundTypeRoundBoughtResVO.java @@ -23,6 +23,8 @@ public class AdRoundTypeRoundBoughtResVO { private Long advertId; @ApiModelProperty(value = "广告轮次ID") private Integer roundId; + @ApiModelProperty(value = "是否可购买") + private Boolean canPurchased; @ApiModelProperty(value = "typeId") private Integer typeId; @ApiModelProperty(value = "广告位置 A B C D E") diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundTypeRoundResVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundTypeRoundResVO.java index fbf23ff41..fc5ccaedf 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundTypeRoundResVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundTypeRoundResVO.java @@ -21,6 +21,8 @@ public class AdRoundTypeRoundResVO { private Long advertId; @ApiModelProperty(value = "广告轮次ID") private Integer roundId; + @ApiModelProperty(value = "是否可购买 true:可购买 false:不可购买") + private Boolean canPurchased; @ApiModelProperty(value = "展示类型") private Integer showType; @ApiModelProperty(value = "广告位置 A B C D E") diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java index e48741f61..4071789d9 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java @@ -221,7 +221,7 @@ public class XktTask { updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(roundId).setLaunchStatus(launchStatus) .setStartTime(java.sql.Date.valueOf(now)).setEndTime(java.sql.Date.valueOf(endDate)).setPosition(position).setStartPrice(advert.getStartPrice()) .setSysIntercept(AdSysInterceptType.UN_INTERCEPT.getValue()).setShowType(advert.getShowType()) - .setDisplayType(advert.getDisplayType()).setDeadline(advert.getDeadline()) + .setDisplayType(advert.getDisplayType()).setDeadline(advert.getDeadline()).setBiddingStatus(AdBiddingStatus.UN_BIDDING.getValue()) .setSymbol(Objects.equals(advert.getShowType(), AdShowType.POSITION_ENUM.getValue()) // 如果是位置枚举的推广位,则需要精确到某一个position的推广位,反之,若是时间范围,则直接精确到播放轮次即可 ? advert.getBasicSymbol() + roundId + position : advert.getBasicSymbol() + roundId)); @@ -1689,7 +1689,7 @@ public class XktTask { .setSysIntercept(AdSysInterceptType.UN_INTERCEPT.getValue()).setShowType(advert.getShowType()).setDisplayType(advert.getDisplayType()) .setStartTime(Date.from(startDate.atStartOfDay(ZoneId.systemDefault()).toInstant())) .setEndTime(Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant())) - .setDeadline(advert.getDeadline()) + .setDeadline(advert.getDeadline()).setBiddingStatus(AdBiddingStatus.UN_BIDDING.getValue()) .setSymbol(Objects.equals(advert.getShowType(), AdShowType.POSITION_ENUM.getValue()) // 如果是位置枚举的推广位,则需要精确到某一个position的推广位,反之,若是时间范围,则直接精确到播放轮次即可 ? advert.getBasicSymbol() + maxRoundId + position : advert.getBasicSymbol() + maxRoundId); diff --git a/sql/ry_20240629.sql b/sql/ry_20240629.sql index 2bec06943..dff81b000 100644 --- a/sql/ry_20240629.sql +++ b/sql/ry_20240629.sql @@ -97,9 +97,9 @@ CREATE TABLE `advert_round` `store_id` bigint UNSIGNED NULL DEFAULT NULL COMMENT '档口ID', `start_price` decimal(10, 2) UNSIGNED NOT NULL COMMENT '起始竞价价格', `pay_price` decimal(10, 2) UNSIGNED NULL DEFAULT NULL COMMENT '档口出价', + `bidding_status` int UNSIGNED NULL DEFAULT NULL COMMENT '竞价状态 最初是:已出价 之后会变成 竞价成功', `bidding_temp_status` int UNSIGNED NULL DEFAULT NULL COMMENT '竞价成功', `reject_reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核驳回理由', - `bidding_status` int UNSIGNED NULL DEFAULT NULL COMMENT '竞价状态 最初是:已出价 之后会变成 竞价成功', `pic_audit_status` int UNSIGNED NULL DEFAULT NULL COMMENT '图片审核状态(待审核、审核通过、审核驳回)', `pic_set_type` int UNSIGNED NULL DEFAULT NULL COMMENT '图片是否已设置', `pic_id` bigint UNSIGNED NULL DEFAULT NULL COMMENT '图片ID', diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundTypeRoundBoughtResDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundTypeRoundBoughtResDTO.java index 7073d08c7..31d893788 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundTypeRoundBoughtResDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundTypeRoundBoughtResDTO.java @@ -23,6 +23,8 @@ public class AdRoundTypeRoundBoughtResDTO { private Long advertRoundId; @ApiModelProperty(value = "广告ID") private Long advertId; + @ApiModelProperty(value = "是否可购买") + private Boolean canPurchased; @ApiModelProperty(value = "广告轮次ID") private Integer roundId; @ApiModelProperty(value = "typeId") diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundTypeRoundResDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundTypeRoundResDTO.java index a0f082a80..17e7477f9 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundTypeRoundResDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundTypeRoundResDTO.java @@ -23,6 +23,8 @@ public class AdRoundTypeRoundResDTO { private Long advertId; @ApiModelProperty(value = "广告轮次ID") private Integer roundId; + @ApiModelProperty(value = "是否可购买") + private Boolean canPurchased; @ApiModelProperty(value = "展示类型") private Integer showType; @ApiModelProperty(value = "广告位置 A B C D E") diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/AdBiddingStatus.java b/xkt/src/main/java/com/ruoyi/xkt/enums/AdBiddingStatus.java index 1f11f8335..edbbad8f0 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/AdBiddingStatus.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/AdBiddingStatus.java @@ -14,6 +14,8 @@ import lombok.Getter; @AllArgsConstructor public enum AdBiddingStatus { + // 未出价 + UN_BIDDING(0, "未出价"), // 已出价 BIDDING(1, "已出价"), // 竞价成功 diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdminAdvertRoundServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdminAdvertRoundServiceImpl.java index 6f4762347..4ad33e307 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdminAdvertRoundServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdminAdvertRoundServiceImpl.java @@ -21,7 +21,6 @@ import com.ruoyi.xkt.service.IAssetService; import lombok.RequiredArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -249,10 +248,6 @@ public class AdminAdvertRoundServiceImpl implements IAdminAdvertRoundService { if (ObjectUtils.isNotEmpty(interceptDTO.getStoreProdIdList())) { advertRound.setProdIdStr(StringUtils.join(interceptDTO.getStoreProdIdList(), ",")); } - // 如果是位置枚举,则设置一个很高的价格(100 - 200)范围,有其它档口愿意出更高价格拿下就随他去 - if (Objects.equals(advertRound.getShowType(), AdShowType.POSITION_ENUM.getValue())) { - advertRound.setPayPrice(BigDecimal.valueOf(RandomUtils.nextLong(10, 20 + 1) * 10)); - } return this.advertRoundMapper.updateById(advertRound); } 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 e19273217..20ce3dbaf 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 @@ -221,13 +221,19 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { List resList = new ArrayList<>(); final Date date = new Date(); advertRoundList.stream().collect(Collectors.groupingBy(AdvertRound::getRoundId)) - .forEach((roundId, list) -> { - AdvertRound advertRound = list.get(0); + .forEach((roundId, currentRoundList) -> { + AdvertRound advertRound = currentRoundList.get(0); Integer durationDay = calculateDurationDay(advertRound.getStartTime(), advertRound.getEndTime(), Boolean.TRUE); AdRoundTypeRoundResDTO typeRoundResDTO = new AdRoundTypeRoundResDTO().setAdvertId(advertRound.getAdvertId()).setRoundId(advertRound.getRoundId()) .setSymbol(advertRound.getSymbol()).setLaunchStatus(advertRound.getLaunchStatus()).setStartTime(advertRound.getStartTime()) .setEndTime(advertRound.getEndTime()).setStartWeekDay(getDayOfWeek(advertRound.getStartTime())).setDurationDay(durationDay) - .setEndWeekDay(getDayOfWeek(advertRound.getEndTime())).setShowType(advertRound.getShowType()).setPosition(advertRound.getPosition()); + .setCanPurchased(Boolean.TRUE).setEndWeekDay(getDayOfWeek(advertRound.getEndTime())) + .setShowType(advertRound.getShowType()).setPosition(advertRound.getPosition()); + // 如果是播放论,并且是否全部为 BIDDING_SUCCESS,若是 则不可购买当前轮次(就算是当前档口购买的,biddingStatus也为2,也将标识置为false) + if (Objects.equals(roundId, AdRoundType.PLAY_ROUND.getValue()) + && currentRoundList.stream().allMatch(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue()))) { + typeRoundResDTO.setCanPurchased(Boolean.FALSE); + } // 如果是播放论,则播放开始时间展示为当天,因为有可能是播放的中间某一天 if (Objects.equals(advertRound.getRoundId(), AdRoundType.PLAY_ROUND.getValue())) { Date tomorrow = Date.from(LocalDate.now().plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant()); @@ -248,7 +254,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { typeRoundResDTO.setStartPrice(curStartPrice); } // 当前档口购买的轮次 - AdvertRound boughtRound = list.stream().filter(x -> Objects.equals(x.getStoreId(), storeId)).findFirst().orElse(null); + AdvertRound boughtRound = currentRoundList.stream().filter(x -> Objects.equals(x.getStoreId(), storeId)).findFirst().orElse(null); if (ObjectUtils.isNotEmpty(boughtRound)) { // 如果是最近的播放轮次,且当前时间在 晚上10:00:01 之后到 当天23:59:59 都显示 biddingTempStatus 字段 Integer biddingStatus = tenClockAfter && Objects.equals(typeRoundResDTO.getRoundId(), minRoundId) @@ -293,10 +299,15 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { boolean tenClockAfter = now.isAfter(LocalTime.of(22, 0, 0)) && now.isBefore(LocalTime.of(23, 59, 59)); final Date date = new Date(); List resList = advertRoundList.stream().map(advertRound -> { - AdRoundTypeRoundBoughtResDTO bought = new AdRoundTypeRoundBoughtResDTO().setTypeId(advertRound.getTypeId()).setAdvertRoundId(advertRound.getId()) + AdRoundTypeRoundBoughtResDTO boughtResDTO = new AdRoundTypeRoundBoughtResDTO().setTypeId(advertRound.getTypeId()).setAdvertRoundId(advertRound.getId()) .setAdvertId(advertRound.getAdvertId()).setRoundId(advertRound.getRoundId()).setPosition(advertRound.getPosition()) .setStartPrice(advertRound.getStartPrice()).setPayPrice(advertRound.getPayPrice()).setStoreId(storeId).setLaunchStatus(advertRound.getLaunchStatus()) .setStartTime(advertRound.getStartTime()).setEndTime(advertRound.getEndTime()).setSymbol(advertRound.getSymbol()); + // 如果是播放论,并且是否全部为 BIDDING_SUCCESS,若是 则不可购买当前轮次(就算是当前档口购买的,biddingStatus也为2,也将标识置为false) + if (Objects.equals(advertRound.getRoundId(), AdRoundType.PLAY_ROUND.getValue()) + && Objects.equals(advertRound.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())) { + boughtResDTO.setCanPurchased(Boolean.FALSE); + } // 如果当前位置没有档口购买,且为第一轮 则需按照剩余时间比例进行减价 if (ObjectUtils.isEmpty(advertRound.getStoreId()) && Objects.equals(advertRound.getRoundId(), AdRoundType.PLAY_ROUND.getValue())) { Integer durationDay = calculateDurationDay(advertRound.getStartTime(), advertRound.getEndTime(), Boolean.TRUE); @@ -304,15 +315,15 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { BigDecimal numerator = BigDecimal.valueOf(calculateDurationDay(date, advertRound.getEndTime(), Boolean.FALSE)); BigDecimal curStartPrice = numerator.multiply(advertRound.getStartPrice()) .divide(BigDecimal.valueOf(durationDay), 0, RoundingMode.HALF_UP); - bought.setStartPrice(curStartPrice); + boughtResDTO.setStartPrice(curStartPrice); } // 当前档口购买的推广位置 if (Objects.equals(advertRound.getStoreId(), storeId)) { Integer biddingStatus = tenClockAfter ? advertRound.getBiddingTempStatus() : advertRound.getBiddingStatus(); - bought.setBiddingStatus(biddingStatus); - bought.setBiddingStatusName(AdBiddingStatus.of(biddingStatus).getLabel()); + boughtResDTO.setBiddingStatus(biddingStatus); + boughtResDTO.setBiddingStatusName(AdBiddingStatus.of(biddingStatus).getLabel()); } - return bought; + return boughtResDTO; }).collect(Collectors.toList()); // 档口未竞价成功的位置 List unBoughtPositionList = advertRoundList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getStoreId()) && !Objects.equals(x.getStoreId(), storeId)) @@ -637,6 +648,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { } LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() .eq(AdvertRound::getAdvertId, createDTO.getAdvertId()).eq(AdvertRound::getRoundId, createDTO.getRoundId()) + .in(AdvertRound::getBiddingStatus, Arrays.asList(AdBiddingStatus.BIDDING.getValue(), AdBiddingStatus.UN_BIDDING.getValue())) .eq(AdvertRound::getDelFlag, Constants.UNDELETED).orderByAsc(AdvertRound::getPayPrice).last("LIMIT 1"); // 如果是 时间范围 的广告位,则不查 系统拦截的数据;其实位置枚举的广告位也可不用查系统拦截的数据,主要是为了真实,给档口留个缝 if (Objects.equals(createDTO.getShowType(), AdShowType.TIME_RANGE.getValue())) { @@ -646,7 +658,11 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { if (StringUtils.isNotBlank(createDTO.getPosition())) { queryWrapper.eq(AdvertRound::getPosition, createDTO.getPosition()); } - AdvertRound minPriceAdvert = Optional.ofNullable(this.advertRoundMapper.selectOne(queryWrapper)).orElseThrow(() -> new ServiceException("获取推广营销位置失败,请联系客服!", HttpStatus.ERROR)); + // 是否有可供购买的广告位 + AdvertRound minPriceAdvert = this.advertRoundMapper.selectOne(queryWrapper); + if (ObjectUtils.isEmpty(minPriceAdvert)) { + throw new ServiceException("当前推广位已售罄,请选购其它推广位噢!", HttpStatus.ERROR); + } // 判断当前档口出价是否低于该推广位最低价格,若是,则提示:"已经有档口出价更高了噢,请重新出价!". if (createDTO.getPayPrice().compareTo(ObjectUtils.defaultIfNull(minPriceAdvert.getPayPrice(), BigDecimal.ZERO)) <= 0) { throw new ServiceException("已经有档口出价更高了噢,请重新出价!", HttpStatus.ERROR);