7.1 责任链校验活动是否有效、用户拼团是否已达上限
This commit is contained in:
parent
16433ffdc2
commit
ac00d61503
@ -24,8 +24,10 @@ public class TrialBalanceEntity {
|
|||||||
private String goodsName;
|
private String goodsName;
|
||||||
/** 原始价格 */
|
/** 原始价格 */
|
||||||
private BigDecimal originalPrice;
|
private BigDecimal originalPrice;
|
||||||
/** 折扣价格 */
|
/** 折扣金额 */
|
||||||
private BigDecimal deductionPrice;
|
private BigDecimal deductionPrice;
|
||||||
|
/** 支付金额 */
|
||||||
|
private BigDecimal payPrice;
|
||||||
/** 拼团目标数量 */
|
/** 拼团目标数量 */
|
||||||
private Integer targetCount;
|
private Integer targetCount;
|
||||||
/** 拼团开始时间 */
|
/** 拼团开始时间 */
|
||||||
|
@ -32,8 +32,10 @@ public class DefaultActivityStrategyFactory {
|
|||||||
private GroupBuyActivityDiscountVO groupBuyActivityDiscountVO;
|
private GroupBuyActivityDiscountVO groupBuyActivityDiscountVO;
|
||||||
// 商品信息
|
// 商品信息
|
||||||
private SkuVO skuVO;
|
private SkuVO skuVO;
|
||||||
// 折扣价格
|
// 折扣金额
|
||||||
private BigDecimal deductionPrice;
|
private BigDecimal deductionPrice;
|
||||||
|
// 支付金额
|
||||||
|
private BigDecimal payPrice;
|
||||||
// 活动可见性限制
|
// 活动可见性限制
|
||||||
private boolean visible;
|
private boolean visible;
|
||||||
// 活动
|
// 活动
|
||||||
|
@ -27,6 +27,9 @@ public class EndNode extends AbstractGroupBuyMarketSupport<MarketProductEntity,
|
|||||||
// 商品信息
|
// 商品信息
|
||||||
SkuVO skuVO = dynamicContext.getSkuVO();
|
SkuVO skuVO = dynamicContext.getSkuVO();
|
||||||
|
|
||||||
|
// 支付金额
|
||||||
|
BigDecimal payPrice = dynamicContext.getPayPrice();
|
||||||
|
|
||||||
// 折扣价格
|
// 折扣价格
|
||||||
BigDecimal deductionPrice = dynamicContext.getDeductionPrice();
|
BigDecimal deductionPrice = dynamicContext.getDeductionPrice();
|
||||||
// 返回空结果
|
// 返回空结果
|
||||||
@ -35,6 +38,7 @@ public class EndNode extends AbstractGroupBuyMarketSupport<MarketProductEntity,
|
|||||||
.goodsName(skuVO.getGoodsName())
|
.goodsName(skuVO.getGoodsName())
|
||||||
.originalPrice(skuVO.getOriginalPrice())
|
.originalPrice(skuVO.getOriginalPrice())
|
||||||
.deductionPrice(deductionPrice)
|
.deductionPrice(deductionPrice)
|
||||||
|
.payPrice(payPrice)
|
||||||
.targetCount(groupBuyActivityDiscountVO.getTarget())
|
.targetCount(groupBuyActivityDiscountVO.getTarget())
|
||||||
.startTime(groupBuyActivityDiscountVO.getStartTime())
|
.startTime(groupBuyActivityDiscountVO.getStartTime())
|
||||||
.endTime(groupBuyActivityDiscountVO.getEndTime())
|
.endTime(groupBuyActivityDiscountVO.getEndTime())
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package edu.whut.domain.trade.adapter.repository;
|
package edu.whut.domain.trade.adapter.repository;
|
||||||
|
|
||||||
import edu.whut.domain.trade.model.aggregate.GroupBuyOrderAggregate;
|
import edu.whut.domain.trade.model.aggregate.GroupBuyOrderAggregate;
|
||||||
|
import edu.whut.domain.trade.model.entity.GroupBuyActivityEntity;
|
||||||
import edu.whut.domain.trade.model.entity.MarketPayOrderEntity;
|
import edu.whut.domain.trade.model.entity.MarketPayOrderEntity;
|
||||||
import edu.whut.domain.trade.model.valobj.GroupBuyProgressVO;
|
import edu.whut.domain.trade.model.valobj.GroupBuyProgressVO;
|
||||||
|
|
||||||
@ -15,4 +16,8 @@ public interface ITradeRepository {
|
|||||||
|
|
||||||
GroupBuyProgressVO queryGroupBuyProgress(String teamId);
|
GroupBuyProgressVO queryGroupBuyProgress(String teamId);
|
||||||
|
|
||||||
|
GroupBuyActivityEntity queryGroupBuyActivityEntityByActivityId(Long activityId);
|
||||||
|
|
||||||
|
Integer queryOrderCountByActivityId(Long activityId, String userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package edu.whut.domain.trade.model.entity;
|
||||||
|
import edu.whut.types.enums.ActivityStatusEnumVO;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼团活动实体对象
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class GroupBuyActivityEntity {
|
||||||
|
|
||||||
|
/** 活动ID */
|
||||||
|
private Long activityId;
|
||||||
|
/** 活动名称 */
|
||||||
|
private String activityName;
|
||||||
|
/** 折扣ID */
|
||||||
|
private String discountId;
|
||||||
|
/** 拼团方式(0自动成团、1达成目标拼团) */
|
||||||
|
private Integer groupType;
|
||||||
|
/** 拼团次数限制 */
|
||||||
|
private Integer takeLimitCount;
|
||||||
|
/** 拼团目标 */
|
||||||
|
private Integer target;
|
||||||
|
/** 拼团时长(分钟) */
|
||||||
|
private Integer validTime;
|
||||||
|
/** 活动状态(0创建、1生效、2过期、3废弃) */
|
||||||
|
private ActivityStatusEnumVO status;
|
||||||
|
/** 活动开始时间 */
|
||||||
|
private Date startTime;
|
||||||
|
/** 活动结束时间 */
|
||||||
|
private Date endTime;
|
||||||
|
/** 人群标签规则标识 */
|
||||||
|
private String tagId;
|
||||||
|
/** 人群标签规则范围 */
|
||||||
|
private String tagScope;
|
||||||
|
|
||||||
|
}
|
@ -28,6 +28,8 @@ public class PayDiscountEntity {
|
|||||||
private BigDecimal originalPrice;
|
private BigDecimal originalPrice;
|
||||||
/** 折扣金额 */
|
/** 折扣金额 */
|
||||||
private BigDecimal deductionPrice;
|
private BigDecimal deductionPrice;
|
||||||
|
/** 支付金额 */
|
||||||
|
private BigDecimal payPrice;
|
||||||
/** 外部交易单号-确保外部调用唯一幂等 */
|
/** 外部交易单号-确保外部调用唯一幂等 */
|
||||||
private String outTradeNo;
|
private String outTradeNo;
|
||||||
|
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package edu.whut.domain.trade.model.entity;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易规则命令实体 进入链路的请求
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TradeRuleCommandEntity {
|
||||||
|
|
||||||
|
/** 用户ID */
|
||||||
|
private String userId;
|
||||||
|
/** 活动ID */
|
||||||
|
private Long activityId;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package edu.whut.domain.trade.model.entity;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易规则过滤反馈实体 链路返回
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TradeRuleFilterBackEntity {
|
||||||
|
|
||||||
|
// 用户参与活动的订单量
|
||||||
|
private Integer userTakeOrderCount;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package edu.whut.domain.trade.service.factory;
|
||||||
|
import edu.whut.domain.trade.model.entity.GroupBuyActivityEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRuleCommandEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRuleFilterBackEntity;
|
||||||
|
import edu.whut.domain.trade.service.filter.ActivityUsabilityRuleFilter;
|
||||||
|
import edu.whut.domain.trade.service.filter.UserTakeLimitRuleFilter;
|
||||||
|
import edu.whut.types.design.framework.link.model2.LinkArmory;
|
||||||
|
import edu.whut.types.design.framework.link.model2.chain.BusinessLinkedList;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易规则过滤链工厂:把各个规则节点按顺序组装成责任链。
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class TradeRuleFilterFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 Spring @Bean 暴露:外部只需注入 BusinessLinkedList 即可调用 apply
|
||||||
|
*/
|
||||||
|
@Bean("tradeRuleFilter")
|
||||||
|
public BusinessLinkedList<TradeRuleCommandEntity, DynamicContext, TradeRuleFilterBackEntity> tradeRuleFilter(ActivityUsabilityRuleFilter activityUsabilityRuleFilter, UserTakeLimitRuleFilter userTakeLimitRuleFilter) {
|
||||||
|
// 1. 组装链
|
||||||
|
LinkArmory<TradeRuleCommandEntity, DynamicContext, TradeRuleFilterBackEntity> linkArmory =
|
||||||
|
new LinkArmory<>("交易规则过滤链", activityUsabilityRuleFilter, userTakeLimitRuleFilter);
|
||||||
|
|
||||||
|
// 2. 返回链容器(即可作为责任链使用)
|
||||||
|
return linkArmory.getLogicLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态上下文:在链路中共享数据,避免重复查询。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class DynamicContext {
|
||||||
|
/** 拼团活动信息,供后续节点复用 */
|
||||||
|
private GroupBuyActivityEntity groupBuyActivity;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package edu.whut.domain.trade.service.filter;
|
||||||
|
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
|
||||||
|
import edu.whut.domain.trade.model.entity.GroupBuyActivityEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRuleCommandEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRuleFilterBackEntity;
|
||||||
|
import edu.whut.domain.trade.service.factory.TradeRuleFilterFactory;
|
||||||
|
import edu.whut.types.design.framework.link.model2.handler.ILogicHandler;
|
||||||
|
import edu.whut.types.enums.ActivityStatusEnumVO;
|
||||||
|
import edu.whut.types.enums.ResponseCode;
|
||||||
|
import edu.whut.types.exception.AppException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 活动的可用性,规则过滤【状态、有效期】
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ActivityUsabilityRuleFilter implements ILogicHandler<TradeRuleCommandEntity, TradeRuleFilterFactory.DynamicContext, TradeRuleFilterBackEntity> {
|
||||||
|
|
||||||
|
private final ITradeRepository repository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TradeRuleFilterBackEntity apply(TradeRuleCommandEntity requestParameter, TradeRuleFilterFactory.DynamicContext dynamicContext) throws Exception {
|
||||||
|
log.info("交易规则过滤-活动的可用性校验{} activityId:{}", requestParameter.getUserId(), requestParameter.getActivityId());
|
||||||
|
|
||||||
|
// 查询拼团活动
|
||||||
|
GroupBuyActivityEntity groupBuyActivity = repository.queryGroupBuyActivityEntityByActivityId(requestParameter.getActivityId());
|
||||||
|
|
||||||
|
// 校验;活动状态 - 可以抛业务异常code,或者把code写入到动态上下文dynamicContext中,最后获取。
|
||||||
|
if (!ActivityStatusEnumVO.EFFECTIVE.equals(groupBuyActivity.getStatus())) {
|
||||||
|
log.info("活动的可用性校验,非生效状态 activityId:{}", requestParameter.getActivityId());
|
||||||
|
throw new AppException(ResponseCode.E0101);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验;活动时间
|
||||||
|
Date currentTime = new Date();
|
||||||
|
if (currentTime.before(groupBuyActivity.getStartTime()) || currentTime.after(groupBuyActivity.getEndTime())) {
|
||||||
|
log.info("活动的可用性校验,非可参与时间范围 activityId:{}", requestParameter.getActivityId());
|
||||||
|
throw new AppException(ResponseCode.E0102);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入动态上下文
|
||||||
|
dynamicContext.setGroupBuyActivity(groupBuyActivity);
|
||||||
|
|
||||||
|
// 走到下一个责任链节点
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package edu.whut.domain.trade.service.filter;
|
||||||
|
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
|
||||||
|
import edu.whut.domain.trade.model.entity.GroupBuyActivityEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRuleCommandEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRuleFilterBackEntity;
|
||||||
|
import edu.whut.domain.trade.service.factory.TradeRuleFilterFactory;
|
||||||
|
import edu.whut.types.design.framework.link.model2.handler.ILogicHandler;
|
||||||
|
import edu.whut.types.enums.ResponseCode;
|
||||||
|
import edu.whut.types.exception.AppException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户参与限制,规则过滤
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class UserTakeLimitRuleFilter implements ILogicHandler<TradeRuleCommandEntity, TradeRuleFilterFactory.DynamicContext, TradeRuleFilterBackEntity> {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ITradeRepository repository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TradeRuleFilterBackEntity apply(TradeRuleCommandEntity requestParameter, TradeRuleFilterFactory.DynamicContext dynamicContext) throws Exception {
|
||||||
|
log.info("交易规则过滤-用户参与次数校验{} activityId:{}", requestParameter.getUserId(), requestParameter.getActivityId());
|
||||||
|
|
||||||
|
GroupBuyActivityEntity groupBuyActivity = dynamicContext.getGroupBuyActivity();
|
||||||
|
|
||||||
|
// 查询用户在一个拼团活动上参与的次数
|
||||||
|
Integer count = repository.queryOrderCountByActivityId(requestParameter.getActivityId(), requestParameter.getUserId());
|
||||||
|
|
||||||
|
if (null != groupBuyActivity.getTakeLimitCount() && count >= groupBuyActivity.getTakeLimitCount()) {
|
||||||
|
log.info("用户参与次数校验,已达可参与上限 activityId:{}", requestParameter.getActivityId());
|
||||||
|
throw new AppException(ResponseCode.E0103);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TradeRuleFilterBackEntity.builder()
|
||||||
|
.userTakeOrderCount(count)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,16 +2,17 @@ package edu.whut.infrastructure.adapter.repository;
|
|||||||
|
|
||||||
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
|
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
|
||||||
import edu.whut.domain.trade.model.aggregate.GroupBuyOrderAggregate;
|
import edu.whut.domain.trade.model.aggregate.GroupBuyOrderAggregate;
|
||||||
import edu.whut.domain.trade.model.entity.MarketPayOrderEntity;
|
import edu.whut.domain.trade.model.entity.*;
|
||||||
import edu.whut.domain.trade.model.entity.PayActivityEntity;
|
|
||||||
import edu.whut.domain.trade.model.entity.PayDiscountEntity;
|
|
||||||
import edu.whut.domain.trade.model.entity.UserEntity;
|
|
||||||
import edu.whut.domain.trade.model.valobj.GroupBuyProgressVO;
|
import edu.whut.domain.trade.model.valobj.GroupBuyProgressVO;
|
||||||
import edu.whut.domain.trade.model.valobj.TradeOrderStatusEnumVO;
|
import edu.whut.domain.trade.model.valobj.TradeOrderStatusEnumVO;
|
||||||
|
import edu.whut.infrastructure.dao.IGroupBuyActivityDao;
|
||||||
import edu.whut.infrastructure.dao.IGroupBuyOrderDao;
|
import edu.whut.infrastructure.dao.IGroupBuyOrderDao;
|
||||||
import edu.whut.infrastructure.dao.IGroupBuyOrderListDao;
|
import edu.whut.infrastructure.dao.IGroupBuyOrderListDao;
|
||||||
|
import edu.whut.infrastructure.dao.po.GroupBuyActivity;
|
||||||
import edu.whut.infrastructure.dao.po.GroupBuyOrder;
|
import edu.whut.infrastructure.dao.po.GroupBuyOrder;
|
||||||
import edu.whut.infrastructure.dao.po.GroupBuyOrderList;
|
import edu.whut.infrastructure.dao.po.GroupBuyOrderList;
|
||||||
|
import edu.whut.types.common.Constants;
|
||||||
|
import edu.whut.types.enums.ActivityStatusEnumVO;
|
||||||
import edu.whut.types.enums.ResponseCode;
|
import edu.whut.types.enums.ResponseCode;
|
||||||
import edu.whut.types.exception.AppException;
|
import edu.whut.types.exception.AppException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -22,7 +23,6 @@ import org.springframework.dao.DuplicateKeyException;
|
|||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仓储实现:负责把领域对象 <-> 数据库 PO 的转换与持久化;
|
* 仓储实现:负责把领域对象 <-> 数据库 PO 的转换与持久化;
|
||||||
@ -37,6 +37,8 @@ public class TradeRepository implements ITradeRepository {
|
|||||||
|
|
||||||
private final IGroupBuyOrderListDao groupBuyOrderListDao;
|
private final IGroupBuyOrderListDao groupBuyOrderListDao;
|
||||||
|
|
||||||
|
private final IGroupBuyActivityDao groupBuyActivityDao;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据外部交易号 & 用户id 查询未支付的锁单记录(用于幂等)
|
* 根据外部交易号 & 用户id 查询未支付的锁单记录(用于幂等)
|
||||||
*/
|
*/
|
||||||
@ -74,13 +76,17 @@ public class TradeRepository implements ITradeRepository {
|
|||||||
UserEntity user = agg.getUserEntity();
|
UserEntity user = agg.getUserEntity();
|
||||||
PayActivityEntity activity = agg.getPayActivityEntity();
|
PayActivityEntity activity = agg.getPayActivityEntity();
|
||||||
PayDiscountEntity discount = agg.getPayDiscountEntity();
|
PayDiscountEntity discount = agg.getPayDiscountEntity();
|
||||||
|
Integer userTakeOrderCount = agg.getUserTakeOrderCount();
|
||||||
|
|
||||||
|
|
||||||
/* ---------- 1. 处理 group_buy_order(团单主表) ---------- */
|
/* ---------- 1. 处理 group_buy_order(团单主表) ---------- */
|
||||||
String teamId = activity.getTeamId();
|
String teamId = activity.getTeamId();
|
||||||
|
//自己发起拼团
|
||||||
if (StringUtils.isBlank(teamId)) {
|
if (StringUtils.isBlank(teamId)) {
|
||||||
// 新建团队,随机 8 位数字作 teamId(示例中用 RandomStringUtils,线上可换雪花算法等)
|
// 新建团队,随机 8 位数字作 teamId(示例中用 RandomStringUtils,线上可换雪花算法等)
|
||||||
teamId = RandomStringUtils.randomNumeric(8);
|
teamId = RandomStringUtils.randomNumeric(8);
|
||||||
|
|
||||||
|
// 构建拼团订单
|
||||||
GroupBuyOrder orderPo = GroupBuyOrder.builder()
|
GroupBuyOrder orderPo = GroupBuyOrder.builder()
|
||||||
.teamId(teamId)
|
.teamId(teamId)
|
||||||
.activityId(activity.getActivityId())
|
.activityId(activity.getActivityId())
|
||||||
@ -88,7 +94,7 @@ public class TradeRepository implements ITradeRepository {
|
|||||||
.channel(discount.getChannel())
|
.channel(discount.getChannel())
|
||||||
.originalPrice(discount.getOriginalPrice())
|
.originalPrice(discount.getOriginalPrice())
|
||||||
.deductionPrice(discount.getDeductionPrice())
|
.deductionPrice(discount.getDeductionPrice())
|
||||||
.payPrice(discount.getDeductionPrice()) // 直减后应付价格
|
.payPrice(discount.getOriginalPrice().subtract(discount.getDeductionPrice()))
|
||||||
.targetCount(activity.getTargetCount())
|
.targetCount(activity.getTargetCount())
|
||||||
.completeCount(0)
|
.completeCount(0)
|
||||||
.lockCount(1) // 首单已锁定
|
.lockCount(1) // 首单已锁定
|
||||||
@ -121,6 +127,8 @@ public class TradeRepository implements ITradeRepository {
|
|||||||
.deductionPrice(discount.getDeductionPrice())
|
.deductionPrice(discount.getDeductionPrice())
|
||||||
.status(TradeOrderStatusEnumVO.CREATE.getCode()) // 0 = 初始锁定
|
.status(TradeOrderStatusEnumVO.CREATE.getCode()) // 0 = 初始锁定
|
||||||
.outTradeNo(discount.getOutTradeNo())
|
.outTradeNo(discount.getOutTradeNo())
|
||||||
|
// 构建 bizId 唯一值;活动id_用户id_参与次数累加
|
||||||
|
.bizId(activity.getActivityId() + Constants.UNDERLINE + user.getUserId() + Constants.UNDERLINE + (userTakeOrderCount + 1))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -153,4 +161,31 @@ public class TradeRepository implements ITradeRepository {
|
|||||||
.lockCount(po.getLockCount())
|
.lockCount(po.getLockCount())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GroupBuyActivityEntity queryGroupBuyActivityEntityByActivityId(Long activityId) {
|
||||||
|
GroupBuyActivity groupBuyActivity = groupBuyActivityDao.queryGroupBuyActivityByActivityId(activityId);
|
||||||
|
return GroupBuyActivityEntity.builder()
|
||||||
|
.activityId(groupBuyActivity.getActivityId())
|
||||||
|
.activityName(groupBuyActivity.getActivityName())
|
||||||
|
.discountId(groupBuyActivity.getDiscountId())
|
||||||
|
.groupType(groupBuyActivity.getGroupType())
|
||||||
|
.takeLimitCount(groupBuyActivity.getTakeLimitCount())
|
||||||
|
.target(groupBuyActivity.getTarget())
|
||||||
|
.validTime(groupBuyActivity.getValidTime())
|
||||||
|
.status(ActivityStatusEnumVO.valueOf(groupBuyActivity.getStatus()))
|
||||||
|
.startTime(groupBuyActivity.getStartTime())
|
||||||
|
.endTime(groupBuyActivity.getEndTime())
|
||||||
|
.tagId(groupBuyActivity.getTagId())
|
||||||
|
.tagScope(groupBuyActivity.getTagScope())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer queryOrderCountByActivityId(Long activityId, String userId) {
|
||||||
|
GroupBuyOrderList groupBuyOrderListReq = new GroupBuyOrderList();
|
||||||
|
groupBuyOrderListReq.setActivityId(activityId);
|
||||||
|
groupBuyOrderListReq.setUserId(userId);
|
||||||
|
return groupBuyOrderListDao.queryOrderCountByActivityId(groupBuyOrderListReq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,6 @@ package edu.whut.types.common;
|
|||||||
public class Constants {
|
public class Constants {
|
||||||
|
|
||||||
public final static String SPLIT = ",";
|
public final static String SPLIT = ",";
|
||||||
|
public final static String UNDERLINE = "_";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,16 @@ import edu.whut.types.design.framework.link.model2.chain.BusinessLinkedList;
|
|||||||
import edu.whut.types.design.framework.link.model2.handler.ILogicHandler;
|
import edu.whut.types.design.framework.link.model2.handler.ILogicHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 链路装配
|
* 链路装配工厂 —— 负责把一组 ILogicHandler 顺序注册到 BusinessLinkedList 中。
|
||||||
*/
|
*/
|
||||||
public class LinkArmory<T, D, R> {
|
public class LinkArmory<T, D, R> {
|
||||||
|
|
||||||
private final BusinessLinkedList<T, D, R> logicLink;
|
private final BusinessLinkedList<T, D, R> logicLink;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param linkName 链路名称,便于日志排查
|
||||||
|
* @param logicHandlers 节点列表,按传入顺序链接
|
||||||
|
*/
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public LinkArmory(String linkName, ILogicHandler<T, D, R>... logicHandlers) {
|
public LinkArmory(String linkName, ILogicHandler<T, D, R>... logicHandlers) {
|
||||||
logicLink = new BusinessLinkedList<>(linkName);
|
logicLink = new BusinessLinkedList<>(linkName);
|
||||||
@ -18,6 +22,7 @@ public class LinkArmory<T, D, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 返回组装完成的链路 */
|
||||||
public BusinessLinkedList<T, D, R> getLogicLink() {
|
public BusinessLinkedList<T, D, R> getLogicLink() {
|
||||||
return logicLink;
|
return logicLink;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,11 @@ package edu.whut.types.design.framework.link.model2.chain;
|
|||||||
import edu.whut.types.design.framework.link.model2.handler.ILogicHandler;
|
import edu.whut.types.design.framework.link.model2.handler.ILogicHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务链路
|
* 业务链路容器 —— 双向链表实现,同时实现 ILogicHandler,从而可以被当作单个节点使用。
|
||||||
|
* 责任链特点:
|
||||||
|
* 链表插入、删除复杂度 O(1),运行期可动态调整节点。
|
||||||
|
* 循环遍历,不使用递归,避免深链路导致的栈溢出风险。
|
||||||
|
* 当某个节点返回非 null 时立即短路结束。
|
||||||
*/
|
*/
|
||||||
public class BusinessLinkedList<T, D, R> extends LinkedList<ILogicHandler<T, D, R>> implements ILogicHandler<T, D, R>{
|
public class BusinessLinkedList<T, D, R> extends LinkedList<ILogicHandler<T, D, R>> implements ILogicHandler<T, D, R>{
|
||||||
|
|
||||||
@ -12,18 +16,25 @@ public class BusinessLinkedList<T, D, R> extends LinkedList<ILogicHandler<T, D,
|
|||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BusinessLinkedList是头节点,它的apply方法就是循环调用后面的节点,直至返回。
|
||||||
|
* 遍历并执行链路。
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public R apply(T requestParameter, D dynamicContext) throws Exception {
|
public R apply(T requestParameter, D dynamicContext) throws Exception {
|
||||||
Node<ILogicHandler<T, D, R>> current = this.first;
|
Node<ILogicHandler<T, D, R>> current = this.first;
|
||||||
do {
|
// 顺序执行,直到链尾或返回结果
|
||||||
ILogicHandler<T, D, R> item = current.item;
|
while (current != null) {
|
||||||
R apply = item.apply(requestParameter, dynamicContext);
|
ILogicHandler<T, D, R> handler = current.item;
|
||||||
if (null != apply) return apply;
|
R result = handler.apply(requestParameter, dynamicContext);
|
||||||
|
if (result != null) {
|
||||||
|
// 节点命中,立即返回
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//result==null,则交给那一节点继续处理
|
||||||
current = current.next;
|
current = current.next;
|
||||||
} while (null != current);
|
}
|
||||||
|
// 全链未命中
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package edu.whut.types.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼团活动状态枚举
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public enum ActivityStatusEnumVO {
|
||||||
|
|
||||||
|
CREATE(0, "创建"),
|
||||||
|
EFFECTIVE(1, "生效"),
|
||||||
|
OVERDUE(2, "过期"),
|
||||||
|
ABANDONED(3, "废弃"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private Integer code;
|
||||||
|
private String info;
|
||||||
|
|
||||||
|
public static ActivityStatusEnumVO valueOf(Integer code) {
|
||||||
|
switch (code) {
|
||||||
|
case 0:
|
||||||
|
return CREATE;
|
||||||
|
case 1:
|
||||||
|
return EFFECTIVE;
|
||||||
|
case 2:
|
||||||
|
return OVERDUE;
|
||||||
|
case 3:
|
||||||
|
return ABANDONED;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("err code not exist!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -43,7 +43,7 @@ public class AppException extends RuntimeException {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "edu.whut.x.api.types.exception.XApiException{" +
|
return "edu.whut.types.exception.AppException{" +
|
||||||
"code='" + code + '\'' +
|
"code='" + code + '\'' +
|
||||||
", info='" + info + '\'' +
|
", info='" + info + '\'' +
|
||||||
'}';
|
'}';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user