mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-08-16 03:01:53 +08:00
fix:修复 mall review @puhui999
This commit is contained in:
@@ -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")
|
||||
|
@@ -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)
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -6,12 +6,6 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
// TODO @puhui:VO 上不写注释,已经有注解啦。
|
||||
/**
|
||||
* 管理后台 - 秒杀时段分页 Request VO
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Schema(description = "管理后台 - 秒杀时段分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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 @puhui999:LocalDateUtils 可以写个工具类?是否是有重叠的时间?感觉别的场景,可能也会有需要
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user