v1.0.27 #37
@@ -43,6 +43,8 @@ public enum GaoPermissionCode implements BuiltinPermissionCode {
|
||||
|
||||
EVENT_RECORD_READ("EVENT_RECORD:READ", "登记事件记录读取", false, false),
|
||||
|
||||
EVENT_RECORD_VERIFY("EVENT_RECORD:VERIFY", "登记事件核销", true, false),
|
||||
|
||||
EVENT_RECORD_EXPORT("EVENT_RECORD:EXPORT", "登记事件记录导出", true, false),
|
||||
|
||||
EVENT_RECORD_UPDATE("EVENT_RECORD:UPDATE", "登记事件记录修改", false, false),
|
||||
|
||||
@@ -111,10 +111,24 @@ public class GaoEventRecordController {
|
||||
record.getCustomer().setAttachmentList(attachmentService.listByBizId(Attachment.BizType.GAO_CUSTOMER, record.getCustomerId()));
|
||||
record.setEvent(eventService.get(record.getEventId()));
|
||||
record.setOperator(userService.get(record.getOperatorUserId()));
|
||||
if (record.getVerifierUserId() != null) {
|
||||
record.setVerifier(userService.get(record.getVerifierUserId()));
|
||||
}
|
||||
record.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.GAO_EVENT_RECORD, record.getId()));
|
||||
return record;
|
||||
}
|
||||
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@RequireGaoPermission(GaoPermissionCode.EVENT_RECORD_VERIFY)
|
||||
@PostMapping("/verify")
|
||||
public void verify(@RequestParam String id) {
|
||||
GaoEventRecord record = service.get(id);
|
||||
TimiException.required(record, "not found event record");
|
||||
storeScopeService.checkStoreId(record.getStoreId());
|
||||
service.verify(id);
|
||||
}
|
||||
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@RequireGaoPermission(GaoPermissionCode.EVENT_RECORD_CREATE)
|
||||
|
||||
@@ -117,6 +117,9 @@ public class GaoEvent extends UUIDEntity {
|
||||
/// true 为登记时要求拍照
|
||||
private Boolean requirePhoto;
|
||||
|
||||
/// true 为登记记录需要核销
|
||||
private Boolean requireVerification;
|
||||
|
||||
/// 登记限制类型
|
||||
private LimitType limitType;
|
||||
|
||||
|
||||
@@ -18,6 +18,23 @@ import java.util.List;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class GaoEventRecord extends UUIDEntity {
|
||||
|
||||
///
|
||||
/// 登记记录核销状态
|
||||
///
|
||||
/// @author Codex
|
||||
/// @since 2026-08-29
|
||||
public enum VerificationStatus {
|
||||
|
||||
/// 该事件不需要核销
|
||||
NOT_REQUIRED,
|
||||
|
||||
/// 等待核销
|
||||
PENDING,
|
||||
|
||||
/// 已核销
|
||||
VERIFIED
|
||||
}
|
||||
|
||||
///
|
||||
/// 登记事件记录附件类型
|
||||
///
|
||||
@@ -49,6 +66,15 @@ public class GaoEventRecord extends UUIDEntity {
|
||||
/// 本次登记提交的整数业务数值
|
||||
private Long numberValue;
|
||||
|
||||
/// 核销状态
|
||||
private VerificationStatus verificationStatus;
|
||||
|
||||
/// 核销用户 ID
|
||||
private String verifierUserId;
|
||||
|
||||
/// 核销时间
|
||||
private Long verifiedAt;
|
||||
|
||||
/// 备注
|
||||
private String remark;
|
||||
|
||||
@@ -70,6 +96,9 @@ public class GaoEventRecord extends UUIDEntity {
|
||||
@Transient
|
||||
private User operator;
|
||||
|
||||
@Transient
|
||||
private User verifier;
|
||||
|
||||
@Transient
|
||||
private List<Attachment> attachmentList;
|
||||
|
||||
|
||||
@@ -44,6 +44,14 @@ public interface GaoEventRecordMapper extends BaseMapper<GaoEventRecord, String>
|
||||
/// @param earnedPointValue 获得积分总和
|
||||
void updateEarnedPointValue(@Param("id") String id, @Param("earnedPointValue") Long earnedPointValue);
|
||||
|
||||
/// 原子更新登记记录核销状态
|
||||
///
|
||||
/// @param id 登记记录 ID
|
||||
/// @param verifierUserId 核销用户 ID
|
||||
/// @param verifiedAt 核销时间
|
||||
/// @return 更新行数
|
||||
int verify(@Param("id") String id, @Param("verifierUserId") String verifierUserId, @Param("verifiedAt") Long verifiedAt);
|
||||
|
||||
/// 按门店和登记日期统计登记记录数
|
||||
///
|
||||
/// @param storeId 门店 ID
|
||||
|
||||
@@ -24,6 +24,11 @@ public interface GaoEventRecordService extends BaseService<GaoEventRecord, Strin
|
||||
/// @return 登记事件记录列表
|
||||
List<GaoEventRecord> listByCustomerId(String customerId);
|
||||
|
||||
/// 核销登记事件记录
|
||||
///
|
||||
/// @param id 登记记录 ID
|
||||
void verify(String id);
|
||||
|
||||
default void createBatch(List<GaoEventRecord> recordList) {
|
||||
for (GaoEventRecord record : TimiJava.safeIterable(recordList)) {
|
||||
create(record);
|
||||
|
||||
+31
@@ -83,6 +83,34 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
||||
return mapper.selectAllByExample(example);
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void verify(String id) {
|
||||
TimiException.required(id, "not found record.id");
|
||||
Logger logger = new Logger(Logger.Module.GAO, "GAO_EVENT_RECORD_VERIFY");
|
||||
try {
|
||||
logger.setContent(id);
|
||||
GaoEventRecord record = get(id);
|
||||
TimiException.required(record, "not found event record");
|
||||
TimiException.requiredTrue(record.getVerificationStatus() == GaoEventRecord.VerificationStatus.PENDING, "登记记录无需核销或已核销");
|
||||
int updated = mapper.verify(id, userLoginService.getRequireLoginUserId(), Time.now());
|
||||
TimiException.requiredTrue(0 < updated, "登记记录无需核销或已核销");
|
||||
logger.setLevel(Logger.Level.INFO);
|
||||
logger.setResult(id);
|
||||
} catch (TimiException e) {
|
||||
logger.setLevel(Logger.Level.WARN);
|
||||
logger.setException(e.getMessage());
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
logger.setLevel(Logger.Level.ERROR);
|
||||
logger.setException(TimiJava.serializeThrowable(e));
|
||||
log.error("核销 GAO 登记记录失败", e);
|
||||
throw new TimiException(TimiCode.ERROR, "核销 GAO 登记记录失败", e);
|
||||
} finally {
|
||||
loggerService.create(logger);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void create(GaoEventRecord record) {
|
||||
@@ -130,6 +158,9 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
||||
dbRecord.setBusinessDayNo(businessDayNo);
|
||||
dbRecord.setPointValue(record.getPointValue());
|
||||
dbRecord.setNumberValue(record.getNumberValue());
|
||||
dbRecord.setVerificationStatus(Boolean.TRUE.equals(event.getRequireVerification())
|
||||
? GaoEventRecord.VerificationStatus.PENDING
|
||||
: GaoEventRecord.VerificationStatus.NOT_REQUIRED);
|
||||
dbRecord.setEarnedPointValue(0L);
|
||||
super.create(dbRecord);
|
||||
// 附件
|
||||
|
||||
+2
@@ -69,6 +69,7 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
||||
event.setValueType(TimiJava.defaultIfNull(event.getValueType(), GaoEvent.ValueType.NONE));
|
||||
event.setRequireValue(TimiJava.defaultIfNull(event.getRequireValue(), false));
|
||||
event.setRequirePhoto(TimiJava.defaultIfNull(event.getRequirePhoto(), false));
|
||||
event.setRequireVerification(TimiJava.defaultIfNull(event.getRequireVerification(), false));
|
||||
event.setLimitType(TimiJava.defaultIfNull(event.getLimitType(), GaoEvent.LimitType.NONE));
|
||||
event.setSort(TimiJava.defaultIfNull(event.getSort(), 0));
|
||||
verifyEvent(event);
|
||||
@@ -122,6 +123,7 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
||||
dbEvent.setRequireValue(dbEvent.getRequireValue());
|
||||
}
|
||||
dbEvent.setRequirePhoto(event.getRequirePhoto());
|
||||
dbEvent.setRequireVerification(TimiJava.defaultIfNull(event.getRequireVerification(), dbEvent.getRequireVerification()));
|
||||
dbEvent.setLimitType(event.getLimitType());
|
||||
dbEvent.setLimitValue(event.getLimitValue());
|
||||
dbEvent.setBeginAt(event.getBeginAt());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.imyeyu.api.modules.gao.vo;
|
||||
|
||||
import com.imyeyu.api.modules.gao.entity.GaoEventRecord;
|
||||
import com.imyeyu.java.bean.BasePage;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -24,6 +25,9 @@ public class GaoEventRecordPage extends BasePage {
|
||||
/// 登记事件 ID 列表,为空查询全部登记事件
|
||||
private List<String> eventIdList;
|
||||
|
||||
/// 核销状态,为空查询全部状态
|
||||
private GaoEventRecord.VerificationStatus verificationStatus;
|
||||
|
||||
/// 关键词,匹配客户、登记事件、备注、登记人
|
||||
private String keyword;
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
ALTER TABLE `gao_event`
|
||||
ADD COLUMN `require_verification` BIT(1) NOT NULL DEFAULT b'0' COMMENT 'true 为登记记录需要核销' AFTER `require_photo`;
|
||||
|
||||
ALTER TABLE `gao_event_record`
|
||||
ADD COLUMN `verification_status` VARCHAR(32) NOT NULL DEFAULT 'NOT_REQUIRED' COMMENT '核销状态,NOT_REQUIRED 无需核销,PENDING 待核销,VERIFIED 已核销' AFTER `number_value`,
|
||||
ADD COLUMN `verifier_user_id` VARCHAR(36) NULL COMMENT '核销用户 ID' AFTER `verification_status`,
|
||||
ADD COLUMN `verified_at` BIGINT NULL COMMENT '核销时间,毫秒' AFTER `verifier_user_id`,
|
||||
ADD KEY `idx_gao_event_record_store_verification` (`store_id`, `verification_status`, `deleted_at`, `registered_at`);
|
||||
@@ -59,6 +59,19 @@
|
||||
AND `deleted_at` IS NULL
|
||||
</update>
|
||||
|
||||
<update id="verify">
|
||||
UPDATE `gao_event_record`
|
||||
SET
|
||||
`verification_status` = 'VERIFIED',
|
||||
`verifier_user_id` = #{verifierUserId},
|
||||
`verified_at` = #{verifiedAt},
|
||||
`updated_at` = ROUND(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000)
|
||||
WHERE
|
||||
`id` = #{id}
|
||||
AND `verification_status` = 'PENDING'
|
||||
AND `deleted_at` IS NULL
|
||||
</update>
|
||||
|
||||
<select id="countByStoreIdAndRegisteredDateValue" resultType="java.lang.Long">
|
||||
SELECT
|
||||
COUNT(1)
|
||||
@@ -105,6 +118,9 @@
|
||||
#{eventId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="verificationStatus != null">
|
||||
AND r.`verification_status` = #{verificationStatus}
|
||||
</if>
|
||||
<if test="keyword != null and keyword.trim() != ''">
|
||||
AND (
|
||||
c.`code` LIKE CONCAT('%', #{keyword}, '%')
|
||||
|
||||
Reference in New Issue
Block a user