生日有礼定时奖励

This commit is contained in:
张松 2025-10-15 11:09:43 +08:00
parent f22f32daf9
commit 86e96d48a4
13 changed files with 236 additions and 21 deletions

View File

@ -0,0 +1,39 @@
package com.czg.task;
import cn.hutool.core.date.DateUtil;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopUserService;
import com.czg.constant.TableValueConstant;
import com.czg.market.service.MkBirthdayGiftService;
import com.czg.market.service.TbMemberConfigService;
import com.czg.order.service.OrderInfoService;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 生日有礼奖励发放
*
* @author ww
* @description
*/
@Slf4j
@Component
public class BirthdayGiftTask {
@Resource
private MkBirthdayGiftService birthdayGiftService;
/**
* 生日有礼奖励发放
*/
@Scheduled(cron = "0 0 12 * * ?")
public void deliver() {
birthdayGiftService.deliver();
}
}

View File

@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
import java.util.List; import java.util.List;
/** /**
* 订单定时任务 * 会员奖励发放
* *
* @author ww * @author ww
* @description * @description
@ -35,13 +35,12 @@ public class MemberTask {
private TbMemberConfigService memberConfigService; private TbMemberConfigService memberConfigService;
/** /**
* order 过期 * 奖励发放
*/ */
// @Scheduled(cron = "0 0 1 * * ? ") @Scheduled(cron = "0 0 1 * * ? ")
public void deliver() { public void deliver() {
shopUserService.list(new QueryWrapper().eq(ShopUser::getIsVip, 1).lt(ShopUser::getNextDeliverTime, DateUtil.date().toLocalDateTime())).forEach(item -> { shopUserService.list(new QueryWrapper().eq(ShopUser::getIsVip, 1).lt(ShopUser::getNextDeliverTime, DateUtil.date().toLocalDateTime())).forEach(item -> {
memberConfigService.deliver(item.getSourceShopId(), item.getUserId(), TableValueConstant.MemberExpFlow.Type.MEMBER_TASK, null, null, null); memberConfigService.deliver(item.getSourceShopId(), item.getUserId(), TableValueConstant.MemberExpFlow.Type.MEMBER_TASK, null, null, null);
}); });
} }

View File

@ -12,6 +12,7 @@ import lombok.experimental.Accessors;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
/** /**
@ -55,7 +56,7 @@ public class ShopUser implements Serializable {
/** /**
* 会员生日 * 会员生日
*/ */
private String birthDay; private LocalDate birthDay;
/** /**
* 0- 1男 * 0- 1男

View File

@ -39,7 +39,7 @@ public class MkBirthdayGiftConfig implements Serializable {
/** /**
* 是否开启 * 是否开启
*/ */
private String deliverTime; private Integer deliverTime;
private String deliverDate; private String deliverDate;
/** /**

View File

@ -6,6 +6,7 @@ import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table; import com.mybatisflex.annotation.Table;
import java.io.Serializable; import java.io.Serializable;
import java.sql.Date; import java.sql.Date;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.io.Serial; import java.io.Serial;
@ -14,6 +15,7 @@ import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/** /**
* 生日有礼记录 实体类 * 生日有礼记录 实体类
@ -26,6 +28,7 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Table("mk_birthday_gift_record") @Table("mk_birthday_gift_record")
@Accessors(chain = true)
public class MkBirthdayGiftRecord implements Serializable { public class MkBirthdayGiftRecord implements Serializable {
@Serial @Serial
@ -33,6 +36,7 @@ public class MkBirthdayGiftRecord implements Serializable {
@Id(keyType = KeyType.Auto) @Id(keyType = KeyType.Auto)
private Long id; private Long id;
private Long sourceId;
/** /**
* 用户id * 用户id
@ -43,7 +47,7 @@ public class MkBirthdayGiftRecord implements Serializable {
/** /**
* 生日 * 生日
*/ */
private Date birthday; private LocalDate birthday;
/** /**
* 创建时间 * 创建时间
*/ */
@ -55,4 +59,10 @@ public class MkBirthdayGiftRecord implements Serializable {
*/ */
private Long mainShopId; private Long mainShopId;
private String pushStatus;
private String pushResp;
private String templateCode;
private String templateContent;
} }

View File

@ -13,6 +13,7 @@ import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/** /**
* 实体类 * 实体类
@ -25,6 +26,7 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Table("mk_birthday_gift_record_coupon") @Table("mk_birthday_gift_record_coupon")
@Accessors(chain = true)
public class MkBirthdayGiftRecordCoupon implements Serializable { public class MkBirthdayGiftRecordCoupon implements Serializable {
@Serial @Serial

View File

@ -42,6 +42,10 @@ public class SmsShopTemplate implements Serializable {
* 模板内容 * 模板内容
*/ */
private String content; private String content;
/**
* 阿里云模板code
*/
private String templateCode;
/** /**
* 排序 * 排序

View File

@ -25,4 +25,6 @@ public interface MkBirthdayGiftService extends IService<MkBirthdayGift> {
Page<MkBirthdayGiftRecordVO> getRecord(Long shopId, String key, LocalDateTime dateTime); Page<MkBirthdayGiftRecordVO> getRecord(Long shopId, String key, LocalDateTime dateTime);
MkBirthdayGiftRecordSummaryVO summary(Long shopId, String key, LocalDateTime dateTime); MkBirthdayGiftRecordSummaryVO summary(Long shopId, String key, LocalDateTime dateTime);
void deliver();
} }

View File

@ -38,4 +38,36 @@ public interface TableValueConstant {
} }
} }
} }
interface BirthdayGiftRecord {
@Getter
enum PushStatus {
WAIT_PUSH("wait_push", "待推送"),
NO_PUSH("no_push", "不用推送"),
SUCCESS("success", "推送成功");
private final String code;
private final String msg;
PushStatus(String code, String msg) {
this.code = code;
this.msg = msg;
}
}
}
interface BirthdayGiftRecordCoupon {
@Getter
enum Type {
GIVE("give", "待推送"),
CONSUME("consume", "推送成功");
private final String code;
private final String msg;
Type(String code, String msg) {
this.code = code;
this.msg = msg;
}
}
}
} }

View File

@ -0,0 +1,32 @@
package com.czg.utils;
import cn.hutool.core.lang.func.Func0;
import lombok.extern.slf4j.Slf4j;
import java.util.function.Consumer;
@Slf4j
public class FunUtils {
/**
* 执行方法并捕获异常
* @param func 方法
* @param value 失败的值
*/
public static <T> T safeRun(Func0<T> func, T value) {
try {
return func.call();
} catch (Exception e) {
log.warn("方法执行失败: {}", e.getMessage());
}
return value;
}
public static void safeRunVoid(Runnable func, String... msg) {
try {
func.run();
} catch (Exception e) {
log.warn(msg.length > 0 ? msg[0] : "方法执行失败: {}", e.getMessage());
}
}
}

View File

@ -1,28 +1,42 @@
package com.czg.service.market.service.impl; package com.czg.service.market.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.czg.account.entity.ShopInfo;
import com.czg.account.entity.ShopUser; import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopInfoService;
import com.czg.account.service.ShopUserService;
import com.czg.config.RabbitPublisher;
import com.czg.constant.TableValueConstant;
import com.czg.market.dto.CouponInfoDTO;
import com.czg.market.dto.MkBirthdayGiftDTO; import com.czg.market.dto.MkBirthdayGiftDTO;
import com.czg.market.dto.MkRewardCouponDTO;
import com.czg.market.entity.*; import com.czg.market.entity.*;
import com.czg.market.service.MkBirthdayGiftRecordCouponService; import com.czg.market.service.*;
import com.czg.market.service.MkBirthdayGiftRecordService;
import com.czg.market.vo.MkBirthdayGiftRecordSummaryVO; import com.czg.market.vo.MkBirthdayGiftRecordSummaryVO;
import com.czg.market.vo.MkBirthdayGiftRecordVO; import com.czg.market.vo.MkBirthdayGiftRecordVO;
import com.czg.market.vo.MkBirthdayGiftVO; import com.czg.market.vo.MkBirthdayGiftVO;
import com.czg.utils.FunUtils;
import com.czg.utils.MyQueryWrapper; import com.czg.utils.MyQueryWrapper;
import com.czg.utils.PageUtil; import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.service.MkBirthdayGiftService;
import com.czg.service.market.mapper.MkBirthdayGiftMapper; import com.czg.service.market.mapper.MkBirthdayGiftMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 生日有礼 服务层实现 * 生日有礼 服务层实现
@ -30,12 +44,26 @@ import java.util.ArrayList;
* @author zs * @author zs
* @since 2025-10-14 * @since 2025-10-14
*/ */
@Slf4j
@Service @Service
public class MkBirthdayGiftServiceImpl extends ServiceImpl<MkBirthdayGiftMapper, MkBirthdayGift> implements MkBirthdayGiftService{ public class MkBirthdayGiftServiceImpl extends ServiceImpl<MkBirthdayGiftMapper, MkBirthdayGift> implements MkBirthdayGiftService{
@Resource @Resource
private MkBirthdayGiftRecordService birthdayGiftRecordService; private MkBirthdayGiftRecordService birthdayGiftRecordService;
@Resource @Resource
private MkBirthdayGiftRecordCouponService birthdayGiftRecordCouponService; private MkBirthdayGiftRecordCouponService birthdayGiftRecordCouponService;
@Resource
private ShopCouponService shopCouponService;
@Resource
private MkShopCouponRecordService shopCouponRecordService;
@Resource
private SmsShopTemplateService smsShopTemplateService;
@Resource
private ShopInfoService shopInfoService;
@Resource
private RabbitPublisher rabbitPublisher;
@DubboReference
private ShopUserService shopUserService;
@Override @Override
public MkBirthdayGiftVO detail(Long shopId) { public MkBirthdayGiftVO detail(Long shopId) {
MkBirthdayGift gift = getOne(new QueryWrapper().eq(MkBirthdayGift::getMainShopId, shopId)); MkBirthdayGift gift = getOne(new QueryWrapper().eq(MkBirthdayGift::getMainShopId, shopId));
@ -113,4 +141,72 @@ public class MkBirthdayGiftServiceImpl extends ServiceImpl<MkBirthdayGiftMapper,
return birthdayGiftRecordCouponService.getOneAsOpt(queryWrapper, MkBirthdayGiftRecordSummaryVO.class).orElseGet(MkBirthdayGiftRecordSummaryVO::new); return birthdayGiftRecordCouponService.getOneAsOpt(queryWrapper, MkBirthdayGiftRecordSummaryVO.class).orElseGet(MkBirthdayGiftRecordSummaryVO::new);
} }
@Override
public void deliver() {
list(new QueryWrapper().eq(MkBirthdayGift::getIsEnable, 1)).forEach(birthdayGift -> {
if (StrUtil.isNotBlank(birthdayGift.getConfigList())) {
SmsShopTemplate shopTemplate = smsShopTemplateService.getById(birthdayGift.getTemplateId());
ShopInfo shopInfo = shopInfoService.getById(birthdayGift.getMainShopId());
FunUtils.safeRunVoid(() -> {
JSONArray.parseArray(birthdayGift.getConfigList()).toJavaList(MkBirthdayGiftConfig.class).forEach(config -> {
LocalDate current = DateUtil.date().toLocalDateTime().toLocalDate();
if ("day".equals(config.getDeliverDate())) {
current = current.plusDays(config.getDeliverTime());
}else {
current = current.plusDays(config.getDeliverTime() * 30);
}
QueryWrapper queryWrapper = new QueryWrapper().isNotNull(ShopUser::getBirthDay)
.eq(ShopUser::getMainShopId, birthdayGift.getMainShopId()).eq(ShopUser::getBirthDay, current);
if ("vip".equals(config.getUserType())) {
queryWrapper.eq(ShopUser::getIsVip, 1);
}
shopUserService.list(queryWrapper).forEach(shopUser -> {
// 发放记录
MkBirthdayGiftRecord giftRecord = new MkBirthdayGiftRecord().setUserId(shopUser.getUserId()).setShopUserId(shopUser.getId())
.setPushStatus(birthdayGift.getSendSms() == 1 ?
TableValueConstant.BirthdayGiftRecord.PushStatus.WAIT_PUSH.getCode() : TableValueConstant.BirthdayGiftRecord.PushStatus.NO_PUSH.getCode())
.setMainShopId(birthdayGift.getMainShopId()).setBirthday(shopUser.getBirthDay())
.setSourceId(birthdayGift.getId()).setTemplateCode(shopTemplate.getTemplateCode()).setTemplateContent(JSONObject.toJSONString(Map.of(
"nickName", shopUser.getNickName(),
"shopName", shopInfo.getShopName(),
"num", config.getCouponInfoList() != null ? config.getCouponInfoList().stream().map(CouponInfoDTO::getNum).reduce(0, Integer::sum) : 0
)));
birthdayGiftRecordService.save(giftRecord);
rabbitPublisher.sendMarketSmsMsg(giftRecord.getId().toString());
// 优惠券信息
if (config.getCouponInfoList() != null && !config.getCouponInfoList().isEmpty()) {
Map<Long, ShopCoupon> couponMap = shopCouponService.list(new QueryWrapper().eq(ShopCoupon::getId, config.getCouponInfoList()
.stream().map(CouponInfoDTO::getId).toList())).stream().collect(Collectors.toMap(ShopCoupon::getId, item -> item));
config.getCouponInfoList().forEach(couponInfo -> {
ShopCoupon shopCoupon = couponMap.get(couponInfo.getId());
if (shopCoupon == null) {
log.warn("优惠券不存在, id: {}", couponInfo.getId());
return;
}
FunUtils.safeRunVoid(() -> {
shopCouponRecordService.grant(birthdayGift.getMainShopId(), new MkRewardCouponDTO().setCouponId(couponInfo.getId())
.setNum(couponInfo.getNum())
.setUserId(shopUser.getUserId())
.setShopId(birthdayGift.getMainShopId()));
MkBirthdayGiftRecordCoupon recordCoupon = new MkBirthdayGiftRecordCoupon().setCouponName(shopCoupon.getTitle()).setNum(couponInfo.getNum())
.setType(TableValueConstant.BirthdayGiftRecordCoupon.Type.GIVE.getCode())
.setRecordId(giftRecord.getId()).setUserId(shopUser.getUserId()).setShopUserId(shopUser.getId());
birthdayGiftRecordCouponService.save(recordCoupon);
}, "优惠券发放失败");
});
}
});
});
});
}
});
}
} }

View File

@ -330,18 +330,13 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
} }
if (levelVO.getCycleRewardCouponList() != null && !levelVO.getCycleRewardCouponList().isEmpty()) { if (levelVO.getCycleRewardCouponList() != null && !levelVO.getCycleRewardCouponList().isEmpty()) {
levelVO.getCycleRewardCouponList().forEach(item -> {
shopCouponRecordService.grant(shopId, new MkRewardCouponDTO().setCouponId(item.getCoupon().getId())
.setNum(item.getNum())
.setUserId(shopUser.getUserId())
.setShopId(shopId));
// TODO 待办 });
ArrayList<MkCouponGiftDTO> giftDTOS = new ArrayList<>();
// levelVO.getCycleRewardCouponList().forEach(item -> {
// giftDTOS.add(new MkCouponGiftDTO().setCouponId(item.getCoupon().getId())
// .setCouponId(item.getCoupon().getId())
// .setCouponName(item.getCoupon().getTitle())
// .setSourceName("会员开通赠券")
// .setSourceId(shopUser)
// .setType(1)
// .setNum(item.getNum()));
// });
// couponGiftService.addCouponGift(memberOrderId, "会员开通赠券", 1, giftDTOS); // couponGiftService.addCouponGift(memberOrderId, "会员开通赠券", 1, giftDTOS);
} }
} }

View File

@ -1,5 +1,6 @@
package com.czg.service.order.utils; package com.czg.service.order.utils;
import cn.hutool.core.lang.func.Func0;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@ -97,4 +98,6 @@ public class FunUtil {
} }
return result; return result;
} }
} }