v0.0.18 #13
@@ -173,7 +173,7 @@
|
||||
<dependency>
|
||||
<groupId>com.imyeyu.spring</groupId>
|
||||
<artifactId>timi-spring</artifactId>
|
||||
<version>0.0.17</version>
|
||||
<version>0.0.18</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.imyeyu.network</groupId>
|
||||
|
||||
@@ -23,6 +23,9 @@ public class GaoRegistrationEvent extends UUIDEntity {
|
||||
/// @since 2026-08-01
|
||||
public enum Status {
|
||||
|
||||
/// 草稿,未发布不可登记
|
||||
DRAFT,
|
||||
|
||||
/// 可登记
|
||||
ACTIVE,
|
||||
|
||||
@@ -55,8 +58,11 @@ public class GaoRegistrationEvent extends UUIDEntity {
|
||||
/// 每个自然月一次
|
||||
NATURAL_MONTH,
|
||||
|
||||
/// 累计限 N 次
|
||||
TOTAL_LIMIT
|
||||
/// 事件总登记次数上限
|
||||
TOTAL_LIMIT,
|
||||
|
||||
/// 单个客户总登记次数上限
|
||||
CUSTOMER_TOTAL_LIMIT
|
||||
}
|
||||
|
||||
/// 登记事件名称
|
||||
@@ -71,9 +77,6 @@ public class GaoRegistrationEvent extends UUIDEntity {
|
||||
/// 状态
|
||||
private Status status;
|
||||
|
||||
/// true 为启用
|
||||
private Boolean enabled;
|
||||
|
||||
/// true 为登记时要求拍照
|
||||
private Boolean requirePhoto;
|
||||
|
||||
@@ -83,6 +86,12 @@ public class GaoRegistrationEvent extends UUIDEntity {
|
||||
/// 登记限制数值,按限制类型表示小时数或次数
|
||||
private Integer limitValue;
|
||||
|
||||
/// 可登记起始时间戳,毫秒,空为不限制
|
||||
private Long beginAt;
|
||||
|
||||
/// 可登记终止时间戳,毫秒,空为不限制
|
||||
private Long endAt;
|
||||
|
||||
/// 排序值
|
||||
private Integer sort;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.imyeyu.api.modules.gao.mapper;
|
||||
import com.imyeyu.api.modules.gao.entity.GaoRegistrationEvent;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -16,6 +15,5 @@ public interface GaoRegistrationEventMapper extends BaseMapper<GaoRegistrationEv
|
||||
|
||||
List<GaoRegistrationEvent> selectByIdList(@Param("idList") List<String> idList);
|
||||
|
||||
@Select("SELECT * FROM `gao_registration_event` WHERE `enabled` = TRUE AND (`status` IS NULL OR `status` = 'ACTIVE') AND `deleted_at` IS NULL ORDER BY `sort` ASC, `created_at` ASC")
|
||||
List<GaoRegistrationEvent> selectEnabledList();
|
||||
List<GaoRegistrationEvent> selectEnabledList(@Param("now") Long now);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,12 @@ public interface GaoRegistrationEventRecordMapper extends BaseMapper<GaoRegistra
|
||||
/// @return 登记数
|
||||
Long countByCustomerIdAndRegistrationEventId(@Param("customerId") String customerId, @Param("registrationEventId") String registrationEventId);
|
||||
|
||||
/// 统计登记事件总登记数
|
||||
///
|
||||
/// @param registrationEventId 登记事件 ID
|
||||
/// @return 登记数
|
||||
Long countByRegistrationEventId(@Param("registrationEventId") String registrationEventId);
|
||||
|
||||
/// 按周期统计登记事件记录
|
||||
///
|
||||
/// @param registrationEventId 登记事件 ID
|
||||
|
||||
+14
-6
@@ -313,21 +313,22 @@ public class GaoRegistrationEventRecordServiceImplement extends AbstractEntitySe
|
||||
|
||||
private void checkRegistrationEventPermission(GaoRegistrationEvent registrationEvent) {
|
||||
List<String> roleCodeList = registrationEventService.listRoleCode(registrationEvent.getId());
|
||||
if (roleCodeList != null && !roleCodeList.isEmpty()) {
|
||||
TimiException.requiredTrue(roleCodeList != null && !roleCodeList.isEmpty(), "登记事件未配置可登记角色");
|
||||
roleChecker.checkAny(ModuleCode.GAO, roleCodeList.toArray(String[]::new));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRegistrationEventCreatable(GaoRegistrationEvent registrationEvent, String customerId, long registeredAt) {
|
||||
TimiException.requiredTrue(Boolean.TRUE.equals(registrationEvent.getEnabled()), "登记事件未启用");
|
||||
TimiException.requiredTrue(registrationEvent.getStatus() == null || registrationEvent.getStatus() == GaoRegistrationEvent.Status.ACTIVE, "登记事件不可登记");
|
||||
TimiException.requiredTrue(registrationEvent.getBeginAt() == null || registrationEvent.getBeginAt() <= registeredAt, "登记事件未到可登记时间");
|
||||
TimiException.requiredTrue(registrationEvent.getEndAt() == null || registeredAt <= registrationEvent.getEndAt(), "登记事件已过可登记时间");
|
||||
GaoRegistrationEvent.LimitType limitType = TimiJava.defaultIfNull(registrationEvent.getLimitType(), GaoRegistrationEvent.LimitType.NONE);
|
||||
switch (limitType) {
|
||||
case DAILY_HALF_DAY -> checkRegistrationLimitRange(customerId, registrationEvent.getId(), getHalfDayBegin(registeredAt), getHalfDayEnd(registeredAt), "该客户当前半日已登记该事件");
|
||||
case NATURAL_DAY -> checkRegistrationLimitRange(customerId, registrationEvent.getId(), getDayBegin(registeredAt), getDayEnd(registeredAt), "该客户当日已登记该事件");
|
||||
case INTERVAL_HOUR -> checkIntervalHourRegistrationLimit(registrationEvent, customerId, registeredAt);
|
||||
case NATURAL_MONTH -> checkRegistrationLimitRange(customerId, registrationEvent.getId(), getMonthBegin(registeredAt), getMonthEnd(registeredAt), "该客户当月已登记该事件");
|
||||
case TOTAL_LIMIT -> checkTotalRegistrationLimit(registrationEvent, customerId);
|
||||
case TOTAL_LIMIT -> checkTotalRegistrationLimit(registrationEvent);
|
||||
case CUSTOMER_TOTAL_LIMIT -> checkCustomerTotalRegistrationLimit(registrationEvent, customerId);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
@@ -345,13 +346,20 @@ public class GaoRegistrationEventRecordServiceImplement extends AbstractEntitySe
|
||||
checkRegistrationLimitRange(customerId, registrationEvent.getId(), beginRegisteredAt, registeredAt, "该客户登记该事件间隔不足");
|
||||
}
|
||||
|
||||
private void checkTotalRegistrationLimit(GaoRegistrationEvent registrationEvent, String customerId) {
|
||||
private void checkCustomerTotalRegistrationLimit(GaoRegistrationEvent registrationEvent, String customerId) {
|
||||
Integer limitValue = registrationEvent.getLimitValue();
|
||||
TimiException.requiredTrue(limitValue != null && 0 < limitValue, "登记事件累计次数配置错误");
|
||||
TimiException.requiredTrue(limitValue != null && 0 < limitValue, "登记事件单客户总次数配置错误");
|
||||
Long count = mapper.countByCustomerIdAndRegistrationEventId(customerId, registrationEvent.getId());
|
||||
TimiException.requiredTrue(TimiJava.defaultIfNull(count, 0L) < limitValue, "该客户登记该事件次数已达上限");
|
||||
}
|
||||
|
||||
private void checkTotalRegistrationLimit(GaoRegistrationEvent registrationEvent) {
|
||||
Integer limitValue = registrationEvent.getLimitValue();
|
||||
TimiException.requiredTrue(limitValue != null && 0 < limitValue, "登记事件总次数配置错误");
|
||||
Long count = mapper.countByRegistrationEventId(registrationEvent.getId());
|
||||
TimiException.requiredTrue(TimiJava.defaultIfNull(count, 0L) < limitValue, "登记事件总次数已达上限");
|
||||
}
|
||||
|
||||
private long getDayBegin(long registeredAt) {
|
||||
ZoneId zoneId = ZoneId.systemDefault();
|
||||
return Instant.ofEpochMilli(registeredAt).atZone(zoneId).toLocalDate().atStartOfDay(zoneId).toInstant().toEpochMilli();
|
||||
|
||||
+35
-7
@@ -6,11 +6,13 @@ import com.imyeyu.api.modules.gao.entity.GaoRegistrationEvent;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoRegistrationEventRoleRelationMapper;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoRegistrationEventMapper;
|
||||
import com.imyeyu.api.modules.gao.service.GaoRegistrationEventService;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import com.imyeyu.spring.service.AbstractEntityService;
|
||||
import com.imyeyu.utils.Time;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -61,7 +63,18 @@ public class GaoRegistrationEventServiceImplement extends AbstractEntityService<
|
||||
@Override
|
||||
public void update(GaoRegistrationEvent entity) {
|
||||
checkEntity(entity, true);
|
||||
super.update(entity);
|
||||
GaoRegistrationEvent current = get(entity.getId());
|
||||
current.setName(entity.getName());
|
||||
current.setDescription(entity.getDescription());
|
||||
current.setColor(entity.getColor());
|
||||
current.setStatus(entity.getStatus());
|
||||
current.setRequirePhoto(entity.getRequirePhoto());
|
||||
current.setLimitType(entity.getLimitType());
|
||||
current.setLimitValue(entity.getLimitValue());
|
||||
current.setBeginAt(entity.getBeginAt());
|
||||
current.setEndAt(entity.getEndAt());
|
||||
current.setSort(entity.getSort());
|
||||
mapper.update(current);
|
||||
saveRoleRelation(entity.getId(), entity.getRoleCodeList());
|
||||
}
|
||||
|
||||
@@ -70,7 +83,6 @@ public class GaoRegistrationEventServiceImplement extends AbstractEntityService<
|
||||
public void delete(String id) {
|
||||
GaoRegistrationEvent entity = get(id);
|
||||
entity.setStatus(GaoRegistrationEvent.Status.DELETED);
|
||||
entity.setEnabled(false);
|
||||
super.update(entity);
|
||||
}
|
||||
|
||||
@@ -83,8 +95,11 @@ public class GaoRegistrationEventServiceImplement extends AbstractEntityService<
|
||||
|
||||
@Override
|
||||
public List<GaoRegistrationEvent> listEnabled() {
|
||||
List<GaoRegistrationEvent> list = mapper.selectEnabledList();
|
||||
List<GaoRegistrationEvent> list = mapper.selectEnabledList(Time.now());
|
||||
loadRegistrationEventLimit(list);
|
||||
list = list.stream()
|
||||
.filter(item -> !TimiJava.isEmpty(item.getRoleCodeList()))
|
||||
.toList();
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -102,16 +117,18 @@ public class GaoRegistrationEventServiceImplement extends AbstractEntityService<
|
||||
if (entity.getStatus() == null) {
|
||||
entity.setStatus(GaoRegistrationEvent.Status.ACTIVE);
|
||||
}
|
||||
if (entity.getEnabled() == null) {
|
||||
entity.setEnabled(true);
|
||||
}
|
||||
if (entity.getRequirePhoto() == null) {
|
||||
entity.setRequirePhoto(false);
|
||||
}
|
||||
if (entity.getLimitType() == null) {
|
||||
entity.setLimitType(GaoRegistrationEvent.LimitType.NONE);
|
||||
}
|
||||
TimiException.requiredTrue(
|
||||
entity.getRoleCodeList() != null && entity.getRoleCodeList().stream().anyMatch(item -> item != null && !item.isBlank()),
|
||||
"not found registrationEvent.roleCodeList"
|
||||
);
|
||||
checkRegistrationLimit(entity);
|
||||
checkRegisterablePeriod(entity);
|
||||
if (entity.getColor() != null) {
|
||||
entity.setColor(entity.getColor().trim());
|
||||
}
|
||||
@@ -122,7 +139,8 @@ public class GaoRegistrationEventServiceImplement extends AbstractEntityService<
|
||||
|
||||
private void checkRegistrationLimit(GaoRegistrationEvent entity) {
|
||||
if (entity.getLimitType() == GaoRegistrationEvent.LimitType.INTERVAL_HOUR
|
||||
|| entity.getLimitType() == GaoRegistrationEvent.LimitType.TOTAL_LIMIT) {
|
||||
|| entity.getLimitType() == GaoRegistrationEvent.LimitType.TOTAL_LIMIT
|
||||
|| entity.getLimitType() == GaoRegistrationEvent.LimitType.CUSTOMER_TOTAL_LIMIT) {
|
||||
TimiException.required(entity.getLimitValue(), "not found registrationEvent.limitValue");
|
||||
TimiException.requiredTrue(0 < entity.getLimitValue(), "registrationEvent.limitValue lte 0");
|
||||
return;
|
||||
@@ -130,6 +148,16 @@ public class GaoRegistrationEventServiceImplement extends AbstractEntityService<
|
||||
entity.setLimitValue(null);
|
||||
}
|
||||
|
||||
private void checkRegisterablePeriod(GaoRegistrationEvent entity) {
|
||||
if (entity.getBeginAt() == null && entity.getEndAt() == null) {
|
||||
return;
|
||||
}
|
||||
TimiException.requiredTrue(
|
||||
entity.getBeginAt() == null || entity.getEndAt() == null || entity.getBeginAt() <= entity.getEndAt(),
|
||||
"registrationEvent.beginAt gt registrationEvent.endAt"
|
||||
);
|
||||
}
|
||||
|
||||
private void saveRoleRelation(String registrationEventId, List<String> roleCodeList) {
|
||||
roleRelationMapper.deleteByRegistrationEventId(registrationEventId);
|
||||
if (roleCodeList == null || roleCodeList.isEmpty()) {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE `gao_registration_event`
|
||||
DROP KEY `idx_gao_registration_event_status`,
|
||||
DROP COLUMN `enabled`,
|
||||
MODIFY COLUMN `status` VARCHAR(32) NOT NULL DEFAULT 'ACTIVE' COMMENT '状态,DRAFT 草稿,ACTIVE 可登记,INACTIVE 不可登记,DELETED 已删除',
|
||||
ADD COLUMN `begin_at` BIGINT NULL COMMENT '可登记起始时间戳,毫秒,空为不限制' AFTER `limit_value`,
|
||||
ADD COLUMN `end_at` BIGINT NULL COMMENT '可登记终止时间戳,毫秒,空为不限制' AFTER `begin_at`,
|
||||
ADD KEY `idx_gao_registration_event_status` (`status`, `deleted_at`, `sort`, `created_at`);
|
||||
@@ -18,4 +18,16 @@
|
||||
</if>
|
||||
AND `deleted_at` IS NULL
|
||||
</select>
|
||||
|
||||
<select id="selectEnabledList" resultType="com.imyeyu.api.modules.gao.entity.GaoRegistrationEvent">
|
||||
SELECT
|
||||
*
|
||||
FROM `gao_registration_event`
|
||||
WHERE
|
||||
(`status` IS NULL OR `status` = 'ACTIVE')
|
||||
AND (`begin_at` IS NULL OR `begin_at` <= #{now})
|
||||
AND (`end_at` IS NULL OR #{now} <= `end_at`)
|
||||
AND `deleted_at` IS NULL
|
||||
ORDER BY `sort` ASC, `created_at` ASC
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
@@ -42,6 +42,15 @@
|
||||
AND `deleted_at` IS NULL
|
||||
</select>
|
||||
|
||||
<select id="countByRegistrationEventId" resultType="java.lang.Long">
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM `gao_registration_event_record`
|
||||
WHERE
|
||||
`registration_event_id` = #{registrationEventId}
|
||||
AND `deleted_at` IS NULL
|
||||
</select>
|
||||
|
||||
<select id="statByRegistrationEventAndPeriodType" resultType="com.imyeyu.api.modules.gao.vo.GaoRegistrationEventPeriodStatView">
|
||||
SELECT
|
||||
`registration_event_id` AS `registrationEventId`,
|
||||
|
||||
Reference in New Issue
Block a user