提交 d47fb273 编写于 作者: 鲸落和鲨掉's avatar 鲸落和鲨掉

用户行为返利入账:活动、积分 用户行为返利结算

上级 019913af
...@@ -23,4 +23,11 @@ public interface IRaffleActivityService { ...@@ -23,4 +23,11 @@ public interface IRaffleActivityService {
* @return 返回结果 * @return 返回结果
*/ */
Response<ActivityDrawResponseDTO> draw(ActivityDrawRequestDTO request); Response<ActivityDrawResponseDTO> draw(ActivityDrawRequestDTO request);
/**
* 日历签到返利接口
*
* @param userId 用户ID
* @return 签到结果
*/
Response<Boolean> calendarSignRebate(String userId);
} }
因为 它太大了无法显示 source diff 。你可以改为 查看blob
此差异已折叠。
此差异已折叠。
...@@ -26,6 +26,7 @@ spring: ...@@ -26,6 +26,7 @@ spring:
topic: topic:
activity_sku_stock_zero: activity_sku_stock_zero activity_sku_stock_zero: activity_sku_stock_zero
send_award: send_award send_award: send_award
send_rebate: send_rebate
# 线程池配置 # 线程池配置
thread: thread:
pool: pool:
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.bugstack.infrastructure.persistent.dao.IDailyBehaviorRebateDao">
<resultMap id="dataMap" type="cn.bugstack.infrastructure.persistent.po.DailyBehaviorRebate">
<id column="id" property="id"/>
<result column="behavior_type" property="behaviorType"/>
<result column="rebate_desc" property="rebateDesc"/>
<result column="rebate_type" property="rebateType"/>
<result column="rebate_config" property="rebateConfig"/>
<result column="state" property="state"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<select id="queryDailyBehaviorRebateByBehaviorType" parameterType="java.lang.String" resultMap="dataMap">
select behavior_type, rebate_desc, rebate_type, rebate_config
from daily_behavior_rebate
where state = 'open'
</select>
</mapper>
\ No newline at end of file
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
<insert id="insertActivityAccountDay" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityAccountDay"> <insert id="insertActivityAccountDay" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityAccountDay">
insert into raffle_activity_account_day( insert into raffle_activity_account_day(
user_id, activity_id, day, day_count, day_count_surplus, create_time, update_time) user_id, activity_id, day, day_count, day_count_surplus, create_time, update_time)
values values
(#{userId}, #{activityId}, #{day}, #{dayCount}, #{dayCountSurplus}, now(), now()) (#{userId}, #{activityId}, #{day}, #{dayCount}, #{dayCountSurplus}, now(), now())
</insert> </insert>
<update id="updateActivityAccountDaySubtractionQuota" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityAccountDay"> <update id="updateActivityAccountDaySubtractionQuota" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityAccountDay">
...@@ -31,9 +31,18 @@ ...@@ -31,9 +31,18 @@
from raffle_activity_account_day from raffle_activity_account_day
where user_id = #{userId} and activity_id = #{activityId} and day = #{day} where user_id = #{userId} and activity_id = #{activityId} and day = #{day}
</select> </select>
<select id="queryRaffleActivityAccountDayPartakeCount" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityAccountDay" resultType="java.lang.Integer"> <select id="queryRaffleActivityAccountDayPartakeCount" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityAccountDay" resultType="java.lang.Integer">
select day_count - day_count_surplus select day_count - day_count_surplus
from raffle_activity_account_day from raffle_activity_account_day
where user_id = #{userId} and activity_id = #{activityId} and day = #{day} where user_id = #{userId} and activity_id = #{activityId} and day = #{day}
</select> </select>
<update id="addAccountQuota" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityAccountDay">
update raffle_activity_account_day
set day_count_surplus = day_count_surplus + #{dayCountSurplus},
day_count = day_count + #{dayCount},
update_time = now()
where user_id = #{userId} and activity_id = #{activityId} and day = #{day}
</update>
</mapper> </mapper>
...@@ -31,5 +31,11 @@ ...@@ -31,5 +31,11 @@
set month_count_surplus = month_count_surplus - 1, update_time = now() set month_count_surplus = month_count_surplus - 1, update_time = now()
where user_id = #{userId} and activity_id = #{activityId} and month = #{month} and month_count_surplus > 0 where user_id = #{userId} and activity_id = #{activityId} and month = #{month} and month_count_surplus > 0
</update> </update>
<update id="addAccountQuota" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityAccountMonth">
update raffle_activity_account_month
set month_count_surplus = month_count_surplus + #{monthCountSurplus},
month_count = month_count + #{monthCount},
update_time = now()
where user_id = #{userId} and activity_id = #{activityId} and month = #{month}
</update>
</mapper> </mapper>
...@@ -20,10 +20,13 @@ ...@@ -20,10 +20,13 @@
from raffle_activity from raffle_activity
where activity_id = #{activityId} where activity_id = #{activityId}
</select> </select>
<select id="queryStrategyIdByActivityId" parameterType="java.lang.Long" resultType="java.lang.Long"> <select id="queryStrategyIdByActivityId" parameterType="java.lang.Long" resultType="java.lang.Long">
select strategy_id from raffle_activity where activity_id = #{activityId} select strategy_id from raffle_activity where activity_id = #{activityId}
</select> </select>
<select id="queryActivityIdByStrategyId" parameterType="java.lang.Long" resultType="java.lang.Long"> <select id="queryActivityIdByStrategyId" parameterType="java.lang.Long" resultType="java.lang.Long">
select activity_id from raffle_activity where strategy_id = #{strategyId} select activity_id from raffle_activity where strategy_id = #{strategyId}
</select> </select>
</mapper> </mapper>
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
<mapper namespace="cn.bugstack.infrastructure.persistent.dao.IRaffleActivitySkuDao"> <mapper namespace="cn.bugstack.infrastructure.persistent.dao.IRaffleActivitySkuDao">
<resultMap id="dataMap" type="cn.bugstack.infrastructure.persistent.po.RaffleActivitySku"> <resultMap id="dataMap" type="cn.bugstack.infrastructure.persistent.po.RaffleActivitySku">
<result column="sku" property="sku"/> <result column="sku" property="sku"/>
<result column="activity_id" property="activityId"/> <result column="activity_id" property="activityId"/>
<result column="activity_count_id" property="activityCountId"/> <result column="activity_count_id" property="activityCountId"/>
...@@ -18,9 +17,6 @@ ...@@ -18,9 +17,6 @@
from raffle_activity_sku from raffle_activity_sku
where sku = #{sku} where sku = #{sku}
</select> </select>
<select id="queryActivitySkuListByActivityId" parameterType="java.lang.Long" resultMap="dataMap">
select sku, activity_count_id, stock_count, stock_count_surplus from raffle_activity_sku where activity_id = #{activityId}
</select>
<update id="updateActivitySkuStock" parameterType="java.lang.Long"> <update id="updateActivitySkuStock" parameterType="java.lang.Long">
update raffle_activity_sku update raffle_activity_sku
...@@ -34,4 +30,8 @@ ...@@ -34,4 +30,8 @@
where sku = #{sku} where sku = #{sku}
</update> </update>
<select id="queryActivitySkuListByActivityId" parameterType="java.lang.Long" resultMap="dataMap">
select sku, activity_count_id, stock_count, stock_count_surplus from raffle_activity_sku where activity_id = #{activityId}
</select>
</mapper> </mapper>
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
from rule_tree_node from rule_tree_node
where tree_id = #{treeId} where tree_id = #{treeId}
</select> </select>
<select id="queryRuleLocks" resultMap="dataMap"> <select id="queryRuleLocks" resultMap="dataMap">
select tree_id, rule_value select tree_id, rule_value
from rule_tree_node from rule_tree_node
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
</select> </select>
<select id="queryStrategyAwardListByStrategyId" parameterType="java.lang.Long" resultMap="dataMap"> <select id="queryStrategyAwardListByStrategyId" parameterType="java.lang.Long" resultMap="dataMap">
select strategy_id, award_id, award_title, award_subtitle, award_count, award_count_surplus, award_rate, sort select strategy_id, award_id, award_title, award_subtitle, award_count, award_count_surplus, award_rate, rule_models, sort
from strategy_award from strategy_award
where strategy_id = #{strategyId} where strategy_id = #{strategyId}
order by sort asc order by sort asc
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.bugstack.infrastructure.persistent.dao.IUserBehaviorRebateOrderDao">
<resultMap id="dataMap" type="cn.bugstack.infrastructure.persistent.po.UserBehaviorRebateOrder">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="order_id" property="orderId"/>
<result column="behavior_type" property="behaviorType"/>
<result column="rebate_desc" property="rebateDesc"/>
<result column="rebate_type" property="rebateType"/>
<result column="rebate_config" property="rebateConfig"/>
<result column="biz_id" property="bizId"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<insert id="insert" parameterType="cn.bugstack.infrastructure.persistent.po.UserBehaviorRebateOrder">
insert into user_behavior_rebate_order(
user_id, order_id, behavior_type, rebate_desc, rebate_type, rebate_config, biz_id, create_time, update_time
) values(
#{userId}, #{orderId}, #{behaviorType}, #{rebateDesc}, #{rebateType}, #{rebateConfig}, #{bizId}, now(), now()
)
</insert>
</mapper>
\ No newline at end of file
...@@ -23,11 +23,6 @@ ...@@ -23,11 +23,6 @@
#{userId}, #{activityId}, #{activityName}, #{strategyId}, #{orderId}, #{orderTime}, #{orderState}, now(), now() #{userId}, #{activityId}, #{activityName}, #{strategyId}, #{orderId}, #{orderTime}, #{orderState}, now(), now()
) )
</insert> </insert>
<update id="updateUserRaffleOrderStateUsed" parameterType="cn.bugstack.infrastructure.persistent.po.UserRaffleOrder">
update user_raffle_order
set order_state = 'used', update_time = now()
where user_id = #{userId} and order_id = #{orderId} and order_state = 'create'
</update>
<select id="queryNoUsedRaffleOrder" parameterType="cn.bugstack.infrastructure.persistent.po.UserRaffleOrder" resultMap="dataMap"> <select id="queryNoUsedRaffleOrder" parameterType="cn.bugstack.infrastructure.persistent.po.UserRaffleOrder" resultMap="dataMap">
select user_id, activity_id, activity_name, strategy_id, order_id, order_time, order_state select user_id, activity_id, activity_name, strategy_id, order_id, order_time, order_state
...@@ -35,4 +30,10 @@ ...@@ -35,4 +30,10 @@
where user_id = #{userId} and activity_id = #{activityId} and order_state = 'create' where user_id = #{userId} and activity_id = #{activityId} and order_state = 'create'
</select> </select>
<update id="updateUserRaffleOrderStateUsed" parameterType="cn.bugstack.infrastructure.persistent.po.UserRaffleOrder">
update user_raffle_order
set order_state = 'used', update_time = now()
where user_id = #{userId} and order_id = #{orderId} and order_state = 'create'
</update>
</mapper> </mapper>
package cn.bugstack.test.award; package cn.bugstack.test.domain.award;
import cn.bugstack.domain.award.model.entity.UserAwardRecordEntity; import cn.bugstack.domain.award.model.entity.UserAwardRecordEntity;
import cn.bugstack.domain.award.model.valobj.AwardStateVO; import cn.bugstack.domain.award.model.valobj.AwardStateVO;
......
package cn.bugstack.test.domain.rebate;
import cn.bugstack.domain.rebate.model.entity.BehaviorEntity;
import cn.bugstack.domain.rebate.model.valobj.BehaviorTypeVO;
import cn.bugstack.domain.rebate.service.IBehaviorRebateService;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 行为返利单测
* @create 2024-04-30 17:53
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class BehaviorRebateServiceTest {
@Resource
private IBehaviorRebateService behaviorRebateService;
@Test
public void test_createOrder() {
BehaviorEntity behaviorEntity = new BehaviorEntity();
behaviorEntity.setUserId("xiaofuge");
behaviorEntity.setBehaviorTypeVO(BehaviorTypeVO.SIGN);
// 重复的 OutBusinessNo 会报错唯一索引冲突,这也是保证幂等的手段,确保不会多记账
behaviorEntity.setOutBusinessNo("20240429");
List<String> orderIds = behaviorRebateService.createOrder(behaviorEntity);
log.info("请求参数:{}", JSON.toJSONString(behaviorEntity));
log.info("测试结果:{}", JSON.toJSONString(orderIds));
}
}
package cn.bugstack.domain.rebate.aggregate;
import cn.bugstack.domain.rebate.model.entity.BehaviorRebateOrderEntity;
import cn.bugstack.domain.rebate.model.entity.TaskEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @ClassName: BehaviorRebateAggregate
* @Description: 行为返利聚合对象
* @Author: zhaoyongfeng
* @Date: 2024/12/21 20:05
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BehaviorRebateAggregate {
/** 用户ID */
private String userId;
/** 行为返利订单实体对象 */
private BehaviorRebateOrderEntity behaviorRebateOrderEntity;
/** 任务实体对象 */
private TaskEntity taskEntity;
}
package cn.bugstack.domain.rebate.event;
import cn.bugstack.types.event.BaseEvent;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @ClassName: SendRebateMessageEvent
* @Description:
* @Author: zhaoyongfeng
* @Date: 2024/12/21 19:05
*/
@Component
public class SendRebateMessageEvent extends BaseEvent<SendRebateMessageEvent.RebateMessage> {
@Value("${spring.rabbitmq.topic.send_rebate}")
private String topic;
public EventMessage<RebateMessage> buildEventMessage(RebateMessage rebateMessage){
return EventMessage.<SendRebateMessageEvent.RebateMessage>builder()
.id(RandomStringUtils.randomNumeric(11))
.timestamp(new Date())
.data(rebateMessage)
.build();
}
@Override
public String topic() {
return topic;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class RebateMessage {
/** 用户ID */
private String userId;
/** 返利描述 */
private String rebateDesc;
/** 返利类型 */
private String rebateType;
/** 返利配置 */
private String rebateConfig;
/** 业务ID - 唯一ID,确保幂等 */
private String bizId;
}
}
package cn.bugstack.domain.rebate.model.entity;
import cn.bugstack.domain.rebate.model.valobj.BehaviorTypeVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @ClassName: BehaviorEntity
* @Description: 行为实体对象
* @Author: zhaoyongfeng
* @Date: 2024/12/21 18:51
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BehaviorEntity {
/**
* 用户ID
*/
private String userId;
/**
* 行为类型;sign 签到、openai_pay 支付
*/
private BehaviorTypeVO behaviorTypeVO;
/**
* 业务ID;签到则是日期字符串,支付则是外部的业务ID
*/
private String outBusinessNo;
}
package cn.bugstack.domain.rebate.model.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.checkerframework.checker.units.qual.A;
/**
* @ClassName: BehaviorRebateOrderEntity
* @Description: 行为返利订单实体对象
* @Author: zhaoyongfeng
* @Date: 2024/12/21 19:23
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class BehaviorRebateOrderEntity {
/** 用户ID */
private String userId;
/** 订单ID */
private String orderId;
/** 行为类型(sign 签到、openai_pay 支付) */
private String behaviorType;
/** 返利描述 */
private String rebateDesc;
/** 返利类型(sku 活动库存充值商品、integral 用户活动积分) */
private String rebateType;
/** 返利配置【sku值,积分值】 */
private String rebateConfig;
/** 业务ID - 拼接的唯一值 */
private String bizId;
}
package cn.bugstack.domain.rebate.model.entity;
import cn.bugstack.domain.rebate.event.SendRebateMessageEvent;
import cn.bugstack.domain.rebate.model.valobj.TaskStateVO;
import cn.bugstack.types.event.BaseEvent;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @ClassName: TaskEntity
* @Description: 任务实体对象
* @Author: zhaoyongfeng
* @Date: 2024/12/21 19:46
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TaskEntity {
/** 活动ID */
private String userId;
/** 消息主题 */
private String topic;
/** 消息编号 */
private String messageId;
/** 消息主体 */
private BaseEvent.EventMessage<SendRebateMessageEvent.RebateMessage> message;
/** 任务状态;create-创建、completed-完成、fail-失败 */
private TaskStateVO state;
}
package cn.bugstack.domain.rebate.model.valobj;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @ClassName: BehaviorTypeVO
* @Description: 行为类型枚举值对象
* @Author: zhaoyongfeng
* @Date: 2024/12/21 19:19
*/
@Getter
@AllArgsConstructor
public enum BehaviorTypeVO {
SIGN("sign", "签到(日历)"),
OPENAI_PAY("openai_pay", "openai 外部支付完成"),
;
private final String code;
private final String info;
}
package cn.bugstack.domain.rebate.model.valobj;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
/**
* @ClassName: DailyBehaviorRebateVO
* @Description: 日常行为返利配置值对象
* @Author: zhaoyongfeng
* @Date: 2024/12/21 19:12
*/
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DailyBehaviorRebateVO {
/** 行为类型(sign 签到、openai_pay 支付) */
private String behaviorType;
/** 返利描述 */
private String rebateDesc;
/** 返利类型(sku 活动库存充值商品、integral 用户活动积分) */
private String rebateType;
/** 返利配置 */
private String rebateConfig;
}
package cn.bugstack.domain.rebate.model.valobj;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
/*
* @return
* @author zhaoyongfeng
* @description 返利类型(sku 活动库存充值商品、integral 用户活动积分)
*/
@Getter
@AllArgsConstructor
public enum RebateTypeVO {
SKU("sku", "活动库存充值商品"),
INTEGRAL("integral", "用户活动积分"),
;
private final String code;
private final String info;
}
package cn.bugstack.domain.rebate.model.valobj;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.checkerframework.checker.units.qual.A;
/**
* @ClassName: TaskStateVO
* @Description:
* @Author: zhaoyongfeng
* @Date: 2024/12/21 19:46
*/
@Getter
@AllArgsConstructor
public enum TaskStateVO {
create("create", "创建"),
complete("complete", "发送完成"),
fail("fail", "发送失败"),
;
private final String code;
private final String desc;
}
package cn.bugstack.domain.rebate.repository;
import cn.bugstack.domain.rebate.aggregate.BehaviorRebateAggregate;
import cn.bugstack.domain.rebate.model.entity.BehaviorEntity;
import cn.bugstack.domain.rebate.model.valobj.BehaviorTypeVO;
import cn.bugstack.domain.rebate.model.valobj.DailyBehaviorRebateVO;
import java.util.List;
/**
* @ClassName: IBehaviorRebateRepository
* @Description:
* @Author: zhaoyongfeng
* @Date: 2024/12/21 18:53
*/
public interface IBehaviorRebateRepository {
List<DailyBehaviorRebateVO> queryDailyBehaviorRebateConfig (BehaviorTypeVO behaviorTypeVO);
void saveUserRebateRecord(String userId, List<BehaviorRebateAggregate> behaviorRebateAggregates);
}
package cn.bugstack.domain.rebate.service;
import cn.bugstack.domain.rebate.event.SendRebateMessageEvent;
import cn.bugstack.domain.rebate.aggregate.BehaviorRebateAggregate;
import cn.bugstack.domain.rebate.model.entity.BehaviorEntity;
import cn.bugstack.domain.rebate.model.entity.BehaviorRebateOrderEntity;
import cn.bugstack.domain.rebate.model.entity.TaskEntity;
import cn.bugstack.domain.rebate.model.valobj.DailyBehaviorRebateVO;
import cn.bugstack.domain.rebate.model.valobj.TaskStateVO;
import cn.bugstack.domain.rebate.repository.IBehaviorRebateRepository;
import cn.bugstack.types.common.Constants;
import cn.bugstack.types.event.BaseEvent;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: BehaviorRebateService
* @Description:
* @Author: zhaoyongfeng
* @Date: 2024/12/21 18:50
*/
@Service
public class BehaviorRebateService implements IBehaviorRebateService{
@Resource
private IBehaviorRebateRepository behaviorRebateRepository;
@Resource
private SendRebateMessageEvent sendRebateMessageEvent;
@Override
public List<String> createOrder(BehaviorEntity behaviorEntity) {
// 1. 查询返利配置
List<DailyBehaviorRebateVO> dailyBehaviorRebateVOS = behaviorRebateRepository.queryDailyBehaviorRebateConfig(behaviorEntity.getBehaviorTypeVO());
if (null == dailyBehaviorRebateVOS || dailyBehaviorRebateVOS.isEmpty()) return new ArrayList<>();
// 2. 构建聚合对象
List<String> orderIds = new ArrayList<>();
List<BehaviorRebateAggregate> behaviorRebateAggregates = new ArrayList<>();
for(DailyBehaviorRebateVO dailyBehaviorRebateVO : dailyBehaviorRebateVOS){
String bizId = behaviorEntity.getUserId() + Constants.UNDERLINE + dailyBehaviorRebateVO.getRebateType() + Constants.UNDERLINE + behaviorEntity.getOutBusinessNo();
BehaviorRebateOrderEntity behaviorRebateOrderEntity = BehaviorRebateOrderEntity.builder()
.userId(behaviorEntity.getUserId())
.orderId(RandomStringUtils.randomNumeric(12))
.behaviorType(dailyBehaviorRebateVO.getBehaviorType())
.rebateDesc(dailyBehaviorRebateVO.getRebateDesc())
.rebateType(dailyBehaviorRebateVO.getRebateType())
.rebateConfig(dailyBehaviorRebateVO.getRebateConfig())
.bizId(bizId)
.build();
orderIds.add(behaviorRebateOrderEntity.getOrderId());
// MQ 消息对象
SendRebateMessageEvent.RebateMessage rebateMessage = SendRebateMessageEvent.RebateMessage.builder()
.userId(behaviorEntity.getUserId())
.rebateType(dailyBehaviorRebateVO.getBehaviorType())
.rebateConfig(dailyBehaviorRebateVO.getRebateConfig())
.bizId(bizId)
.build();
// 构建事件消息
BaseEvent.EventMessage<SendRebateMessageEvent.RebateMessage> rebateMessageEventMessage = sendRebateMessageEvent.buildEventMessage(rebateMessage);
// 组装任务对象
TaskEntity taskEntity = new TaskEntity();
taskEntity.setUserId(behaviorEntity.getUserId());
taskEntity.setTopic(sendRebateMessageEvent.topic());
taskEntity.setMessageId(rebateMessageEventMessage.getId());
taskEntity.setMessage(rebateMessageEventMessage);
taskEntity.setState(TaskStateVO.create);
BehaviorRebateAggregate behaviorRebateAggregate = BehaviorRebateAggregate.builder()
.userId(behaviorEntity.getUserId())
.behaviorRebateOrderEntity(behaviorRebateOrderEntity)
.taskEntity(taskEntity)
.build();
behaviorRebateAggregates.add(behaviorRebateAggregate);
}
// 3. 存储聚合对象数据
behaviorRebateRepository.saveUserRebateRecord(behaviorEntity.getUserId(), behaviorRebateAggregates);
// 4. 返回订单ID集合
return orderIds;
}
}
package cn.bugstack.domain.rebate.service;
import cn.bugstack.domain.rebate.model.entity.BehaviorEntity;
import java.util.List;
/*
* @return
* @author zhaoyongfeng
* @description 行为返利服务接口
*/
public interface IBehaviorRebateService {
/*
* 创建行为动作的入账订单
*
* @param behaviorEntity 行为实体对象
* @return 订单ID
*/
List<String> createOrder(BehaviorEntity behaviorEntity);
}
package cn.bugstack.infrastructure.persistent.dao;
import cn.bugstack.infrastructure.persistent.po.DailyBehaviorRebate;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 日常行为返利活动配置
* @create 2024-04-30 13:48
*/
@Mapper
public interface IDailyBehaviorRebateDao {
List<DailyBehaviorRebate> queryDailyBehaviorRebateByBehaviorType(String behaviorType);
}
...@@ -21,6 +21,10 @@ public interface IRaffleActivityAccountDao { ...@@ -21,6 +21,10 @@ public interface IRaffleActivityAccountDao {
int updateActivityAccountSubtractionQuota(RaffleActivityAccount raffleActivityAccount); int updateActivityAccountSubtractionQuota(RaffleActivityAccount raffleActivityAccount);
int updateActivityAccountMonthSubtractionQuota(RaffleActivityAccount raffleActivityAccount);
int updateActivityAccountDaySubtractionQuota(RaffleActivityAccount raffleActivityAccount);
void updateActivityAccountMonthSurplusImageQuota(RaffleActivityAccount raffleActivityAccount); void updateActivityAccountMonthSurplusImageQuota(RaffleActivityAccount raffleActivityAccount);
void updateActivityAccountDaySurplusImageQuota(RaffleActivityAccount raffleActivityAccount); void updateActivityAccountDaySurplusImageQuota(RaffleActivityAccount raffleActivityAccount);
......
...@@ -18,6 +18,9 @@ public interface IRaffleActivityAccountDayDao { ...@@ -18,6 +18,9 @@ public interface IRaffleActivityAccountDayDao {
int updateActivityAccountDaySubtractionQuota(RaffleActivityAccountDay raffleActivityAccountDay); int updateActivityAccountDaySubtractionQuota(RaffleActivityAccountDay raffleActivityAccountDay);
void insertActivityAccountDay(RaffleActivityAccountDay raffleActivityAccountDay); void insertActivityAccountDay(RaffleActivityAccountDay raffleActivityAccountDay);
@DBRouter @DBRouter
Integer queryRaffleActivityAccountDayPartakeCount(RaffleActivityAccountDay raffleActivityAccountDay); Integer queryRaffleActivityAccountDayPartakeCount(RaffleActivityAccountDay raffleActivityAccountDay);
void addAccountQuota(RaffleActivityAccountDay raffleActivityAccountDay);
} }
...@@ -19,4 +19,5 @@ public interface IRaffleActivityAccountMonthDao { ...@@ -19,4 +19,5 @@ public interface IRaffleActivityAccountMonthDao {
void insertActivityAccountMonth(RaffleActivityAccountMonth raffleActivityAccountMonth); void insertActivityAccountMonth(RaffleActivityAccountMonth raffleActivityAccountMonth);
void addAccountQuota(RaffleActivityAccountMonth raffleActivityAccountMonth);
} }
...@@ -16,4 +16,5 @@ public interface IRaffleActivityDao { ...@@ -16,4 +16,5 @@ public interface IRaffleActivityDao {
Long queryStrategyIdByActivityId(Long activityId); Long queryStrategyIdByActivityId(Long activityId);
Long queryActivityIdByStrategyId(Long strategyId); Long queryActivityIdByStrategyId(Long strategyId);
} }
...@@ -20,4 +20,5 @@ public interface IRaffleActivitySkuDao { ...@@ -20,4 +20,5 @@ public interface IRaffleActivitySkuDao {
void clearActivitySkuStock(Long sku); void clearActivitySkuStock(Long sku);
List<RaffleActivitySku> queryActivitySkuListByActivityId(Long activityId); List<RaffleActivitySku> queryActivitySkuListByActivityId(Long activityId);
} }
...@@ -16,4 +16,5 @@ public interface IRuleTreeNodeDao { ...@@ -16,4 +16,5 @@ public interface IRuleTreeNodeDao {
List<RuleTreeNode> queryRuleTreeNodeListByTreeId(String treeId); List<RuleTreeNode> queryRuleTreeNodeListByTreeId(String treeId);
List<RuleTreeNode> queryRuleLocks(String[] treeIds); List<RuleTreeNode> queryRuleLocks(String[] treeIds);
} }
...@@ -13,11 +13,15 @@ import java.util.List; ...@@ -13,11 +13,15 @@ import java.util.List;
*/ */
@Mapper @Mapper
public interface ITaskDao { public interface ITaskDao {
void insert(Task task); void insert(Task task);
@DBRouter @DBRouter
void updateTaskSendMessageCompleted(Task task); void updateTaskSendMessageCompleted(Task task);
@DBRouter @DBRouter
void updateTaskSendMessageFail(Task task); void updateTaskSendMessageFail(Task task);
List<Task> queryNoSendMessageTaskList(); List<Task> queryNoSendMessageTaskList();
} }
package cn.bugstack.infrastructure.persistent.dao; package cn.bugstack.infrastructure.persistent.dao;
import cn.bugstack.infrastructure.persistent.po.UserAwardRecord; import cn.bugstack.infrastructure.persistent.po.UserAwardRecord;
import cn.bugstack.middleware.db.router.annotation.DBRouter;
import cn.bugstack.middleware.db.router.annotation.DBRouterStrategy; import cn.bugstack.middleware.db.router.annotation.DBRouterStrategy;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
...@@ -13,5 +12,7 @@ import org.apache.ibatis.annotations.Mapper; ...@@ -13,5 +12,7 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper @Mapper
@DBRouterStrategy(splitTable = true) @DBRouterStrategy(splitTable = true)
public interface IUserAwardRecordDao { public interface IUserAwardRecordDao {
void insert(UserAwardRecord userAwardRecord); void insert(UserAwardRecord userAwardRecord);
} }
package cn.bugstack.infrastructure.persistent.dao;
import cn.bugstack.infrastructure.persistent.po.UserBehaviorRebateOrder;
import cn.bugstack.middleware.db.router.annotation.DBRouterStrategy;
import org.apache.ibatis.annotations.Mapper;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 用户行为返利流水订单表
* @create 2024-04-30 13:48
*/
@Mapper
@DBRouterStrategy(splitTable = true)
public interface IUserBehaviorRebateOrderDao {
void insert(UserBehaviorRebateOrder userBehaviorRebateOrder);
}
...@@ -20,4 +20,5 @@ public interface IUserRaffleOrderDao { ...@@ -20,4 +20,5 @@ public interface IUserRaffleOrderDao {
UserRaffleOrder queryNoUsedRaffleOrder(UserRaffleOrder userRaffleOrderReq); UserRaffleOrder queryNoUsedRaffleOrder(UserRaffleOrder userRaffleOrderReq);
int updateUserRaffleOrderStateUsed(UserRaffleOrder userRaffleOrderReq); int updateUserRaffleOrderStateUsed(UserRaffleOrder userRaffleOrderReq);
} }
package cn.bugstack.infrastructure.persistent.po;
import lombok.Data;
import java.util.Date;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 日常行为返利活动配置 持久化对象
* @create 2024-04-30 13:38
*/
@Data
public class DailyBehaviorRebate {
/** 自增ID */
private Long id;
/** 行为类型(sign 签到、openai_pay 支付) */
private String behaviorType;
/** 返利描述 */
private String rebateDesc;
/** 返利类型(sku 活动库存充值商品、integral 用户活动积分) */
private String rebateType;
/** 返利配置 */
private String rebateConfig;
/** 状态(open 开启、close 关闭) */
private String state;
/** 创建时间 */
private Date createTime;
/** 更新时间 */
private Date updateTime;
}
...@@ -21,23 +21,41 @@ public class RaffleActivityAccountDay { ...@@ -21,23 +21,41 @@ public class RaffleActivityAccountDay {
private final SimpleDateFormat dateFormatDay = new SimpleDateFormat("yyyy-MM-dd"); private final SimpleDateFormat dateFormatDay = new SimpleDateFormat("yyyy-MM-dd");
/** 自增ID */ /**
* 自增ID
*/
private String id; private String id;
/** 用户ID */ /**
* 用户ID
*/
private String userId; private String userId;
/** 活动ID */ /**
* 活动ID
*/
private Long activityId; private Long activityId;
/** 日期(yyyy-mm-dd) */ /**
* 日期(yyyy-mm-dd)
*/
private String day; private String day;
/** 日次数 */ /**
* 日次数
*/
private Integer dayCount; private Integer dayCount;
/** 日次数-剩余 */ /**
* 日次数-剩余
*/
private Integer dayCountSurplus; private Integer dayCountSurplus;
/** 创建时间 */ /**
* 创建时间
*/
private Date createTime; private Date createTime;
/** 更新时间 */ /**
* 更新时间
*/
private Date updateTime; private Date updateTime;
public String currentDay() { public String currentDay() {
return dateFormatDay.format(new Date()); return dateFormatDay.format(new Date());
} }
} }
...@@ -5,6 +5,7 @@ import lombok.Builder; ...@@ -5,6 +5,7 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
/** /**
...@@ -17,6 +18,7 @@ import java.util.Date; ...@@ -17,6 +18,7 @@ import java.util.Date;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class RaffleActivityAccountMonth { public class RaffleActivityAccountMonth {
private final SimpleDateFormat dateFormatMonth = new SimpleDateFormat("yyyy-MM");
/** 自增ID */ /** 自增ID */
private String id; private String id;
...@@ -34,5 +36,7 @@ public class RaffleActivityAccountMonth { ...@@ -34,5 +36,7 @@ public class RaffleActivityAccountMonth {
private Date createTime; private Date createTime;
/** 更新时间 */ /** 更新时间 */
private Date updateTime; private Date updateTime;
public String currentMonth() {
return dateFormatMonth.format(new Date());
}
} }
...@@ -11,6 +11,7 @@ import java.util.Date; ...@@ -11,6 +11,7 @@ import java.util.Date;
*/ */
@Data @Data
public class RaffleActivitySku { public class RaffleActivitySku {
/** /**
* 商品sku * 商品sku
*/ */
......
...@@ -5,7 +5,7 @@ import lombok.Data; ...@@ -5,7 +5,7 @@ import lombok.Data;
import java.util.Date; import java.util.Date;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 任务表,发送MQ * @description 任务表,发送MQ
* @create 2024-04-03 15:30 * @create 2024-04-03 15:30
*/ */
...@@ -14,7 +14,7 @@ public class Task { ...@@ -14,7 +14,7 @@ public class Task {
/** 自增ID */ /** 自增ID */
private String id; private String id;
/** 用户ID */ /** 活动ID */
private String userId; private String userId;
/** 消息主题 */ /** 消息主题 */
private String topic; private String topic;
......
package cn.bugstack.infrastructure.persistent.po;
import lombok.Data;
import java.util.Date;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 用户行为返利流水订单表 持久化对象
* @create 2024-04-30 13:43
*/
@Data
public class UserBehaviorRebateOrder {
/** 自增ID */
private Long id;
/** 用户ID */
private String userId;
/** 订单ID */
private String orderId;
/** 行为类型(sign 签到、openai_pay 支付) */
private String behaviorType;
/** 返利描述 */
private String rebateDesc;
/** 返利类型(sku 活动库存充值商品、integral 用户活动积分) */
private String rebateType;
/** 返利配置【sku值,积分值】 */
private String rebateConfig;
/** 业务ID - 拼接的唯一值 */
private String bizId;
/** 创建时间 */
private Date createTime;
/** 更新时间 */
private Date updateTime;
}
...@@ -143,7 +143,7 @@ public class ActivityRepository implements IActivityRepository { ...@@ -143,7 +143,7 @@ public class ActivityRepository implements IActivityRepository {
raffleActivityOrder.setState(activityOrderEntity.getState().getCode()); raffleActivityOrder.setState(activityOrderEntity.getState().getCode());
raffleActivityOrder.setOutBusinessNo(activityOrderEntity.getOutBusinessNo()); raffleActivityOrder.setOutBusinessNo(activityOrderEntity.getOutBusinessNo());
// 账户对象 // 账户对象 - 总
RaffleActivityAccount raffleActivityAccount = new RaffleActivityAccount(); RaffleActivityAccount raffleActivityAccount = new RaffleActivityAccount();
raffleActivityAccount.setUserId(createOrderAggregate.getUserId()); raffleActivityAccount.setUserId(createOrderAggregate.getUserId());
raffleActivityAccount.setActivityId(createOrderAggregate.getActivityId()); raffleActivityAccount.setActivityId(createOrderAggregate.getActivityId());
...@@ -154,6 +154,23 @@ public class ActivityRepository implements IActivityRepository { ...@@ -154,6 +154,23 @@ public class ActivityRepository implements IActivityRepository {
raffleActivityAccount.setMonthCount(createOrderAggregate.getMonthCount()); raffleActivityAccount.setMonthCount(createOrderAggregate.getMonthCount());
raffleActivityAccount.setMonthCountSurplus(createOrderAggregate.getMonthCount()); raffleActivityAccount.setMonthCountSurplus(createOrderAggregate.getMonthCount());
// 账户对象 - 月
RaffleActivityAccountMonth raffleActivityAccountMonth = new RaffleActivityAccountMonth();
raffleActivityAccountMonth.setUserId(createOrderAggregate.getUserId());
raffleActivityAccountMonth.setActivityId(createOrderAggregate.getActivityId());
raffleActivityAccountMonth.setMonth(raffleActivityAccountMonth.currentMonth());
raffleActivityAccountMonth.setMonthCount(createOrderAggregate.getMonthCount());
raffleActivityAccountMonth.setMonthCountSurplus(createOrderAggregate.getMonthCount());
// 账户对象 - 日
RaffleActivityAccountDay raffleActivityAccountDay = new RaffleActivityAccountDay();
raffleActivityAccountDay.setUserId(createOrderAggregate.getUserId());
raffleActivityAccountDay.setActivityId(createOrderAggregate.getActivityId());
raffleActivityAccountDay.setDay(raffleActivityAccountDay.currentDay());
raffleActivityAccountDay.setDayCount(createOrderAggregate.getDayCount());
raffleActivityAccountDay.setDayCountSurplus(createOrderAggregate.getDayCount());
// 以用户ID作为切分键,通过 doRouter 设定路由【这样就保证了下面的操作,都是同一个链接下,也就保证了事务的特性】 // 以用户ID作为切分键,通过 doRouter 设定路由【这样就保证了下面的操作,都是同一个链接下,也就保证了事务的特性】
dbRouter.doRouter(createOrderAggregate.getUserId()); dbRouter.doRouter(createOrderAggregate.getUserId());
// 编程式事务 // 编程式事务
...@@ -167,6 +184,10 @@ public class ActivityRepository implements IActivityRepository { ...@@ -167,6 +184,10 @@ public class ActivityRepository implements IActivityRepository {
if (0 == count) { if (0 == count) {
raffleActivityAccountDao.insert(raffleActivityAccount); raffleActivityAccountDao.insert(raffleActivityAccount);
} }
// 4. 更新账户 - 月
raffleActivityAccountMonthDao.addAccountQuota(raffleActivityAccountMonth);
// 5. 更新账户 - 日
raffleActivityAccountDayDao.addAccountQuota(raffleActivityAccountDay);
return 1; return 1;
} catch (DuplicateKeyException e) { } catch (DuplicateKeyException e) {
status.setRollbackOnly(); status.setRollbackOnly();
......
package cn.bugstack.trigger.listener;
import cn.bugstack.domain.activity.model.entity.SkuRechargeEntity;
import cn.bugstack.domain.activity.service.IRaffleActivityAccountQuotaService;
import cn.bugstack.domain.rebate.event.SendRebateMessageEvent;
import cn.bugstack.domain.rebate.model.valobj.RebateTypeVO;
import cn.bugstack.types.enums.ResponseCode;
import cn.bugstack.types.event.BaseEvent;
import cn.bugstack.types.exception.AppException;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @ClassName: RebateMessageCustomer
* @Description: 监听;行为返利消息
* @Author: zhaoyongfeng
* @Date: 2024/12/24 20:57
*/
@Slf4j
@Component
public class RebateMessageCustomer {
@Value("${spring.rabbitmq.topic.send_rebate}")
private String topic;
@Resource
private IRaffleActivityAccountQuotaService raffleActivityAccountQuotaService;
@RabbitListener(queuesToDeclare = @Queue(value = "${spring.rabbitmq.topic.send_rebate}"))
public void listener(String message){
try{
log.info("监听用户行为返利消息 topic: {} message: {}", topic, message);
// 1. 转换消息
BaseEvent.EventMessage<SendRebateMessageEvent.RebateMessage> eventMessage = JSON.parseObject(message, new TypeReference<BaseEvent.EventMessage<SendRebateMessageEvent.RebateMessage>>() {
}.getType());
SendRebateMessageEvent.RebateMessage rebateMessage = eventMessage.getData();
if(!RebateTypeVO.SKU.getCode().equals(rebateMessage.getRebateType())){
log.info("监听用户行为返利消息 - 非sku奖励暂时不处理 topic: {} message: {}", topic, message);
return ;
}
// 2.入账奖励
SkuRechargeEntity skuRechargeEntity = new SkuRechargeEntity();
skuRechargeEntity.setUserId(rebateMessage.getUserId());
skuRechargeEntity.setSku(Long.valueOf(rebateMessage.getRebateConfig()));
skuRechargeEntity.setOutBusinessNo(rebateMessage.getBizId());
raffleActivityAccountQuotaService.createOrder(skuRechargeEntity);
}catch (AppException e){
if (ResponseCode.INDEX_DUP.getCode().equals(e.getCode())) {
log.warn("监听用户行为返利消息,消费重复 topic: {} message: {}", topic, message, e);
return;
}
throw e;
}catch (Exception e){
log.error("监听用户行为返利消息,消费失败 topic: {} message: {}", topic, message, e);
throw e;
}
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册