fix:修复 mall review @puhui999

This commit is contained in:
puhui999
2023-07-10 16:35:49 +08:00
parent 9cbd0fec1c
commit e7d8643665
38 changed files with 207 additions and 244 deletions

View File

@@ -19,11 +19,6 @@ import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/**
* 管理后台 - 秒杀时段相关接口
*
* @author HUIHUI
*/
@Tag(name = "管理后台 - 秒杀时段")
@RestController
@RequestMapping("/promotion/seckill-config")

View File

@@ -9,11 +9,6 @@ import lombok.ToString;
import java.time.LocalDateTime;
import java.util.List;
/**
* 管理后台 - 秒杀活动 Response VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀活动 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)

View File

@@ -1,9 +1,13 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
import java.time.LocalTime;
import java.util.List;
/**
* 秒杀时段 Base VO提供给添加、修改、详细的子 VO 使用
@@ -26,12 +30,24 @@ public class SeckillConfigBaseVO {
@NotNull(message = "结束时间点不能为空")
private String endTime;
@Schema(description = "秒杀", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")
@NotNull(message = "秒杀图不能为空")
private String picUrl;
@Schema(description = "秒杀轮播", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]")
@NotNull(message = "秒杀轮播图不能为空")
private List<String> sliderPicUrls;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "状态不能为空")
private Integer status;
@AssertTrue(message = "秒杀时段开始时间和结束时间不能相等")
@JsonIgnore
public boolean isValidStartTimeValid() {
return !LocalTime.parse(startTime).equals(LocalTime.parse(endTime));
}
@AssertTrue(message = "秒杀时段开始时间不能在结束时间之后")
@JsonIgnore
public boolean isValidEndTimeValid() {
return !LocalTime.parse(startTime).isAfter(LocalTime.parse(endTime));
}
}

View File

@@ -6,12 +6,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
// TODO @puhuiVO 上不写注释,已经有注解啦。
/**
* 管理后台 - 秒杀时段分页 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀时段分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)

View File

@@ -1,16 +1,9 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.*;
/**
* 管理后台 - 秒杀参与商品创建 Request VO
*
* @author HUIHUI
*/
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 秒杀参与商品创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)

View File

@@ -1,14 +1,12 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
/**
* 管理后台 - 秒杀参与商品 Response VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀参与商品 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)

View File

@@ -5,11 +5,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 管理后台 - 秒杀参与商品更新 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀参与商品更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)

View File

@@ -3,22 +3,27 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
import java.util.List;
/**
* 秒杀时段 DO
*
* @author 芋道源码
*/
@TableName("promotion_seckill_config")
@TableName(value = "promotion_seckill_config", autoResultMap = true)
@KeySequence("promotion_seckill_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SeckillConfigDO extends BaseDO {
/**
@@ -38,14 +43,14 @@ public class SeckillConfigDO extends BaseDO {
* 结束时间点
*/
private String endTime;
// TODO puhui999应该是轮播图 private List<String> sliderPicUrls;
/**
* 秒杀
* 秒杀轮播
*/
private String picUrl;
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> sliderPicUrls;
/**
* 状态
*
* <p>
* 枚举 {@link CommonStatusEnum 对应的类}
*/
private Integer status;

View File

@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.Seck
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> {
@@ -17,4 +19,9 @@ public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> {
.orderByDesc(SeckillConfigDO::getId));
}
default List<SeckillConfigDO> selectListByStatus(Integer status) {
return selectList(SeckillConfigDO::getStatus, status);
}
}

View File

@@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
@@ -12,14 +13,13 @@ import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillCo
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.time.LocalTime;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
@@ -37,9 +37,10 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
private SeckillConfigMapper seckillConfigMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) {
// 校验时间段是否冲突
validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime());
validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime(), null);
// 插入
SeckillConfigDO seckillConfig = SeckillConfigConvert.INSTANCE.convert(createReqVO);
@@ -49,18 +50,30 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) {
// 校验存在
validateSeckillConfigExists(updateReqVO.getId());
// 校验时间段是否冲突
validateSeckillConfigConflict(updateReqVO.getStartTime(), updateReqVO.getEndTime());
validateSeckillConfigConflict(updateReqVO.getStartTime(), updateReqVO.getEndTime(), updateReqVO.getId());
// 更新
SeckillConfigDO updateObj = SeckillConfigConvert.INSTANCE.convert(updateReqVO);
seckillConfigMapper.updateById(updateObj);
}
// TODO @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧; 更新状态不用那么多必须的参数,更新的时候需要校验时间段
@Override
public void updateSeckillConfigStatus(Long id, Integer status) {
// 校验秒杀时段是否存在
validateSeckillConfigExists(id);
// 更新状态
seckillConfigMapper.updateById(new SeckillConfigDO().setId(id).setStatus(status));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteSeckillConfig(Long id) {
// 校验存在
validateSeckillConfigExists(id);
@@ -81,39 +94,29 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
* @param startTime 开始时间
* @param endTime 结束时间
*/
private void validateSeckillConfigConflict(String startTime, String endTime) {
private void validateSeckillConfigConflict(String startTime, String endTime, Long seckillConfigId) {
LocalTime startTime1 = LocalTime.parse(startTime);
LocalTime endTime1 = LocalTime.parse(endTime);
// TODO @puhui999 这个可以用 validator 里的 assertTrue 去做哈;
// 检查选择的时间是否相等
if (startTime1.equals(endTime1)) {
throw exception(SECKILL_TIME_EQUAL);
}
// 检查开始时间是否在结束时间之前
if (startTime1.isAfter(endTime1)) {
throw exception(SECKILL_START_TIME_BEFORE_END_TIME);
}
// 查询出所有的时段配置
List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList();
// 更新时排除自己
if (seckillConfigId != null) {
configDOs.removeIf(item -> ObjectUtil.equal(item.getId(), seckillConfigId));
}
// 过滤出重叠的时段 ids
// TODO @puhui999感觉 findOne 就可以了?
Set<Long> ids = configDOs.stream().filter((config) -> {
boolean hasConflict = configDOs.stream().anyMatch(config -> {
LocalTime startTime2 = LocalTime.parse(config.getStartTime());
LocalTime endTime2 = LocalTime.parse(config.getEndTime());
// 判断时间是否重叠
// 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []
// todo @puhui999LocalDateUtils 可以写个工具类?是否是有重叠的时间?感觉别的场景,可能也会有需要
return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)
// 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 ()
|| startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)
// 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 ()
|| startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2);
}).map(SeckillConfigDO::getId).collect(Collectors.toSet());
if (CollUtil.isNotEmpty(ids)) {
return LocalDateTimeUtils.checkTimeOverlap(startTime1, endTime1, startTime2, endTime2);
});
if (hasConflict) {
throw exception(SECKILL_TIME_CONFLICTS);
}
}
@Override
public SeckillConfigDO getSeckillConfig(Long id) {
return seckillConfigMapper.selectById(id);
@@ -148,23 +151,9 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
return seckillConfigMapper.selectPage(pageVO);
}
// TODO @puhui999:写个查询状态的; 尽可能通用哈
@Override
public List<SeckillConfigDO> getListAllSimple() {
return seckillConfigMapper.selectList(SeckillConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
}
// TODO @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧;
@Override
public void updateSeckillConfigStatus(Long id, Integer status) {
// 校验秒杀时段是否存在
validateSeckillConfigExists(id);
SeckillConfigDO seckillConfigDO = new SeckillConfigDO();
seckillConfigDO.setId(id);
seckillConfigDO.setStatus(status);
// 更新状态
seckillConfigMapper.updateById(seckillConfigDO);
return seckillConfigMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
}
}