diff --git a/src/main/java/com/ycwl/basic/puzzle/mapper/MemberPuzzleMapper.java b/src/main/java/com/ycwl/basic/puzzle/mapper/MemberPuzzleMapper.java index b5322cb2..57a30458 100644 --- a/src/main/java/com/ycwl/basic/puzzle/mapper/MemberPuzzleMapper.java +++ b/src/main/java/com/ycwl/basic/puzzle/mapper/MemberPuzzleMapper.java @@ -46,4 +46,9 @@ public interface MemberPuzzleMapper { * 根据人脸ID和记录ID查询 */ MemberPuzzleEntity getByFaceAndRecord(@Param("faceId") Long faceId, @Param("recordId") Long recordId); + + /** + * 查询指定时间范围内生成且未购买的免费拼图记录 + */ + List listFreeUnpurchased(@Param("startTime") java.util.Date startTime, @Param("endTime") java.util.Date endTime); } diff --git a/src/main/java/com/ycwl/basic/task/FreePuzzleNotificationTask.java b/src/main/java/com/ycwl/basic/task/FreePuzzleNotificationTask.java new file mode 100644 index 00000000..8ceaf752 --- /dev/null +++ b/src/main/java/com/ycwl/basic/task/FreePuzzleNotificationTask.java @@ -0,0 +1,87 @@ +package com.ycwl.basic.task; + +import cn.hutool.core.date.DateUtil; +import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; +import com.ycwl.basic.mapper.MemberMapper; +import com.ycwl.basic.model.pc.member.resp.MemberRespVO; +import com.ycwl.basic.model.pc.notify.req.WechatSubscribeNotifyTriggerRequest; +import com.ycwl.basic.puzzle.mapper.MemberPuzzleMapper; +import com.ycwl.basic.repository.ScenicRepository; +import com.ycwl.basic.service.notify.WechatSubscribeNotifyTriggerService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.HashMap; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 免费拼图通知任务 + */ +@Component +@Slf4j +public class FreePuzzleNotificationTask { + + @Autowired + private MemberPuzzleMapper memberPuzzleMapper; + @Autowired + private MemberMapper memberMapper; + @Autowired + private ScenicRepository scenicRepository; + @Autowired + private WechatSubscribeNotifyTriggerService notifyTriggerService; + + /** + * 每天晚7点执行 + * 查找昨天生成的,未购买的且is_free字段等于1的member,触发“FREE_PUZZLE”通知 + */ + @Scheduled(cron = "0 0 19 * * ?") + public void sendFreePuzzleNotification() { + log.info("开始执行免费拼图通知任务"); + // 昨天开始时间 + Date startTime = DateUtil.beginOfDay(DateUtil.yesterday()); + // 昨天结束时间 + Date endTime = DateUtil.endOfDay(DateUtil.yesterday()); + + // 查询符合条件的记录 + var list = memberPuzzleMapper.listFreeUnpurchased(startTime, endTime); + log.info("查询到需发送免费拼图通知记录数: {}", list.size()); + + Set sentMemberIds = ConcurrentHashMap.newKeySet(); + + list.parallelStream().forEach(item -> { + if (!sentMemberIds.add(item.getMemberId())) { + return; + } + + try { + MemberRespVO member = memberMapper.getById(item.getMemberId()); + if (member == null || member.getOpenId() == null) { + return; + } + + // 构造参数 + HashMap variables = new HashMap<>(); + ScenicV2DTO scenic = scenicRepository.getScenicBasic(item.getScenicId()); + variables.put("activityName", "免费领取三拼图"); + variables.put("scenicName", scenic.getName()); + + WechatSubscribeNotifyTriggerRequest request = WechatSubscribeNotifyTriggerRequest.builder() + .scenicId(item.getScenicId()) + .memberId(item.getMemberId()) + .openId(member.getOpenId()) + .bizId(String.valueOf(item.getId())) + .variables(variables) + .build(); + + notifyTriggerService.trigger("FREE_PUZZLE", request); + } catch (Exception e) { + log.error("发送免费拼图通知失败: memberId={}", item.getMemberId(), e); + } + }); + log.info("免费拼图通知任务执行结束"); + } +} diff --git a/src/main/resources/mapper/MemberPuzzleMapper.xml b/src/main/resources/mapper/MemberPuzzleMapper.xml index b016ac57..0b526d9e 100644 --- a/src/main/resources/mapper/MemberPuzzleMapper.xml +++ b/src/main/resources/mapper/MemberPuzzleMapper.xml @@ -67,4 +67,13 @@ LIMIT 1 + +