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

引入Dubbo分布式框架和Zookeeper配置中心+添加积分兑换服务和接口

上级 5f0ef351
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/docs/dev-ops/mysql/sql/big_market.sql" dialect="MySQL" />
<file url="file://$PROJECT_DIR$/docs/dev-ops/mysql/sql/big_market_01.sql" dialect="MySQL" />
<file url="file://$PROJECT_DIR$/docs/dev-ops/mysql/sql/big_market_02.sql" dialect="MySQL" />
</component>
</project>
\ No newline at end of file
package cn.bugstack.trigger.api;
import cn.bugstack.trigger.api.response.Response;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description DCC 动态配置中心
* @create 2024-07-13 08:58
*/
public interface IDCCService {
Response<Boolean> updateConfig(String key, String value);
}
package cn.bugstack.trigger.api; package cn.bugstack.trigger.api;
import cn.bugstack.trigger.api.dto.ActivityDrawRequestDTO; import cn.bugstack.trigger.api.dto.*;
import cn.bugstack.trigger.api.dto.ActivityDrawResponseDTO; import cn.bugstack.trigger.api.response.Response;
import cn.bugstack.trigger.api.dto.UserActivityAccountRequestDTO;
import cn.bugstack.trigger.api.dto.UserActivityAccountResponseDTO; import java.math.BigDecimal;
import cn.bugstack.types.model.Response; import java.util.List;
/* /*
* @return * @return
...@@ -14,37 +14,66 @@ import cn.bugstack.types.model.Response; ...@@ -14,37 +14,66 @@ import cn.bugstack.types.model.Response;
public interface IRaffleActivityService { public interface IRaffleActivityService {
/** /**
* 活动装配,数据预热缓存 * 活动装配,数据预热缓存
*
* @param activityId 活动ID * @param activityId 活动ID
* @return 装配结果 * @return 装配结果
*/ */
Response<Boolean> armory(Long activityId); cn.bugstack.trigger.api.response.Response<Boolean> armory(Long activityId);
/** /**
* 活动抽奖接口 * 活动抽奖接口
*
* @param request 请求对象 * @param request 请求对象
* @return 返回结果 * @return 返回结果
*/ */
Response<ActivityDrawResponseDTO> draw(ActivityDrawRequestDTO request); cn.bugstack.trigger.api.response.Response<ActivityDrawResponseDTO> draw(ActivityDrawRequestDTO request);
/** /**
* 日历签到返利接口 * 日历签到返利接口
* *
* @param userId 用户ID * @param userId 用户ID
* @return 签到结果 * @return 签到结果
*/ */
Response<Boolean> calendarSignRebate(String userId); cn.bugstack.trigger.api.response.Response<Boolean> calendarSignRebate(String userId);
/** /**
* 判断是否完成日历签到返利接口 * 判断是否完成日历签到返利接口
* *
* @param userId 用户ID * @param userId 用户ID
* @return 签到结果 true 已签到,false 未签到 * @return 签到结果 true 已签到,false 未签到
*/ */
Response<Boolean> isCalendarSignRebate(String userId); cn.bugstack.trigger.api.response.Response<Boolean> isCalendarSignRebate(String userId);
/** /**
* 查询用户活动账户 * 查询用户活动账户
* *
* @param request 请求对象「活动ID、用户ID」 * @param request 请求对象「活动ID、用户ID」
* @return 返回结果「总额度、月额度、日额度」 * @return 返回结果「总额度、月额度、日额度」
*/ */
Response<UserActivityAccountResponseDTO> queryUserActivityAccount(UserActivityAccountRequestDTO request); cn.bugstack.trigger.api.response.Response<UserActivityAccountResponseDTO> queryUserActivityAccount(UserActivityAccountRequestDTO request);
/**
* 查询sku商品集合
*
* @param activityId 活动ID
* @return 商品集合
*/
cn.bugstack.trigger.api.response.Response<List<SkuProductResponseDTO>> querySkuProductListByActivityId(Long activityId);
/**
* 查询用户积分值
*
* @param userId 用户ID
* @return 可用积分
*/
cn.bugstack.trigger.api.response.Response<BigDecimal> queryUserCreditAccount(String userId);
/**
* 积分支付兑换商品
*
* @param request 请求对象「用户ID、商品ID」
* @return 兑换结果
*/
Response<Boolean> creditPayExchangeSku(SkuProductShopCartRequestDTO request);
} }
package cn.bugstack.trigger.api; package cn.bugstack.trigger.api;
import cn.bugstack.trigger.api.dto.*; import cn.bugstack.trigger.api.dto.*;
import cn.bugstack.types.model.Response; import cn.bugstack.trigger.api.response.Response;
import java.util.List; import java.util.List;
/* /*
...@@ -18,30 +18,31 @@ public interface IRaffleStrategyService { ...@@ -18,30 +18,31 @@ public interface IRaffleStrategyService {
* @param strategyId 策略ID * @param strategyId 策略ID
* @return 装配结果 * @return 装配结果
*/ */
Response<Boolean> strategyArmory(Long strategyId); cn.bugstack.trigger.api.response.Response<Boolean> strategyArmory(Long strategyId);
/** /**
* 查询抽奖奖品列表配置 * 查询抽奖奖品列表配置
* *
* @param requestDTO 抽奖奖品列表查询请求参数 * @param request 抽奖奖品列表查询请求参数
* @return 奖品列表数据 * @return 奖品列表数据
*/ */
Response<List<RaffleAwardListResponseDTO>> queryRaffleAwardList(RaffleAwardListRequestDTO requestDTO); cn.bugstack.trigger.api.response.Response<List<RaffleAwardListResponseDTO>> queryRaffleAwardList(RaffleAwardListRequestDTO request);
/**
* 随机抽奖接口
*
* @param requestDTO 请求参数
* @return 抽奖结果
*/
Response<RaffleResponseDTO> randomRaffle(RaffleRequestDTO requestDTO);
/** /**
* 查询抽奖策略权重规则,给用户展示出抽奖N次后必中奖奖品范围 * 查询抽奖策略权重规则,给用户展示出抽奖N次后必中奖奖品范围
* *
* @param request 请求对象 * @param request 请求对象
* @return 权重奖品配置列表「这里会返回全部,前端可按需展示一条已达标的,或者一条要达标的」 * @return 权重奖品配置列表「这里会返回全部,前端可按需展示一条已达标的,或者一条要达标的」
*/ */
Response<List<RaffleStrategyRuleWeightResponseDTO>> queryRaffleStrategyRuleWeight(RaffleStrategyRuleWeightRequestDTO request); cn.bugstack.trigger.api.response.Response<List<RaffleStrategyRuleWeightResponseDTO>> queryRaffleStrategyRuleWeight(RaffleStrategyRuleWeightRequestDTO request);
/**
* 随机抽奖接口
*
* @param request 请求参数
* @return 抽奖结果
*/
Response<RaffleStrategyResponseDTO> randomRaffle(RaffleStrategyRequestDTO request);
} }
...@@ -2,14 +2,16 @@ package cn.bugstack.trigger.api.dto; ...@@ -2,14 +2,16 @@ package cn.bugstack.trigger.api.dto;
import lombok.Data; import lombok.Data;
import java.io.Serializable;
/** /**
* @ClassName: ActivityDrawRequestDTO * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 活动抽奖请求对象 * @description 活动抽奖请求对象
* @Author: zhaoyongfeng * @create 2024-04-13 09:29
* @Date: 2024/12/10 22:06
*/ */
@Data @Data
public class ActivityDrawRequestDTO { public class ActivityDrawRequestDTO implements Serializable {
/** /**
* 用户ID * 用户ID
*/ */
...@@ -19,4 +21,5 @@ public class ActivityDrawRequestDTO { ...@@ -19,4 +21,5 @@ public class ActivityDrawRequestDTO {
* 活动ID * 活动ID
*/ */
private Long activityId; private Long activityId;
} }
...@@ -5,16 +5,18 @@ import lombok.Builder; ...@@ -5,16 +5,18 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/* import java.io.Serializable;
* @return
* @author zhaoyongfeng /**
* @description 活动抽奖返回对象 * @author Fuzhengwei bugstack.cn @小傅哥
* @description
* @create 2024-04-13 09:34
*/ */
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class ActivityDrawResponseDTO { public class ActivityDrawResponseDTO implements Serializable {
// 奖品ID // 奖品ID
private Integer awardId; private Integer awardId;
......
...@@ -2,14 +2,15 @@ package cn.bugstack.trigger.api.dto; ...@@ -2,14 +2,15 @@ package cn.bugstack.trigger.api.dto;
import lombok.Data; import lombok.Data;
import java.io.Serializable;
/** /**
* @ClassName: RaffleAwardListRequestDTO * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 抽奖奖品列表,请求对象 * @description 抽奖奖品列表,请求对象
* @Author: zhaoyongfeng * @create 2024-02-14 09:46
* @Date: 2024/11/22 16:35
*/ */
@Data @Data
public class RaffleAwardListRequestDTO { public class RaffleAwardListRequestDTO implements Serializable {
// 用户ID // 用户ID
private String userId; private String userId;
...@@ -17,4 +18,3 @@ public class RaffleAwardListRequestDTO { ...@@ -17,4 +18,3 @@ public class RaffleAwardListRequestDTO {
private Long activityId; private Long activityId;
} }
...@@ -5,17 +5,18 @@ import lombok.Builder; ...@@ -5,17 +5,18 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serializable;
/** /**
* @ClassName: RaffleAwardListRequestDTO * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 抽奖奖品列表,应答对象 * @description 抽奖奖品列表,应答对象
* @Author: zhaoyongfeng * @create 2024-02-14 09:43
* @Date: 2024/11/22 16:35
*/ */
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class RaffleAwardListResponseDTO { public class RaffleAwardListResponseDTO implements Serializable {
// 奖品ID // 奖品ID
private Integer awardId; private Integer awardId;
...@@ -33,5 +34,3 @@ public class RaffleAwardListResponseDTO { ...@@ -33,5 +34,3 @@ public class RaffleAwardListResponseDTO {
private Integer waitUnLockCount; private Integer waitUnLockCount;
} }
package cn.bugstack.trigger.api.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 抽奖请求参数
* @create 2024-02-14 17:26
*/
@Data
public class RaffleStrategyRequestDTO implements Serializable {
// 抽奖策略ID
private Long strategyId;
}
package cn.bugstack.trigger.api.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 抽奖应答结果
* @create 2024-02-14 17:26
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RaffleStrategyResponseDTO implements Serializable {
// 奖品ID
private Integer awardId;
// 排序编号【策略奖品配置的奖品顺序编号】
private Integer awardIndex;
}
...@@ -2,16 +2,19 @@ package cn.bugstack.trigger.api.dto; ...@@ -2,16 +2,19 @@ package cn.bugstack.trigger.api.dto;
import lombok.Data; import lombok.Data;
import java.io.Serializable;
/** /**
* @ClassName: RaffleStrategyRuleWeightRequestDTO * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 抽奖策略规则,权重配置,查询N次抽奖可解锁奖品范围,请求对象 * @description 抽奖策略规则,权重配置,查询N次抽奖可解锁奖品范围,请求对象
* @Author: zhaoyongfeng * @create 2024-05-03 09:35
* @Date: 2024/12/26 0:14
*/ */
@Data @Data
public class RaffleStrategyRuleWeightRequestDTO { public class RaffleStrategyRuleWeightRequestDTO implements Serializable {
// 用户ID // 用户ID
private String userId; private String userId;
// 抽奖活动ID // 抽奖活动ID
private Long activityId; private Long activityId;
} }
...@@ -2,16 +2,17 @@ package cn.bugstack.trigger.api.dto; ...@@ -2,16 +2,17 @@ package cn.bugstack.trigger.api.dto;
import lombok.Data; import lombok.Data;
import java.io.Serializable;
import java.util.List; import java.util.List;
/** /**
* @ClassName: RaffleStrategyRuleWeightResponseDTO * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 抽奖策略规则,权重配置,查询N次抽奖可解锁奖品范围,应答对象
* @Author: zhaoyongfeng * @create 2024-05-03 09:35
* @Date: 2024/12/26 0:13
*/ */
@Data @Data
public class RaffleStrategyRuleWeightResponseDTO { public class RaffleStrategyRuleWeightResponseDTO implements Serializable {
// 权重规则配置的抽奖次数 // 权重规则配置的抽奖次数
private Integer ruleWeightCount; private Integer ruleWeightCount;
// 用户在一个活动下完成的总抽奖次数 // 用户在一个活动下完成的总抽奖次数
...@@ -26,4 +27,5 @@ public class RaffleStrategyRuleWeightResponseDTO { ...@@ -26,4 +27,5 @@ public class RaffleStrategyRuleWeightResponseDTO {
// 奖品标题 // 奖品标题
private String awardTitle; private String awardTitle;
} }
} }
package cn.bugstack.trigger.api.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description sku商品对象
* @create 2024-06-15 09:12
*/
@Data
public class SkuProductResponseDTO implements Serializable {
/**
* 商品sku
*/
private Long sku;
/**
* 活动ID
*/
private Long activityId;
/**
* 活动个人参与次数ID
*/
private Long activityCountId;
/**
* 库存总量
*/
private Integer stockCount;
/**
* 剩余库存
*/
private Integer stockCountSurplus;
/**
* 商品金额【积分】
*/
private BigDecimal productAmount;
/**
* 活动商品数量
*/
private ActivityCount activityCount;
@Data
public static class ActivityCount {
/**
* 总次数
*/
private Integer totalCount;
/**
* 日次数
*/
private Integer dayCount;
/**
* 月次数
*/
private Integer monthCount;
}
}
package cn.bugstack.trigger.api.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 商品购物车请求对象
* @create 2024-06-15 08:03
*/
@Data
public class SkuProductShopCartRequestDTO implements Serializable {
/**
* 用户ID
*/
private String userId;
/**
* sku 商品
*/
private Long sku;
}
...@@ -2,14 +2,16 @@ package cn.bugstack.trigger.api.dto; ...@@ -2,14 +2,16 @@ package cn.bugstack.trigger.api.dto;
import lombok.Data; import lombok.Data;
import java.io.Serializable;
/** /**
* @ClassName: UserActivityAccountRequestDTO * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 用户活动账户请求对象
* @Author: zhaoyongfeng * @create 2024-05-03 07:17
* @Date: 2024/12/25 23:25
*/ */
@Data @Data
public class UserActivityAccountRequestDTO { public class UserActivityAccountRequestDTO implements Serializable {
/** /**
* 用户ID * 用户ID
*/ */
...@@ -19,4 +21,5 @@ public class UserActivityAccountRequestDTO { ...@@ -19,4 +21,5 @@ public class UserActivityAccountRequestDTO {
* 活动ID * 活动ID
*/ */
private Long activityId; private Long activityId;
} }
...@@ -5,17 +5,19 @@ import lombok.Builder; ...@@ -5,17 +5,19 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serializable;
/** /**
* @ClassName: UserActivityAccountReponseDTO * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 用户活动账户应答对象
* @Author: zhaoyongfeng * @create 2024-05-03 07:18
* @Date: 2024/12/25 23:22
*/ */
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class UserActivityAccountResponseDTO { public class UserActivityAccountResponseDTO implements Serializable {
/** /**
* 总次数 * 总次数
*/ */
...@@ -45,4 +47,5 @@ public class UserActivityAccountResponseDTO { ...@@ -45,4 +47,5 @@ public class UserActivityAccountResponseDTO {
* 月次数-剩余 * 月次数-剩余
*/ */
private Integer monthCountSurplus; private Integer monthCountSurplus;
} }
package cn.bugstack.types.model; package cn.bugstack.trigger.api.response;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
...@@ -7,12 +7,6 @@ import lombok.NoArgsConstructor; ...@@ -7,12 +7,6 @@ import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
/**
* @ClassName: Response
* @Description:
* @Author: zhaoyongfeng
* @Date: 2024/11/22 16:44
*/
@Data @Data
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
......
...@@ -82,6 +82,10 @@ ...@@ -82,6 +82,10 @@
<groupId>org.redisson</groupId> <groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId> <artifactId>redisson-spring-boot-starter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-random-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>cn.bugstack.middleware</groupId> <groupId>cn.bugstack.middleware</groupId>
<artifactId>db-router-spring-boot-starter</artifactId> <artifactId>db-router-spring-boot-starter</artifactId>
...@@ -90,6 +94,29 @@ ...@@ -90,6 +94,29 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId> <artifactId>spring-boot-starter-amqp</artifactId>
</dependency> </dependency>
<!-- Dubbo + Nacos -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
<dependency>
<groupId>plus.gaga</groupId>
<artifactId>business-behavior-monitor-sdk</artifactId>
<version>1.1</version>
</dependency>
<!-- 工程模块;启动依赖 trigger->domain, infrastructure--> <!-- 工程模块;启动依赖 trigger->domain, infrastructure-->
<dependency> <dependency>
<groupId>cn.bugstack</groupId> <groupId>cn.bugstack</groupId>
......
package cn.bugstack; package cn.bugstack;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.beans.factory.annotation.Configurable; import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
...@@ -8,6 +9,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; ...@@ -8,6 +9,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@Configurable @Configurable
@EnableScheduling @EnableScheduling
@EnableDubbo
public class Application { public class Application {
public static void main(String[] args){ public static void main(String[] args){
......
package cn.bugstack.config;
import cn.bugstack.types.annotations.DCCValue;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.CuratorCache;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* 基于 Zookeeper 的配置中心实现原理
*/
@Slf4j
@Configuration
public class DCCValueBeanFactory implements BeanPostProcessor {
private static final String BASE_CONFIG_PATH = "/big-market-dcc";
private static final String BASE_CONFIG_PATH_CONFIG = BASE_CONFIG_PATH + "/config";
private final CuratorFramework client;
private final Map<String, Object> dccObjGroup = new HashMap<>();
public DCCValueBeanFactory(CuratorFramework client) throws Exception {
this.client = client;
// 节点判断
if (null == client.checkExists().forPath(BASE_CONFIG_PATH_CONFIG)) {
client.create().creatingParentsIfNeeded().forPath(BASE_CONFIG_PATH_CONFIG);
log.info("DCC 节点监听 base node {} not absent create new done!", BASE_CONFIG_PATH_CONFIG);
}
CuratorCache curatorCache = CuratorCache.build(client, BASE_CONFIG_PATH_CONFIG);
curatorCache.start();
curatorCache.listenable().addListener((type, oldData, data) -> {
switch (type) {
case NODE_CHANGED:
String dccValuePath = data.getPath();
Object objBean = dccObjGroup.get(dccValuePath);
if (null == objBean) return;
try {
// 1. getDeclaredField 方法用于获取指定类中声明的所有字段,包括私有字段、受保护字段和公共字段。
// 2. getField 方法用于获取指定类中的公共字段,即只能获取到公共访问修饰符(public)的字段。
Field field = objBean.getClass().getDeclaredField(dccValuePath.substring(dccValuePath.lastIndexOf("/") + 1));
field.setAccessible(true);
field.set(objBean, new String(data.getData()));
field.setAccessible(false);
} catch (Exception e) {
throw new RuntimeException(e);
}
break;
default:
break;
}
});
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class<?> beanClass = bean.getClass();
Field[] fields = beanClass.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(DCCValue.class)) {
continue;
}
DCCValue dccValue = field.getAnnotation(DCCValue.class);
String value = dccValue.value();
if (StringUtils.isBlank(value)) {
throw new RuntimeException(field.getName() + " @DCCValue is not config value config case 「isSwitch/isSwitch:1」");
}
String[] splits = value.split(":");
String key = splits[0];
String defaultValue = splits.length == 2 ? splits[1] : null;
try {
// 判断当前节点是否存在,不存在则创建出 Zookeeper 节点
String keyPath = BASE_CONFIG_PATH_CONFIG.concat("/").concat(key);
if (null == client.checkExists().forPath(keyPath)) {
client.create().creatingParentsIfNeeded().forPath(keyPath);
if (StringUtils.isNotBlank(defaultValue)) {
field.setAccessible(true);
field.set(bean, defaultValue);
field.setAccessible(false);
}
log.info("DCC 节点监听 创建节点 {}", keyPath);
} else {
String configValue = new String(client.getData().forPath(keyPath));
if (StringUtils.isNotBlank(configValue)) {
field.setAccessible(true);
field.set(bean, configValue);
field.setAccessible(false);
log.info("DCC 节点监听 设置配置 {} {} {}", keyPath, field.getName(), configValue);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
dccObjGroup.put(BASE_CONFIG_PATH_CONFIG.concat("/").concat(key), bean);
}
return bean;
}
}
package cn.bugstack.config;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(ZookeeperClientConfigProperties.class)
public class ZooKeeperClientConfig {
/**
* 多参数构建ZooKeeper客户端连接
*
* @return client
*/
@Bean(name = "zookeeperClient")
public CuratorFramework createWithOptions(ZookeeperClientConfigProperties properties) {
ExponentialBackoffRetry backoffRetry = new ExponentialBackoffRetry(properties.getBaseSleepTimeMs(), properties.getMaxRetries());
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString(properties.getConnectString())
.retryPolicy(backoffRetry)
.sessionTimeoutMs(properties.getSessionTimeoutMs())
.connectionTimeoutMs(properties.getConnectionTimeoutMs())
.build();
client.start();
return client;
}
}
package cn.bugstack.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "zookeeper.sdk.config", ignoreInvalidFields = true)
public class ZookeeperClientConfigProperties {
private String connectString;
private int baseSleepTimeMs;
private int maxRetries;
private int sessionTimeoutMs;
private int connectionTimeoutMs;
}
...@@ -27,6 +27,7 @@ spring: ...@@ -27,6 +27,7 @@ spring:
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 send_rebate: send_rebate
credit_adjust_success: credit_adjust_success
# 线程池配置 # 线程池配置
thread: thread:
pool: pool:
...@@ -115,6 +116,27 @@ redis: ...@@ -115,6 +116,27 @@ redis:
retry-interval: 1000 retry-interval: 1000
ping-interval: 60000 ping-interval: 60000
keep-alive: true keep-alive: true
dubbo:
application:
name: big-market
version: 1.0
registry:
id: nacos-registry
address: nacos://127.0.0.1:8848
protocol:
name: dubbo
port: -1
scan:
base-packages: cn.bugstack.trigger.api
zookeeper:
sdk:
config:
connect-string: 127.0.0.1:2181
base-sleep-time-ms: 1000
max-retries: 3
session-timeout-ms: 18000
connection-timeout-ms: 30000
# 日志 # 日志
logging: logging:
......
...@@ -75,4 +75,11 @@ ...@@ -75,4 +75,11 @@
where user_id = #{userId} and activity_id = #{activityId} where user_id = #{userId} and activity_id = #{activityId}
</update> </update>
<select id="queryAccountByUserId" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityAccount" resultMap="dataMap">
select user_id, activity_id, total_count, total_count_surplus, day_count,
day_count_surplus, month_count, month_count_surplus
from raffle_activity_account
where user_id = #{userId} and activity_id = #{activityId}
</select>
</mapper> </mapper>
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
<result column="total_count" property="totalCount"/> <result column="total_count" property="totalCount"/>
<result column="day_count" property="dayCount"/> <result column="day_count" property="dayCount"/>
<result column="month_count" property="monthCount"/> <result column="month_count" property="monthCount"/>
<result column="pay_amount" property="payAmount"/>
<result column="state" property="state"/> <result column="state" property="state"/>
<result column="out_business_no" property="outBusinessNo"/> <result column="out_business_no" property="outBusinessNo"/>
<result column="create_time" property="createTime"/> <result column="create_time" property="createTime"/>
...@@ -22,17 +23,35 @@ ...@@ -22,17 +23,35 @@
<insert id="insert" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityOrder"> <insert id="insert" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityOrder">
insert into raffle_activity_order insert into raffle_activity_order
(user_id, sku, activity_id, activity_name, strategy_id, order_id, order_time, state, out_business_no, total_count, day_count, month_count, (user_id, sku, activity_id, activity_name, strategy_id, order_id, order_time, pay_amount, state, out_business_no, total_count, day_count, month_count,
create_time, update_time) create_time, update_time)
values values
(#{userId}, #{sku}, #{activityId}, #{activityName}, #{strategyId}, #{orderId}, #{orderTime}, #{state}, #{outBusinessNo}, #{totalCount}, #{dayCount}, #{monthCount}, (#{userId}, #{sku}, #{activityId}, #{activityName}, #{strategyId}, #{orderId}, #{orderTime}, #{payAmount}, #{state}, #{outBusinessNo}, #{totalCount}, #{dayCount}, #{monthCount},
now(), now()) now(), now())
</insert> </insert>
<select id="queryRaffleActivityOrderByUserId" parameterType="java.lang.String" resultMap="dataMap"> <select id="queryRaffleActivityOrderByUserId" parameterType="java.lang.String" resultMap="dataMap">
select user_id, sku, activity_id, activity_name, strategy_id, order_id, order_time, state select user_id, sku, activity_id, activity_name, strategy_id, order_id, order_time, pay_amount, state
from raffle_activity_order from raffle_activity_order
where user_id = #{userId} where user_id = #{userId}
</select> </select>
<select id="queryRaffleActivityOrder" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityOrder" resultMap="dataMap">
select user_id, sku, activity_id, activity_name, strategy_id, order_id, order_time, total_count, day_count, month_count, pay_amount, state
from raffle_activity_order
where user_id = #{userId} and out_business_no = #{outBusinessNo}
</select>
<update id="updateOrderCompleted" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityOrder">
update raffle_activity_order set state = 'completed', update_time = now()
where user_id = #{userId} and out_business_no = #{outBusinessNo} and state = 'wait_pay'
</update>
<select id="queryUnpaidActivityOrder" parameterType="cn.bugstack.infrastructure.persistent.po.RaffleActivityOrder" resultMap="dataMap">
select user_id, order_id, out_business_no, pay_amount
from raffle_activity_order
where user_id = #{userId} and sku = #{sku} and state = 'wait_pay' and order_time >= NOW() - INTERVAL 1 MONTH
limit 1
</select>
</mapper> </mapper>
...@@ -9,12 +9,13 @@ ...@@ -9,12 +9,13 @@
<result column="activity_count_id" property="activityCountId"/> <result column="activity_count_id" property="activityCountId"/>
<result column="stock_count" property="stockCount"/> <result column="stock_count" property="stockCount"/>
<result column="stock_count_surplus" property="stockCountSurplus"/> <result column="stock_count_surplus" property="stockCountSurplus"/>
<result column="product_amount" property="productAmount"/>
<result column="create_time" property="createTime"/> <result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/> <result column="update_time" property="updateTime"/>
</resultMap> </resultMap>
<select id="queryActivitySku" parameterType="java.lang.Long" resultMap="dataMap"> <select id="queryActivitySku" parameterType="java.lang.Long" resultMap="dataMap">
select sku, activity_id, activity_count_id, stock_count, stock_count_surplus select sku, activity_id, activity_count_id, stock_count, stock_count_surplus, product_amount
from raffle_activity_sku from raffle_activity_sku
where sku = #{sku} where sku = #{sku}
</select> </select>
...@@ -32,7 +33,9 @@ ...@@ -32,7 +33,9 @@
</update> </update>
<select id="queryActivitySkuListByActivityId" parameterType="java.lang.Long" resultMap="dataMap"> <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 sku, activity_count_id, stock_count, stock_count_surplus, product_amount
from raffle_activity_sku
where activity_id = #{activityId}
</select> </select>
</mapper> </mapper>
...@@ -12,14 +12,20 @@ ...@@ -12,14 +12,20 @@
<result column="update_time" property="updateTime"/> <result column="update_time" property="updateTime"/>
</resultMap> </resultMap>
<update id="updateAddAmount" parameterType="cn.bugstack.infrastructure.persistent.po.UserAwardRecord"> <update id="updateAddAmount" parameterType="cn.bugstack.infrastructure.persistent.po.UserCreditAccount">
update user_credit_account set update user_credit_account set
total_amount = total_amount + #{totalAmount}, total_amount = total_amount + #{totalAmount},
available_amount = available_amount + #{availableAmount} available_amount = available_amount + #{availableAmount}
where user_id = #{userId} where user_id = #{userId}
</update> </update>
<insert id="insert" parameterType="cn.bugstack.infrastructure.persistent.po.UserAwardRecord"> <update id="updateSubtractionAmount" parameterType="cn.bugstack.infrastructure.persistent.po.UserCreditAccount">
update user_credit_account set
available_amount = available_amount + #{availableAmount}
where user_id = #{userId} and available_amount > 0
</update>
<insert id="insert" parameterType="cn.bugstack.infrastructure.persistent.po.UserCreditAccount">
insert into user_credit_account( insert into user_credit_account(
user_id, total_amount, available_amount, account_status, create_time, update_time user_id, total_amount, available_amount, account_status, create_time, update_time
) values ( ) values (
...@@ -27,4 +33,9 @@ ...@@ -27,4 +33,9 @@
) )
</insert> </insert>
<select id="queryUserCreditAccount" parameterType="cn.bugstack.infrastructure.persistent.po.UserCreditAccount" resultMap="dataMap">
select user_id, total_amount, available_amount, account_status from user_credit_account
where user_id = #{userId}
</select>
</mapper> </mapper>
<?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.IUserCreditOrderDao">
<resultMap id="dataMap" type="cn.bugstack.infrastructure.persistent.po.UserCreditOrder">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="order_id" property="orderId"/>
<result column="trade_name" property="tradeName"/>
<result column="trade_type" property="tradeType"/>
<result column="trade_amount" property="tradeAmount"/>
<result column="out_business_no" property="outBusinessNo"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<insert id="insert" parameterType="cn.bugstack.infrastructure.persistent.po.UserCreditOrder">
insert into user_credit_order(user_id, order_id, trade_name, trade_type, trade_amount, out_business_no, create_time, update_time)
values(
#{userId},#{orderId},#{tradeName},#{tradeType},#{tradeAmount},#{outBusinessNo},now(),now()
)
</insert>
</mapper>
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
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
from user_raffle_order from user_raffle_order
where user_id = #{userId} and activity_id = #{activityId} and order_state = 'create' where user_id = #{userId} and activity_id = #{activityId} and order_state = 'create'
order by create_time desc
limit 1
</select> </select>
<update id="updateUserRaffleOrderStateUsed" parameterType="cn.bugstack.infrastructure.persistent.po.UserRaffleOrder"> <update id="updateUserRaffleOrderStateUsed" parameterType="cn.bugstack.infrastructure.persistent.po.UserRaffleOrder">
......
package cn.bugstack.test; package cn.bugstack.test;
import cn.bugstack.trigger.api.dto.RaffleAwardListRequestDTO;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 功能测试
* @create 2023-12-23 11:39
*/
@Slf4j @Slf4j
@RunWith(SpringRunner.class) //@RunWith(SpringRunner.class)
@SpringBootTest //@SpringBootTest
public class ApiTest { public class ApiTest {
@Test
public void test_integer(){
System.out.println(Integer.parseInt("aaa"));
}
@Test @Test
public void test() { public void test() {
log.info("测试完成"); RaffleAwardListRequestDTO requestDTO = new RaffleAwardListRequestDTO();
requestDTO.setUserId("xiaofuge");
requestDTO.setActivityId(100301L);
log.info(JSON.toJSONString(requestDTO));
}
public static void main(String[] args) {
double convert = convert(0.0018);
System.out.println(convert);
}
private static double convert(double min){
double current = min;
double max = 1;
while (current % 1 != 0){
current = current * 10;
max = max * 10;
}
return max;
} }
} }
package cn.bugstack.test;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.CuratorEventType;
import org.apache.curator.framework.api.CuratorListener;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
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.nio.charset.StandardCharsets;
import java.util.List;
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ZookeeperTest {
@Resource
private CuratorFramework curatorFramework;
@Test
public void test_all() throws Exception {
String path = "/big-market-dcc/config/downgradeSwitch";
String data = "0";
curatorFramework.create().withMode(CreateMode.EPHEMERAL).forPath(path, data.getBytes(StandardCharsets.UTF_8));
for (int i = 0; i < 2; i++) {
curatorFramework.setData().forPath(path, String.valueOf(i).getBytes(StandardCharsets.UTF_8));
}
}
/**
* 创建永久节点
*/
@Test
public void createNode() throws Exception {
String path = "/big-market-dcc/config/downgradeSwitch/test/a";
String data = "0";
if (null == curatorFramework.checkExists().forPath(path)) {
curatorFramework.create().creatingParentsIfNeeded().forPath(path);
}
}
/**
* 创建临时节点
*/
@Test
public void createEphemeralNode() throws Exception {
String path = "/big-market-dcc/config/epnode";
String data = "0";
curatorFramework.create().withMode(CreateMode.EPHEMERAL).forPath(path, data.getBytes(StandardCharsets.UTF_8));
}
/**
* 创建临时有序节点
*/
@Test
public void crateEphemeralSequentialNode() throws Exception {
String path = "/big-market-dcc/config/epsnode";
String data = "0";
curatorFramework.create()
.withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
.forPath(path, data.getBytes(StandardCharsets.UTF_8));
}
/**
* 往节点种设置数据
*/
@Test
public void setData() throws Exception {
curatorFramework.setData().forPath("/big-market-dcc/config/downgradeSwitch", "111".getBytes(StandardCharsets.UTF_8));
curatorFramework.setData().forPath("/big-market-dcc/config/userWhiteList", "222".getBytes(StandardCharsets.UTF_8));
}
@Test
public void getData() throws Exception {
String downgradeSwitch = new String(curatorFramework.getData().forPath("/big-market-dcc/config/downgradeSwitch"), StandardCharsets.UTF_8);
log.info("测试结果: {}", downgradeSwitch);
String userWhiteList = new String(curatorFramework.getData().forPath("/big-market-dcc/config/userWhiteList"), StandardCharsets.UTF_8);
log.info("测试结果: {}", userWhiteList);
}
/**
* 异步修改数据
*/
@Test
public void setDataAsync() throws Exception {
String path = "/big-market-dcc/config/downgradeSwitch";
String data = "0";
CuratorListener listener = (client, event) -> {
Stat stat = event.getStat();
log.info("stat=" + JSON.toJSONString(stat));
CuratorEventType eventType = event.getType();
log.info("eventType=" + eventType.name());
};
curatorFramework.getCuratorListenable().addListener(listener);
curatorFramework.setData().inBackground().forPath(path, data.getBytes(StandardCharsets.UTF_8));
}
/**
* 删除节点
*/
@Test
public void deleteData() throws Exception {
String path = "/big-market-dcc/config/downgradeSwitch";
curatorFramework.delete().deletingChildrenIfNeeded().forPath(path);
}
/**
* 安全删除节点
*/
@Test
public void guaranteedDeleteData() throws Exception {
String path = "/big-market-dcc/config/downgradeSwitch";
curatorFramework.delete().guaranteed().forPath(path);
}
/**
* 获取子节点下的全部子节点路径集合
*/
@Test
public void watchedGetChildren() throws Exception {
String path = "/big-market-dcc";
List<String> children = curatorFramework.getChildren().watched().forPath(path);
log.info("测试结果:{}", JSON.toJSONString(children));
}
/**
* 获取节点数据
*/
@Test
public void getDataByPath() throws Exception {
String path = "/big-market-dcc/config/downgradeSwitch";
String fullClassName = "";
String jsonStr = new String(curatorFramework.getData().forPath(path), StandardCharsets.UTF_8);
Class clazz = Class.forName(fullClassName);
log.info("测试结果:{}", JSON.parseObject(jsonStr, clazz));
}
}
package cn.bugstack.test.domain.activity; package cn.bugstack.test.domain.activity;
import cn.bugstack.domain.activity.model.entity.SkuRechargeEntity; import cn.bugstack.domain.activity.model.entity.SkuRechargeEntity;
import cn.bugstack.domain.activity.model.entity.UnpaidActivityOrderEntity;
import cn.bugstack.domain.activity.model.valobj.OrderTradeTypeVO;
import cn.bugstack.domain.activity.service.IRaffleActivityAccountQuotaService; import cn.bugstack.domain.activity.service.IRaffleActivityAccountQuotaService;
import cn.bugstack.domain.activity.service.armory.IActivityArmory; import cn.bugstack.domain.activity.service.armory.IActivityArmory;
import cn.bugstack.types.exception.AppException; import cn.bugstack.types.exception.AppException;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Before; import org.junit.Before;
...@@ -43,8 +46,9 @@ public class RaffleActivityAccountQuotaServiceTest { ...@@ -43,8 +46,9 @@ public class RaffleActivityAccountQuotaServiceTest {
skuRechargeEntity.setSku(9011L); skuRechargeEntity.setSku(9011L);
// outBusinessNo 作为幂等仿重使用,同一个业务单号2次使用会抛出索引冲突 Duplicate entry '700091009111' for key 'uq_out_business_no' 确保唯一性。 // outBusinessNo 作为幂等仿重使用,同一个业务单号2次使用会抛出索引冲突 Duplicate entry '700091009111' for key 'uq_out_business_no' 确保唯一性。
skuRechargeEntity.setOutBusinessNo("700091009119"); skuRechargeEntity.setOutBusinessNo("700091009119");
String orderId = raffleActivityAccountQuotaService.createOrder(skuRechargeEntity); skuRechargeEntity.setOrderTradeType(OrderTradeTypeVO.rebate_no_pay_trade);
log.info("测试结果:{}", orderId); UnpaidActivityOrderEntity unpaidActivityOrder = raffleActivityAccountQuotaService.createOrder(skuRechargeEntity);
log.info("测试结果:{}", JSON.toJSONString(unpaidActivityOrder));
} }
/** /**
...@@ -62,8 +66,9 @@ public class RaffleActivityAccountQuotaServiceTest { ...@@ -62,8 +66,9 @@ public class RaffleActivityAccountQuotaServiceTest {
skuRechargeEntity.setSku(9011L); skuRechargeEntity.setSku(9011L);
// outBusinessNo 作为幂等仿重使用,同一个业务单号2次使用会抛出索引冲突 Duplicate entry '700091009111' for key 'uq_out_business_no' 确保唯一性。 // outBusinessNo 作为幂等仿重使用,同一个业务单号2次使用会抛出索引冲突 Duplicate entry '700091009111' for key 'uq_out_business_no' 确保唯一性。
skuRechargeEntity.setOutBusinessNo(RandomStringUtils.randomNumeric(12)); skuRechargeEntity.setOutBusinessNo(RandomStringUtils.randomNumeric(12));
String orderId = raffleActivityAccountQuotaService.createOrder(skuRechargeEntity); skuRechargeEntity.setOrderTradeType(OrderTradeTypeVO.rebate_no_pay_trade);
log.info("测试结果:{}", orderId); UnpaidActivityOrderEntity unpaidActivityOrder = raffleActivityAccountQuotaService.createOrder(skuRechargeEntity);
log.info("测试结果:{}", JSON.toJSONString(unpaidActivityOrder));
} catch (AppException e) { } catch (AppException e) {
log.warn(e.getInfo()); log.warn(e.getInfo());
} }
...@@ -72,4 +77,16 @@ public class RaffleActivityAccountQuotaServiceTest { ...@@ -72,4 +77,16 @@ public class RaffleActivityAccountQuotaServiceTest {
new CountDownLatch(1).await(); new CountDownLatch(1).await();
} }
@Test
public void test_credit_pay_trade() {
SkuRechargeEntity skuRechargeEntity = new SkuRechargeEntity();
skuRechargeEntity.setUserId("xiaofuge");
skuRechargeEntity.setSku(9011L);
// outBusinessNo 作为幂等仿重使用,同一个业务单号2次使用会抛出索引冲突 Duplicate entry '700091009111' for key 'uq_out_business_no' 确保唯一性。
skuRechargeEntity.setOutBusinessNo("70009240609001");
skuRechargeEntity.setOrderTradeType(OrderTradeTypeVO.credit_pay_trade);
UnpaidActivityOrderEntity unpaidActivityOrder = raffleActivityAccountQuotaService.createOrder(skuRechargeEntity);
log.info("测试结果:{}", JSON.toJSONString(unpaidActivityOrder));
}
} }
...@@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringRunner; ...@@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource; import javax.annotation.Resource;
/** /**
* @author zyf * @author Fuzhengwei bugstack.cn @小傅哥
* @description 抽奖活动订单单测 * @description 抽奖活动订单单测
* @create 2024-03-16 11:51 * @create 2024-03-16 11:51
*/ */
......
package cn.bugstack.test.domain.award; package cn.bugstack.test.domain.award;
import cn.bugstack.domain.award.model.entity.DistributeAwardEntity;
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;
import cn.bugstack.domain.award.service.IAwardService; import cn.bugstack.domain.award.service.IAwardService;
...@@ -15,7 +16,7 @@ import java.util.Date; ...@@ -15,7 +16,7 @@ import java.util.Date;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
/** /**
* @author zyf * @author Fuzhengwei bugstack.cn @小傅哥
* @description 奖品服务测试 * @description 奖品服务测试
* @create 2024-04-06 11:27 * @create 2024-04-06 11:27
*/ */
...@@ -32,9 +33,9 @@ public class AwardServiceTest { ...@@ -32,9 +33,9 @@ public class AwardServiceTest {
*/ */
@Test @Test
public void test_saveUserAwardRecord() throws InterruptedException { public void test_saveUserAwardRecord() throws InterruptedException {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 100; i++) {
UserAwardRecordEntity userAwardRecordEntity = new UserAwardRecordEntity(); UserAwardRecordEntity userAwardRecordEntity = new UserAwardRecordEntity();
userAwardRecordEntity.setUserId("zyf"); userAwardRecordEntity.setUserId("xiaofuge");
userAwardRecordEntity.setActivityId(100301L); userAwardRecordEntity.setActivityId(100301L);
userAwardRecordEntity.setStrategyId(100006L); userAwardRecordEntity.setStrategyId(100006L);
userAwardRecordEntity.setOrderId(RandomStringUtils.randomNumeric(12)); userAwardRecordEntity.setOrderId(RandomStringUtils.randomNumeric(12));
...@@ -49,4 +50,15 @@ public class AwardServiceTest { ...@@ -49,4 +50,15 @@ public class AwardServiceTest {
new CountDownLatch(1).await(); new CountDownLatch(1).await();
} }
@Test
public void test_distributeAward() throws InterruptedException {
DistributeAwardEntity distributeAwardEntity = new DistributeAwardEntity();
distributeAwardEntity.setUserId("xiaofuge");
distributeAwardEntity.setOrderId("690124733440");
distributeAwardEntity.setAwardId(101);
distributeAwardEntity.setAwardConfig("0.01,1"); // 0.01,1 黑名单指定积分值
awardService.distributeAward(distributeAwardEntity);
}
} }
package cn.bugstack.test.domain.credit;
import cn.bugstack.domain.credit.model.entity.TradeEntity;
import cn.bugstack.domain.credit.model.valobj.TradeNameVO;
import cn.bugstack.domain.credit.model.valobj.TradeTypeVO;
import cn.bugstack.domain.credit.service.ICreditAdjustService;
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.math.BigDecimal;
import java.util.concurrent.CountDownLatch;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 积分额度增加服务测试
* @create 2024-06-01 10:22
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class CreditAdjustServiceTest {
@Resource
private ICreditAdjustService creditAdjustService;
@Test
public void test_createOrder_forward() {
TradeEntity tradeEntity = new TradeEntity();
tradeEntity.setUserId("xiaofuge");
tradeEntity.setTradeName(TradeNameVO.REBATE);
tradeEntity.setTradeType(TradeTypeVO.FORWARD);
tradeEntity.setAmount(new BigDecimal("10.19"));
tradeEntity.setOutBusinessNo("12406039900002");
creditAdjustService.createOrder(tradeEntity);
}
@Test
public void test_createOrder_reverse() {
TradeEntity tradeEntity = new TradeEntity();
tradeEntity.setUserId("xiaofuge");
tradeEntity.setTradeName(TradeNameVO.REBATE);
tradeEntity.setTradeType(TradeTypeVO.REVERSE);
tradeEntity.setAmount(new BigDecimal("-10.19"));
tradeEntity.setOutBusinessNo("20000990991");
creditAdjustService.createOrder(tradeEntity);
}
@Test
public void test_createOrder_pay() throws InterruptedException {
TradeEntity tradeEntity = new TradeEntity();
tradeEntity.setUserId("xiaofuge");
tradeEntity.setTradeName(TradeNameVO.CONVERT_SKU);
tradeEntity.setTradeType(TradeTypeVO.REVERSE);
tradeEntity.setAmount(new BigDecimal("-1.68"));
tradeEntity.setOutBusinessNo("70009240609001");
creditAdjustService.createOrder(tradeEntity);
new CountDownLatch(1).await();
}
}
package cn.bugstack.test.domain.rebate; package cn.bugstack.test.domain.rebate;
import cn.bugstack.domain.activity.service.armory.IActivityArmory;
import cn.bugstack.domain.rebate.model.entity.BehaviorEntity; import cn.bugstack.domain.rebate.model.entity.BehaviorEntity;
import cn.bugstack.domain.rebate.model.valobj.BehaviorTypeVO; import cn.bugstack.domain.rebate.model.valobj.BehaviorTypeVO;
import cn.bugstack.domain.rebate.service.IBehaviorRebateService; import cn.bugstack.domain.rebate.service.IBehaviorRebateService;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
...@@ -12,6 +14,7 @@ import org.springframework.test.context.junit4.SpringRunner; ...@@ -12,6 +14,7 @@ import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch;
/** /**
* @author Fuzhengwei bugstack.cn @小傅哥 * @author Fuzhengwei bugstack.cn @小傅哥
...@@ -26,17 +29,27 @@ public class BehaviorRebateServiceTest { ...@@ -26,17 +29,27 @@ public class BehaviorRebateServiceTest {
@Resource @Resource
private IBehaviorRebateService behaviorRebateService; private IBehaviorRebateService behaviorRebateService;
@Resource
private IActivityArmory activityArmory;
@Before
public void init() {
activityArmory.assembleActivitySkuByActivityId(100301L);
}
@Test @Test
public void test_createOrder() { public void test_createOrder() throws InterruptedException {
BehaviorEntity behaviorEntity = new BehaviorEntity(); BehaviorEntity behaviorEntity = new BehaviorEntity();
behaviorEntity.setUserId("xiaofuge"); behaviorEntity.setUserId("xiaofuge");
behaviorEntity.setBehaviorTypeVO(BehaviorTypeVO.SIGN); behaviorEntity.setBehaviorTypeVO(BehaviorTypeVO.SIGN);
// 重复的 OutBusinessNo 会报错唯一索引冲突,这也是保证幂等的手段,确保不会多记账 // 重复的 OutBusinessNo 会报错唯一索引冲突,这也是保证幂等的手段,确保不会多记账
behaviorEntity.setOutBusinessNo("20240429"); behaviorEntity.setOutBusinessNo("20240601006");
List<String> orderIds = behaviorRebateService.createOrder(behaviorEntity); List<String> orderIds = behaviorRebateService.createOrder(behaviorEntity);
log.info("请求参数:{}", JSON.toJSONString(behaviorEntity)); log.info("请求参数:{}", JSON.toJSONString(behaviorEntity));
log.info("测试结果:{}", JSON.toJSONString(orderIds)); log.info("测试结果:{}", JSON.toJSONString(orderIds));
new CountDownLatch(1).await();
} }
} }
...@@ -4,6 +4,7 @@ import cn.bugstack.domain.strategy.service.armory.IStrategyArmory; ...@@ -4,6 +4,7 @@ import cn.bugstack.domain.strategy.service.armory.IStrategyArmory;
import cn.bugstack.domain.strategy.service.rule.chain.ILogicChain; import cn.bugstack.domain.strategy.service.rule.chain.ILogicChain;
import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory; import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import cn.bugstack.domain.strategy.service.rule.chain.impl.RuleWeightLogicChain; import cn.bugstack.domain.strategy.service.rule.chain.impl.RuleWeightLogicChain;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -15,15 +16,15 @@ import org.springframework.test.util.ReflectionTestUtils; ...@@ -15,15 +16,15 @@ import org.springframework.test.util.ReflectionTestUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
/** /**
* @ClassName: LogicChainTest * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 抽奖责任链测试,验证不同的规则走不同的责任链
* @Author: zhaoyongfeng * @create 2024-01-20 11:20
* @Date: 2024/11/18 22:49
*/ */
@Slf4j @Slf4j
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest @SpringBootTest
public class LogicChainTest { public class LogicChainTest {
@Resource @Resource
private IStrategyArmory strategyArmory; private IStrategyArmory strategyArmory;
@Resource @Resource
...@@ -41,9 +42,9 @@ public class LogicChainTest { ...@@ -41,9 +42,9 @@ public class LogicChainTest {
@Test @Test
public void test_LogicChain_rule_blacklist() { public void test_LogicChain_rule_blacklist() {
ILogicChain logicChain = defaultChainFactory.openLogicChain(100001L); ILogicChain logicChain = defaultChainFactory.openLogicChain(100003L);
DefaultChainFactory.StrategyAwardVO awardId = logicChain.logic("user001", 100001L); DefaultChainFactory.StrategyAwardVO strategyAwardVO = logicChain.logic("user001", 100003L);
log.info("测试结果:{}", awardId); log.info("测试结果:{}", JSON.toJSONString(strategyAwardVO));
} }
@Test @Test
...@@ -52,16 +53,15 @@ public class LogicChainTest { ...@@ -52,16 +53,15 @@ public class LogicChainTest {
ReflectionTestUtils.setField(ruleWeightLogicChain, "userScore", 4900L); ReflectionTestUtils.setField(ruleWeightLogicChain, "userScore", 4900L);
ILogicChain logicChain = defaultChainFactory.openLogicChain(100001L); ILogicChain logicChain = defaultChainFactory.openLogicChain(100001L);
DefaultChainFactory.StrategyAwardVO awardId = logicChain.logic("xiaofuge", 100001L); DefaultChainFactory.StrategyAwardVO strategyAwardVO = logicChain.logic("xiaofuge", 100001L);
log.info("测试结果:{}", awardId); log.info("测试结果:{}", JSON.toJSONString(strategyAwardVO));
} }
@Test @Test
public void test_LogicChain_rule_default() { public void test_LogicChain_rule_default() {
ILogicChain logicChain = defaultChainFactory.openLogicChain(100001L); ILogicChain logicChain = defaultChainFactory.openLogicChain(100001L);
DefaultChainFactory.StrategyAwardVO awardId = logicChain.logic("xiaofuge", 100001L); DefaultChainFactory.StrategyAwardVO strategyAwardVO = logicChain.logic("xiaofuge", 100001L);
log.info("测试结果:{}", awardId); log.info("测试结果:{}", JSON.toJSONString(strategyAwardVO));
} }
} }
package cn.bugstack.test.domain.strategy; package cn.bugstack.test.domain.strategy;
import cn.bugstack.domain.strategy.model.valobj.*; import cn.bugstack.domain.strategy.model.valobj.*;
import cn.bugstack.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine; import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine;
import com.alibaba.fastjson.JSON; import cn.bugstack.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -15,10 +15,9 @@ import java.util.ArrayList; ...@@ -15,10 +15,9 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
/** /**
* @ClassName: LogicTreeTest * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 规则树测试
* @Author: zhaoyongfeng * @create 2024-01-27 13:23
* @Date: 2024/11/20 16:58
*/ */
@Slf4j @Slf4j
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
...@@ -97,10 +96,9 @@ public class LogicTreeTest { ...@@ -97,10 +96,9 @@ public class LogicTreeTest {
IDecisionTreeEngine treeEngine = defaultTreeFactory.openLogicTree(ruleTreeVO); IDecisionTreeEngine treeEngine = defaultTreeFactory.openLogicTree(ruleTreeVO);
DefaultTreeFactory.StrategyAwardVO data = treeEngine.process("xiaofuge", 100001L, 100,null); DefaultTreeFactory.StrategyAwardVO data = treeEngine.process("xiaofuge", 100001L, 100, null);
log.info("测试结果:{}", JSON.toJSONString(data)); log.info("测试结果:{}", JSON.toJSONString(data));
} }
} }
...@@ -2,34 +2,41 @@ package cn.bugstack.test.domain.strategy; ...@@ -2,34 +2,41 @@ package cn.bugstack.test.domain.strategy;
import cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity; import cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity;
import cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity; import cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity;
import cn.bugstack.domain.strategy.model.valobj.RuleWeightVO;
import cn.bugstack.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import cn.bugstack.domain.strategy.service.IRaffleRule;
import cn.bugstack.domain.strategy.service.IRaffleStock; import cn.bugstack.domain.strategy.service.IRaffleStock;
import cn.bugstack.domain.strategy.service.IRaffleStrategy; import cn.bugstack.domain.strategy.service.IRaffleStrategy;
import cn.bugstack.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import cn.bugstack.domain.strategy.service.armory.IStrategyArmory; import cn.bugstack.domain.strategy.service.armory.IStrategyArmory;
import cn.bugstack.domain.strategy.service.rule.chain.impl.RuleWeightLogicChain; import cn.bugstack.domain.strategy.service.rule.chain.impl.RuleWeightLogicChain;
import cn.bugstack.domain.strategy.service.rule.tree.impl.RuleLockLogicTreeNode; import cn.bugstack.domain.strategy.service.rule.tree.impl.RuleLockLogicTreeNode;
import cn.bugstack.types.common.Constants;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/** /**
* @ClassName: RaffleStrategyTest * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 抽奖策略测试
* @Author: zhaoyongfeng * @create 2024-01-06 13:28
* @Date: 2024/11/17 17:11
*/ */
@SpringBootTest
@Slf4j @Slf4j
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest
public class RaffleStrategyTest { public class RaffleStrategyTest {
@Resource @Resource
private IStrategyArmory strategyArmory; private IStrategyArmory strategyArmory;
@Resource @Resource
...@@ -40,23 +47,23 @@ public class RaffleStrategyTest { ...@@ -40,23 +47,23 @@ public class RaffleStrategyTest {
private RuleLockLogicTreeNode ruleLockLogicTreeNode; private RuleLockLogicTreeNode ruleLockLogicTreeNode;
@Resource @Resource
private IRaffleStock raffleStock; private IRaffleStock raffleStock;
@Resource
private IRaffleRule raffleRule;
@Before @Before
public void setUp() { public void setUp() {
// 策略装配 100001、100002、100003 // 策略装配 100001、100002、100003
// log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100001L)); log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100001L));
log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100006L)); log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100006L));
// 通过反射 mock 规则中的值 // 通过反射 mock 规则中的值;到本节不需要在使用了。
ReflectionTestUtils.setField(ruleWeightLogicChain, "userScore", 4900L); /*ReflectionTestUtils.setField(ruleWeightLogicChain, "userScore", 4900L);*/
ReflectionTestUtils.setField(ruleLockLogicTreeNode, "userRaffleCount", 10L); /*ReflectionTestUtils.setField(ruleLockLogicTreeNode, "userRaffleCount", 10L);*/
} }
@Test @Test
public void test_performRaffle() throws InterruptedException { public void test_performRaffle() throws InterruptedException {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 1; i++) {
RaffleFactorEntity raffleFactorEntity = RaffleFactorEntity.builder() RaffleFactorEntity raffleFactorEntity = RaffleFactorEntity.builder()
.userId("xiaofuge") .userId("xiaofuge")
.strategyId(100006L) .strategyId(100006L)
...@@ -72,7 +79,6 @@ public class RaffleStrategyTest { ...@@ -72,7 +79,6 @@ public class RaffleStrategyTest {
new CountDownLatch(1).await(); new CountDownLatch(1).await();
} }
@Test @Test
public void test_performRaffle_blacklist() { public void test_performRaffle_blacklist() {
RaffleFactorEntity raffleFactorEntity = RaffleFactorEntity.builder() RaffleFactorEntity raffleFactorEntity = RaffleFactorEntity.builder()
...@@ -91,7 +97,7 @@ public class RaffleStrategyTest { ...@@ -91,7 +97,7 @@ public class RaffleStrategyTest {
* ReflectionTestUtils.setField(ruleLockLogicFilter, "userRaffleCount", 10L); * ReflectionTestUtils.setField(ruleLockLogicFilter, "userRaffleCount", 10L);
*/ */
@Test @Test
public void test_raffle_center_rule_lock(){ public void test_raffle_center_rule_lock() {
RaffleFactorEntity raffleFactorEntity = RaffleFactorEntity.builder() RaffleFactorEntity raffleFactorEntity = RaffleFactorEntity.builder()
.userId("xiaofuge") .userId("xiaofuge")
.strategyId(100003L) .strategyId(100003L)
...@@ -103,12 +109,16 @@ public class RaffleStrategyTest { ...@@ -103,12 +109,16 @@ public class RaffleStrategyTest {
log.info("测试结果:{}", JSON.toJSONString(raffleAwardEntity)); log.info("测试结果:{}", JSON.toJSONString(raffleAwardEntity));
} }
@Test @Test
public void test_takeQueueValue() throws InterruptedException { public void test_takeQueueValue() throws InterruptedException {
StrategyAwardStockKeyVO strategyAwardStockKeyVO = raffleStock.takeQueueValue(); StrategyAwardStockKeyVO strategyAwardStockKeyVO = raffleStock.takeQueueValue();
log.info("测试结果:{}", JSON.toJSONString(strategyAwardStockKeyVO)); log.info("测试结果:{}", JSON.toJSONString(strategyAwardStockKeyVO));
} }
@Test
public void test_raffleRule() {
List<RuleWeightVO> ruleWeightVOS = raffleRule.queryAwardRuleWeightByActivityId(100301L);
log.info("测试结果:{}", JSON.toJSONString(ruleWeightVOS));
}
} }
...@@ -15,10 +15,9 @@ import javax.annotation.Resource; ...@@ -15,10 +15,9 @@ import javax.annotation.Resource;
import java.util.*; import java.util.*;
/** /**
* @ClassName: StrategyTest * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 策略领域测试
* @Author: zhaoyongfeng * @create 2023-12-23 11:33
* @Date: 2024/11/17 17:18
*/ */
@Slf4j @Slf4j
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
...@@ -36,7 +35,7 @@ public class StrategyTest { ...@@ -36,7 +35,7 @@ public class StrategyTest {
*/ */
@Before @Before
public void test_strategyArmory() { public void test_strategyArmory() {
boolean success = strategyArmory.assembleLotteryStrategy(100001L); boolean success = strategyArmory.assembleLotteryStrategy(100005L);
log.info("测试结果:{}", success); log.info("测试结果:{}", success);
} }
...@@ -45,7 +44,7 @@ public class StrategyTest { ...@@ -45,7 +44,7 @@ public class StrategyTest {
*/ */
@Test @Test
public void test_getRandomAwardId() { public void test_getRandomAwardId() {
log.info("测试结果:{} - 奖品ID值", strategyDispatch.getRandomAwardId(100001L)); log.info("测试结果:{} - 奖品ID值", strategyDispatch.getRandomAwardId(100001L));
} }
/** /**
...@@ -107,4 +106,3 @@ public class StrategyTest { ...@@ -107,4 +106,3 @@ public class StrategyTest {
} }
} }
...@@ -2,7 +2,7 @@ package cn.bugstack.test.infrastructure; ...@@ -2,7 +2,7 @@ package cn.bugstack.test.infrastructure;
import cn.bugstack.infrastructure.persistent.dao.IAwardDao; import cn.bugstack.infrastructure.persistent.dao.IAwardDao;
import cn.bugstack.infrastructure.persistent.po.Award; import cn.bugstack.infrastructure.persistent.po.Award;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -13,22 +13,22 @@ import javax.annotation.Resource; ...@@ -13,22 +13,22 @@ import javax.annotation.Resource;
import java.util.List; import java.util.List;
/** /**
* @ClassName: AwardDaoTest * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 奖品持久化单元测试
* @Author: zhaoyongfeng * @create 2023-12-16 13:36
* @Date: 2024/11/13 21:12
*/ */
@SpringBootTest
@Slf4j @Slf4j
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest
public class AwardDaoTest { public class AwardDaoTest {
@Resource @Resource
private IAwardDao awardDao; private IAwardDao awardDao;
@Test @Test
public void Test_queryAwardList(){ public void test_queryAwardList() {
List<Award> awards = awardDao.queryAwardList(); List<Award> awards = awardDao.queryAwardList();
log.info("测试结果:{}",awards); log.info("测试结果:{}", JSON.toJSONString(awards));
} }
} }
package cn.bugstack.test.infrastructure;
import cn.bugstack.infrastructure.persistent.dao.IRaffleActivityAccountDayDao;
import cn.bugstack.infrastructure.persistent.po.RaffleActivityAccountDay;
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;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动日账户DAO
* @create 2024-04-20 10:15
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class RaffleActivityAccountDayDaoTest {
@Resource
private IRaffleActivityAccountDayDao raffleActivityAccountDayDao;
@Test
public void test_queryRaffleActivityAccountDayPartakeCount() {
RaffleActivityAccountDay raffleActivityAccountDay = new RaffleActivityAccountDay();
raffleActivityAccountDay.setActivityId(100301L);
raffleActivityAccountDay.setUserId("xiaofuge");
raffleActivityAccountDay.setDay(raffleActivityAccountDay.currentDay());
Integer dayPartakeCount = raffleActivityAccountDayDao.queryRaffleActivityAccountDayPartakeCount(raffleActivityAccountDay);
log.info("测试结果:{}", dayPartakeCount);
}
}
...@@ -2,7 +2,7 @@ package cn.bugstack.test.infrastructure; ...@@ -2,7 +2,7 @@ package cn.bugstack.test.infrastructure;
import cn.bugstack.infrastructure.persistent.dao.IRaffleActivityDao; import cn.bugstack.infrastructure.persistent.dao.IRaffleActivityDao;
import cn.bugstack.infrastructure.persistent.po.RaffleActivity; import cn.bugstack.infrastructure.persistent.po.RaffleActivity;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -12,15 +12,15 @@ import org.springframework.test.context.junit4.SpringRunner; ...@@ -12,15 +12,15 @@ import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource; import javax.annotation.Resource;
/** /**
* @ClassName: RaffleActivityDaoTest * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 抽奖活动配置Dao测试
* @Author: zhaoyongfeng * @create 2024-03-09 11:30
* @Date: 2024/11/26 14:41
*/ */
@Slf4j @Slf4j
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest @SpringBootTest
public class RaffleActivityDaoTest { public class RaffleActivityDaoTest {
@Resource @Resource
private IRaffleActivityDao raffleActivityDao; private IRaffleActivityDao raffleActivityDao;
...@@ -29,4 +29,5 @@ public class RaffleActivityDaoTest { ...@@ -29,4 +29,5 @@ public class RaffleActivityDaoTest {
RaffleActivity raffleActivity = raffleActivityDao.queryRaffleActivityByActivityId(100301L); RaffleActivity raffleActivity = raffleActivityDao.queryRaffleActivityByActivityId(100301L);
log.info("测试结果:{}", JSON.toJSONString(raffleActivity)); log.info("测试结果:{}", JSON.toJSONString(raffleActivity));
} }
} }
...@@ -5,6 +5,7 @@ import cn.bugstack.infrastructure.persistent.po.RaffleActivityOrder; ...@@ -5,6 +5,7 @@ import cn.bugstack.infrastructure.persistent.po.RaffleActivityOrder;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.RandomStringUtils;
import org.jeasy.random.EasyRandom;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
...@@ -15,10 +16,9 @@ import java.util.Date; ...@@ -15,10 +16,9 @@ import java.util.Date;
import java.util.List; import java.util.List;
/** /**
* @ClassName: RaffleActivityOrderDaoTest * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 抽奖活动订单测试
* @Author: zhaoyongfeng * @create 2024-03-09 10:51
* @Date: 2024/11/26 14:46
*/ */
@Slf4j @Slf4j
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
...@@ -28,6 +28,25 @@ public class RaffleActivityOrderDaoTest { ...@@ -28,6 +28,25 @@ public class RaffleActivityOrderDaoTest {
@Resource @Resource
private IRaffleActivityOrderDao raffleActivityOrderDao; private IRaffleActivityOrderDao raffleActivityOrderDao;
private final EasyRandom easyRandom = new EasyRandom();
@Test
public void test_insert_random() {
for (int i = 0; i < 5; i++) {
RaffleActivityOrder raffleActivityOrder = new RaffleActivityOrder();
// EasyRandom 可以通过指定对象类的方式,随机生成对象值。如;easyRandom.nextObject(String.class)、easyRandom.nextObject(RaffleActivityOrder.class)
raffleActivityOrder.setUserId(easyRandom.nextObject(String.class));
raffleActivityOrder.setActivityId(100301L);
raffleActivityOrder.setActivityName("测试活动");
raffleActivityOrder.setStrategyId(100006L);
raffleActivityOrder.setOrderId(RandomStringUtils.randomNumeric(12));
raffleActivityOrder.setOrderTime(new Date());
raffleActivityOrder.setState("not_used");
// 插入数据
raffleActivityOrderDao.insert(raffleActivityOrder);
}
}
@Test @Test
public void test_insert() { public void test_insert() {
RaffleActivityOrder raffleActivityOrder = new RaffleActivityOrder(); RaffleActivityOrder raffleActivityOrder = new RaffleActivityOrder();
......
package cn.bugstack.test.infrastructure;
import cn.bugstack.infrastructure.persistent.dao.IRuleTreeNodeDao;
import cn.bugstack.infrastructure.persistent.po.RuleTreeNode;
import com.alibaba.fastjson.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-20 09:40
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class RuleTreeNodeDaoTest {
@Resource
private IRuleTreeNodeDao ruleTreeNodeDao;
@Test
public void test_queryRuleLocks() {
List<RuleTreeNode> ruleTreeNodes = ruleTreeNodeDao.queryRuleLocks(new String[]{"tree_lock_1", "tree_lock_2"});
log.info("测试结果:{}", JSON.toJSONString(ruleTreeNodes));
}
}
package cn.bugstack.test.infrastructure;
import cn.bugstack.domain.strategy.model.valobj.RuleTreeVO;
import cn.bugstack.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import cn.bugstack.domain.strategy.repository.IStrategyRepository;
import cn.bugstack.infrastructure.persistent.redis.IRedisService;
import cn.bugstack.types.common.Constants;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 策略仓储测试
* @create 2024-02-03 09:43
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class StrategyRepositoryTest {
@Resource
private IStrategyRepository strategyRepository;
@Resource
private IRedisService redisService;
@Test
public void queryRuleTreeVOByTreeId() {
RuleTreeVO ruleTreeVO = strategyRepository.queryRuleTreeVOByTreeId("tree_lock");
log.info("测试结果:{}", JSON.toJSONString(ruleTreeVO));
}
@Test
public void test_cacheStrategyAwardCount() {
String cacheKey = Constants.RedisKey.STRATEGY_AWARD_COUNT_KEY + "300001" + Constants.UNDERLINE + "102";
strategyRepository.cacheStrategyAwardCount(cacheKey, 10);
}
@Test
public void test_subtractionAwardStock() {
String cacheKey = Constants.RedisKey.STRATEGY_AWARD_COUNT_KEY + "300001" + Constants.UNDERLINE + "102";
strategyRepository.subtractionAwardStock(cacheKey);
}
@Test
public void test_getValue() {
String cacheKey = Constants.RedisKey.STRATEGY_AWARD_COUNT_KEY + "300001" + Constants.UNDERLINE + "102";
Integer value = redisService.getValue(cacheKey);
log.info("测试结果:{}", value);
}
@Test
public void test_queue() throws InterruptedException {
String cacheKey = Constants.RedisKey.STRATEGY_AWARD_COUNT_QUERY_KEY;
RBlockingQueue<StrategyAwardStockKeyVO> blockingQueue = redisService.getBlockingQueue(cacheKey);
RDelayedQueue<StrategyAwardStockKeyVO> delayedQueue = redisService.getDelayedQueue(blockingQueue);
delayedQueue.offer(StrategyAwardStockKeyVO.builder()
.strategyId(100001L)
.awardId(102)
.build(), 3, TimeUnit.SECONDS);
new CountDownLatch(1).await();
}
}
package cn.bugstack.test.trigger; package cn.bugstack.test.trigger;
import cn.bugstack.trigger.api.IRaffleActivityService; import cn.bugstack.trigger.api.IRaffleActivityService;
import cn.bugstack.trigger.api.dto.ActivityDrawRequestDTO; import cn.bugstack.trigger.api.dto.*;
import cn.bugstack.trigger.api.dto.ActivityDrawResponseDTO; import cn.bugstack.trigger.api.response.Response;
import cn.bugstack.types.model.Response;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/** /**
* @author Fuzhengwei bugstack.cn @小傅哥 * @author Fuzhengwei bugstack.cn @小傅哥
...@@ -26,21 +30,101 @@ public class RaffleActivityControllerTest { ...@@ -26,21 +30,101 @@ public class RaffleActivityControllerTest {
@Resource @Resource
private IRaffleActivityService raffleActivityService; private IRaffleActivityService raffleActivityService;
@Resource
private CuratorFramework curatorFramework;
@Test @Test
public void test_armory() { public void test_armory() {
Response<Boolean> response = raffleActivityService.armory(100301L); Response<Boolean> response = raffleActivityService.armory(100301L);
log.info("测试结果:{}", JSON.toJSONString(response)); log.info("测试结果:{}", JSON.toJSONString(response));
} }
@Test
public void test_set_dcc_value() throws Exception {
curatorFramework.setData().forPath("/big-market-dcc/config/degradeSwitch", "close".getBytes(StandardCharsets.UTF_8));
}
@Test @Test
public void test_draw() { public void test_draw() {
for (int i = 0; i < 1; i++) {
ActivityDrawRequestDTO request = new ActivityDrawRequestDTO();
request.setActivityId(100301L);
request.setUserId("xiaofuge");
Response<ActivityDrawResponseDTO> response = raffleActivityService.draw(request);
log.info("请求参数:{}", JSON.toJSONString(request));
log.info("测试结果:{}", JSON.toJSONString(response));
}
}
@Test
public void test_blacklist_draw() throws InterruptedException {
ActivityDrawRequestDTO request = new ActivityDrawRequestDTO(); ActivityDrawRequestDTO request = new ActivityDrawRequestDTO();
request.setActivityId(100301L); request.setActivityId(100301L);
request.setUserId("xiaofuge"); request.setUserId("user001");
Response<ActivityDrawResponseDTO> response = raffleActivityService.draw(request); Response<ActivityDrawResponseDTO> response = raffleActivityService.draw(request);
log.info("请求参数:{}", JSON.toJSONString(request)); log.info("请求参数:{}", JSON.toJSONString(request));
log.info("测试结果:{}", JSON.toJSONString(response)); log.info("测试结果:{}", JSON.toJSONString(response));
// 让程序挺住方便测试,也可以去掉
// new CountDownLatch(1).await();
}
@Test
public void test_calendarSignRebate() throws InterruptedException {
Response<Boolean> response = raffleActivityService.calendarSignRebate("user002");
log.info("测试结果:{}", JSON.toJSONString(response));
// 让程序挺住方便测试,也可以去掉
new CountDownLatch(1).await();
}
@Test
public void test_isCalendarSignRebate() {
Response<Boolean> response = raffleActivityService.isCalendarSignRebate("xiaofuge");
log.info("测试结果:{}", JSON.toJSONString(response));
}
@Test
public void test_queryUserActivityAccount() {
UserActivityAccountRequestDTO request = new UserActivityAccountRequestDTO();
request.setActivityId(100301L);
request.setUserId("xiaofuge");
// 查询数据
Response<UserActivityAccountResponseDTO> response = raffleActivityService.queryUserActivityAccount(request);
log.info("请求参数:{}", JSON.toJSONString(request));
log.info("测试结果:{}", JSON.toJSONString(response));
}
@Test
public void test_querySkuProductListByActivityId() {
Long request = 100301L;
Response<List<SkuProductResponseDTO>> response = raffleActivityService.querySkuProductListByActivityId(request);
log.info("请求参数:{}", JSON.toJSONString(request));
log.info("测试结果:{}", JSON.toJSONString(response));
}
@Test
public void test_queryUserCreditAccount() {
String request = "xiaofuge";
Response<BigDecimal> response = raffleActivityService.queryUserCreditAccount(request);
log.info("请求参数:{}", JSON.toJSONString(request));
log.info("测试结果:{}", JSON.toJSONString(response));
}
@Test
public void test_creditPayExchangeSku() throws InterruptedException {
SkuProductShopCartRequestDTO request = new SkuProductShopCartRequestDTO();
request.setUserId("xiaofuge");
request.setSku(9014L);
Response<Boolean> response = raffleActivityService.creditPayExchangeSku(request);
log.info("请求参数:{}", JSON.toJSONString(request));
log.info("测试结果:{}", JSON.toJSONString(response));
new CountDownLatch(1).await();
} }
} }
package cn.bugstack.test.trigger; package cn.bugstack.test.trigger;
import cn.bugstack.trigger.api.IRaffleStrategyService; import cn.bugstack.trigger.api.IRaffleStrategyService;
import cn.bugstack.trigger.api.dto.RaffleAwardListRequestDTO; import cn.bugstack.trigger.api.dto.*;
import cn.bugstack.trigger.api.dto.RaffleAwardListResponseDTO; import cn.bugstack.trigger.api.response.Response;
import cn.bugstack.types.model.Response;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Test; import org.junit.Test;
...@@ -38,4 +37,15 @@ public class RaffleStrategyControllerTest { ...@@ -38,4 +37,15 @@ public class RaffleStrategyControllerTest {
log.info("测试结果:{}", JSON.toJSONString(response)); log.info("测试结果:{}", JSON.toJSONString(response));
} }
@Test
public void test_queryRaffleStrategyRuleWeight() {
RaffleStrategyRuleWeightRequestDTO request = new RaffleStrategyRuleWeightRequestDTO();
request.setUserId("xiaofuge");
request.setActivityId(100301L);
Response<List<RaffleStrategyRuleWeightResponseDTO>> response = raffleStrategyService.queryRaffleStrategyRuleWeight(request);
log.info("请求参数:{}", JSON.toJSONString(request));
log.info("测试结果:{}", JSON.toJSONString(response));
}
} }
...@@ -4,12 +4,11 @@ import cn.bugstack.types.event.BaseEvent; ...@@ -4,12 +4,11 @@ import cn.bugstack.types.event.BaseEvent;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.Date; import java.util.Date;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动sku库存清空消息 * @description 活动sku库存清空消息
* @create 2024-03-30 12:43 * @create 2024-03-30 12:43
*/ */
......
...@@ -10,16 +10,16 @@ import lombok.Data; ...@@ -10,16 +10,16 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* @ClassName: CreatePartakeOrderAggregate * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 参与活动订单聚合对象
* @Author: zhaoyongfeng * @create 2024-04-05 08:31
* @Date: 2024/12/6 23:59
*/ */
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class CreatePartakeOrderAggregate { public class CreatePartakeOrderAggregate {
/** /**
* 用户ID * 用户ID
*/ */
......
package cn.bugstack.domain.activity.model.aggregate; package cn.bugstack.domain.activity.model.aggregate;
import cn.bugstack.domain.activity.model.entity.ActivityOrderEntity; import cn.bugstack.domain.activity.model.entity.ActivityOrderEntity;
import cn.bugstack.domain.activity.model.valobj.OrderStateVO;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
...@@ -47,4 +48,8 @@ public class CreateQuotaOrderAggregate { ...@@ -47,4 +48,8 @@ public class CreateQuotaOrderAggregate {
*/ */
private ActivityOrderEntity activityOrderEntity; private ActivityOrderEntity activityOrderEntity;
public void setOrderState(OrderStateVO orderState) {
this.activityOrderEntity.setState(orderState);
}
} }
...@@ -6,16 +6,16 @@ import lombok.Data; ...@@ -6,16 +6,16 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* @ClassName: ActivityAccountDayEntity * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 活动账户(日)实体对象 * @description 活动账户(日)实体对象
* @Author: zhaoyongfeng * @create 2024-04-05 08:37
* @Date: 2024/12/6 23:40
*/ */
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class ActivityAccountDayEntity { public class ActivityAccountDayEntity {
/** 用户ID */ /** 用户ID */
private String userId; private String userId;
/** 活动ID */ /** 活动ID */
......
...@@ -6,8 +6,8 @@ import lombok.Data; ...@@ -6,8 +6,8 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动账户实体对象 * @description 活动账户(总)实体对象
* @create 2024-03-16 10:43 * @create 2024-03-16 10:43
*/ */
@Data @Data
......
...@@ -6,16 +6,16 @@ import lombok.Data; ...@@ -6,16 +6,16 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* @ClassName: ActivityAccountMonthEntity * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 活动账户(月)实体对象 * @description 活动账户(月)实体对象
* @Author: zhaoyongfeng * @create 2024-04-05 08:38
* @Date: 2024/12/6 23:40
*/ */
@Data @Data
@Builder @Builder
@NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor
public class ActivityAccountMonthEntity { public class ActivityAccountMonthEntity {
/** 用户ID */ /** 用户ID */
private String userId; private String userId;
/** 活动ID */ /** 活动ID */
...@@ -26,4 +26,5 @@ public class ActivityAccountMonthEntity { ...@@ -26,4 +26,5 @@ public class ActivityAccountMonthEntity {
private Integer monthCount; private Integer monthCount;
/** 月次数-剩余 */ /** 月次数-剩余 */
private Integer monthCountSurplus; private Integer monthCountSurplus;
} }
...@@ -6,7 +6,7 @@ import lombok.Data; ...@@ -6,7 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动次数实体对象 * @description 活动次数实体对象
* @create 2024-03-16 11:19 * @create 2024-03-16 11:19
*/ */
......
...@@ -9,7 +9,7 @@ import lombok.NoArgsConstructor; ...@@ -9,7 +9,7 @@ import lombok.NoArgsConstructor;
import java.util.Date; import java.util.Date;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动实体对象 * @description 活动实体对象
* @create 2024-03-16 11:15 * @create 2024-03-16 11:15
*/ */
......
...@@ -6,10 +6,11 @@ import lombok.Builder; ...@@ -6,10 +6,11 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动参与实体对象 * @description 活动参与实体对象
* @create 2024-03-16 09:02 * @create 2024-03-16 09:02
*/ */
...@@ -69,6 +70,11 @@ public class ActivityOrderEntity { ...@@ -69,6 +70,11 @@ public class ActivityOrderEntity {
*/ */
private Integer monthCount; private Integer monthCount;
/**
* 支付金额
*/
private BigDecimal payAmount;
/** /**
* 订单状态 * 订单状态
*/ */
......
...@@ -5,8 +5,10 @@ import lombok.Builder; ...@@ -5,8 +5,10 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动sku实体对象 * @description 活动sku实体对象
* @create 2024-03-16 10:29 * @create 2024-03-16 10:29
*/ */
...@@ -26,5 +28,7 @@ public class ActivitySkuEntity { ...@@ -26,5 +28,7 @@ public class ActivitySkuEntity {
private Integer stockCount; private Integer stockCount;
/** 剩余库存 */ /** 剩余库存 */
private Integer stockCountSurplus; private Integer stockCountSurplus;
/** 商品金额【积分】 */
private BigDecimal productAmount;
} }
package cn.bugstack.domain.activity.model.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 出货单实体对象
* @create 2024-06-08 20:02
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DeliveryOrderEntity {
/**
* 用户ID
*/
private String userId;
/**
* 业务仿重ID - 外部透传。返利、行为等唯一标识
*/
private String outBusinessNo;
}
...@@ -6,16 +6,16 @@ import lombok.Data; ...@@ -6,16 +6,16 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* @ClassName: PartakeRaffleActivityEntity * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 参与抽奖活动实体对象 * @description 参与抽奖活动实体对象
* @Author: zhaoyongfeng * @create 2024-04-04 20:02
* @Date: 2024/12/6 21:21
*/ */
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class PartakeRaffleActivityEntity { public class PartakeRaffleActivityEntity {
/** /**
* 用户ID * 用户ID
*/ */
...@@ -25,4 +25,5 @@ public class PartakeRaffleActivityEntity { ...@@ -25,4 +25,5 @@ public class PartakeRaffleActivityEntity {
* 活动ID * 活动ID
*/ */
private Long activityId; private Long activityId;
} }
package cn.bugstack.domain.activity.model.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description sku商品实体对象
* @create 2024-06-15 09:17
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SkuProductEntity {
/**
* 商品sku
*/
private Long sku;
/**
* 活动ID
*/
private Long activityId;
/**
* 活动个人参与次数ID
*/
private Long activityCountId;
/**
* 库存总量
*/
private Integer stockCount;
/**
* 剩余库存
*/
private Integer stockCountSurplus;
/**
* 商品金额【积分】
*/
private BigDecimal productAmount;
/**
* 活动配置的次数 - 购买商品后可以获得的次数
*/
private ActivityCount activityCount;
@Data
public static class ActivityCount {
/**
* 总次数
*/
private Integer totalCount;
/**
* 日次数
*/
private Integer dayCount;
/**
* 月次数
*/
private Integer monthCount;
}
}
package cn.bugstack.domain.activity.model.entity; package cn.bugstack.domain.activity.model.entity;
import cn.bugstack.domain.activity.model.valobj.OrderTradeTypeVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动商品充值实体对象 * @description 活动商品充值实体对象
* @create 2024-03-23 09:11 * @create 2024-03-23 09:11
*/ */
@Data @Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SkuRechargeEntity { public class SkuRechargeEntity {
/** 用户ID */ /** 用户ID */
...@@ -16,5 +23,7 @@ public class SkuRechargeEntity { ...@@ -16,5 +23,7 @@ public class SkuRechargeEntity {
private Long sku; private Long sku;
/** 幂等业务单号,外部谁充值谁透传,这样来保证幂等(多次调用也能确保结果唯一,不会多次充值)。 */ /** 幂等业务单号,外部谁充值谁透传,这样来保证幂等(多次调用也能确保结果唯一,不会多次充值)。 */
private String outBusinessNo; private String outBusinessNo;
/** 用户ID */
private OrderTradeTypeVO orderTradeType = OrderTradeTypeVO.rebate_no_pay_trade;
} }
package cn.bugstack.domain.activity.model.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 未完成支付的活动单
* @create 2024-06-15 08:31
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UnpaidActivityOrderEntity {
// 用户ID
private String userId;
// 订单ID
private String orderId;
// 外部透传ID
private String outBusinessNo;
// 订单金额
private BigDecimal payAmount;
}
package cn.bugstack.domain.activity.model.entity; package cn.bugstack.domain.activity.model.entity;
import cn.bugstack.domain.activity.model.valobj.UserRaffleOrderStateVO; import cn.bugstack.domain.activity.model.valobj.UserRaffleOrderStateVO;
import cn.bugstack.domain.award.model.valobj.AwardStateVO;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
...@@ -10,10 +9,9 @@ import lombok.NoArgsConstructor; ...@@ -10,10 +9,9 @@ import lombok.NoArgsConstructor;
import java.util.Date; import java.util.Date;
/** /**
* @ClassName: UserRaffleOrderEntity * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 用户抽奖订单实体对象 * @description 用户抽奖订单实体对象
* @Author: zhaoyongfeng * @create 2024-04-04 18:53
* @Date: 2024/12/6 21:21
*/ */
@Data @Data
@Builder @Builder
...@@ -37,4 +35,5 @@ public class UserRaffleOrderEntity { ...@@ -37,4 +35,5 @@ public class UserRaffleOrderEntity {
private UserRaffleOrderStateVO orderState; private UserRaffleOrderStateVO orderState;
/** 结束时间 */ /** 结束时间 */
private Date endDateTime; private Date endDateTime;
} }
...@@ -6,7 +6,7 @@ import lombok.Data; ...@@ -6,7 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动sku库存 key 值对象 * @description 活动sku库存 key 值对象
* @create 2024-03-30 09:44 * @create 2024-03-30 09:44
*/ */
......
...@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor; ...@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 活动状态值对象 * @description 活动状态值对象
* @create 2024-03-16 11:16 * @create 2024-03-16 11:16
*/ */
......
package cn.bugstack.domain.activity.model.valobj; package cn.bugstack.domain.activity.model.valobj;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter; import lombok.Getter;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 订单状态枚举值对象(用于描述对象属性的值,如枚举,不影响数据库操作的对象,无生命周期) * @description 订单状态枚举值对象(用于描述对象属性的值,如枚举,不影响数据库操作的对象,无生命周期)
* @create 2024-03-16 10:34 * @create 2024-03-16 10:34
*/ */
...@@ -13,7 +12,9 @@ import lombok.Getter; ...@@ -13,7 +12,9 @@ import lombok.Getter;
@AllArgsConstructor @AllArgsConstructor
public enum OrderStateVO { public enum OrderStateVO {
completed("completed", "完成"); wait_pay("wait_pay","待支付"),
completed("completed", "完成"),
;
private final String code; private final String code;
private final String desc; private final String desc;
......
package cn.bugstack.domain.activity.model.valobj;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 订单交易类型
* @create 2024-06-08 18:27
*/
@Getter
@AllArgsConstructor
public enum OrderTradeTypeVO {
credit_pay_trade("credit_pay_trade","积分兑换,需要支付类交易"),
rebate_no_pay_trade("rebate_no_pay_trade", "返利奖品,不需要支付类交易"),
;
private final String code;
private final String desc;
}
...@@ -4,14 +4,14 @@ import lombok.AllArgsConstructor; ...@@ -4,14 +4,14 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/** /**
* @ClassName: UserRaffleOrderStateVO * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 用户抽奖订单状态枚举 * @description 用户抽奖订单状态枚举
* @Author: zhaoyongfeng * @create 2024-04-04 18:55
* @Date: 2024/12/6 21:22
*/ */
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum UserRaffleOrderStateVO { public enum UserRaffleOrderStateVO {
create("create", "创建"), create("create", "创建"),
used("used", "已使用"), used("used", "已使用"),
cancel("cancel", "已作废"), cancel("cancel", "已作废"),
......
...@@ -5,24 +5,26 @@ import cn.bugstack.domain.activity.model.aggregate.CreateQuotaOrderAggregate; ...@@ -5,24 +5,26 @@ import cn.bugstack.domain.activity.model.aggregate.CreateQuotaOrderAggregate;
import cn.bugstack.domain.activity.model.entity.*; import cn.bugstack.domain.activity.model.entity.*;
import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO; import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
/* /**
* @return * @author Fuzhengwei bugstack.cn @小傅哥
* @author zhaoyongfeng
* @description 活动仓储接口 * @description 活动仓储接口
* * @create 2024-03-16 10:31
* @param null
*/ */
public interface IActivityRepository { public interface IActivityRepository {
ActivitySkuEntity queryActivitySku(Long sku); ActivitySkuEntity queryActivitySku(Long sku);
ActivityEntity queryRaffleActivityByActivityId(Long activityId); ActivityEntity queryRaffleActivityByActivityId(Long activityId);
ActivityCountEntity queryRaffleActivityCountByActivityCountId(Long activityCountId); ActivityCountEntity queryRaffleActivityCountByActivityCountId(Long activityCountId);
void doSaveOrder(CreateQuotaOrderAggregate createOrderAggregate); void doSaveNoPayOrder(CreateQuotaOrderAggregate createOrderAggregate);
void doSaveCreditPayOrder(CreateQuotaOrderAggregate createQuotaOrderAggregate);
void cacheActivitySkuStockCount(String cacheKey, Integer stockCount); void cacheActivitySkuStockCount(String cacheKey, Integer stockCount);
...@@ -55,4 +57,13 @@ public interface IActivityRepository { ...@@ -55,4 +57,13 @@ public interface IActivityRepository {
ActivityAccountEntity queryActivityAccountEntity(Long activityId, String userId); ActivityAccountEntity queryActivityAccountEntity(Long activityId, String userId);
Integer queryRaffleActivityAccountPartakeCount(Long activityId, String userId); Integer queryRaffleActivityAccountPartakeCount(Long activityId, String userId);
void updateOrder(DeliveryOrderEntity deliveryOrderEntity);
UnpaidActivityOrderEntity queryUnpaidActivityOrder(SkuRechargeEntity skuRechargeEntity);
List<SkuProductEntity> querySkuProductEntityListByActivityId(Long activityId);
BigDecimal queryUserCreditAccountAmount(String userId);
} }
package cn.bugstack.domain.activity.service; package cn.bugstack.domain.activity.service;
import cn.bugstack.domain.activity.model.entity.ActivityAccountEntity; import cn.bugstack.domain.activity.model.entity.ActivityAccountEntity;
import cn.bugstack.domain.activity.model.entity.DeliveryOrderEntity;
import cn.bugstack.domain.activity.model.entity.SkuRechargeEntity; import cn.bugstack.domain.activity.model.entity.SkuRechargeEntity;
import cn.bugstack.domain.activity.model.entity.UnpaidActivityOrderEntity;
/* /**
* @return * @author Fuzhengwei bugstack.cn @小傅哥
* @author zhaoyongfeng * @description 抽奖活动账户额度服务
* @description 抽奖活动订单接口 * @create 2024-03-16 08:38
*/ */
public interface IRaffleActivityAccountQuotaService { public interface IRaffleActivityAccountQuotaService {
/** /**
* 创建 sku 账户充值订单,给用户增加抽奖次数 * 创建 sku 账户充值订单,给用户增加抽奖次数
* <p> * <p>
...@@ -16,31 +19,41 @@ public interface IRaffleActivityAccountQuotaService { ...@@ -16,31 +19,41 @@ public interface IRaffleActivityAccountQuotaService {
* 2. 对于用户可获得的抽奖次数,比如首次进来就有一次,则是依赖于运营配置的动作,在前端页面上。用户点击后,可以获得一次抽奖次数。 * 2. 对于用户可获得的抽奖次数,比如首次进来就有一次,则是依赖于运营配置的动作,在前端页面上。用户点击后,可以获得一次抽奖次数。
* *
* @param skuRechargeEntity 活动商品充值实体对象 * @param skuRechargeEntity 活动商品充值实体对象
* @return 活动ID * @return 未支付订单
*/ */
String createOrder(SkuRechargeEntity skuRechargeEntity); UnpaidActivityOrderEntity createOrder(SkuRechargeEntity skuRechargeEntity);
/** /**
* 查询活动账户 - 日,参与次数 * 订单出货 - 积分充值
* @param deliveryOrderEntity 出货单实体对象
*/
void updateOrder(DeliveryOrderEntity deliveryOrderEntity);
/**
* 查询活动账户 - 总,参与次数
* *
* @param activityId 活动ID * @param activityId 活动ID
* @param userId 用户ID * @param userId 用户ID
* @return 参与次数 * @return 参与次数
*/ */
Integer queryRaffleActivityAccountDayPartakeCount(Long activityId, String userId); Integer queryRaffleActivityAccountPartakeCount(Long activityId, String userId);
/** /**
* 查询活动账户额度「总、月、日」 * 查询活动账户 - 日,参与次数
* *
* @param activityId 活动ID * @param activityId 活动ID
* @param userId 用户ID * @param userId 用户ID
* @return 账户实体 * @return 参与次数
*/ */
ActivityAccountEntity queryActivityAccountEntity(Long activityId, String userId); Integer queryRaffleActivityAccountDayPartakeCount(Long activityId, String userId);
/** /**
* 查询活动账户 - 总,参与次数 * 查询活动账户额度「总、月、日」
* *
* @param activityId 活动ID * @param activityId 活动ID
* @param userId 用户ID * @param userId 用户ID
* @return 参与次数 * @return 账户实体
*/ */
Integer queryRaffleActivityAccountPartakeCount(Long activityId, String userId); ActivityAccountEntity queryActivityAccountEntity(Long activityId, String userId);
} }
...@@ -2,27 +2,29 @@ package cn.bugstack.domain.activity.service; ...@@ -2,27 +2,29 @@ package cn.bugstack.domain.activity.service;
import cn.bugstack.domain.activity.model.entity.PartakeRaffleActivityEntity; import cn.bugstack.domain.activity.model.entity.PartakeRaffleActivityEntity;
import cn.bugstack.domain.activity.model.entity.UserRaffleOrderEntity; import cn.bugstack.domain.activity.model.entity.UserRaffleOrderEntity;
/*
* @return /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 抽奖活动参与服务 * @description 抽奖活动参与服务
* @create 2024-04-04 19:50
*/ */
public interface IRaffleActivityPartakeService { public interface IRaffleActivityPartakeService {
/** /**
* 创建抽奖单;用户参与抽奖活动,扣减活动账户库存,产生抽奖单。如存在未被使用的抽奖单则直接返回已存在的抽奖单。 * 创建抽奖单;用户参与抽奖活动,扣减活动账户库存,产生抽奖单。如存在未被使用的抽奖单则直接返回已存在的抽奖单。
* *
* @param partakeRaffleActivityEntity 参与抽奖活动实体对象 * @param userId 用户ID
* @param activityId 活动ID
* @return 用户抽奖订单实体对象 * @return 用户抽奖订单实体对象
*/ */
UserRaffleOrderEntity createOrder(PartakeRaffleActivityEntity partakeRaffleActivityEntity); UserRaffleOrderEntity createOrder(String userId, Long activityId);
/** /**
* 创建抽奖单;用户参与抽奖活动,扣减活动账户库存,产生抽奖单。如存在未被使用的抽奖单则直接返回已存在的抽奖单。 * 创建抽奖单;用户参与抽奖活动,扣减活动账户库存,产生抽奖单。如存在未被使用的抽奖单则直接返回已存在的抽奖单。
* *
* @param userId 用户ID * @param partakeRaffleActivityEntity 参与抽奖活动实体对象
* @param activityId 活动ID
* @return 用户抽奖订单实体对象 * @return 用户抽奖订单实体对象
*/ */
UserRaffleOrderEntity createOrder(String userId, Long activityId); UserRaffleOrderEntity createOrder(PartakeRaffleActivityEntity partakeRaffleActivityEntity);
} }
package cn.bugstack.domain.activity.service;
import cn.bugstack.domain.activity.model.entity.SkuProductEntity;
import java.util.List;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description sku商品服务接口
* @create 2024-06-15 09:14
*/
public interface IRaffleActivitySkuProductService {
/**
* 查询当前活动ID下,创建的 sku 商品。「sku可以兑换活动抽奖次数」
* @param activityId 活动ID
* @return 返回sku商品集合
*/
List<SkuProductEntity> querySkuProductEntityListByActivityId(Long activityId);
}
...@@ -2,12 +2,13 @@ package cn.bugstack.domain.activity.service; ...@@ -2,12 +2,13 @@ package cn.bugstack.domain.activity.service;
import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO; import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
/* /**
* @return * @author Fuzhengwei bugstack.cn @小傅哥
* @author zhaoyongfeng * @description 抽奖活动SKU库存服务
* @description 活动sku库存处理接口 * @create 2024-03-30 09:55
*/ */
public interface IRaffleActivitySkuStockService { public interface IRaffleActivitySkuStockService {
/** /**
* 获取活动sku库存消耗队列 * 获取活动sku库存消耗队列
* *
...@@ -34,4 +35,5 @@ public interface IRaffleActivitySkuStockService { ...@@ -34,4 +35,5 @@ public interface IRaffleActivitySkuStockService {
* @param sku 活动商品 * @param sku 活动商品
*/ */
void clearActivitySkuStock(Long sku); void clearActivitySkuStock(Long sku);
} }
package cn.bugstack.domain.activity.service.armory; package cn.bugstack.domain.activity.service.armory;
import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity; import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity;
import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
import cn.bugstack.domain.activity.repository.IActivityRepository; import cn.bugstack.domain.activity.repository.IActivityRepository;
import cn.bugstack.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import cn.bugstack.types.common.Constants; import cn.bugstack.types.common.Constants;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -11,7 +9,6 @@ import org.springframework.stereotype.Service; ...@@ -11,7 +9,6 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
/** /**
* @author Fuzhengwei bugstack.cn @小傅哥 * @author Fuzhengwei bugstack.cn @小傅哥
...@@ -25,21 +22,6 @@ public class ActivityArmory implements IActivityArmory, IActivityDispatch { ...@@ -25,21 +22,6 @@ public class ActivityArmory implements IActivityArmory, IActivityDispatch {
@Resource @Resource
private IActivityRepository activityRepository; private IActivityRepository activityRepository;
@Override
public boolean assembleActivitySku(Long sku) {
// 预热活动sku库存
ActivitySkuEntity activitySkuEntity = activityRepository.queryActivitySku(sku);
cacheActivitySkuStockCount(sku, activitySkuEntity.getStockCount());
// 预热活动【查询时预热到缓存】
activityRepository.queryRaffleActivityByActivityId(activitySkuEntity.getActivityId());
// 预热活动次数【查询时预热到缓存】
activityRepository.queryRaffleActivityCountByActivityCountId(activitySkuEntity.getActivityCountId());
return true;
}
@Override @Override
public boolean assembleActivitySkuByActivityId(Long activityId) { public boolean assembleActivitySkuByActivityId(Long activityId) {
List<ActivitySkuEntity> activitySkuEntities = activityRepository.queryActivitySkuListByActivityId(activityId); List<ActivitySkuEntity> activitySkuEntities = activityRepository.queryActivitySkuListByActivityId(activityId);
...@@ -55,6 +37,21 @@ public class ActivityArmory implements IActivityArmory, IActivityDispatch { ...@@ -55,6 +37,21 @@ public class ActivityArmory implements IActivityArmory, IActivityDispatch {
return true; return true;
} }
@Override
public boolean assembleActivitySku(Long sku) {
// 预热活动sku库存
ActivitySkuEntity activitySkuEntity = activityRepository.queryActivitySku(sku);
cacheActivitySkuStockCount(sku, activitySkuEntity.getStockCountSurplus());
// 预热活动【查询时预热到缓存】
activityRepository.queryRaffleActivityByActivityId(activitySkuEntity.getActivityId());
// 预热活动次数【查询时预热到缓存】
activityRepository.queryRaffleActivityCountByActivityCountId(activitySkuEntity.getActivityCountId());
return true;
}
private void cacheActivitySkuStockCount(Long sku, Integer stockCount) { private void cacheActivitySkuStockCount(Long sku, Integer stockCount) {
String cacheKey = Constants.RedisKey.ACTIVITY_SKU_STOCK_COUNT_KEY + sku; String cacheKey = Constants.RedisKey.ACTIVITY_SKU_STOCK_COUNT_KEY + sku;
activityRepository.cacheActivitySkuStockCount(cacheKey, stockCount); activityRepository.cacheActivitySkuStockCount(cacheKey, stockCount);
......
...@@ -7,7 +7,8 @@ package cn.bugstack.domain.activity.service.armory; ...@@ -7,7 +7,8 @@ package cn.bugstack.domain.activity.service.armory;
*/ */
public interface IActivityArmory { public interface IActivityArmory {
boolean assembleActivitySkuByActivityId(Long activityId);
boolean assembleActivitySku(Long sku); boolean assembleActivitySku(Long sku);
boolean assembleActivitySkuByActivityId(Long activityId);
} }
package cn.bugstack.domain.activity.service.armory; package cn.bugstack.domain.activity.service.armory;
import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
import java.util.Date; import java.util.Date;
/** /**
......
...@@ -12,23 +12,22 @@ import cn.bugstack.types.exception.AppException; ...@@ -12,23 +12,22 @@ import cn.bugstack.types.exception.AppException;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import javax.annotation.Resource;
import java.util.Date; import java.util.Date;
/** /**
* @ClassName: AbstractRaffleActivityPartake * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 抽奖活动参与抽奖类
* @Author: zhaoyongfeng * @create 2024-04-05 07:53
* @Date: 2024/12/6 23:34
*/ */
@Slf4j @Slf4j
public abstract class AbstractRaffleActivityPartake implements IRaffleActivityPartakeService { public abstract class AbstractRaffleActivityPartake implements IRaffleActivityPartakeService {
@Resource
protected final IActivityRepository activityRepository; protected final IActivityRepository activityRepository;
public AbstractRaffleActivityPartake(IActivityRepository activityRepository) { public AbstractRaffleActivityPartake(IActivityRepository activityRepository) {
this.activityRepository = activityRepository; this.activityRepository = activityRepository;
} }
@Override @Override
public UserRaffleOrderEntity createOrder(String userId, Long activityId) { public UserRaffleOrderEntity createOrder(String userId, Long activityId) {
return createOrder(PartakeRaffleActivityEntity.builder() return createOrder(PartakeRaffleActivityEntity.builder()
...@@ -36,29 +35,32 @@ public abstract class AbstractRaffleActivityPartake implements IRaffleActivityPa ...@@ -36,29 +35,32 @@ public abstract class AbstractRaffleActivityPartake implements IRaffleActivityPa
.activityId(activityId) .activityId(activityId)
.build()); .build());
} }
@Override @Override
public UserRaffleOrderEntity createOrder(PartakeRaffleActivityEntity partakeRaffleActivityEntity) { public UserRaffleOrderEntity createOrder(PartakeRaffleActivityEntity partakeRaffleActivityEntity) {
// 0. 基础信息 // 0. 基础信息
String userId = partakeRaffleActivityEntity.getUserId(); String userId = partakeRaffleActivityEntity.getUserId();
Long activityId = partakeRaffleActivityEntity.getActivityId(); Long activityId = partakeRaffleActivityEntity.getActivityId();
Date currentDate = new Date(); Date currentDate = new Date();
log.info("创建活动抽奖单开始 userId:{} activityId:{}", userId, activityId);
// 1. 活动查询 // 1. 活动查询
ActivityEntity activityEntity = activityRepository.queryRaffleActivityByActivityId(activityId); ActivityEntity activityEntity = activityRepository.queryRaffleActivityByActivityId(activityId);
// 校验;活动状态 // 校验;活动状态
if (!ActivityStateVO.open.equals(activityEntity.getState())) { if (!ActivityStateVO.open.equals(activityEntity.getState())) {
log.error("创建活动抽奖单失败,活动状态未开启 activityId:{} state:{}", activityId, activityEntity.getState());
throw new AppException(ResponseCode.ACTIVITY_STATE_ERROR.getCode(), ResponseCode.ACTIVITY_STATE_ERROR.getInfo()); throw new AppException(ResponseCode.ACTIVITY_STATE_ERROR.getCode(), ResponseCode.ACTIVITY_STATE_ERROR.getInfo());
} }
// 校验;活动日期「开始时间 <- 当前时间 -> 结束时间」 // 校验;活动日期「开始时间 <- 当前时间 -> 结束时间」
if (activityEntity.getBeginDateTime().after(currentDate) || activityEntity.getEndDateTime().before(currentDate)) { if (activityEntity.getBeginDateTime().after(currentDate) || activityEntity.getEndDateTime().before(currentDate)) {
log.error("创建活动抽奖单失败,活动时间未开始 activityId:{} state:{}", activityId, activityEntity.getState());
throw new AppException(ResponseCode.ACTIVITY_DATE_ERROR.getCode(), ResponseCode.ACTIVITY_DATE_ERROR.getInfo()); throw new AppException(ResponseCode.ACTIVITY_DATE_ERROR.getCode(), ResponseCode.ACTIVITY_DATE_ERROR.getInfo());
} }
// 2. 查询未被使用的活动参与订单记录 // 2. 查询未被使用的活动参与订单记录
UserRaffleOrderEntity userRaffleOrderEntity = activityRepository.queryNoUsedRaffleOrder(partakeRaffleActivityEntity); UserRaffleOrderEntity userRaffleOrderEntity = activityRepository.queryNoUsedRaffleOrder(partakeRaffleActivityEntity);
if (null != userRaffleOrderEntity) { if (null != userRaffleOrderEntity) {
log.info("创建参与活动订单 userId:{} activityId:{} userRaffleOrderEntity:{}", userId, activityId, JSON.toJSONString(userRaffleOrderEntity)); log.info("创建参与活动订单存在 userId:{} activityId:{} userRaffleOrderEntity:{}", userId, activityId, JSON.toJSONString(userRaffleOrderEntity));
return userRaffleOrderEntity; return userRaffleOrderEntity;
} }
...@@ -73,14 +75,13 @@ public abstract class AbstractRaffleActivityPartake implements IRaffleActivityPa ...@@ -73,14 +75,13 @@ public abstract class AbstractRaffleActivityPartake implements IRaffleActivityPa
// 6. 保存聚合对象 - 一个领域内的一个聚合是一个事务操作 // 6. 保存聚合对象 - 一个领域内的一个聚合是一个事务操作
activityRepository.saveCreatePartakeOrderAggregate(createPartakeOrderAggregate); activityRepository.saveCreatePartakeOrderAggregate(createPartakeOrderAggregate);
log.info("创建活动抽奖单完成 userId:{} activityId:{} orderId:{}", userId, activityId, userRaffleOrder.getOrderId());
// 7. 返回订单信息 // 7. 返回订单信息
return userRaffleOrder; return userRaffleOrder;
} }
protected abstract CreatePartakeOrderAggregate doFilterAccount(String userId, Long activityId, Date currentDate); protected abstract CreatePartakeOrderAggregate doFilterAccount(String userId, Long activityId, Date currentDate);
protected abstract UserRaffleOrderEntity buildUserRaffleOrder(String userId, Long activityId, Date currentDate); protected abstract UserRaffleOrderEntity buildUserRaffleOrder(String userId, Long activityId, Date currentDate);
} }
...@@ -13,13 +13,13 @@ import java.text.SimpleDateFormat; ...@@ -13,13 +13,13 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
/** /**
* @ClassName: RaffleActivityPartakeService * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description
* @Author: zhaoyongfeng * @create 2024-04-05 07:53
* @Date: 2024/12/7 0:00
*/ */
@Service @Service
public class RaffleActivityPartakeService extends AbstractRaffleActivityPartake{ public class RaffleActivityPartakeService extends AbstractRaffleActivityPartake{
private final SimpleDateFormat dateFormatMonth = new SimpleDateFormat("yyyy-MM"); private final SimpleDateFormat dateFormatMonth = new SimpleDateFormat("yyyy-MM");
private final SimpleDateFormat dateFormatDay = new SimpleDateFormat("yyyy-MM-dd"); private final SimpleDateFormat dateFormatDay = new SimpleDateFormat("yyyy-MM-dd");
...@@ -54,7 +54,7 @@ public class RaffleActivityPartakeService extends AbstractRaffleActivityPartake{ ...@@ -54,7 +54,7 @@ public class RaffleActivityPartakeService extends AbstractRaffleActivityPartake{
activityAccountMonthEntity.setActivityId(activityId); activityAccountMonthEntity.setActivityId(activityId);
activityAccountMonthEntity.setMonth(month); activityAccountMonthEntity.setMonth(month);
activityAccountMonthEntity.setMonthCount(activityAccountEntity.getMonthCount()); activityAccountMonthEntity.setMonthCount(activityAccountEntity.getMonthCount());
activityAccountMonthEntity.setMonthCountSurplus(activityAccountEntity.getMonthCountSurplus()); activityAccountMonthEntity.setMonthCountSurplus(activityAccountEntity.getMonthCount());
} }
// 查询日账户额度 // 查询日账户额度
...@@ -71,7 +71,7 @@ public class RaffleActivityPartakeService extends AbstractRaffleActivityPartake{ ...@@ -71,7 +71,7 @@ public class RaffleActivityPartakeService extends AbstractRaffleActivityPartake{
activityAccountDayEntity.setActivityId(activityId); activityAccountDayEntity.setActivityId(activityId);
activityAccountDayEntity.setDay(day); activityAccountDayEntity.setDay(day);
activityAccountDayEntity.setDayCount(activityAccountEntity.getDayCount()); activityAccountDayEntity.setDayCount(activityAccountEntity.getDayCount());
activityAccountDayEntity.setDayCountSurplus(activityAccountEntity.getDayCountSurplus()); activityAccountDayEntity.setDayCountSurplus(activityAccountEntity.getDayCount());
} }
// 构建对象 // 构建对象
...@@ -99,6 +99,7 @@ public class RaffleActivityPartakeService extends AbstractRaffleActivityPartake{ ...@@ -99,6 +99,7 @@ public class RaffleActivityPartakeService extends AbstractRaffleActivityPartake{
userRaffleOrder.setOrderId(RandomStringUtils.randomNumeric(12)); userRaffleOrder.setOrderId(RandomStringUtils.randomNumeric(12));
userRaffleOrder.setOrderTime(currentDate); userRaffleOrder.setOrderTime(currentDate);
userRaffleOrder.setOrderState(UserRaffleOrderStateVO.create); userRaffleOrder.setOrderState(UserRaffleOrderStateVO.create);
userRaffleOrder.setEndDateTime(activityEntity.getEndDateTime());
return userRaffleOrder; return userRaffleOrder;
} }
......
package cn.bugstack.domain.activity.service.product;
import cn.bugstack.domain.activity.model.entity.SkuProductEntity;
import cn.bugstack.domain.activity.repository.IActivityRepository;
import cn.bugstack.domain.activity.service.IRaffleActivitySkuProductService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description sku商品服务
* @create 2024-06-15 09:30
*/
@Service
public class RaffleActivitySkuProductService implements IRaffleActivitySkuProductService {
@Resource
private IActivityRepository repository;
@Override
public List<SkuProductEntity> querySkuProductEntityListByActivityId(Long activityId) {
return repository.querySkuProductEntityListByActivityId(activityId);
}
}
...@@ -2,8 +2,10 @@ package cn.bugstack.domain.activity.service.quota; ...@@ -2,8 +2,10 @@ package cn.bugstack.domain.activity.service.quota;
import cn.bugstack.domain.activity.model.aggregate.CreateQuotaOrderAggregate; import cn.bugstack.domain.activity.model.aggregate.CreateQuotaOrderAggregate;
import cn.bugstack.domain.activity.model.entity.*; import cn.bugstack.domain.activity.model.entity.*;
import cn.bugstack.domain.activity.model.valobj.OrderTradeTypeVO;
import cn.bugstack.domain.activity.repository.IActivityRepository; import cn.bugstack.domain.activity.repository.IActivityRepository;
import cn.bugstack.domain.activity.service.IRaffleActivityAccountQuotaService; import cn.bugstack.domain.activity.service.IRaffleActivityAccountQuotaService;
import cn.bugstack.domain.activity.service.quota.policy.ITradePolicy;
import cn.bugstack.domain.activity.service.quota.rule.IActionChain; import cn.bugstack.domain.activity.service.quota.rule.IActionChain;
import cn.bugstack.domain.activity.service.quota.rule.factory.DefaultActivityChainFactory; import cn.bugstack.domain.activity.service.quota.rule.factory.DefaultActivityChainFactory;
import cn.bugstack.types.enums.ResponseCode; import cn.bugstack.types.enums.ResponseCode;
...@@ -11,18 +13,27 @@ import cn.bugstack.types.exception.AppException; ...@@ -11,18 +13,27 @@ import cn.bugstack.types.exception.AppException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
/* import java.math.BigDecimal;
* @return import java.util.Map;
* @author zhaoyongfeng
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 抽奖活动抽象类,定义标准的流程 * @description 抽奖活动抽象类,定义标准的流程
* @create 2024-03-16 08:42
*/ */
@Slf4j @Slf4j
public abstract class AbstractRaffleActivityAccountQuota extends RaffleActivityAccountQuotaSupport implements IRaffleActivityAccountQuotaService { public abstract class AbstractRaffleActivityAccountQuota extends RaffleActivityAccountQuotaSupport implements IRaffleActivityAccountQuotaService {
public AbstractRaffleActivityAccountQuota(IActivityRepository activityRepository, DefaultActivityChainFactory defaultActivityChainFactory) {
// 不同类型的交易策略实现类,通过构造函数注入到 Map 中,教程;https://bugstack.cn/md/road-map/spring-dependency-injection.html
private final Map<String, ITradePolicy> tradePolicyGroup;
public AbstractRaffleActivityAccountQuota(IActivityRepository activityRepository, DefaultActivityChainFactory defaultActivityChainFactory, Map<String, ITradePolicy> tradePolicyGroup) {
super(activityRepository, defaultActivityChainFactory); super(activityRepository, defaultActivityChainFactory);
this.tradePolicyGroup = tradePolicyGroup;
} }
@Override @Override
public String createOrder(SkuRechargeEntity skuRechargeEntity) { public UnpaidActivityOrderEntity createOrder(SkuRechargeEntity skuRechargeEntity) {
// 1. 参数校验 // 1. 参数校验
String userId = skuRechargeEntity.getUserId(); String userId = skuRechargeEntity.getUserId();
Long sku = skuRechargeEntity.getSku(); Long sku = skuRechargeEntity.getSku();
...@@ -31,31 +42,46 @@ public abstract class AbstractRaffleActivityAccountQuota extends RaffleActivityA ...@@ -31,31 +42,46 @@ public abstract class AbstractRaffleActivityAccountQuota extends RaffleActivityA
throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo()); throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
} }
// 2. 查询基础信息 // 2. 查询未支付订单「一个月以内的未支付订单」& 支付类型查询,非支付的走兑换
// 2.1 通过sku查询活动信息 if (OrderTradeTypeVO.credit_pay_trade.equals(skuRechargeEntity.getOrderTradeType())){
UnpaidActivityOrderEntity unpaidCreditOrder = activityRepository.queryUnpaidActivityOrder(skuRechargeEntity);
if (null != unpaidCreditOrder) return unpaidCreditOrder;
}
// 3. 查询基础信息「sku、活动、次数」
ActivitySkuEntity activitySkuEntity = queryActivitySku(sku); ActivitySkuEntity activitySkuEntity = queryActivitySku(sku);
// 2.2 查询活动信息
ActivityEntity activityEntity = queryRaffleActivityByActivityId(activitySkuEntity.getActivityId()); ActivityEntity activityEntity = queryRaffleActivityByActivityId(activitySkuEntity.getActivityId());
// 2.3 查询次数信息(用户在活动上可参与的次数)
ActivityCountEntity activityCountEntity = queryRaffleActivityCountByActivityCountId(activitySkuEntity.getActivityCountId()); ActivityCountEntity activityCountEntity = queryRaffleActivityCountByActivityCountId(activitySkuEntity.getActivityCountId());
// 3. 活动动作规则校验 「过滤失败则直接抛异常」 // 4. 账户额度 【交易属性的兑换,需要校验额度账户】
if (OrderTradeTypeVO.credit_pay_trade.equals(skuRechargeEntity.getOrderTradeType())){
BigDecimal availableAmount = activityRepository.queryUserCreditAccountAmount(userId);
if (availableAmount.compareTo(activitySkuEntity.getProductAmount()) < 0) {
throw new AppException(ResponseCode.USER_CREDIT_ACCOUNT_NO_AVAILABLE_AMOUNT.getCode(), ResponseCode.USER_CREDIT_ACCOUNT_NO_AVAILABLE_AMOUNT.getInfo());
}
}
// 5. 活动动作规则校验 「过滤失败则直接抛异常」- 责任链扣减sku库存
IActionChain actionChain = defaultActivityChainFactory.openActionChain(); IActionChain actionChain = defaultActivityChainFactory.openActionChain();
actionChain.action(activitySkuEntity, activityEntity, activityCountEntity); actionChain.action(activitySkuEntity, activityEntity, activityCountEntity);
// 4. 构建订单聚合对象 // 6. 构建订单聚合对象
CreateQuotaOrderAggregate createOrderAggregate = buildOrderAggregate(skuRechargeEntity, activitySkuEntity, activityEntity, activityCountEntity); CreateQuotaOrderAggregate createOrderAggregate = buildOrderAggregate(skuRechargeEntity, activitySkuEntity, activityEntity, activityCountEntity);
// 5. 保存订单 // 7. 交易策略 - 【积分兑换,支付类订单】【返利无支付交易订单,直接充值到账】【订单状态变更交易类型策略】
doSaveOrder(createOrderAggregate); ITradePolicy tradePolicy = tradePolicyGroup.get(skuRechargeEntity.getOrderTradeType().getCode());
tradePolicy.trade(createOrderAggregate);
// 6. 返回单号 // 8. 返回订单信息
return createOrderAggregate.getActivityOrderEntity().getOrderId(); ActivityOrderEntity activityOrderEntity = createOrderAggregate.getActivityOrderEntity();
return UnpaidActivityOrderEntity.builder()
.userId(userId)
.orderId(activityOrderEntity.getOrderId())
.outBusinessNo(activityOrderEntity.getOutBusinessNo())
.payAmount(activityOrderEntity.getPayAmount())
.build();
} }
protected abstract CreateQuotaOrderAggregate buildOrderAggregate(SkuRechargeEntity skuRechargeEntity, ActivitySkuEntity activitySkuEntity, ActivityEntity activityEntity, ActivityCountEntity activityCountEntity); protected abstract CreateQuotaOrderAggregate buildOrderAggregate(SkuRechargeEntity skuRechargeEntity, ActivitySkuEntity activitySkuEntity, ActivityEntity activityEntity, ActivityCountEntity activityCountEntity);
protected abstract void doSaveOrder(CreateQuotaOrderAggregate createOrderAggregate);
} }
...@@ -3,24 +3,26 @@ package cn.bugstack.domain.activity.service.quota; ...@@ -3,24 +3,26 @@ package cn.bugstack.domain.activity.service.quota;
import cn.bugstack.domain.activity.model.aggregate.CreateQuotaOrderAggregate; import cn.bugstack.domain.activity.model.aggregate.CreateQuotaOrderAggregate;
import cn.bugstack.domain.activity.model.entity.*; import cn.bugstack.domain.activity.model.entity.*;
import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO; import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
import cn.bugstack.domain.activity.model.valobj.OrderStateVO;
import cn.bugstack.domain.activity.repository.IActivityRepository; import cn.bugstack.domain.activity.repository.IActivityRepository;
import cn.bugstack.domain.activity.service.IRaffleActivitySkuStockService; import cn.bugstack.domain.activity.service.IRaffleActivitySkuStockService;
import cn.bugstack.domain.activity.service.quota.policy.ITradePolicy;
import cn.bugstack.domain.activity.service.quota.rule.factory.DefaultActivityChainFactory; import cn.bugstack.domain.activity.service.quota.rule.factory.DefaultActivityChainFactory;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Date; import java.util.Date;
import java.util.Map;
/* /**
* @return * @author Fuzhengwei bugstack.cn @小傅哥
* @author zhaoyongfeng
* @description 抽奖活动服务 * @description 抽奖活动服务
* @create 2024-03-16 08:41
*/ */
@Service @Service
public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAccountQuota implements IRaffleActivitySkuStockService { public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAccountQuota implements IRaffleActivitySkuStockService {
public RaffleActivityAccountQuotaService(IActivityRepository activityRepository, DefaultActivityChainFactory defaultActivityChainFactory) {
super(activityRepository, defaultActivityChainFactory); public RaffleActivityAccountQuotaService(IActivityRepository activityRepository, DefaultActivityChainFactory defaultActivityChainFactory, Map<String, ITradePolicy> tradePolicyGroup) {
super(activityRepository, defaultActivityChainFactory, tradePolicyGroup);
} }
@Override @Override
...@@ -38,7 +40,7 @@ public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAcc ...@@ -38,7 +40,7 @@ public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAcc
activityOrderEntity.setTotalCount(activityCountEntity.getTotalCount()); activityOrderEntity.setTotalCount(activityCountEntity.getTotalCount());
activityOrderEntity.setDayCount(activityCountEntity.getDayCount()); activityOrderEntity.setDayCount(activityCountEntity.getDayCount());
activityOrderEntity.setMonthCount(activityCountEntity.getMonthCount()); activityOrderEntity.setMonthCount(activityCountEntity.getMonthCount());
activityOrderEntity.setState(OrderStateVO.completed); activityOrderEntity.setPayAmount(activitySkuEntity.getProductAmount());
activityOrderEntity.setOutBusinessNo(skuRechargeEntity.getOutBusinessNo()); activityOrderEntity.setOutBusinessNo(skuRechargeEntity.getOutBusinessNo());
// 构建聚合对象 // 构建聚合对象
...@@ -52,11 +54,6 @@ public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAcc ...@@ -52,11 +54,6 @@ public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAcc
.build(); .build();
} }
@Override
protected void doSaveOrder(CreateQuotaOrderAggregate createOrderAggregate) {
activityRepository.doSaveOrder(createOrderAggregate);
}
@Override @Override
public ActivitySkuStockKeyVO takeQueueValue() throws InterruptedException { public ActivitySkuStockKeyVO takeQueueValue() throws InterruptedException {
return activityRepository.takeQueueValue(); return activityRepository.takeQueueValue();
...@@ -77,6 +74,16 @@ public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAcc ...@@ -77,6 +74,16 @@ public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAcc
activityRepository.clearActivitySkuStock(sku); activityRepository.clearActivitySkuStock(sku);
} }
@Override
public void updateOrder(DeliveryOrderEntity deliveryOrderEntity) {
activityRepository.updateOrder(deliveryOrderEntity);
}
@Override
public Integer queryRaffleActivityAccountPartakeCount(Long activityId, String userId) {
return activityRepository.queryRaffleActivityAccountPartakeCount(activityId, userId);
}
@Override @Override
public Integer queryRaffleActivityAccountDayPartakeCount(Long activityId, String userId) { public Integer queryRaffleActivityAccountDayPartakeCount(Long activityId, String userId) {
return activityRepository.queryRaffleActivityAccountDayPartakeCount(activityId, userId); return activityRepository.queryRaffleActivityAccountDayPartakeCount(activityId, userId);
...@@ -87,8 +94,4 @@ public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAcc ...@@ -87,8 +94,4 @@ public class RaffleActivityAccountQuotaService extends AbstractRaffleActivityAcc
return activityRepository.queryActivityAccountEntity(activityId, userId); return activityRepository.queryActivityAccountEntity(activityId, userId);
} }
@Override
public Integer queryRaffleActivityAccountPartakeCount(Long activityId, String userId) {
return activityRepository.queryRaffleActivityAccountPartakeCount(activityId, userId);
}
} }
...@@ -6,12 +6,13 @@ import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity; ...@@ -6,12 +6,13 @@ import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity;
import cn.bugstack.domain.activity.repository.IActivityRepository; import cn.bugstack.domain.activity.repository.IActivityRepository;
import cn.bugstack.domain.activity.service.quota.rule.factory.DefaultActivityChainFactory; import cn.bugstack.domain.activity.service.quota.rule.factory.DefaultActivityChainFactory;
/* /**
* @return * @author Fuzhengwei bugstack.cn @小傅哥
* @author zhaoyongfeng
* @description 抽奖活动的支撑类 * @description 抽奖活动的支撑类
* @create 2024-03-23 09:27
*/ */
public class RaffleActivityAccountQuotaSupport { public class RaffleActivityAccountQuotaSupport {
protected DefaultActivityChainFactory defaultActivityChainFactory; protected DefaultActivityChainFactory defaultActivityChainFactory;
protected IActivityRepository activityRepository; protected IActivityRepository activityRepository;
...@@ -32,4 +33,5 @@ public class RaffleActivityAccountQuotaSupport { ...@@ -32,4 +33,5 @@ public class RaffleActivityAccountQuotaSupport {
public ActivityCountEntity queryRaffleActivityCountByActivityCountId(Long activityCountId) { public ActivityCountEntity queryRaffleActivityCountByActivityCountId(Long activityCountId) {
return activityRepository.queryRaffleActivityCountByActivityCountId(activityCountId); return activityRepository.queryRaffleActivityCountByActivityCountId(activityCountId);
} }
} }
package cn.bugstack.domain.activity.service.quota.policy;
import cn.bugstack.domain.activity.model.aggregate.CreateQuotaOrderAggregate;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 交易策略接口,包括;返利兑换(不用支付),积分订单(需要支付)
* @create 2024-06-08 18:04
*/
public interface ITradePolicy {
void trade(CreateQuotaOrderAggregate createQuotaOrderAggregate);
}
package cn.bugstack.domain.activity.service.quota.policy.impl;
import cn.bugstack.domain.activity.model.aggregate.CreateQuotaOrderAggregate;
import cn.bugstack.domain.activity.model.valobj.OrderStateVO;
import cn.bugstack.domain.activity.repository.IActivityRepository;
import cn.bugstack.domain.activity.service.quota.policy.ITradePolicy;
import org.springframework.stereotype.Service;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 积分兑换,支付类订单
* @create 2024-06-08 18:12
*/
@Service("credit_pay_trade")
public class CreditPayTradePolicy implements ITradePolicy {
private final IActivityRepository activityRepository;
public CreditPayTradePolicy(IActivityRepository activityRepository) {
this.activityRepository = activityRepository;
}
@Override
public void trade(CreateQuotaOrderAggregate createQuotaOrderAggregate) {
createQuotaOrderAggregate.setOrderState(OrderStateVO.wait_pay);
activityRepository.doSaveCreditPayOrder(createQuotaOrderAggregate);
}
}
package cn.bugstack.domain.activity.service.quota.policy.impl;
import cn.bugstack.domain.activity.model.aggregate.CreateQuotaOrderAggregate;
import cn.bugstack.domain.activity.model.valobj.OrderStateVO;
import cn.bugstack.domain.activity.repository.IActivityRepository;
import cn.bugstack.domain.activity.service.quota.policy.ITradePolicy;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 返利无支付交易订单,直接充值到账
* @create 2024-06-08 18:10
*/
@Service("rebate_no_pay_trade")
public class RebateNoPayTradePolicy implements ITradePolicy {
private final IActivityRepository activityRepository;
public RebateNoPayTradePolicy(IActivityRepository activityRepository) {
this.activityRepository = activityRepository;
}
@Override
public void trade(CreateQuotaOrderAggregate createQuotaOrderAggregate) {
// 不需要支付则修改订单金额为0,状态为完成,直接给用户账户充值
createQuotaOrderAggregate.setOrderState(OrderStateVO.completed);
createQuotaOrderAggregate.getActivityOrderEntity().setPayAmount(BigDecimal.ZERO);
activityRepository.doSaveNoPayOrder(createQuotaOrderAggregate);
}
}
...@@ -12,7 +12,7 @@ import org.springframework.stereotype.Component; ...@@ -12,7 +12,7 @@ import org.springframework.stereotype.Component;
import java.util.Date; import java.util.Date;
/** /**
* @author zyf * @author Fuzhengwei bugstack.cn @小傅哥
* @description 用户奖品记录事件消息 * @description 用户奖品记录事件消息
* @create 2024-04-06 09:43 * @create 2024-04-06 09:43
*/ */
......
...@@ -8,17 +8,18 @@ import lombok.Data; ...@@ -8,17 +8,18 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* @ClassName: UserAwardRecordAggregate * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 用户中奖记录聚合对象 【聚合代表一个事务操作】 * @description 用户中奖记录聚合对象 【聚合代表一个事务操作】
* @Author: zhaoyongfeng * @create 2024-04-06 09:40
* @Date: 2024/12/9 16:24
*/ */
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class UserAwardRecordAggregate { public class UserAwardRecordAggregate {
private UserAwardRecordEntity userAwardRecordEntity; private UserAwardRecordEntity userAwardRecordEntity;
private TaskEntity taskEntity; private TaskEntity taskEntity;
} }
...@@ -9,16 +9,16 @@ import lombok.Data; ...@@ -9,16 +9,16 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* @ClassName: TaskEntity * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 任务实体对象 * @description 任务实体对象
* @Author: zhaoyongfeng * @create 2024-04-06 09:38
* @Date: 2024/12/9 16:22
*/ */
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class TaskEntity { public class TaskEntity {
/** 活动ID */ /** 活动ID */
private String userId; private String userId;
/** 消息主题 */ /** 消息主题 */
...@@ -29,4 +29,5 @@ public class TaskEntity { ...@@ -29,4 +29,5 @@ public class TaskEntity {
private BaseEvent.EventMessage<SendAwardMessageEvent.SendAwardMessage> message; private BaseEvent.EventMessage<SendAwardMessageEvent.SendAwardMessage> message;
/** 任务状态;create-创建、completed-完成、fail-失败 */ /** 任务状态;create-创建、completed-完成、fail-失败 */
private TaskStateVO state; private TaskStateVO state;
} }
...@@ -9,16 +9,16 @@ import lombok.NoArgsConstructor; ...@@ -9,16 +9,16 @@ import lombok.NoArgsConstructor;
import java.util.Date; import java.util.Date;
/** /**
* @ClassName: UserAwardEntity * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: 用户中奖记录实体对象 * @description 用户中奖记录实体对象
* @Author: zhaoyongfeng * @create 2024-04-06 09:06
* @Date: 2024/12/9 15:44
*/ */
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class UserAwardRecordEntity { public class UserAwardRecordEntity {
/** 用户ID */ /** 用户ID */
private String userId; private String userId;
/** 活动ID */ /** 活动ID */
...@@ -37,4 +37,5 @@ public class UserAwardRecordEntity { ...@@ -37,4 +37,5 @@ public class UserAwardRecordEntity {
private AwardStateVO awardState; private AwardStateVO awardState;
/** 奖品配置信息;发奖的时候,可以根据 */ /** 奖品配置信息;发奖的时候,可以根据 */
private String awardConfig; private String awardConfig;
} }
...@@ -3,9 +3,10 @@ package cn.bugstack.domain.award.model.valobj; ...@@ -3,9 +3,10 @@ package cn.bugstack.domain.award.model.valobj;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/* /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 奖品状态枚举值对象 * @description 奖品状态枚举值对象 【值对象,用于描述对象属性的值,一个对象中,一个属性,有多个状态值。】
* @create 2024-04-06 09:13
*/ */
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
......
...@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor; ...@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/** /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 任务状态值对象 * @description 任务状态值对象
* @create 2024-04-06 10:00 * @create 2024-04-06 10:00
*/ */
......
...@@ -2,12 +2,14 @@ package cn.bugstack.domain.award.repository; ...@@ -2,12 +2,14 @@ package cn.bugstack.domain.award.repository;
import cn.bugstack.domain.award.model.aggregate.GiveOutPrizesAggregate; import cn.bugstack.domain.award.model.aggregate.GiveOutPrizesAggregate;
import cn.bugstack.domain.award.model.aggregate.UserAwardRecordAggregate; import cn.bugstack.domain.award.model.aggregate.UserAwardRecordAggregate;
/*
* @return 奖品仓储服务 /**
* @author zhaoyongfeng * @author Fuzhengwei bugstack.cn @小傅哥
* @description 奖品仓储服务 * @description 奖品仓储服务
* @create 2024-04-06 09:02
*/ */
public interface IAwardRepository { public interface IAwardRepository {
void saveUserAwardRecord(UserAwardRecordAggregate userAwardRecordAggregate); void saveUserAwardRecord(UserAwardRecordAggregate userAwardRecordAggregate);
String queryAwardConfig(Integer awardId); String queryAwardConfig(Integer awardId);
......
package cn.bugstack.domain.award.service; package cn.bugstack.domain.award.service;
import cn.bugstack.domain.award.model.aggregate.UserAwardRecordAggregate;
import cn.bugstack.domain.award.event.SendAwardMessageEvent; import cn.bugstack.domain.award.event.SendAwardMessageEvent;
import cn.bugstack.domain.award.model.aggregate.UserAwardRecordAggregate;
import cn.bugstack.domain.award.model.entity.DistributeAwardEntity; import cn.bugstack.domain.award.model.entity.DistributeAwardEntity;
import cn.bugstack.domain.award.model.entity.TaskEntity; import cn.bugstack.domain.award.model.entity.TaskEntity;
import cn.bugstack.domain.award.model.entity.UserAwardRecordEntity; import cn.bugstack.domain.award.model.entity.UserAwardRecordEntity;
...@@ -12,18 +12,16 @@ import cn.bugstack.types.event.BaseEvent; ...@@ -12,18 +12,16 @@ import cn.bugstack.types.event.BaseEvent;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Map; import java.util.Map;
/** /**
* @ClassName: AwardService * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 奖品服务
* @Author: zhaoyongfeng * @create 2024-04-06 09:39
* @Date: 2024/12/9 15:41
*/ */
@Service
@Slf4j @Slf4j
public class AwardService implements IAwardService{ @Service
public class AwardService implements IAwardService {
private final IAwardRepository awardRepository; private final IAwardRepository awardRepository;
private final SendAwardMessageEvent sendAwardMessageEvent; private final SendAwardMessageEvent sendAwardMessageEvent;
...@@ -34,6 +32,7 @@ public class AwardService implements IAwardService{ ...@@ -34,6 +32,7 @@ public class AwardService implements IAwardService{
this.sendAwardMessageEvent = sendAwardMessageEvent; this.sendAwardMessageEvent = sendAwardMessageEvent;
this.distributeAwardMap = distributeAwardMap; this.distributeAwardMap = distributeAwardMap;
} }
@Override @Override
public void saveUserAwardRecord(UserAwardRecordEntity userAwardRecordEntity) { public void saveUserAwardRecord(UserAwardRecordEntity userAwardRecordEntity) {
// 构建消息对象 // 构建消息对象
...@@ -62,6 +61,8 @@ public class AwardService implements IAwardService{ ...@@ -62,6 +61,8 @@ public class AwardService implements IAwardService{
// 存储聚合对象 - 一个事务下,用户的中奖记录 // 存储聚合对象 - 一个事务下,用户的中奖记录
awardRepository.saveUserAwardRecord(userAwardRecordAggregate); awardRepository.saveUserAwardRecord(userAwardRecordAggregate);
log.info("中奖记录保存完成 userId:{} orderId:{}", userAwardRecordEntity.getUserId(), userAwardRecordEntity.getOrderId());
} }
@Override @Override
...@@ -72,13 +73,17 @@ public class AwardService implements IAwardService{ ...@@ -72,13 +73,17 @@ public class AwardService implements IAwardService{
log.error("分发奖品,奖品ID不存在。awardKey:{}", awardKey); log.error("分发奖品,奖品ID不存在。awardKey:{}", awardKey);
return; return;
} }
// 奖品服务 // 奖品服务
IDistributeAward distributeAward = distributeAwardMap.get(awardKey); IDistributeAward distributeAward = distributeAwardMap.get(awardKey);
if (null == distributeAward) { if (null == distributeAward) {
log.error("分发奖品,对应的服务不存在。awardKey:{}", awardKey); log.error("分发奖品,对应的服务不存在。awardKey:{}", awardKey);
throw new RuntimeException("分发奖品,奖品" + awardKey + "对应的服务不存在"); throw new RuntimeException("分发奖品,奖品" + awardKey + "对应的服务不存在");
} }
// 发放奖品 // 发放奖品
distributeAward.giveOutPrizes(distributeAwardEntity); distributeAward.giveOutPrizes(distributeAwardEntity);
} }
} }
...@@ -3,17 +3,18 @@ package cn.bugstack.domain.award.service; ...@@ -3,17 +3,18 @@ package cn.bugstack.domain.award.service;
import cn.bugstack.domain.award.model.entity.DistributeAwardEntity; import cn.bugstack.domain.award.model.entity.DistributeAwardEntity;
import cn.bugstack.domain.award.model.entity.UserAwardRecordEntity; import cn.bugstack.domain.award.model.entity.UserAwardRecordEntity;
/* /**
* @return * @author Fuzhengwei bugstack.cn @小傅哥
* @author zhaoyongfeng * @description 奖品服务接口
* @description * @create 2024-04-06 09:03
*
* @param null
*/ */
public interface IAwardService { public interface IAwardService {
void saveUserAwardRecord(UserAwardRecordEntity userAwardRecordEntity); void saveUserAwardRecord(UserAwardRecordEntity userAwardRecordEntity);
/** /**
* 配送发货奖品 * 配送发货奖品
*/ */
void distributeAward(DistributeAwardEntity distributeAwardEntity); void distributeAward(DistributeAwardEntity distributeAwardEntity);
} }
...@@ -2,11 +2,13 @@ package cn.bugstack.domain.award.service.distribute; ...@@ -2,11 +2,13 @@ package cn.bugstack.domain.award.service.distribute;
import cn.bugstack.domain.award.model.entity.DistributeAwardEntity; import cn.bugstack.domain.award.model.entity.DistributeAwardEntity;
/* /**
* @return * @author Fuzhengwei bugstack.cn @小傅哥
* @author zhaoyongfeng
* @description 分发奖品接口 * @description 分发奖品接口
* @create 2024-05-18 08:22
*/ */
public interface IDistributeAward { public interface IDistributeAward {
void giveOutPrizes(DistributeAwardEntity distributeAwardEntity); void giveOutPrizes(DistributeAwardEntity distributeAwardEntity);
} }
...@@ -10,22 +10,22 @@ import cn.bugstack.domain.award.service.distribute.IDistributeAward; ...@@ -10,22 +10,22 @@ import cn.bugstack.domain.award.service.distribute.IDistributeAward;
import cn.bugstack.types.common.Constants; import cn.bugstack.types.common.Constants;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.MathContext; import java.math.MathContext;
/** /**
* @ClassName: UserCreditRandomAward * @author Fuzhengwei bugstack.cn @小傅哥
* @Description: * @description 用户积分奖品,支持 award_config 透传,满足黑名单积分奖励。
* @Author: zhaoyongfeng * @create 2024-05-18 08:53
* @Date: 2024/12/28 17:55
*/ */
@Component("user_credit_random") @Component("user_credit_random")
public class UserCreditRandomAward implements IDistributeAward { public class UserCreditRandomAward implements IDistributeAward {
@Resource @Resource
private IAwardRepository repository; private IAwardRepository repository;
@Override @Override
public void giveOutPrizes(DistributeAwardEntity distributeAwardEntity) { public void giveOutPrizes(DistributeAwardEntity distributeAwardEntity) {
// 奖品ID // 奖品ID
...@@ -35,12 +35,15 @@ public class UserCreditRandomAward implements IDistributeAward { ...@@ -35,12 +35,15 @@ public class UserCreditRandomAward implements IDistributeAward {
if (StringUtils.isBlank(awardConfig)) { if (StringUtils.isBlank(awardConfig)) {
awardConfig = repository.queryAwardConfig(awardId); awardConfig = repository.queryAwardConfig(awardId);
} }
String[] creditRange = awardConfig.split(Constants.SPLIT); String[] creditRange = awardConfig.split(Constants.SPLIT);
if (creditRange.length != 2) { if (creditRange.length != 2) {
throw new RuntimeException("award_config 「" + awardConfig + "」配置不是一个范围值,如 1,100"); throw new RuntimeException("award_config 「" + awardConfig + "」配置不是一个范围值,如 1,100");
} }
// 生成随机积分值 // 生成随机积分值
BigDecimal creditAmount = generateRandom(new BigDecimal(creditRange[0]), new BigDecimal(creditRange[1])); BigDecimal creditAmount = generateRandom(new BigDecimal(creditRange[0]), new BigDecimal(creditRange[1]));
// 构建聚合对象 // 构建聚合对象
UserAwardRecordEntity userAwardRecordEntity = GiveOutPrizesAggregate.buildDistributeUserAwardRecordEntity( UserAwardRecordEntity userAwardRecordEntity = GiveOutPrizesAggregate.buildDistributeUserAwardRecordEntity(
distributeAwardEntity.getUserId(), distributeAwardEntity.getUserId(),
...@@ -48,6 +51,7 @@ public class UserCreditRandomAward implements IDistributeAward { ...@@ -48,6 +51,7 @@ public class UserCreditRandomAward implements IDistributeAward {
distributeAwardEntity.getAwardId(), distributeAwardEntity.getAwardId(),
AwardStateVO.complete AwardStateVO.complete
); );
UserCreditAwardEntity userCreditAwardEntity = GiveOutPrizesAggregate.buildUserCreditAwardEntity(distributeAwardEntity.getUserId(), creditAmount); UserCreditAwardEntity userCreditAwardEntity = GiveOutPrizesAggregate.buildUserCreditAwardEntity(distributeAwardEntity.getUserId(), creditAmount);
GiveOutPrizesAggregate giveOutPrizesAggregate = new GiveOutPrizesAggregate(); GiveOutPrizesAggregate giveOutPrizesAggregate = new GiveOutPrizesAggregate();
...@@ -58,9 +62,11 @@ public class UserCreditRandomAward implements IDistributeAward { ...@@ -58,9 +62,11 @@ public class UserCreditRandomAward implements IDistributeAward {
// 存储发奖对象 // 存储发奖对象
repository.saveGiveOutPrizesAggregate(giveOutPrizesAggregate); repository.saveGiveOutPrizesAggregate(giveOutPrizesAggregate);
} }
private BigDecimal generateRandom(BigDecimal min, BigDecimal max) { private BigDecimal generateRandom(BigDecimal min, BigDecimal max) {
if (min.equals(max)) return min; if (min.equals(max)) return min;
BigDecimal randomBigDecimal = min.add(BigDecimal.valueOf(Math.random()).multiply(max.subtract(min))); BigDecimal randomBigDecimal = min.add(BigDecimal.valueOf(Math.random()).multiply(max.subtract(min)));
return randomBigDecimal.round(new MathContext(3)); return randomBigDecimal.round(new MathContext(3));
} }
} }
package cn.bugstack.domain.credit.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.math.BigDecimal;
import java.util.Date;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 积分账户调整成功消息【充值、支付,成功消息】
* @create 2024-06-08 19:19
*/
@Component
public class CreditAdjustSuccessMessageEvent extends BaseEvent<CreditAdjustSuccessMessageEvent.CreditAdjustSuccessMessage> {
@Value("${spring.rabbitmq.topic.credit_adjust_success}")
private String topic;
@Override
public EventMessage<CreditAdjustSuccessMessage> buildEventMessage(CreditAdjustSuccessMessage data) {
return EventMessage.<CreditAdjustSuccessMessage>builder()
.id(RandomStringUtils.randomNumeric(11))
.timestamp(new Date())
.data(data)
.build();
}
@Override
public String topic() {
return topic;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class CreditAdjustSuccessMessage {
/**
* 用户ID
*/
private String userId;
/**
* 订单ID
*/
private String orderId;
/**
* 交易金额
*/
private BigDecimal amount;
/**
* 业务仿重ID - 外部透传。返利、行为等唯一标识
*/
private String outBusinessNo;
}
}
package cn.bugstack.domain.credit.model.aggregate;
import cn.bugstack.domain.award.model.valobj.TaskStateVO;
import cn.bugstack.domain.credit.event.CreditAdjustSuccessMessageEvent;
import cn.bugstack.domain.credit.model.entity.CreditAccountEntity;
import cn.bugstack.domain.credit.model.entity.CreditOrderEntity;
import cn.bugstack.domain.credit.model.entity.TaskEntity;
import cn.bugstack.domain.credit.model.valobj.TradeNameVO;
import cn.bugstack.domain.credit.model.valobj.TradeTypeVO;
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 java.math.BigDecimal;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 交易聚合对象
* @create 2024-06-01 09:48
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TradeAggregate {
// 用户ID
private String userId;
// 积分账户实体
private CreditAccountEntity creditAccountEntity;
// 积分订单实体
private CreditOrderEntity creditOrderEntity;
// 任务实体 - 补偿 MQ 消息
private TaskEntity taskEntity;
public static CreditAccountEntity createCreditAccountEntity(String userId, BigDecimal adjustAmount) {
return CreditAccountEntity.builder().userId(userId).adjustAmount(adjustAmount).build();
}
public static CreditOrderEntity createCreditOrderEntity(String userId,
TradeNameVO tradeName,
TradeTypeVO tradeType,
BigDecimal tradeAmount,
String outBusinessNo) {
return CreditOrderEntity.builder()
.userId(userId)
.orderId(RandomStringUtils.randomNumeric(12))
.tradeName(tradeName)
.tradeType(tradeType)
.tradeAmount(tradeAmount)
.outBusinessNo(outBusinessNo)
.build();
}
public static TaskEntity createTaskEntity(String userId, String topic, String messageId, BaseEvent.EventMessage<CreditAdjustSuccessMessageEvent.CreditAdjustSuccessMessage> message) {
TaskEntity taskEntity = new TaskEntity();
taskEntity.setUserId(userId);
taskEntity.setTopic(topic);
taskEntity.setMessageId(messageId);
taskEntity.setMessage(message);
taskEntity.setState(TaskStateVO.create);
return taskEntity;
}
}
package cn.bugstack.domain.credit.model.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 积分账户实体
* @create 2024-06-01 09:08
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CreditAccountEntity {
/** 用户ID */
private String userId;
/** 可用积分,每次扣减的值 */
private BigDecimal adjustAmount;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册