master:推广营销模块功能调整;

pull/1121/head
liujiang 2025-05-11 20:41:27 +08:00
parent 71728560c2
commit f26d2bf275
25 changed files with 278 additions and 179 deletions

View File

@ -47,8 +47,7 @@ public class AdvertRoundController extends XktBaseController {
*/
@ApiOperation(value = "根据广告ID获取推广轮次列表并返回当前档口在这些推广轮次的数据", httpMethod = "GET", response = R.class)
@GetMapping(value = "/{advertId}/{storeId}/{showType}")
public R<AdRoundStoreResVO> getStoreAdInfo(@PathVariable("advertId") Long advertId, @PathVariable("storeId") Long storeId,
@PathVariable("showType") Integer showType) {
public R<AdRoundStoreResVO> 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));
}

View File

@ -39,7 +39,7 @@ public class UserFavoritesController extends XktBaseController {
// @PreAuthorize("@ss.hasPermi('system:favorites:add')")
@ApiOperation(value = "用户收藏商品", httpMethod = "POST", response = R.class)
@Log(title = "用户收藏商品", businessType = BusinessType.INSERT)
@PostMapping
@PostMapping("/batch")
public R<Integer> create(@Validated @RequestBody UserFavoriteVO favoriteVO) {
return success(userFavService.create(BeanUtil.toBean(favoriteVO, UserFavoriteDTO.class)));
}

View File

@ -72,6 +72,10 @@ public class AdRoundStoreResVO {
private Integer typeId;
@ApiModelProperty(value = "广告位置 A B C D E")
private String position;
@ApiModelProperty(value = "起拍价格")
private BigDecimal startPrice;
@ApiModelProperty(value = "推广档口出价")
private BigDecimal payPrice;
@ApiModelProperty(value = "投放开始时间")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date startTime;
@ -101,6 +105,12 @@ public class AdRoundStoreResVO {
private String typeName;
@ApiModelProperty(value = "推广档口ID")
private Long storeId;
@ApiModelProperty(value = "投放开始时间")
@JsonFormat(pattern = "MM月dd日", timezone = "GMT+8")
private Date startTime;
@ApiModelProperty(value = "投放结束时间")
@JsonFormat(pattern = "MM月dd日", timezone = "GMT+8")
private Date endTime;
@ApiModelProperty(value = "对象锁符号")
private String symbol;
@ApiModelProperty(value = "广告位置 A B C D E")

View File

@ -60,7 +60,7 @@ public class StoreProdResVO {
@ApiModelProperty(value = "档口服务承诺")
private StoreProdSvcVO svc;
@ApiModelProperty(value = "详情内容")
private StoreProdDetailVO detail;
private String detail;
@ApiModelProperty(value = "档口商品生产工艺")
private StoreProdProcessVO process;
@ -149,13 +149,6 @@ public class StoreProdResVO {
private String refundWithinThreeDay;
}
@Data
@ApiModel(value = "档口商品详情")
public static class StoreProdDetailVO {
@ApiModelProperty(value = "详情内容")
private String detail;
}
@Data
@ApiModel(value = "档口商品工艺")
public static class StoreProdProcessVO {

View File

@ -5,7 +5,10 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.ruoyi.web.controller.xkt.vo.storeColor.StoreColorVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
@ -92,10 +95,9 @@ public class StoreProdVO {
private List<StoreProdColorPriceVO> priceList;
@ApiModelProperty(value = "档口服务承诺")
private StoreProdSvcVO svc;
@NotNull(message = "详情内容不能为空!")
@Valid
@NotBlank(message = "详情内容不能为空!")
@ApiModelProperty(value = "详情内容", required = true)
private StoreProdDetailVO detail;
private String detail;
@ApiModelProperty(value = "档口生产工艺")
private StoreProdProcessVO process;
@ -172,8 +174,7 @@ public class StoreProdVO {
@Data
@ApiModel(value = "商品颜色列表")
public static class StoreProdColorVO {
@NotNull(message = "档口颜色ID不能为空!")
@ApiModelProperty(value = "档口颜色ID", required = true)
@ApiModelProperty(value = "档口颜色ID")
private Long storeColorId;
@NotBlank(message = "颜色名称不能为空!")
@ApiModelProperty(value = "颜色名称", required = true)
@ -185,9 +186,10 @@ public class StoreProdVO {
@Data
@ApiModel(value = "档口尺码列表")
@AllArgsConstructor
@NoArgsConstructor
public static class StoreProdColorSizeVO {
@NotNull(message = "档口颜色ID不能为空!")
@ApiModelProperty(value = "档口颜色ID", required = true)
@ApiModelProperty(value = "档口颜色ID")
private Long storeColorId;
@ApiModelProperty(value = "商品尺码", required = true)
@NotNull(message = "档口商品定价不能为空!")
@ -200,9 +202,11 @@ public class StoreProdVO {
@Data
@ApiModel(value = "档口颜色价格列表")
public static class StoreProdColorPriceVO {
@NotNull(message = "档口商品颜色ID不能为空!")
@ApiModelProperty(value = "档口商品颜色ID", required = true)
@ApiModelProperty(value = "档口商品颜色ID")
private Long storeColorId;
@NotBlank(message = "颜色名称不能为空!")
@ApiModelProperty(value = "颜色名称", required = true)
private String colorName;
@NotNull(message = "档口商品定价不能为空!")
@ApiModelProperty(value = "档口商品定价", required = true)
private BigDecimal price;
@ -221,14 +225,6 @@ public class StoreProdVO {
private String refundWithinThreeDay;
}
@Data
@ApiModel(value = "详情内容")
public static class StoreProdDetailVO {
@NotBlank(message = "详情内容不能为空!")
@ApiModelProperty(value = "详情内容", required = true)
private String detail;
}
@Data
@ApiModel(value = "档口生产工艺")
public static class StoreProdProcessVO {

View File

@ -20,8 +20,9 @@ import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserFavBatchDeleteVO {
@NotNull(message = "批量操作ID列表不能为空!")
@ApiModelProperty("用户收藏ID")
List<Long> userFavoriteIdList;
@NotNull(message = "档口商品ID列表不能为空!")
@ApiModelProperty("档口商品ID列表")
List<Long> storeProdIdList;
}

View File

@ -4,8 +4,11 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author liujiang
@ -17,11 +20,20 @@ import javax.validation.constraints.NotNull;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserFavoriteVO {
@NotNull(message = "档口ID不能为空!")
@ApiModelProperty(value = "档口ID")
private Long storeId;
@NotNull(message = "档口商品ID不能为空!")
@ApiModelProperty(value = "档口商品ID")
private Long storeProdId;
@ApiModelProperty("用户新增收藏列表")
private List<UFBatchVO> batchList;
@Data
@ApiModel(value = "用户新增收藏")
@Accessors(chain = true)
@Valid
public static class UFBatchVO {
@NotNull(message = "档口ID不能为空!")
@ApiModelProperty(value = "档口ID")
private Long storeId;
@NotNull(message = "档口商品ID不能为空!")
@ApiModelProperty(value = "档口商品ID")
private Long storeProdId;
}
}

View File

@ -13,13 +13,13 @@ import java.util.List;
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("电商卖家新增店铺关注")
@ApiModel("电商卖家取消店铺关注")
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserSubscDeleteVO {
@NotNull(message = "用户关注ID列表不能为空!")
@ApiModelProperty(value = "用户关注ID")
private List<Long> userSubscIdList;
@NotNull(message = "档口ID列表不能为空!")
@ApiModelProperty(value = "档口ID列表")
private List<Long> storeIdList;
}

View File

@ -13,7 +13,7 @@ import java.util.List;
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("电商卖家取消店铺关注")
@ApiModel("电商卖家店铺关注")
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserSubscVO {

View File

@ -333,7 +333,7 @@ public class XktTask {
final String position = String.valueOf((char) ('A' + j));
// 当前播放轮次id
final int roundId = i + 1;
updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(roundId).setLaunchStatus(launchStatus)
updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(roundId).setLaunchStatus(launchStatus).setShowType(advert.getShowType())
.setStartTime(java.sql.Date.valueOf(now)).setEndTime(java.sql.Date.valueOf(endDate)).setPosition(position).setStartPrice(advert.getStartPrice())
.setSymbol(Objects.equals(advert.getShowType(), AdShowType.POSITION_ENUM.getValue())
// 如果是位置枚举的推广位则需要精确到某一个position的推广位反之若是时间范围则直接精确到播放轮次即可
@ -380,7 +380,7 @@ public class XktTask {
// 依次按照26个字母顺序 如果i == 0 则A i == 1 则B i==2则C
final String position = String.valueOf((char) ('A' + j));
// 生成最新的下一轮推广位
updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(maxRoundId)
updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(maxRoundId).setShowType(advert.getShowType())
.setLaunchStatus(AdLaunchStatus.UN_LAUNCH.getValue()).setPosition(position).setStartPrice(advert.getStartPrice())
// java.sql.Date 直接转化成yyyy-MM-dd格式
.setStartTime(java.sql.Date.valueOf(startDate)).setEndTime(java.sql.Date.valueOf(endDate))

View File

@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
import java.util.List;
@ -18,11 +19,11 @@ import java.util.List;
@ApiModel("系统商品分类列表")
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@Accessors(chain = true)
public class ProdCateListResDTO {
@ApiModelProperty(value = "商品分类主键")
@JsonProperty(value = "prodCateId")
private Long id;
private Long prodCateId;
@ApiModelProperty(value = "分类名称")
private String name;
@ApiModelProperty(value = "分类名称")

View File

@ -123,7 +123,8 @@ public class SysProductCategoryServiceImpl implements ISysProductCategoryService
if (CollectionUtils.isEmpty(prodCateList)) {
return new ArrayList<>();
}
List<ProdCateListResDTO> resList = BeanUtil.copyToList(prodCateList, ProdCateListResDTO.class);
List<ProdCateListResDTO> resList = prodCateList.stream()
.map(x -> BeanUtil.toBean(x, ProdCateListResDTO.class).setProdCateId(x.getId())).collect(Collectors.toList());
return this.buildCateTree(resList);
}
@ -184,7 +185,7 @@ public class SysProductCategoryServiceImpl implements ISysProductCategoryService
*/
private List<ProdCateListResDTO> buildCateTree(List<ProdCateListResDTO> cateList) {
List<ProdCateListResDTO> returnList = new ArrayList<>();
List<Long> tempList = cateList.stream().map(ProdCateListResDTO::getId).collect(Collectors.toList());
List<Long> tempList = cateList.stream().map(ProdCateListResDTO::getProdCateId).collect(Collectors.toList());
for (Iterator<ProdCateListResDTO> iterator = cateList.iterator(); iterator.hasNext(); ) {
ProdCateListResDTO category = iterator.next();
// 如果是顶级节点, 遍历该父节点的所有子节点
@ -225,7 +226,7 @@ public class SysProductCategoryServiceImpl implements ISysProductCategoryService
Iterator<ProdCateListResDTO> it = cateList.iterator();
while (it.hasNext()) {
ProdCateListResDTO n = it.next();
if (n.getParentId().longValue() == cate.getId().longValue()) {
if (n.getParentId().longValue() == cate.getProdCateId().longValue()) {
tlist.add(n);
}
}

View File

@ -27,6 +27,10 @@ public class AdvertRound extends XktBaseEntity {
*/
@TableId
private Long id;
/**
* 广
*/
private Integer showType;
/**
*
*/

View File

@ -27,6 +27,10 @@ public class AdvertRoundRecord extends XktBaseEntity {
*/
@TableId
private Long id;
/**
* 广
*/
private Integer showType;
/**
*
*/

View File

@ -51,16 +51,16 @@ public class AdRoundStoreResDTO {
private BigDecimal startPrice;
@ApiModelProperty(value = "轮次持续时间")
private Integer durationDay;
// @ApiModelProperty(value = "typeId")
// private Integer typeId;
// @ApiModelProperty(value = "推广档口ID")
// private Long storeId;
@ApiModelProperty(value = "对象锁符号")
private String symbol;
@ApiModelProperty(value = "价状态")
@ApiModelProperty(value = "出价状态")
private Integer biddingStatus;
@ApiModelProperty(value = "价状态名称")
@ApiModelProperty(value = "价状态名称")
private String biddingStatusName;
// @ApiModelProperty(value = "竞价状态")
// private Integer biddingTempStatus;
// @ApiModelProperty(value = "竞价状态名称22点 后 显示这个)")
// private String biddingTempStatusName;
}
@Data
@ -76,18 +76,24 @@ public class AdRoundStoreResDTO {
private Integer typeId;
@ApiModelProperty(value = "广告位置 A B C D E")
private String position;
@ApiModelProperty(value = "起拍价格")
private BigDecimal startPrice;
@ApiModelProperty(value = "推广档口出价")
private BigDecimal payPrice;
@ApiModelProperty(value = "投放开始时间")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date startTime;
@ApiModelProperty(value = "投放结束时间")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date endTime;
@ApiModelProperty(value = "价状态")
@ApiModelProperty(value = "价状态")
private Integer biddingStatus;
@ApiModelProperty(value = "价状态名称")
@ApiModelProperty(value = "价状态名称")
private String biddingStatusName;
// @ApiModelProperty(value = "推广档口ID")
// private Long storeId;
// @ApiModelProperty(value = "竞价状态")
// private Integer biddingTempStatus;
// @ApiModelProperty(value = "竞价状态名称22点 后 显示这个)")
// private String biddingTempStatusName;
@ApiModelProperty(value = "对象锁符号")
private String symbol;
}
@ -97,8 +103,12 @@ public class AdRoundStoreResDTO {
@Accessors(chain = true)
@ApiModel(value = "已抢购的推广记录")
public static class ADRSRoundRecordDTO {
@ApiModelProperty(value = "推广订购ID", hidden = true)
private Long advertRoundId;
@ApiModelProperty(value = "广告ID")
private Long advertId;
@ApiModelProperty(value = "1 时间范围 2位置枚举")
private Integer showType;
@ApiModelProperty(value = "广告轮次ID")
private Integer roundId;
@ApiModelProperty(value = "广告类型ID")
@ -107,11 +117,15 @@ public class AdRoundStoreResDTO {
private String typeName;
@ApiModelProperty(value = "推广档口ID")
private Long storeId;
@ApiModelProperty(value = "投放开始时间")
private Date startTime;
@ApiModelProperty(value = "投放结束时间")
private Date endTime;
@ApiModelProperty(value = "对象锁符号")
private String symbol;
@ApiModelProperty(value = "广告位置 A B C D E")
private String position;
@ApiModelProperty(value = "价状态")
@ApiModelProperty(value = "价状态")
private Integer biddingStatus;
@ApiModelProperty(value = "竞价状态名称及描述")
private String biddingStatusName;

View File

@ -15,6 +15,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;
@ -58,6 +59,8 @@ public class StoreProdDTO {
private Integer listingWay;
@ApiModelProperty(value = "商品状态")
private Integer prodStatus;
@ApiModelProperty(value = "详情内容")
private String detail;
@ApiModelProperty(value = "定时发货时间(精确到小时)")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date listingWaySchedule;
@ -76,8 +79,6 @@ public class StoreProdDTO {
private List<StoreProdColorPriceSimpleDTO> priceList;
@ApiModelProperty(value = "档口服务承诺")
private StoreProdSvcDTO svc;
@ApiModelProperty(value = "详情内容")
private StoreProdDetailDTO detail;
@ApiModelProperty(value = "档口生产工艺")
private StoreProdProcessDTO process;

View File

@ -71,7 +71,7 @@ public class StoreProdResDTO {
@ApiModelProperty(value = "档口服务承诺")
private StoreProdSvcDTO svc;
@ApiModelProperty(value = "详情内容")
private StoreProdDetailDTO detail;
private String detail;
@ApiModelProperty(value = "档口生产工艺信息")
private StoreProdProcessDTO process;

View File

@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
@ -17,7 +18,7 @@ import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserFavBatchDeleteDTO {
@ApiModelProperty("用户收藏ID")
List<Long> userFavoriteIdList;
@ApiModelProperty("档口商品ID列表")
List<Long> storeProdIdList;
}

View File

@ -4,6 +4,10 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author liujiang
@ -15,9 +19,17 @@ import lombok.Data;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserFavoriteDTO {
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "档口商品ID")
private Long storeProdId;
@ApiModelProperty("用户新增收藏列表")
private List<UFBatchVO> batchList;
@Data
@ApiModel(value = "用户新增收藏")
@Accessors(chain = true)
public static class UFBatchVO {
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "档口商品ID")
private Long storeProdId;
}
}

View File

@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
@ -17,7 +18,7 @@ import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserSubscDeleteDTO {
@ApiModelProperty(value = "用户关注ID")
private List<Long> userSubscIdList;
@ApiModelProperty(value = "档口ID列表")
private List<Long> storeIdList;
}

View File

@ -42,4 +42,5 @@ public interface AdvertRoundRecordMapper extends BaseMapper<AdvertRoundRecord> {
List<AdvertRoundRecord> selectListByPosition(@Param("advertId") Long advertId, @Param("storeId") Long storeId,
@Param("voucherDate") Date voucherDate, @Param("positionList") List<String> positionList);
}

View File

@ -22,6 +22,7 @@ import com.ruoyi.xkt.mapper.StoreMapper;
import com.ruoyi.xkt.service.IAdvertRoundService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@ -31,10 +32,7 @@ import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.time.temporal.ChronoUnit;
@ -158,16 +156,35 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
*/
@Override
@Transactional(readOnly = true)
public AdRoundStoreResDTO getStoreAdInfo(final Long storeId,final Long advertId,final Integer showType) {
// 获取当前 正在播放 和 待播放的推广轮次
List<AdvertRound> advertRoundList = this.advertRoundMapper.selectList(new LambdaQueryWrapper<AdvertRound>()
.eq(AdvertRound::getAdvertId, advertId).eq(AdvertRound::getDelFlag, Constants.UNDELETED)
.in(AdvertRound::getLaunchStatus, Arrays.asList(AdLaunchStatus.LAUNCHING.getValue(), AdLaunchStatus.UN_LAUNCH.getValue())));
if (CollectionUtils.isEmpty(advertRoundList)) {
return AdRoundStoreResDTO.builder().build();
}
public AdRoundStoreResDTO getStoreAdInfo(final Long storeId, final Long advertId,final Integer showType) {
final LocalTime now = LocalTime.now();
// 当前时间 是否在 晚上22:00:01 到 晚上23:59:59之间 决定 biddingStatus 和 biddingTempStatus 用那一个字段
boolean tenClockAfter = now.isAfter(LocalTime.of(22, 0, 1)) && now.isBefore(LocalTime.of(23, 59, 59));
// 当天
final Date voucherDate = java.sql.Date.valueOf(LocalDate.now());
// 获取当前所有 正在投放 和 待投放的推广轮次
List<AdvertRound> allRoundList = this.advertRoundMapper.selectList(new LambdaQueryWrapper<AdvertRound>()
.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<AdvertRoundRecord> allRecordList = this.advertRoundRecordMapper.selectList(new LambdaQueryWrapper<AdvertRoundRecord>()
.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<AdvertRound> 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))
@ -176,39 +193,14 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
advertRoundList = voucherDate.before(firstRoundEndTime)
? advertRoundList.stream().filter(x -> !Objects.equals(x.getRoundId(), AdRoundType.FIFTH_ROUND.getValue())).collect(Collectors.toList())
: advertRoundList.stream().filter(x -> !Objects.equals(x.getRoundId(), AdRoundType.PLAY_ROUND.getValue())).collect(Collectors.toList());
AdRoundStoreResDTO roundResDTO = AdRoundStoreResDTO.builder().build();
// 如果投放类型是:时间范围,则只需要返回每一轮的开始时间和结束时间;如果投放类型是:位置枚举,则需要返回每一个位置的详细情况
if (Objects.equals(showType, AdShowType.TIME_RANGE.getValue())) {
// 有档口购买的所有轮次
Set<Integer> roundIdSet = advertRoundList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPayPrice())).map(AdvertRound::getRoundId).collect(Collectors.toSet());
// 当前档口购买的轮次
Set<Integer> boughtIdSet = advertRoundList.stream().filter(x -> Objects.equals(x.getStoreId(), storeId)).map(AdvertRound::getRoundId).collect(Collectors.toSet());
// 当前档口未购买的轮次
roundIdSet.removeAll(boughtIdSet);
List<AdvertRoundRecord> recordList = CollectionUtils.isNotEmpty(roundIdSet)
? this.advertRoundRecordMapper.selectListByRoundId(advertId, storeId, voucherDate, roundIdSet) : new ArrayList<>();
// 获取已抢购推广位列表
// AdRoundStoreResDTO roundResDTO = AdRoundStoreResDTO.builder().boughtRoundList().build();
roundResDTO.setBoughtRoundList(this.getStoreBoughtList(storeId, advertRoundList, recordList));
// 构建当前round基础数据
List<AdRoundStoreResDTO.ADRSRoundTimeRangeDTO> rangeDTOList = advertRoundList.stream().map(x -> new AdRoundStoreResDTO.ADRSRoundTimeRangeDTO()
.setAdvertId(x.getAdvertId()).setRoundId(x.getRoundId()).setSymbol(x.getSymbol()).setStartTime(x.getStartTime()).setEndTime(x.getEndTime())
@ -218,8 +210,17 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
// 当前档口购买的推广轮次
Map<Integer, AdvertRound> boughtRoundMap = advertRoundList.stream().filter(x -> Objects.equals(x.getStoreId(), storeId))
.collect(Collectors.toMap(AdvertRound::getRoundId, Function.identity()));
Map<Integer, AdvertRoundRecord> unBoughtRoundMap = recordList.stream().collect(Collectors.toConcurrentMap(AdvertRoundRecord::getRoundId, Function.identity()));
// 未购买的推广轮次记录
Map<Integer, AdvertRoundRecord> 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 -> {
// 只有播放轮才按照时间计算折扣价
@ -233,7 +234,8 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
// 已购买推广位轮次
final AdvertRound boughtRound = boughtRoundMap.get(x.getRoundId());
if (ObjectUtils.isNotEmpty(boughtRound) && ObjectUtils.isNotEmpty(boughtRound.getBiddingStatus())) {
x.setBiddingStatus(boughtRound.getBiddingStatus());
// 如果是最近的播放轮次,且当前时间在 晚上10:00:01 之后到 当天23:59:59 都显示 biddingTempStatus 字段
x.setBiddingStatus(tenClockAfter && Objects.equals(x.getRoundId(), minRoundId) ? boughtRound.getBiddingTempStatus() : boughtRound.getBiddingStatus());
x.setBiddingStatusName(Objects.requireNonNull(AdBiddingStatus.of(boughtRound.getBiddingStatus())).getLabel());
}
// 未购买推广位轮次
@ -256,76 +258,38 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
final List<String> boughtPositionList = minRoundList.stream().filter(x -> Objects.equals(x.getStoreId(), storeId)).map(AdvertRound::getPosition).collect(Collectors.toList());
// 该轮次 剩下的未购买的位置
positionList.removeAll(boughtPositionList);
List<AdvertRoundRecord> recordList = CollectionUtils.isNotEmpty(positionList)
? this.advertRoundRecordMapper.selectListByPosition(advertId, storeId, voucherDate, positionList ) : new ArrayList<>();
// 从recordList中筛选出当前轮其它位置 未竞价成功 的数据
Map<String, AdvertRoundRecord> unBoughtRecordMap = recordList.stream().filter(x -> Objects.equals(x.getRoundId(), minRoundId)
&& Objects.equals(x.getStoreId(), storeId) && Objects.equals(x.getVoucherDate(), voucherDate) && Objects.equals(x.getAdvertId(), advertId)
// 排除掉已购买过的位置
&& (CollectionUtils.isEmpty(boughtPositionList) || !boughtPositionList.contains(x.getPosition())))
.collect(Collectors.toMap(AdvertRoundRecord::getPosition, Function.identity(),
// 从unBoughtRecordList中取出每个位置最大createTime的数据仅取一条
BinaryOperator.maxBy(Comparator.comparing(AdvertRoundRecord::getCreateTime))));
Map<String, AdvertRoundRecord> 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<AdRoundStoreResDTO.ADRSRoundPositionDTO> positionDTOList = minRoundList.stream().map(x -> {
// 当前轮次有购买记录
if (Objects.equals(x.getStoreId(), storeId)) {
return BeanUtil.toBean(x, AdRoundStoreResDTO.ADRSRoundPositionDTO.class)
.setBiddingStatusName(Objects.requireNonNull(AdBiddingStatus.of(x.getBiddingStatus())).getLabel());
// 晚上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(Objects.requireNonNull(AdBiddingStatus.of(biddingStatus)).getLabel());
}
// 其它轮次有购买轮次
// 其它轮次有购买记录
if (ObjectUtils.isNotEmpty(unBoughtRecordMap.get(x.getPosition()))) {
return BeanUtil.toBean(unBoughtRecordMap.get(x.getPosition()), AdRoundStoreResDTO.ADRSRoundPositionDTO.class)
.setBiddingStatusName(Objects.requireNonNull(AdBiddingStatus.of(unBoughtRecordMap.get(x.getPosition()).getBiddingStatus())).getLabel());
.setBiddingStatusName(Objects.requireNonNull(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);
}
// TODO 返回 biddingTempStatus
// TODO 返回 biddingTempStatus
// TODO 返回 biddingTempStatus
// 已抢购推广列表 显示单据日期大于等于当天的数据 针对某一轮 如果抢购成功了,则这一轮所以失败的记录都不显示。如果未来的某一轮:已出价或者竞价失败有多次,则只显示最新的那一条数据。
// 如果是已出价,要显示最新出价。如果是竞价失败,要显示最新的价格
// 针对当前播放轮,如果竞价成功,则显示。就算是当前轮最后一天 也要显示 竞价成功
// 写 sql 从advertRound中获取 advertId 和 roundId 最高的价格
/* Map<Integer, BigDecimal> otherRoundMaxPriceMap = advertRoundList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPayPrice()))
.filter(x -> remainRoundIdList.contains(x.getRoundId()))
.collect(Collectors.groupingBy(
AdvertRound::getRoundId,
Collectors.reducing(BigDecimal.ZERO, AdvertRound::getPayPrice, BigDecimal::max)
));*/
// 根据广告ID获取所有推广轮次列表如果有其他档口的数据则 需要过滤
// 这里要返回两个部分的数据 1. 左边的档口广告列表 2. 右边的已购推广位竞价结果
// 如果左边某个推广位竞价失败,则失败的当天展示;第二天该推广位就不再展示竞价失败 字样了。但是右边的“已订购推广列表”,一直展示知道该推广位播放完毕
// 当天不是第一轮最后一天类型位时间范围则显示前4轮推广位类型为位置枚举则显示前1轮。是最后一天类型为时间范围显示第2轮到第4轮类型为位置枚举则显示第二轮
// 再判断当前当前与每一轮推广营销中的关系,已出价、竞价失败、竞价成功等
}
/**
* 广
* 1. 广advert_idround_idpay_price[eg: A B C D E]
@ -366,7 +330,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
boolean isOverBuy = this.advertRoundMapper.isStallOverBuy(createDTO.getAdvertId(), createDTO.getRoundId(), createDTO.getStoreId(),
Arrays.asList(AdLaunchStatus.LAUNCHING.getValue(), AdLaunchStatus.UN_LAUNCH.getValue()));
if (isOverBuy) {
throw new ServiceException("已达到该推广位最大购买额度,不可超买哦!", HttpStatus.ERROR);
throw new ServiceException("已购买过该推广位,不可超买哦!", HttpStatus.ERROR);
}
LambdaQueryWrapper<AdvertRound> queryWrapper = new LambdaQueryWrapper<AdvertRound>()
.eq(AdvertRound::getAdvertId, createDTO.getAdvertId()).eq(AdvertRound::getRoundId, createDTO.getRoundId())
@ -535,5 +499,84 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
return (int) start.until(end, ChronoUnit.DAYS) + 1;
}
/**
* 广
* @param allRoundList 广
* @param allRecordList 广
* @param storeId ID
* @param voucherDate
* @param tenClockAfter 10
* @return
*/
private List<AdRoundStoreResDTO.ADRSRoundRecordDTO> getStoreBoughtRecordList(List<AdvertRound> allRoundList, List<AdvertRoundRecord> allRecordList,
Long storeId, Date voucherDate, boolean tenClockAfter) {
// 按照advertId进行分组取最小的roundId列表
Map<Long, Optional<Integer>> minRoundIdMap = allRoundList.stream().collect(Collectors.groupingBy(AdvertRound::getAdvertId,
Collectors.mapping(AdvertRound::getRoundId, Collectors.minBy(Comparator.comparing(Integer::intValue)))));
// 最小的roundId列表
List<Integer> roundIdList = minRoundIdMap.values().stream().filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
// 筛选档口 所有的 已购买 推广位数据
List<AdRoundStoreResDTO.ADRSRoundRecordDTO> 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(Objects.requireNonNull(AdBiddingStatus.of(biddingStatus)).getLabel())
.setAdvertRoundId(x.getId()).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<Integer, BigDecimal> 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<Long, BigDecimal> 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<Integer> boughtTimeRangeRoundIdList = boughtRoundList.stream().filter(x -> Objects.equals(x.getShowType(), AdShowType.TIME_RANGE.getValue()))
.map(AdRoundStoreResDTO.ADRSRoundRecordDTO::getRoundId).collect(Collectors.toList());
// 已购买的 位置枚举 的 advertRoundId 列表
final List<Long> boughtPositionAdvertRoundIdList = boughtRoundList.stream().filter(x -> Objects.equals(x.getShowType(), AdShowType.POSITION_ENUM.getValue()))
.map(AdRoundStoreResDTO.ADRSRoundRecordDTO::getAdvertRoundId).collect(Collectors.toList());
// 购买失败的 时间范围播放轮次的 列表
Map<Integer, AdvertRoundRecord> 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<Long, AdvertRoundRecord> 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(Objects.requireNonNull(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(Objects.requireNonNull(AdBiddingStatus.of(record.getBiddingStatus())).getLabel()
+ ",最新出价:" + positionEnumMaxPriceMap.get(record.getAdvertRoundId()))
);
});
}
return boughtRoundList;
}
}

View File

@ -112,10 +112,9 @@ public class StoreProductServiceImpl implements IStoreProductService {
StoreProductService storeProductSvc = this.storeProdSvcMapper.selectByStoreProdId(storeProdId);
// 档口生产工艺信息
StoreProductProcess prodProcess = this.storeProdProcMapper.selectByStoreProdId(storeProdId);
return storeProdResDTO.setFileList(fileResList).setAllColorList(allColorList)
return storeProdResDTO.setFileList(fileResList).setAllColorList(allColorList).setDetail(prodDetail.getDetail())
.setColorList(colorList).setPriceList(priceList).setSizeList(sizeList)
.setCateAttr(BeanUtil.toBean(cateAttr, StoreProdCateAttrDTO.class))
.setDetail(BeanUtil.toBean(prodDetail, StoreProdDetailDTO.class))
.setSvc(BeanUtil.toBean(storeProductSvc, StoreProdSvcDTO.class))
.setProcess(BeanUtil.toBean(prodProcess, StoreProdProcessDTO.class));
}
@ -613,7 +612,7 @@ public class StoreProductServiceImpl implements IStoreProductService {
.setStoreProdId(storeProd.getId())).collect(Collectors.toList());
this.storeProdColorPriceMapper.insert(priceList);
// 档口详情内容
StoreProductDetail storeProdDetail = BeanUtil.toBean(storeProdDTO.getDetail(), StoreProductDetail.class).setStoreProdId(storeProd.getId());
StoreProductDetail storeProdDetail = new StoreProductDetail().setDetail(storeProdDTO.getDetail()).setStoreProdId(storeProd.getId());
this.storeProdDetailMapper.insert(storeProdDetail);
// 档口服务承诺
if (ObjectUtils.isNotEmpty(storeProdDTO.getSvc())) {

View File

@ -60,16 +60,20 @@ public class UserFavoritesServiceImpl implements IUserFavoritesService {
public Integer create(UserFavoriteDTO favoriteDTO) {
// 获取当前登录用户
LoginUser loginUser = SecurityUtils.getLoginUser();
// 判断当前商品是否已加入进货车
UserFavorites exist = this.userFavMapper.selectOne(new LambdaQueryWrapper<UserFavorites>()
.eq(UserFavorites::getUserId, loginUser.getUserId()).eq(UserFavorites::getStoreProdId, favoriteDTO.getStoreProdId())
// 筛选已经加入收藏的商品
List<UserFavorites> existList = this.userFavMapper.selectList(new LambdaQueryWrapper<UserFavorites>()
.eq(UserFavorites::getUserId, loginUser.getUserId())
.in(UserFavorites::getStoreProdId, favoriteDTO.getBatchList().stream().map(UserFavoriteDTO.UFBatchVO::getStoreProdId).collect(Collectors.toList()))
.eq(UserFavorites::getDelFlag, Constants.UNDELETED));
if (ObjectUtils.isNotEmpty(exist)) {
throw new ServiceException("当前商品已加入收藏", HttpStatus.ERROR);
}
UserFavorites userFavorites = BeanUtil.toBean(favoriteDTO, UserFavorites.class);
userFavorites.setUserId(loginUser.getUserId());
return this.userFavMapper.insert(userFavorites);
// 已经加入购物车的商品
final List<Long> existStoreProdIdList = CollectionUtils.isNotEmpty(existList)
? existList.stream().map(UserFavorites::getStoreProdId).collect(Collectors.toList()) : new ArrayList<>();
// 购物车列表
List<UserFavorites> list = favoriteDTO.getBatchList().stream()
.filter(x -> CollectionUtils.isNotEmpty(existStoreProdIdList) ? !existStoreProdIdList.contains(x.getStoreProdId()) : Boolean.TRUE)
.map(x -> BeanUtil.toBean(x, UserFavorites.class).setUserId(loginUser.getUserId()))
.collect(Collectors.toList());
return this.userFavMapper.insert(list).size();
}
/**
@ -195,7 +199,8 @@ public class UserFavoritesServiceImpl implements IUserFavoritesService {
// 获取当前登录用户
LoginUser loginUser = SecurityUtils.getLoginUser();
List<UserFavorites> favoriteList = this.userFavMapper.selectList(new LambdaQueryWrapper<UserFavorites>()
.eq(UserFavorites::getUserId, loginUser.getUserId()).in(UserFavorites::getId, batchDTO.getUserFavoriteIdList())
.eq(UserFavorites::getUserId, loginUser.getUserId())
.in(UserFavorites::getStoreProdId, batchDTO.getStoreProdIdList())
.eq(UserFavorites::getDelFlag, Constants.UNDELETED));
if (CollectionUtils.isEmpty(favoriteList)) {
return 0;

View File

@ -74,7 +74,8 @@ public class UserSubscriptionsServiceImpl implements IUserSubscriptionsService {
// 获取当前登录用户
LoginUser loginUser = SecurityUtils.getLoginUser();
List<UserSubscriptions> list = Optional.ofNullable(this.userSubscMapper.selectList(new LambdaQueryWrapper<UserSubscriptions>()
.eq(UserSubscriptions::getUserId, loginUser.getUserId()).in(UserSubscriptions::getId, deleteDTO.getUserSubscIdList())
.eq(UserSubscriptions::getUserId, loginUser.getUserId())
.in(UserSubscriptions::getStoreId, deleteDTO.getStoreIdList())
.eq(UserSubscriptions::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("用户关注档口不存在!", HttpStatus.ERROR));
list.forEach(x -> x.setDelFlag(Constants.DELETED));