后台-系统设置-扩展变量-手机广告位-内容正文顶部 |
代码设计
1、接口调用流程图
平台和商家发布优惠券
用户领取优惠券
使用优惠券
2、相关代码展示
发布优惠券
@RestController
@RequestMapping("/seller/promotion/coupons")
@Api(description = "优惠券相关API")
@Validated
public class CouponSellerController {
@ApiOperation(value = "添加优惠券", response = CouponDO.class)
@PostMapping
public CouponDO add(@Valid CouponDO couponDO) {
Seller seller = UserContext.getSeller();
couponDO.setSellerId(seller.getSellerId());
couponDO.setSellerName(seller.getSellerName());
this.couponManager.add(couponDO);
return couponDO;
}
}
@Service
public class CouponManagerImpl implements CouponManager {
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor
= {ServiceException.class, RuntimeException.class, Exception.class})
public CouponDO add(CouponDO coupon) {
//检测开始时间和结束时间
PromotionValid.paramValid(coupon.getStartTime(), coupon.getEndTime(), 1, null);
if (coupon.getLimitNum() < 0) {
throw new ServiceException(PromotionErrorCode.E406.code(),
"限领数量不能为负数");
}
//校验每人限领数是都大于发行量
if (coupon.getLimitNum() > coupon.getCreateNum()) {
throw new ServiceException(PromotionErrorCode.E405.code(),
"限领数量超出发行量");
}
if (coupon.getCouponPrice() == null || coupon.getCouponPrice() <= 0) {
throw new ServiceException(PromotionErrorCode.E409.code(),
"优惠券面额必须大于0元");
}
if (coupon.getCouponThresholdPrice() == null ||
coupon.getCouponThresholdPrice() <= 0) {
throw new ServiceException(PromotionErrorCode.E409.code(),
"优惠券门槛价格必须大于0元");
}
//校验优惠券面额是否小于门槛价格
if (coupon.getCouponPrice() >= coupon.getCouponThresholdPrice()) {
throw new ServiceException(PromotionErrorCode.E409.code(),
"优惠券面额必须小于优惠券门槛价格");
}
//开始时间取前段+00:00:00 结束时间取前段+23:59:59
String startStr = DateUtil.toString(coupon.getStartTime(), "yyyy-MM-dd");
String endStr = DateUtil.toString(coupon.getEndTime(), "yyyy-MM-dd");
coupon.setStartTime(DateUtil.getDateline(startStr + " 00:00:00"));
coupon.setEndTime(DateUtil.getDateline(endStr + " 23:59:59",
"yyyy-MM-dd hh:mm:ss"));
this.paramValid(coupon.getStartTime(), coupon.getEndTime());
coupon.setReceivedNum(0);
coupon.setUsedNum(0);
//部分商品和分类的id存储增加,,
if (CouponUseScope.SOME_GOODS.name().equals(coupon.getUseScope()) ||
CouponUseScope.CATEGORY.name().equals(coupon.getUseScope())) {
coupon.setScopeId("," + coupon.getScopeId() + ",");
}
this.couponMapper.insert(coupon);
//启用延时任务创建优惠券脚本信息
PromotionScriptMsg promotionScriptMsg = new PromotionScriptMsg();
promotionScriptMsg.setPromotionId(coupon.getCouponId());
promotionScriptMsg.setPromotionName(coupon.getTitle());
promotionScriptMsg.setPromotionType(PromotionTypeEnum.COUPON);
promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.CREATE);
promotionScriptMsg.setEndTime(coupon.getEndTime());
String uniqueKey = "{TIME_TRIGGER_" + PromotionTypeEnum.COUPON.name()
+ "}_" + coupon.getCouponId();
timeTrigger.add(TimeExecute.COUPON_SCRIPT_EXECUTER, promotionScriptMsg,
coupon.getStartTime(), uniqueKey);
return coupon;
}
}
用户领取优惠券
@RestController
@RequestMapping("/members/coupon")
@Api(description = "会员优惠券相关API")
@Validated
public class MemberCouponBuyerController {
@ApiOperation(value = "用户领取优惠券")
@ApiImplicitParams({
@ApiImplicitParam(name = "coupon_id", value = "优惠券id", required = true,
dataType = "String", paramType = "path")
})
@PostMapping(value = "/{coupon_id}/receive")
public String receiveBonus(@ApiIgnore @PathVariable("coupon_id") Long couponId) {
//限领检测
this.memberCouponManager.checkLimitNum(couponId);
Buyer buyer = UserContext.getBuyer();
this.memberCouponManager.receiveBonus(buyer.getUid(),
buyer.getUsername(), couponId);
return "";
}
}
@Service
public class MemberCouponManagerImpl implements MemberCouponManager {
@Override
@Transactional(value = "memberTransactionManager", propagation =
Propagation.REQUIRED, rollbackFor = Exception.class)
public void receiveBonus(Long memberId, String memberName, Long couponId) {
//根据优惠券id获取优惠券信息
CouponDO couponDO = this.couponClient.getModel(couponId);
//如果会员id不为空
if (memberId != null) {
//添加会员优惠券表
MemberCoupon memberCoupon = new MemberCoupon(couponDO);
//设置优惠券创建时间
memberCoupon.setCreateTime(DateUtil.getDateline());
//设置会员ID
memberCoupon.setMemberId(memberId);
//设置会员名称
memberCoupon.setMemberName(memberName);
//设置优惠券使用状态 0:未使用,1:已使用,2:已过期,3:已作废
memberCoupon.setUsedStatus(0);
//会员优惠券入库
memberCouponMapper.insert(memberCoupon);
// 修改优惠券已被领取的数量
this.couponClient.addReceivedNum(couponId);
}
}
@Override
public void checkLimitNum(Long couponId) {
//根据优惠券ID获取优惠券信息
CouponDO couponDO = this.couponClient.getModel(couponId);
//获取当前登录的会员信息
Buyer buyer = UserContext.getBuyer();
//获取每人限领数量
int limitNum = couponDO.getLimitNum();
//新建查询条件包装器
QueryWrapper
//以会员id为查询条件
wrapper.eq("member_id", buyer.getUid());
//以优惠券id为查询条件
wrapper.eq("coupon_id", couponId);
//查询会员优惠券数量
int num = memberCouponMapper.selectCount(wrapper);
//判断优惠券是否已被领完
if (couponDO.getReceivedNum() >= couponDO.getCreateNum()) {
throw new ServiceException(MemberErrorCode.E203.code(), "优惠券已被领完");
}
//判断优惠券是否已达到限领数量
if (limitNum != 0 && num >= limitNum) {
throw new ServiceException(MemberErrorCode.E203.code(),
"优惠券限领" + limitNum + "个");
}
}
}
使用优惠券
@Api(description = "购物车价格计算API")
@RestController
@RequestMapping("/trade/promotion")
@Validated
public class TradePromotionController {
@ApiOperation(value = "设置优惠券", notes = "使用优惠券的时候分为三种情况:前2种情况couponId 不为0,不为空。第3种情况couponId为0," +
"1、使用优惠券:在刚进入订单结算页,为使用任何优惠券之前。" +
"2、切换优惠券:在1、情况之后,当用户切换优惠券的时候。" +
"3、取消已使用的优惠券:用户不想使用优惠券的时候。")
@ApiImplicitParams({
@ApiImplicitParam(name = "seller_id", value = "店铺ID", required = true,
dataType = "int", paramType = "path"),
@ApiImplicitParam(name = "mc_id", value = "优惠券ID", required = true,
dataType = "int", paramType = "path"),
@ApiImplicitParam(name = "way", value = "结算方式,BUY_NOW:立即购买,CART:"
+"购物车", required = true, dataType = "String")
})
@PostMapping(value = "/{seller_id}/seller/{mc_id}/coupon")
public void setCoupon(@NotNull(message = "店铺id不能为空")
@PathVariable("seller_id") Long sellerId,
@NotNull(message = "优惠券id不能为空")
@PathVariable("mc_id") Long mcId,
@NotNull(message = "结算方式不能为空")
@RequestParam String way) {
CartBuilder cartBuilder =
new DefaultCartBuilder(CartType.CART, cartSkuRenderer, null,
cartPriceCalculator, checkDataRebderer);
CartView cartViewold =
cartBuilder.renderSku(CheckedWay.valueOf(way)).countPrice(false).build();
//先判断优惠券能否使用
MemberCoupon memberCoupon = promotionManager.detectCoupon(
sellerId, mcId, cartViewold.getCartList());
//查询要结算的某卖家的购物信息
CartView cartView = cartBuilder.renderSku(CheckedWay.valueOf(way))
.countPrice(true).build();
//设置优惠券 goodsPrice
promotionManager.useCoupon(sellerId, mcId, cartView.getCartList(),
memberCoupon);
}
}
@Service
public class CartPromotionManagerImpl implements CartPromotionManager {
@Override
public void useCoupon(Long sellerId, Long mcId, List
MemberCoupon memberCoupon) {
if (memberCoupon != null) {
//查询选中的促销
SelectedPromotionVo selectedPromotionVo = getSelectedPromotion();
CouponVO couponVO = new CouponVO(memberCoupon);
SelectedPromotionVo selectedPromotion = getSelectedPromotion();
selectedPromotion.putCooupon(sellerId, couponVO);
logger.debug("使用优惠券:" + couponVO);
logger.debug("促销信息为:" + selectedPromotionVo);
String cacheKey = this.getOriginKey();
cache.put(cacheKey, selectedPromotion);
}
}
}
创建和删除优惠券促销脚本
@Component("couponScriptTimeTriggerExecuter")
public class CouponScriptTimeTriggerExecuter implements TimeTriggerExecuter {
@Override
public void execute(Object object) {
PromotionScriptMsg promotionScriptMsg = (PromotionScriptMsg) object;
//获取促销活动ID
Long promotionId = promotionScriptMsg.getPromotionId();
//优惠券级别缓存key
String cacheKey = CachePrefix.COUPON_PROMOTION.getPrefix() + promotionId;
//如果是优惠券开始生效
if (ScriptOperationTypeEnum.CREATE.equals(
promotionScriptMsg.getOperationType())) {
//获取优惠券详情
CouponDO coupon = this.couponClient.getModel(promotionId);
//渲染并读取优惠券脚本信息
String script = renderCouponScript(coupon);
//将优惠券脚本信息放入缓存
cache.put(cacheKey, script);
//优惠券生效后,立马设置一个优惠券失效的流程
promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.DELETE);
String uniqueKey = "{TIME_TRIGGER_"
+ promotionScriptMsg.getPromotionType().name()
+ "}_" + promotionId;
timeTrigger.add(TimeExecute.COUPON_SCRIPT_EXECUTER, promotionScriptMsg,
promotionScriptMsg.getEndTime(), uniqueKey);
this.logger.debug("优惠券[" + promotionScriptMsg.getPromotionName()
+ "]开始生效,id=[" + promotionId + "]");
} else {
//删除缓存中的促销脚本数据
cache.remove(cacheKey);
this.logger.debug("优惠券[" + promotionScriptMsg.getPromotionName()
+ "]已经失效,id=[" + promotionId + "]");
}
}
/**
* 渲染并读取优惠券脚本信息
* @param coupon 优惠券信息
* @return
*/
private String renderCouponScript(CouponDO coupon) {
Map
Map
params.put("startTime", coupon.getStartTime().toString());
params.put("endTime", coupon.getEndTime().toString());
params.put("couponPrice", coupon.getCouponPrice());
model.put("coupon", params);
String path = "coupon.ftl";
String script = ScriptUtil.renderScript(path, model);
logger.debug("生成优惠券脚本:" + script);
return script;
}
}
优惠券脚本引擎模板文件—coupon.ftl
<#--验证优惠券是否在有效期内@param coupon 优惠券信息对象(内置常量)
.startTime 有效期开始时间
.endTime 有效期结束时间@param $currentTime 当前时间(变量)@return {boolean}-->
function validTime(){
if (${coupon.startTime} <= $currentTime && $currentTime <= ${coupon.endTime}) {
return true;
}
return false;
}
<#--优惠券金额计算@param coupon 优惠券信息对象(内置常量)
.couponPrice 优惠券面额@param $price 商品总价(变量,如果有商品参与了其它促销活动,为商品优惠后的总价)@returns {*}-->
function countPrice() {
var resultPrice = $price - ${coupon.couponPrice};
return resultPrice < 0 ? 0 : resultPrice.toString();
}
根据以上内容可以了解到优惠券的代码设计是怎么样的,想了解更多详情,可以持续关注易族智汇javashop。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。