Skip to content

Commit

Permalink
完成领取活动业务逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
Casflawed committed Aug 23, 2023
1 parent f368e1b commit c4f6a95
Show file tree
Hide file tree
Showing 15 changed files with 386 additions and 20 deletions.
1 change: 1 addition & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions lottery-project/lottery-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package com.flameking.lottery.common.util;

import org.apache.commons.lang3.ObjectUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware{
/** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory;

private static ApplicationContext applicationContext;

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory;
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
SpringUtils.applicationContext = applicationContext;
}

/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException
{
return (T) beanFactory.getBean(name);
}

/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException
{
T result = (T) beanFactory.getBean(clz);
return result;
}

/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name)
{
return beanFactory.containsBean(name);
}

/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
*
* @param name
* @return boolean
* @throws NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.isSingleton(name);
}

/**
* @param name
* @return Class 注册对象的类型
* @throws NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getType(name);
}

/**
* 如果给定的bean名字在bean定义中有别名,则返回这些别名
*
* @param name
* @return
* @throws NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getAliases(name);
}

/**
* 获取aop代理对象
*
* @param invoker
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker)
{
return (T) AopContext.currentProxy();
}

/**
* 获取当前的环境配置,无配置返回null
*
* @return 当前的环境配置
*/
public static String[] getActiveProfiles()
{
return applicationContext.getEnvironment().getActiveProfiles();
}

/**
* 获取当前的环境配置,当有多个环境配置时,只获取第一个
*
* @return 当前的环境配置
*/
public static String getActiveProfile()
{
final String[] activeProfiles = getActiveProfiles();
return ObjectUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
}
5 changes: 5 additions & 0 deletions lottery-project/lottery-domain/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
<artifactId>commons-lang3</artifactId>
</dependency>

<dependency>
<groupId>com.flameking.middleware.db.router</groupId>
<artifactId>db-router-spring-boot-starter</artifactId>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.flameking.lottery.domain.activity.repository;

import com.flameking.lottery.domain.activity.model.vo.ActivityBillVO;

public interface IUserTakeActivityCountRepository {
boolean subtractionLeftCount(ActivityBillVO bill);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.flameking.lottery.domain.activity.repository;

import com.flameking.lottery.domain.activity.model.aggregates.PartakeReq;
import com.flameking.lottery.domain.activity.model.vo.ActivityBillVO;

public interface IUserTakeActivityRepository {
boolean takeActivity(PartakeReq partake, ActivityBillVO bill, Long takeId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,36 @@
import com.flameking.lottery.domain.activity.model.aggregates.PartakeReq;
import com.flameking.lottery.domain.activity.model.res.PartakeResult;
import com.flameking.lottery.domain.activity.model.vo.ActivityBillVO;
import com.flameking.lottery.domain.activity.repository.IActivityRepository;
import com.flameking.lottery.domain.activity.repository.IUserTakeActivityCountRepository;
import com.flameking.lottery.domain.activity.repository.IUserTakeActivityRepository;
import com.flameking.lottery.domain.activity.service.partake.IActivityPartake;
import com.flameking.lottery.domain.ids.IIdGenerator;
import com.flameking.middleware.db.router.annotation.DbRouter;
import com.flameking.middleware.db.router.strategy.IDbRouterStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Map;

@Component
@Slf4j
public class ActivityPartakeImpl implements IActivityPartake {
@Autowired
private IActivityRepository activityRepository;
@Autowired
private IDbRouterStrategy doRouter;
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private IUserTakeActivityCountRepository userTakeActivityCountRepository;
@Autowired
private IUserTakeActivityRepository userTakeActivityRepository;
@Autowired
private Map<Constants.Ids, IIdGenerator> idGeneratorMap;

@Override
public PartakeResult doPartake(PartakeReq req) {
Expand All @@ -24,20 +47,94 @@ public PartakeResult doPartake(PartakeReq req) {
return new PartakeResult(checkResult.getCode(), checkResult.getInfo());
}
//扣减活动剩余参与次数

Result subtractionActivityResult = subtractionActivityStock(req);
if (!Constants.ResponseCode.SUCCESS.getCode().equals(subtractionActivityResult.getCode())) {
return new PartakeResult(subtractionActivityResult.getCode(), subtractionActivityResult.getInfo());
}
//更新or插入用户参与次数信息
Result grabResult = grabActivity(req, activityBillVO);
if (!Constants.ResponseCode.SUCCESS.getCode().equals(grabResult.getCode())) {
return new PartakeResult(grabResult.getCode(), grabResult.getInfo());
}

//查询用户参与活动信息
PartakeResult partakeResult = new PartakeResult(Constants.ResponseCode.SUCCESS.getCode(), Constants.ResponseCode.SUCCESS.getInfo());
partakeResult.setStrategyId(activityBillVO.getStrategyId());
return partakeResult;
}

return null;
private Result subtractionActivityStock(PartakeReq req) {
boolean data = activityRepository.subtractionActivityStock(req.getActivityId());
if (!data) {
log.error("扣减活动库存失败 activityId:{}", req.getActivityId());
return Result.buildResult(Constants.ResponseCode.NO_UPDATE);
}
return Result.buildSuccessResult();
}

private Result checkActivityBill(PartakeReq req, ActivityBillVO activityBillVO) {
return null;

private Result checkActivityBill(PartakeReq partake, ActivityBillVO bill) {
// 校验:活动状态
if (!Constants.ActivityState.DOING.getCode().equals(bill.getState())) {
log.warn("活动当前状态非可用 state:{}", bill.getState());
return Result.buildResult(Constants.ResponseCode.UN_ERROR, "活动当前状态非可用");
}

// 校验:活动日期
if (bill.getBeginDateTime().after(partake.getPartakeDate()) || bill.getEndDateTime().before(partake.getPartakeDate())) {
log.warn("活动时间范围非可用 beginDateTime:{} endDateTime:{}", bill.getBeginDateTime(), bill.getEndDateTime());
return Result.buildResult(Constants.ResponseCode.UN_ERROR, "活动时间范围非可用");
}

// 校验:活动库存
if (bill.getStockSurplusCount() <= 0) {
log.warn("活动剩余库存非可用 stockSurplusCount:{}", bill.getStockSurplusCount());
return Result.buildResult(Constants.ResponseCode.UN_ERROR, "活动剩余库存非可用");
}

// 校验:个人库存 - 个人活动剩余可领取次数
if (bill.getUserTakeLeftCount() != null && bill.getUserTakeLeftCount() <= 0) {
log.warn("个人领取次数非可用 userTakeLeftCount:{}", bill.getUserTakeLeftCount());
return Result.buildResult(Constants.ResponseCode.UN_ERROR, "个人领取次数非可用");
}

return Result.buildSuccessResult();
}

private ActivityBillVO queryActivityBill(PartakeReq req) {
return null;
return activityRepository.queryActivityBill(req);
}

/**
* 领取活动
*
* @param partake 参与活动请求
* @param bill 活动账单
* @return 领取结果
*/
@DbRouter
protected Result grabActivity(PartakeReq partake, ActivityBillVO bill) {
// doRouter.doRouter(partake.getUId());,用了这个就必须手动释放ThreadLocal内的路由信息
return transactionTemplate.execute(status -> {
try {
// 扣减个人已参与次数
boolean updateCount = userTakeActivityCountRepository.subtractionLeftCount(bill);
if (!updateCount) {
status.setRollbackOnly();
log.error("领取活动,扣减个人已参与次数失败 activityId:{} uId:{}", partake.getActivityId(), partake.getUId());
return Result.buildResult(Constants.ResponseCode.NO_UPDATE);
}
// 插入领取活动信息
Long takeId = idGeneratorMap.get(Constants.Ids.SnowFlake).nextId();
userTakeActivityRepository.takeActivity(partake, bill, takeId);

} catch (DuplicateKeyException e) {
status.setRollbackOnly();
log.error("领取活动,唯一索引冲突 activityId:{} uId:{}", partake.getActivityId(), partake.getUId(), e);
return Result.buildResult(Constants.ResponseCode.INDEX_DUP);
}
return Result.buildSuccessResult();
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.flameking.lottery.infrastructure.repository.impl;

import com.flameking.lottery.domain.activity.model.vo.ActivityBillVO;
import com.flameking.lottery.domain.activity.repository.IUserTakeActivityCountRepository;
import com.flameking.lottery.infrastructure.entity.UserTakeActivityCount;
import com.flameking.lottery.infrastructure.service.IUserTakeActivityCountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class UserTakeActivityCountRepository implements IUserTakeActivityCountRepository {
@Autowired
private IUserTakeActivityCountService userTakeActivityCountService;

public boolean subtractionLeftCount(ActivityBillVO bill) {
if (null == bill.getUserTakeLeftCount()) {
UserTakeActivityCount userTakeActivityCount = new UserTakeActivityCount();
userTakeActivityCount.setUId(bill.getUId());
userTakeActivityCount.setActivityId(bill.getActivityId());
userTakeActivityCount.setTotalCount(bill.getTakeCount());
userTakeActivityCount.setLeftCount(bill.getTakeCount() - 1);
return userTakeActivityCountService.create(userTakeActivityCount);
} else {
UserTakeActivityCount userTakeActivityCount = new UserTakeActivityCount();
userTakeActivityCount.setUId(bill.getUId());
userTakeActivityCount.setActivityId(bill.getActivityId());
return userTakeActivityCountService.updateLeftCount(userTakeActivityCount);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.flameking.lottery.infrastructure.repository.impl;

import com.flameking.lottery.domain.activity.model.aggregates.PartakeReq;
import com.flameking.lottery.domain.activity.model.vo.ActivityBillVO;
import com.flameking.lottery.domain.activity.repository.IUserTakeActivityRepository;
import com.flameking.lottery.infrastructure.entity.UserTakeActivity;
import com.flameking.lottery.infrastructure.service.IUserTakeActivityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class UserTakeActivityRepository implements IUserTakeActivityRepository {
@Autowired
private IUserTakeActivityService userTakeActivityService;

@Override
public boolean takeActivity(PartakeReq partake, ActivityBillVO bill, Long takeId) {
UserTakeActivity userTakeActivity = new UserTakeActivity();
userTakeActivity.setUId(bill.getUId());
userTakeActivity.setTakeId(takeId);
userTakeActivity.setActivityId(bill.getActivityId());
userTakeActivity.setActivityName(bill.getActivityName());
userTakeActivity.setTakeDate(partake.getPartakeDate());

if (null == bill.getUserTakeLeftCount()) {
userTakeActivity.setTakeCount(1);
} else {
userTakeActivity.setTakeCount(bill.getTakeCount() - bill.getUserTakeLeftCount());
}
String uuid = bill.getUId() + "_" + bill.getActivityId() + "_" + bill.getTakeCount();
userTakeActivity.setUuid(uuid);

return userTakeActivityService.create(userTakeActivity);
}
}
Loading

0 comments on commit c4f6a95

Please sign in to comment.