diff --git a/cash-api/market-server/src/main/java/com/czg/controller/admin/SmsPushEventController.java b/cash-api/market-server/src/main/java/com/czg/controller/admin/SmsPushEventController.java index d9477eb9..6c03cff8 100644 --- a/cash-api/market-server/src/main/java/com/czg/controller/admin/SmsPushEventController.java +++ b/cash-api/market-server/src/main/java/com/czg/controller/admin/SmsPushEventController.java @@ -5,6 +5,7 @@ import com.czg.market.service.SmsPushEventService; import com.czg.resp.CzgResult; import com.czg.sa.StpKit; import com.czg.validator.group.InsertGroup; +import com.czg.validator.group.UpdateGroup; import com.mybatisflex.core.paginate.Page; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -45,6 +46,16 @@ public class SmsPushEventController { return CzgResult.success(); } + /** + * 更新 + */ + @PutMapping + public CzgResult upPushEvent(@RequestBody @Validated(UpdateGroup.class) SmsPushEventDTO param) { + param.setShopId(StpKit.USER.getShopId()); + pushEventService.upPushEvent(param); + return CzgResult.success(); + } + /** * 删除任务 */ diff --git a/cash-api/order-server/src/main/java/com/czg/config/RedisKeyExpirationListener.java b/cash-api/order-server/src/main/java/com/czg/config/RedisKeyExpirationListener.java index 0206bd49..f94ddfa9 100644 --- a/cash-api/order-server/src/main/java/com/czg/config/RedisKeyExpirationListener.java +++ b/cash-api/order-server/src/main/java/com/czg/config/RedisKeyExpirationListener.java @@ -3,6 +3,7 @@ package com.czg.config; import com.czg.account.service.ShopTableService; import com.czg.market.entity.MkShopCouponRecord; import com.czg.market.service.MkShopCouponRecordService; +import com.czg.market.service.SmsPushEventService; import com.czg.order.service.OrderInfoService; import com.mybatisflex.core.query.QueryWrapper; import jakarta.annotation.Resource; @@ -34,6 +35,8 @@ public class RedisKeyExpirationListener implements MessageListener { private ShopTableService tableService; @Resource private MkShopCouponRecordService mkShopCouponRecordService; + @Resource + private SmsPushEventService smsPushEventService; //redis key失效监听 @@ -66,6 +69,10 @@ public class RedisKeyExpirationListener implements MessageListener { .eq(MkShopCouponRecord::getStatus, 0) .eq(MkShopCouponRecord::getId, Long.parseLong(couponId)) ); + } else if (expiredKey.startsWith(RedisCst.classKeyExpired.EXPIRED_SMS)) { + log.info("监听到短信定时发放优惠券,sms_push_event任务Id: {}", expiredKey); + String eventId = expiredKey.substring(RedisCst.classKeyExpired.EXPIRED_SMS.length()); + smsPushEventService.sendPushEventCoupon(eventId); } } } diff --git a/cash-common/cash-common-redis/src/main/java/com/czg/config/RedisCst.java b/cash-common/cash-common-redis/src/main/java/com/czg/config/RedisCst.java index b6e3e4e0..33418110 100644 --- a/cash-common/cash-common-redis/src/main/java/com/czg/config/RedisCst.java +++ b/cash-common/cash-common-redis/src/main/java/com/czg/config/RedisCst.java @@ -23,6 +23,8 @@ public interface RedisCst { public static final String EXPIRED_TABLE = "expired:table:"; //优惠券过期 public static final String EXPIRED_COUPON = "expired:coupon:"; + //短信定时发放 倒计时KEY + public static final String EXPIRED_SMS = "expired:sms:"; } diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/dto/SmsPushEventDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/market/dto/SmsPushEventDTO.java index f013f801..c9c63eae 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/market/dto/SmsPushEventDTO.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/dto/SmsPushEventDTO.java @@ -31,7 +31,7 @@ public class SmsPushEventDTO implements Serializable { @Serial private static final long serialVersionUID = 1L; - + @NotNull(message = "id不能为空", groups = {InsertGroup.class, UpdateGroup.class}) private Long id; private Long shopId; @@ -44,18 +44,18 @@ public class SmsPushEventDTO implements Serializable { /** * 模板ID */ - @NotNull(message = "模板ID不能为空", groups = InsertGroup.class) + @NotNull(message = "模板ID不能为空", groups = {InsertGroup.class, UpdateGroup.class}) private Long pushEventId; /** * 1 全部用户 2范围用户 3 指定用户 指定暂定一个用户 */ - @NotNull(message = "发送范围不能为空", groups = InsertGroup.class) + @NotNull(message = "发送范围不能为空", groups = {InsertGroup.class, UpdateGroup.class}) private Long userType; /** * 预计人数 */ - @NotNull(message = "预计人数不能为空", groups = InsertGroup.class) + @NotNull(message = "预计人数不能为空", groups = {InsertGroup.class, UpdateGroup.class}) private Long estimateNum; /** * 实际人数 @@ -79,13 +79,13 @@ public class SmsPushEventDTO implements Serializable { /** * 发送内容 */ - @NotBlank(message = "发送内容不能为空", groups = InsertGroup.class) + @NotBlank(message = "发送内容不能为空", groups = {InsertGroup.class, UpdateGroup.class}) private String content; /** * 发送参数json * {"店铺名称":"火锅店","时间":"2025-02-17"} */ - @NotBlank(message = "发送参数json不能为空", groups = InsertGroup.class) + @NotBlank(message = "发送参数json不能为空", groups = {InsertGroup.class, UpdateGroup.class}) private String json; /** @@ -96,7 +96,7 @@ public class SmsPushEventDTO implements Serializable { /** * 发送类型 1 立即发送 2定时发送 */ - @NotNull(message = "发送类型不能为空", groups = InsertGroup.class) + @NotNull(message = "发送类型不能为空", groups = {InsertGroup.class, UpdateGroup.class}) private Integer sendType; /** diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/service/SmsPushEventService.java b/cash-common/cash-common-service/src/main/java/com/czg/market/service/SmsPushEventService.java index 5a41067c..397b555b 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/market/service/SmsPushEventService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/service/SmsPushEventService.java @@ -1,6 +1,5 @@ package com.czg.market.service; -import com.czg.BaseQueryParam; import com.czg.market.dto.SmsPushEventDTO; import com.czg.market.entity.SmsPushEvent; import com.mybatisflex.core.paginate.Page; @@ -24,5 +23,15 @@ public interface SmsPushEventService extends IService { */ void addPushEvent(SmsPushEventDTO param); + /** + * 发送营销推送发送任务中的优惠券 + */ + void sendPushEventCoupon(String eventId); + + /** + * 更新营销推送发送任务 + */ + void upPushEvent(SmsPushEventDTO param); + void deletePushEvent(Long id); } diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkConsumeCashbackRecordServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkConsumeCashbackRecordServiceImpl.java index e43dba5c..a68a9607 100644 --- a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkConsumeCashbackRecordServiceImpl.java +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkConsumeCashbackRecordServiceImpl.java @@ -26,7 +26,7 @@ import java.util.Map; * @since 2025-10-13 */ @Service -public class MkConsumeCashbackRecordServiceImpl extends ServiceImpl implements MkConsumeCashbackRecordService{ +public class MkConsumeCashbackRecordServiceImpl extends ServiceImpl implements MkConsumeCashbackRecordService { @Override public Map getRecord(Long mainShopId, Long shopId, String key, LocalDateTime startTime, LocalDateTime endTime) { QueryWrapper queryWrapper = new MyQueryWrapper().eq(MkConsumeCashbackRecord::getMainShopId, mainShopId) @@ -76,7 +76,7 @@ public class MkConsumeCashbackRecordServiceImpl extends ServiceImpl map = BeanUtil.beanToMap(pageAs(PageUtil.buildPage(), queryWrapper, MkConsumeCashbackRecordVO.class)); - map.put("totalAmount", amount); + map.put("totalAmount", amount == null ? BigDecimal.ZERO : amount); return map; } } diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsPushEventServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsPushEventServiceImpl.java index d677b690..6633a3dd 100644 --- a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsPushEventServiceImpl.java +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsPushEventServiceImpl.java @@ -8,6 +8,7 @@ import com.alibaba.fastjson2.JSONObject; import com.czg.account.entity.ShopUser; import com.czg.account.service.AShopUserService; import com.czg.config.RabbitPublisher; +import com.czg.config.RedisCst; import com.czg.exception.CzgException; import com.czg.market.dto.MkShopCouponGiftDTO; import com.czg.market.dto.SmsPushEventDTO; @@ -15,6 +16,7 @@ import com.czg.market.entity.SmsPushEvent; import com.czg.market.entity.SmsPushEventUser; import com.czg.market.service.MkShopCouponRecordService; import com.czg.market.service.SmsPushEventService; +import com.czg.service.RedisService; import com.czg.service.market.mapper.SmsPushEventMapper; import com.czg.service.market.mapper.SmsPushEventUserMapper; import com.czg.utils.AssertUtil; @@ -49,6 +51,8 @@ public class SmsPushEventServiceImpl extends ServiceImpl getPushEventPage(Integer page, Integer size, Long shopId, Long id) { @@ -96,6 +100,38 @@ public class SmsPushEventServiceImpl extends ServiceImpl { try { @@ -106,29 +142,48 @@ public class SmsPushEventServiceImpl extends ServiceImpl userList = shopUserService.getPushEventUserList(param.getSmsPushEventUser()); - // 2. 将JSON字符串解析为JSONArray - JSONArray couponArray = JSON.parseArray(param.getCoupon()); + //发放优惠券 + CompletableFuture.runAsync(() -> { + try { + List userList = shopUserService.getPushEventUserList(param.getSmsPushEventUser()); + // 2. 将JSON字符串解析为JSONArray + JSONArray couponArray = JSON.parseArray(param.getCoupon()); - // 3. 遍历JSONArray,逐个获取JSONObject的字段值 - for (int i = 0; i < couponArray.size(); i++) { - // 获取单个优惠券的JSONObject对象 - JSONObject couponObj = couponArray.getJSONObject(i); - // 通过键名获取对应值(需注意字段类型,按需转换) - Long id = couponObj.getLong("id"); - Integer num = couponObj.getInteger("num"); - MkShopCouponGiftDTO giftDTO = new MkShopCouponGiftDTO(); - giftDTO.setShopId(param.getShopId()); - giftDTO.setSourceId(param.getId()); - giftDTO.setCouponId(id); - giftDTO.setSource("营销短信发放"); - couponRecordService.batchReceiveCoupon(giftDTO, num, userList); - } + // 3. 遍历JSONArray,逐个获取JSONObject的字段值 + for (int i = 0; i < couponArray.size(); i++) { + // 获取单个优惠券的JSONObject对象 + JSONObject couponObj = couponArray.getJSONObject(i); + // 通过键名获取对应值(需注意字段类型,按需转换) + Long id = couponObj.getLong("id"); + Integer num = couponObj.getInteger("num"); + MkShopCouponGiftDTO giftDTO = new MkShopCouponGiftDTO(); + giftDTO.setShopId(param.getShopId()); + giftDTO.setSourceId(param.getId()); + giftDTO.setCouponId(id); + giftDTO.setSource("营销短信发放"); + couponRecordService.batchReceiveCoupon(giftDTO, num, userList); + } + } catch (Exception e) { + log.error("异步发放优惠券失败", e); + } + }); } /** @@ -138,6 +193,10 @@ public class SmsPushEventServiceImpl extends ServiceImpl