diff --git a/src/main/java/com/ycwl/basic/controller/mobile/notify/UserNotificationAuthController.java b/src/main/java/com/ycwl/basic/controller/mobile/notify/UserNotificationAuthController.java new file mode 100644 index 00000000..da76cf47 --- /dev/null +++ b/src/main/java/com/ycwl/basic/controller/mobile/notify/UserNotificationAuthController.java @@ -0,0 +1,237 @@ +package com.ycwl.basic.controller.mobile.notify; + +import com.ycwl.basic.config.JwtInfo; +import com.ycwl.basic.model.mobile.notify.req.NotificationAuthCheckReq; +import com.ycwl.basic.model.mobile.notify.req.NotificationAuthConsumeReq; +import com.ycwl.basic.model.mobile.notify.req.NotificationAuthRecordReq; +import com.ycwl.basic.model.mobile.notify.req.NotificationAuthRecordsReq; +import com.ycwl.basic.model.mobile.notify.resp.NotificationAuthCheckResp; +import com.ycwl.basic.model.mobile.notify.resp.NotificationAuthConsumeResp; +import com.ycwl.basic.model.mobile.notify.resp.NotificationAuthRecordResp; +import com.ycwl.basic.model.pc.notify.entity.UserNotificationAuthorizationEntity; +import com.ycwl.basic.service.UserNotificationAuthorizationService; +import com.ycwl.basic.utils.ResponseData; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 用户通知授权记录Controller (移动端API) + * + * @Author: System + * @Date: 2024/12/28 + */ +@RestController +@RequestMapping("/api/mobile/notify/auth") +@Slf4j +public class UserNotificationAuthController { + + @Autowired + private UserNotificationAuthorizationService userNotificationAuthorizationService; + + /** + * 检查用户通知授权状态 + */ + @PostMapping("/check") + public ResponseData checkAuthorization( + @JwtInfo Long memberId, + @Valid @RequestBody NotificationAuthCheckReq req) { + log.info("检查用户通知授权状态: memberId={}, templateId={}, scenicId={}", + memberId, req.getTemplateId(), req.getScenicId()); + + try { + UserNotificationAuthorizationEntity record = userNotificationAuthorizationService + .checkAuthorization(memberId, req.getTemplateId(), req.getScenicId()); + + NotificationAuthCheckResp resp = new NotificationAuthCheckResp(); + if (record != null) { + resp.setHasAuthorization(true); + resp.setRemainingCount(record.getRemainingCount()); + resp.setAuthorizationCount(record.getAuthorizationCount()); + resp.setConsumedCount(record.getConsumedCount()); + resp.setLastAuthorizedTime(record.getLastAuthorizedTime()); + resp.setLastConsumedTime(record.getLastConsumedTime()); + resp.setTemplateId(record.getTemplateId()); + resp.setScenicId(record.getScenicId()); + } else { + resp.setHasAuthorization(false); + resp.setRemainingCount(0); + resp.setAuthorizationCount(0); + resp.setConsumedCount(0); + resp.setTemplateId(req.getTemplateId()); + resp.setScenicId(req.getScenicId()); + } + + return ResponseData.success(resp); + } catch (Exception e) { + log.error("检查用户通知授权状态失败", e); + return ResponseData.fail("检查授权状态失败: " + e.getMessage()); + } + } + + /** + * 记录用户通知授权 + */ + @PostMapping("/record") + public ResponseData recordAuthorization( + @JwtInfo Long memberId, + @Valid @RequestBody NotificationAuthRecordReq req) { + log.info("记录用户通知授权: memberId={}, templateId={}, scenicId={}", + memberId, req.getTemplateId(), req.getScenicId()); + + try { + UserNotificationAuthorizationEntity record = userNotificationAuthorizationService + .recordAuthorization(memberId, req.getTemplateId(), req.getScenicId()); + + NotificationAuthRecordResp resp = new NotificationAuthRecordResp(); + BeanUtils.copyProperties(record, resp); + + return ResponseData.success(resp); + } catch (Exception e) { + log.error("记录用户通知授权失败", e); + return ResponseData.fail("记录授权失败: " + e.getMessage()); + } + } + + /** + * 消费通知授权 + */ + @PostMapping("/consume") + public ResponseData consumeAuthorization( + @JwtInfo Long memberId, + @Valid @RequestBody NotificationAuthConsumeReq req) { + log.info("消费通知授权: memberId={}, templateId={}, scenicId={}", + memberId, req.getTemplateId(), req.getScenicId()); + + try { + boolean consumeSuccess = userNotificationAuthorizationService + .consumeAuthorization(memberId, req.getTemplateId(), req.getScenicId()); + + NotificationAuthConsumeResp resp = new NotificationAuthConsumeResp(); + resp.setConsumeSuccess(consumeSuccess); + + if (consumeSuccess) { + Integer remainingCount = userNotificationAuthorizationService + .getRemainingCount(memberId, req.getTemplateId(), req.getScenicId()); + resp.setRemainingCount(remainingCount); + } else { + resp.setFailReason("授权次数不足或授权记录不存在"); + resp.setRemainingCount(0); + } + + return ResponseData.success(resp); + } catch (Exception e) { + log.error("消费通知授权失败", e); + return ResponseData.fail("消费授权失败: " + e.getMessage()); + } + } + + /** + * 查询用户通知授权记录 + */ + @GetMapping("/records") + public ResponseData> getUserAuthorizationRecords( + @JwtInfo Long memberId, + @Valid NotificationAuthRecordsReq req) { + log.info("查询用户通知授权记录: memberId={}, templateId={}", memberId, req.getTemplateId()); + + try { + List records; + if (req.getTemplateId() != null && !req.getTemplateId().trim().isEmpty()) { + records = userNotificationAuthorizationService + .getUserAuthorizationsByTemplate(memberId, req.getTemplateId()); + } else { + records = userNotificationAuthorizationService.getUserAuthorizations(memberId); + } + + List respList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(records)) { + for (UserNotificationAuthorizationEntity record : records) { + NotificationAuthRecordResp resp = new NotificationAuthRecordResp(); + BeanUtils.copyProperties(record, resp); + // TODO: 可以在这里添加景区名称查询 + respList.add(resp); + } + } + + return ResponseData.success(respList); + } catch (Exception e) { + log.error("查询用户通知授权记录失败", e); + return ResponseData.fail("查询授权记录失败: " + e.getMessage()); + } + } + + /** + * 获取用户授权统计信息 + */ + @GetMapping("/stats") + public ResponseData getAuthorizationStats(@JwtInfo Long memberId) { + log.info("获取用户授权统计信息: memberId={}", memberId); + + try { + List records = userNotificationAuthorizationService + .getUserAuthorizations(memberId); + + int totalTemplates = records.size(); + int totalAuthorizations = records.stream() + .mapToInt(UserNotificationAuthorizationEntity::getAuthorizationCount) + .sum(); + int totalConsumed = records.stream() + .mapToInt(UserNotificationAuthorizationEntity::getConsumedCount) + .sum(); + int totalRemaining = totalAuthorizations - totalConsumed; + + // 创建统计信息对象 + AuthorizationStats stats = new AuthorizationStats(); + stats.totalTemplates = totalTemplates; + stats.totalAuthorizations = totalAuthorizations; + stats.totalConsumed = totalConsumed; + stats.totalRemaining = totalRemaining; + stats.queryTime = new Date(); + + return ResponseData.success(stats); + } catch (Exception e) { + log.error("获取用户授权统计信息失败", e); + return ResponseData.fail("获取统计信息失败: " + e.getMessage()); + } + } + + /** + * 授权统计信息DTO + */ + @Data + public static class AuthorizationStats { + /** + * 总模板数 + */ + private int totalTemplates; + + /** + * 总授权次数 + */ + private int totalAuthorizations; + + /** + * 总消费次数 + */ + private int totalConsumed; + + /** + * 剩余授权次数 + */ + private int totalRemaining; + + /** + * 查询时间 + */ + private Date queryTime; + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/mapper/UserNotificationAuthorizationMapper.java b/src/main/java/com/ycwl/basic/mapper/UserNotificationAuthorizationMapper.java new file mode 100644 index 00000000..728b0205 --- /dev/null +++ b/src/main/java/com/ycwl/basic/mapper/UserNotificationAuthorizationMapper.java @@ -0,0 +1,92 @@ +package com.ycwl.basic.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ycwl.basic.model.pc.notify.entity.UserNotificationAuthorizationEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 用户通知授权记录Mapper接口 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Mapper +public interface UserNotificationAuthorizationMapper extends BaseMapper { + + /** + * 根据用户ID、模板ID和景区ID查询授权记录 + * + * @param memberId 用户ID + * @param templateId 模板ID + * @param scenicId 景区ID + * @return 授权记录 + */ + UserNotificationAuthorizationEntity selectByMemberAndTemplateAndScenic( + @Param("memberId") Long memberId, + @Param("templateId") String templateId, + @Param("scenicId") Long scenicId + ); + + /** + * 根据用户ID查询授权记录列表 + * + * @param memberId 用户ID + * @return 授权记录列表 + */ + List selectByMemberId(@Param("memberId") Long memberId); + + /** + * 根据用户ID和模板ID查询授权记录列表 + * + * @param memberId 用户ID + * @param templateId 模板ID + * @return 授权记录列表 + */ + List selectByMemberIdAndTemplateId( + @Param("memberId") Long memberId, + @Param("templateId") String templateId + ); + + /** + * 根据景区ID查询授权记录列表 + * + * @param scenicId 景区ID + * @return 授权记录列表 + */ + List selectByScenicId(@Param("scenicId") Long scenicId); + + /** + * 增加授权次数 + * + * @param id 记录ID + * @param count 增加的数量 + * @return 影响行数 + */ + int increaseAuthorizationCount(@Param("id") Long id, @Param("count") Integer count); + + /** + * 增加消费次数 + * + * @param id 记录ID + * @param count 增加的数量 + * @return 影响行数 + */ + int increaseConsumedCount(@Param("id") Long id, @Param("count") Integer count); + + /** + * 检查用户是否还有剩余授权次数 + * + * @param memberId 用户ID + * @param templateId 模板ID + * @param scenicId 景区ID + * @return 剩余授权次数 + */ + Integer selectRemainingCount( + @Param("memberId") Long memberId, + @Param("templateId") String templateId, + @Param("scenicId") Long scenicId + ); +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthCheckReq.java b/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthCheckReq.java new file mode 100644 index 00000000..ad17a502 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthCheckReq.java @@ -0,0 +1,28 @@ +package com.ycwl.basic.model.mobile.notify.req; + +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +/** + * 通知授权检查请求 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Data +public class NotificationAuthCheckReq { + + /** + * 通知模板ID + */ + @NotBlank(message = "模板ID不能为空") + private String templateId; + + /** + * 景区ID + */ + @NotNull(message = "景区ID不能为空") + private Long scenicId; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthConsumeReq.java b/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthConsumeReq.java new file mode 100644 index 00000000..3bfe3f16 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthConsumeReq.java @@ -0,0 +1,28 @@ +package com.ycwl.basic.model.mobile.notify.req; + +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +/** + * 通知授权消费请求 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Data +public class NotificationAuthConsumeReq { + + /** + * 通知模板ID + */ + @NotBlank(message = "模板ID不能为空") + private String templateId; + + /** + * 景区ID + */ + @NotNull(message = "景区ID不能为空") + private Long scenicId; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthRecordReq.java b/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthRecordReq.java new file mode 100644 index 00000000..2b3c1068 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthRecordReq.java @@ -0,0 +1,28 @@ +package com.ycwl.basic.model.mobile.notify.req; + +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +/** + * 通知授权记录请求 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Data +public class NotificationAuthRecordReq { + + /** + * 通知模板ID + */ + @NotBlank(message = "模板ID不能为空") + private String templateId; + + /** + * 景区ID + */ + @NotNull(message = "景区ID不能为空") + private Long scenicId; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthRecordsReq.java b/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthRecordsReq.java new file mode 100644 index 00000000..3dcfd062 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/mobile/notify/req/NotificationAuthRecordsReq.java @@ -0,0 +1,28 @@ +package com.ycwl.basic.model.mobile.notify.req; + +import lombok.Data; + +/** + * 通知授权记录查询请求 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Data +public class NotificationAuthRecordsReq { + + /** + * 模板ID(可选) + */ + private String templateId; + + /** + * 页码 + */ + private Integer page = 1; + + /** + * 每页大小 + */ + private Integer size = 10; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/mobile/notify/resp/NotificationAuthCheckResp.java b/src/main/java/com/ycwl/basic/model/mobile/notify/resp/NotificationAuthCheckResp.java new file mode 100644 index 00000000..ef4929f9 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/mobile/notify/resp/NotificationAuthCheckResp.java @@ -0,0 +1,55 @@ +package com.ycwl.basic.model.mobile.notify.resp; + +import lombok.Data; + +import java.util.Date; + +/** + * 通知授权检查响应 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Data +public class NotificationAuthCheckResp { + + /** + * 是否有授权 + */ + private Boolean hasAuthorization; + + /** + * 剩余授权次数 + */ + private Integer remainingCount; + + /** + * 总授权次数 + */ + private Integer authorizationCount; + + /** + * 已消费次数 + */ + private Integer consumedCount; + + /** + * 最后授权时间 + */ + private Date lastAuthorizedTime; + + /** + * 最后消费时间 + */ + private Date lastConsumedTime; + + /** + * 模板ID + */ + private String templateId; + + /** + * 景区ID + */ + private Long scenicId; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/mobile/notify/resp/NotificationAuthConsumeResp.java b/src/main/java/com/ycwl/basic/model/mobile/notify/resp/NotificationAuthConsumeResp.java new file mode 100644 index 00000000..be253fbb --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/mobile/notify/resp/NotificationAuthConsumeResp.java @@ -0,0 +1,28 @@ +package com.ycwl.basic.model.mobile.notify.resp; + +import lombok.Data; + +/** + * 通知授权消费响应 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Data +public class NotificationAuthConsumeResp { + + /** + * 是否消费成功 + */ + private Boolean consumeSuccess; + + /** + * 剩余授权次数 + */ + private Integer remainingCount; + + /** + * 消费失败原因 + */ + private String failReason; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/mobile/notify/resp/NotificationAuthRecordResp.java b/src/main/java/com/ycwl/basic/model/mobile/notify/resp/NotificationAuthRecordResp.java new file mode 100644 index 00000000..89db3a42 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/mobile/notify/resp/NotificationAuthRecordResp.java @@ -0,0 +1,70 @@ +package com.ycwl.basic.model.mobile.notify.resp; + +import lombok.Data; + +import java.util.Date; + +/** + * 通知授权记录响应 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Data +public class NotificationAuthRecordResp { + + /** + * 记录ID + */ + private Long id; + + /** + * 模板ID + */ + private String templateId; + + /** + * 景区ID + */ + private Long scenicId; + + /** + * 景区名称 + */ + private String scenicName; + + /** + * 授权次数 + */ + private Integer authorizationCount; + + /** + * 已消费次数 + */ + private Integer consumedCount; + + /** + * 剩余授权次数 + */ + private Integer remainingCount; + + /** + * 最后授权时间 + */ + private Date lastAuthorizedTime; + + /** + * 最后消费时间 + */ + private Date lastConsumedTime; + + /** + * 状态 + */ + private Integer status; + + /** + * 创建时间 + */ + private Date createTime; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/pc/notify/entity/UserNotificationAuthorizationEntity.java b/src/main/java/com/ycwl/basic/model/pc/notify/entity/UserNotificationAuthorizationEntity.java new file mode 100644 index 00000000..b1379f08 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/pc/notify/entity/UserNotificationAuthorizationEntity.java @@ -0,0 +1,79 @@ +package com.ycwl.basic.model.pc.notify.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +/** + * 用户通知授权记录实体类 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Data +@TableName("user_notification_authorization") +public class UserNotificationAuthorizationEntity { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 用户ID + */ + private Long memberId; + + /** + * 通知模板ID(微信消息模板ID) + */ + private String templateId; + + /** + * 景区ID + */ + private Long scenicId; + + /** + * 授权次数 + */ + private Integer authorizationCount; + + /** + * 已消费次数 + */ + private Integer consumedCount; + + /** + * 剩余授权次数(计算字段) + */ + private Integer remainingCount; + + /** + * 最后授权时间 + */ + private Date lastAuthorizedTime; + + /** + * 最后消费时间 + */ + private Date lastConsumedTime; + + /** + * 状态:1-有效,0-无效 + */ + private Integer status; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/service/UserNotificationAuthorizationService.java b/src/main/java/com/ycwl/basic/service/UserNotificationAuthorizationService.java new file mode 100644 index 00000000..6260d754 --- /dev/null +++ b/src/main/java/com/ycwl/basic/service/UserNotificationAuthorizationService.java @@ -0,0 +1,87 @@ +package com.ycwl.basic.service; + +import com.ycwl.basic.model.pc.notify.entity.UserNotificationAuthorizationEntity; + +import java.util.List; + +/** + * 用户通知授权记录Service接口 + * + * @Author: System + * @Date: 2024/12/28 + */ +public interface UserNotificationAuthorizationService { + + /** + * 检查用户是否对指定模板有授权 + * + * @param memberId 用户ID + * @param templateId 模板ID + * @param scenicId 景区ID + * @return 授权记录,如果没有授权返回null + */ + UserNotificationAuthorizationEntity checkAuthorization(Long memberId, String templateId, Long scenicId); + + /** + * 检查用户是否还有剩余授权次数 + * + * @param memberId 用户ID + * @param templateId 模板ID + * @param scenicId 景区ID + * @return 剩余授权次数,0表示没有剩余 + */ + Integer getRemainingCount(Long memberId, String templateId, Long scenicId); + + /** + * 记录用户授权 + * + * @param memberId 用户ID + * @param templateId 模板ID + * @param scenicId 景区ID + * @return 授权记录 + */ + UserNotificationAuthorizationEntity recordAuthorization(Long memberId, String templateId, Long scenicId); + + /** + * 消费一次授权 + * + * @param memberId 用户ID + * @param templateId 模板ID + * @param scenicId 景区ID + * @return 是否消费成功 + */ + boolean consumeAuthorization(Long memberId, String templateId, Long scenicId); + + /** + * 查询用户的授权记录列表 + * + * @param memberId 用户ID + * @return 授权记录列表 + */ + List getUserAuthorizations(Long memberId); + + /** + * 查询用户对指定模板的授权记录列表 + * + * @param memberId 用户ID + * @param templateId 模板ID + * @return 授权记录列表 + */ + List getUserAuthorizationsByTemplate(Long memberId, String templateId); + + /** + * 查询景区的授权记录列表 + * + * @param scenicId 景区ID + * @return 授权记录列表 + */ + List getScenicAuthorizations(Long scenicId); + + /** + * 根据ID查询授权记录 + * + * @param id 记录ID + * @return 授权记录 + */ + UserNotificationAuthorizationEntity getById(Long id); +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/service/impl/UserNotificationAuthorizationServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/UserNotificationAuthorizationServiceImpl.java new file mode 100644 index 00000000..359c473f --- /dev/null +++ b/src/main/java/com/ycwl/basic/service/impl/UserNotificationAuthorizationServiceImpl.java @@ -0,0 +1,138 @@ +package com.ycwl.basic.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ycwl.basic.mapper.UserNotificationAuthorizationMapper; +import com.ycwl.basic.model.pc.notify.entity.UserNotificationAuthorizationEntity; +import com.ycwl.basic.service.UserNotificationAuthorizationService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; + +/** + * 用户通知授权记录Service实现类 + * + * @Author: System + * @Date: 2024/12/28 + */ +@Service +@Slf4j +public class UserNotificationAuthorizationServiceImpl implements UserNotificationAuthorizationService { + + @Autowired + private UserNotificationAuthorizationMapper userNotificationAuthorizationMapper; + + @Override + public UserNotificationAuthorizationEntity checkAuthorization(Long memberId, String templateId, Long scenicId) { + log.debug("检查用户授权: memberId={}, templateId={}, scenicId={}", memberId, templateId, scenicId); + return userNotificationAuthorizationMapper.selectByMemberAndTemplateAndScenic(memberId, templateId, scenicId); + } + + @Override + public Integer getRemainingCount(Long memberId, String templateId, Long scenicId) { + log.debug("获取剩余授权次数: memberId={}, templateId={}, scenicId={}", memberId, templateId, scenicId); + Integer remainingCount = userNotificationAuthorizationMapper.selectRemainingCount(memberId, templateId, scenicId); + return remainingCount != null ? remainingCount : 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public UserNotificationAuthorizationEntity recordAuthorization(Long memberId, String templateId, Long scenicId) { + log.info("记录用户授权: memberId={}, templateId={}, scenicId={}", memberId, templateId, scenicId); + + // 先查询是否已存在记录 + UserNotificationAuthorizationEntity existingRecord = userNotificationAuthorizationMapper + .selectByMemberAndTemplateAndScenic(memberId, templateId, scenicId); + + if (existingRecord != null) { + // 增加授权次数 + int updated = userNotificationAuthorizationMapper.increaseAuthorizationCount(existingRecord.getId(), 1); + if (updated > 0) { + log.info("成功增加授权次数: recordId={}, newCount={}", existingRecord.getId(), + existingRecord.getAuthorizationCount() + 1); + // 重新查询最新数据 + return userNotificationAuthorizationMapper.selectById(existingRecord.getId()); + } else { + log.error("增加授权次数失败: recordId={}", existingRecord.getId()); + throw new RuntimeException("增加授权次数失败"); + } + } else { + // 创建新记录 + UserNotificationAuthorizationEntity newRecord = new UserNotificationAuthorizationEntity(); + newRecord.setMemberId(memberId); + newRecord.setTemplateId(templateId); + newRecord.setScenicId(scenicId); + newRecord.setAuthorizationCount(1); + newRecord.setConsumedCount(0); + newRecord.setLastAuthorizedTime(new Date()); + newRecord.setStatus(1); + newRecord.setCreateTime(new Date()); + newRecord.setUpdateTime(new Date()); + + int inserted = userNotificationAuthorizationMapper.insert(newRecord); + if (inserted > 0) { + log.info("成功创建授权记录: recordId={}", newRecord.getId()); + return newRecord; + } else { + log.error("创建授权记录失败: memberId={}, templateId={}, scenicId={}", memberId, templateId, scenicId); + throw new RuntimeException("创建授权记录失败"); + } + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean consumeAuthorization(Long memberId, String templateId, Long scenicId) { + log.info("消费授权: memberId={}, templateId={}, scenicId={}", memberId, templateId, scenicId); + + UserNotificationAuthorizationEntity record = userNotificationAuthorizationMapper + .selectByMemberAndTemplateAndScenic(memberId, templateId, scenicId); + + if (record == null) { + log.warn("未找到授权记录: memberId={}, templateId={}, scenicId={}", memberId, templateId, scenicId); + return false; + } + + if (record.getRemainingCount() <= 0) { + log.warn("剩余授权次数不足: recordId={}, remainingCount={}", record.getId(), record.getRemainingCount()); + return false; + } + + int updated = userNotificationAuthorizationMapper.increaseConsumedCount(record.getId(), 1); + if (updated > 0) { + log.info("成功消费授权: recordId={}, newConsumedCount={}", record.getId(), + record.getConsumedCount() + 1); + return true; + } else { + log.error("消费授权失败: recordId={}", record.getId()); + return false; + } + } + + @Override + public List getUserAuthorizations(Long memberId) { + log.debug("查询用户授权记录: memberId={}", memberId); + return userNotificationAuthorizationMapper.selectByMemberId(memberId); + } + + @Override + public List getUserAuthorizationsByTemplate(Long memberId, String templateId) { + log.debug("查询用户模板授权记录: memberId={}, templateId={}", memberId, templateId); + return userNotificationAuthorizationMapper.selectByMemberIdAndTemplateId(memberId, templateId); + } + + @Override + public List getScenicAuthorizations(Long scenicId) { + log.debug("查询景区授权记录: scenicId={}", scenicId); + return userNotificationAuthorizationMapper.selectByScenicId(scenicId); + } + + @Override + public UserNotificationAuthorizationEntity getById(Long id) { + log.debug("根据ID查询授权记录: id={}", id); + return userNotificationAuthorizationMapper.selectById(id); + } +} \ No newline at end of file diff --git a/src/main/resources/mapper/UserNotificationAuthorizationMapper.xml b/src/main/resources/mapper/UserNotificationAuthorizationMapper.xml new file mode 100644 index 00000000..26baf1d9 --- /dev/null +++ b/src/main/resources/mapper/UserNotificationAuthorizationMapper.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + id, member_id, template_id, scenic_id, authorization_count, consumed_count, + remaining_count, last_authorized_time, last_consumed_time, status, create_time, update_time + + + + + + + + + + + + + + + + + UPDATE user_notification_authorization + SET authorization_count = authorization_count + #{count}, + last_authorized_time = NOW(), + update_time = NOW() + WHERE id = #{id} + AND status = 1 + + + + + UPDATE user_notification_authorization + SET consumed_count = consumed_count + #{count}, + last_consumed_time = NOW(), + update_time = NOW() + WHERE id = #{id} + AND status = 1 + AND consumed_count + #{count} <= authorization_count + + + + + + \ No newline at end of file