2026-06-24 f4bd1f3c89d906131495a0aca5aaf82966378510
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package cn.iocoder.yudao.module.promotion.service.seckill;
 
import cn.hutool.core.collection.CollUtil;
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.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;
import cn.iocoder.yudao.module.promotion.convert.seckill.SeckillConfigConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillConfigDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
 
import jakarta.annotation.Resource;
import java.time.LocalTime;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
 
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.isBetween;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
 
/**
 * 秒杀时段 Service 实现类
 *
 * @author halfninety
 */
@Service
@Validated
public class SeckillConfigServiceImpl implements SeckillConfigService {
 
    @Resource
    private SeckillConfigMapper seckillConfigMapper;
 
    @Override
    public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) {
        // 校验时间段是否冲突
        validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime(), null);
 
        // 插入
        SeckillConfigDO seckillConfig = SeckillConfigConvert.INSTANCE.convert(createReqVO);
        seckillConfigMapper.insert(seckillConfig);
        // 返回
        return seckillConfig.getId();
    }
 
    @Override
    public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) {
        // 校验存在
        validateSeckillConfigExists(updateReqVO.getId());
        // 校验时间段是否冲突
        validateSeckillConfigConflict(updateReqVO.getStartTime(), updateReqVO.getEndTime(), updateReqVO.getId());
 
        // 更新
        SeckillConfigDO updateObj = SeckillConfigConvert.INSTANCE.convert(updateReqVO);
        seckillConfigMapper.updateById(updateObj);
    }
 
    @Override
    public void updateSeckillConfigStatus(Long id, Integer status) {
        // 校验秒杀时段是否存在
        validateSeckillConfigExists(id);
 
        // 更新状态
        seckillConfigMapper.updateById(new SeckillConfigDO().setId(id).setStatus(status));
    }
 
    @Override
    public SeckillConfigDO getCurrentSeckillConfig() {
        List<SeckillConfigDO> list = seckillConfigMapper.selectList(SeckillConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
        return findFirst(list, config -> isBetween(config.getStartTime(), config.getEndTime()));
    }
 
    @Override
    public void deleteSeckillConfig(Long id) {
        // 校验存在
        validateSeckillConfigExists(id);
 
        // 删除
        seckillConfigMapper.deleteById(id);
    }
 
    private void validateSeckillConfigExists(Long id) {
        if (seckillConfigMapper.selectById(id) == null) {
            throw exception(SECKILL_CONFIG_NOT_EXISTS);
        }
    }
 
    /**
     * 校验时间是否存在冲突
     *
     * @param startTimeStr 开始时间
     * @param endTimeStr   结束时间
     */
    private void validateSeckillConfigConflict(String startTimeStr, String endTimeStr, Long id) {
        // 1. 查询出所有的时段配置
        LocalTime startTime = LocalTime.parse(startTimeStr);
        LocalTime endTime = LocalTime.parse(endTimeStr);
        List<SeckillConfigDO> configs = seckillConfigMapper.selectList();
        // 更新时排除自己
        if (id != null) {
            configs.removeIf(item -> ObjectUtil.equal(item.getId(), id));
        }
 
        // 2. 判断是否有重叠的时间
        boolean hasConflict = configs.stream().anyMatch(config -> LocalDateTimeUtils.isOverlap(startTime, endTime,
                LocalTime.parse(config.getStartTime()), LocalTime.parse(config.getEndTime())));
        if (hasConflict) {
            throw exception(SECKILL_CONFIG_TIME_CONFLICTS);
        }
    }
 
 
    @Override
    public SeckillConfigDO getSeckillConfig(Long id) {
        return seckillConfigMapper.selectById(id);
    }
 
    @Override
    public List<SeckillConfigDO> getSeckillConfigList() {
        return seckillConfigMapper.selectList();
    }
 
    @Override
    public void validateSeckillConfigExists(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        // 1. 如果有数量不匹配,说明有不存在的,则抛出 SECKILL_CONFIG_NOT_EXISTS 业务异常
        List<SeckillConfigDO> configs = seckillConfigMapper.selectByIds(ids);
        if (configs.size() != ids.size()) {
            throw exception(SECKILL_CONFIG_NOT_EXISTS);
        }
 
        // 2. 如果存在关闭,则抛出 SECKILL_CONFIG_DISABLE 业务异常
        configs.forEach(config -> {
            if (ObjectUtil.equal(config.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
                throw exception(SECKILL_CONFIG_DISABLE);
            }
        });
    }
 
    @Override
    public PageResult<SeckillConfigDO> getSeckillConfigPage(SeckillConfigPageReqVO pageVO) {
        return seckillConfigMapper.selectPage(pageVO);
    }
 
    @Override
    public List<SeckillConfigDO> getSeckillConfigListByStatus(Integer status) {
        List<SeckillConfigDO> list = seckillConfigMapper.selectListByStatus(status);
        list.sort(Comparator.comparing(SeckillConfigDO::getStartTime));
        return list;
    }
 
}