限时抢购促销活动:代码设计详细说明

后台-系统设置-扩展变量-手机广告位-内容正文顶部

代码设计

1、接口调用流程图

  平台发布促销活动

  商家选择商品参与限时抢购活动

  平台审核商家参与活动的商品

2、相关代码展示

新增和修改限时抢购活动

  @RestController

  @RequestMapping("/admin/promotion/seckills")

  @Api(description = "限时抢购活动相关API")

  @Validated

  public class SeckillManagerController {

  @ApiOperation(value = "添加限时抢购入库", response = SeckillVO.class)

  @PostMapping

  public SeckillVO add(@Valid @RequestBody SeckillVO seckill) {

  this.verifyParam(seckill);

  seckill.setSeckillStatus(SeckillStatusEnum.EDITING.name());

  this.seckillManager.add(seckill);

  return seckill;

  }

  @PutMapping(value = "/{id}")

  @ApiOperation(value = "修改限时抢购入库", response = SeckillDO.class)

  @ApiImplicitParams({

  @ApiImplicitParam(name = "id", value = "主键",

  required = true, dataType = "int", paramType = "path")

  })

  public SeckillVO edit(@Valid @RequestBody SeckillVO seckill,

  @PathVariable @NotNull(message = "限时抢购ID参数错误") Long id) {

  this.verifyParam(seckill);

  this.seckillManager.edit(seckill, id);

  return seckill;

  }

  }

  @Service

  public class SeckillManagerImpl extends AbstractPromotionRuleManagerImpl implements SeckillManager {

  @Override

  @Transactional(propagation = Propagation.REQUIRED,

  rollbackFor = {ServiceException.class, RuntimeException.class})

  public SeckillVO add(SeckillVO seckill) {

  //验证活动名称是否为空

  this.checkName(seckill.getSeckillName(), null);

  String date = DateUtil.toString(seckill.getStartDay(), "yyyy-MM-dd");

  long startTime = DateUtil.getDateline(date + " 00:00:00",

  "yyyy-MM-dd HH:mm:ss");

  long endTime = DateUtil.getDateline(date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");

  this.verifyTime(startTime, endTime, PromotionTypeEnum.SECKILL, null);

  SeckillDO seckillDO = new SeckillDO();

  seckillDO.setDeleteStatus(DeleteStatusEnum.NORMAL.value());

  BeanUtils.copyProperties(seckill, seckillDO);

  seckillMapper.insert(seckillDO);

  Long id = seckillDO.getSeckillId();

  this.seckillRangeManager.addList(seckill.getRangeList(), id);

  //开启延时任务执行器

  openTimeExecuter(seckill, endTime, id);

  return seckill;

  }

  @Override

  @Transactional(propagation = Propagation.REQUIRED,

  rollbackFor = {ServiceException.class})

  public SeckillVO edit(SeckillVO seckill, Long id) {

  //验证活动名称是否为空

  this.checkName(seckill.getSeckillName(), id);

  String date = DateUtil.toString(seckill.getStartDay(), "yyyy-MM-dd");

  long startTime = DateUtil.getDateline(date + " 00:00:00",

  "yyyy-MM-dd HH:mm:ss");

  long endTime = DateUtil.getDateline(date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");

  PromotionValid.paramValid(startTime, endTime, 1, null);

  this.verifyTime(startTime, endTime, PromotionTypeEnum.SECKILL, id);

  SeckillDO seckillDO = new SeckillDO();

  BeanUtils.copyProperties(seckill, seckillDO);

  seckillDO.setSeckillId(id);

  seckillMapper.updateById(seckillDO);

  this.seckillRangeManager.addList(seckill.getRangeList(), id);

  //开启延时任务执行器

  openTimeExecuter(seckill, endTime, id);

  return seckill;

  }

  }

发布限时抢购活动

  @RestController

  @RequestMapping("/admin/promotion/seckills")

  @Api(description = "限时抢购活动相关API")

  @Validated

  public class SeckillManagerController {

  @ApiOperation(value = "发布限时抢购活动")

  @PostMapping("/{seckill_id}/release")

  @ApiImplicitParams({

  @ApiImplicitParam(name = "seckill_id", value = "要查询的限时抢购入库主键",

  required = true, dataType = "int", paramType = "path")

  })

  public SeckillVO publish(@Valid @RequestBody SeckillVO seckill,

  @ApiIgnore @PathVariable("seckill_id") Long seckillId) {

  this.verifyParam(seckill);

  //发布状态

  seckill.setSeckillStatus(SeckillStatusEnum.RELEASE.name());

  if (seckillId == null || seckillId == 0) {

  seckillManager.add(seckill);

  } else {

  seckillManager.edit(seckill, seckillId);

  }

  return seckill;

  }

  }

平台审核商家参与限时抢购活动的商品

  @RestController

  @RequestMapping("/admin/promotion/seckills")

  @Api(description = "限时抢购活动相关API")

  @Validated

  public class SeckillManagerController {

  @ApiOperation(value = "批量审核商品")

  @PostMapping(value = "/batch/audit")

  public String batchAudit(@Valid @RequestBody SeckillAuditParam param) {

  this.seckillManager.batchAuditGoods(param);

  return "";

  }

  }

  @Service

  public class SeckillManagerImpl extends AbstractPromotionRuleManagerImpl implements SeckillManager {

  @Override

  @Transactional(propagation = Propagation.REQUIRED,

  rollbackFor = {ServiceException.class, RuntimeException.class})

  public void batchAuditGoods(SeckillAuditParam param) {

  if (param.getApplyIds() == null || param.getApplyIds().length == 0) {

  throw new ServiceException(GoodsErrorCode.E301.code(), "请选择要审核的商品");

  }

  if (StringUtil.isEmpty(param.getStatus())) {

  throw new ServiceException(PromotionErrorCode.E400.code(), "审核状态值不正确");

  }

  //状态值不正确

  SeckillGoodsApplyStatusEnum applyStatusEnum =

  SeckillGoodsApplyStatusEnum.valueOf(param.getStatus());

  //驳回,原因必填

  if (applyStatusEnum.equals(SeckillGoodsApplyStatusEnum.FAIL)) {

  if (StringUtil.isEmpty(param.getFailReason())) {

  throw new ServiceException(PromotionErrorCode.E400.code(),

  "驳回原因必填");

  }

  if (param.getFailReason().length() > 500) {

  throw new ServiceException(PromotionErrorCode.E400.code(),

  "驳回原因长度不能超过500个字符");

  }

  }

  //审核状态 true:审核通过,false:审核未通过

  boolean auditStatus = SeckillGoodsApplyStatusEnum.PASS.equals(applyStatusEnum);

  //参与限时抢购促销活动并且已被平台审核通过的商品集合

  List goodsList = new ArrayList<>();

  //审核通过的限时抢购商品集合

  List promotionGoodsDOS = new ArrayList<>();

  Long actId = 0L;

  //批量审核

  for (Long applyId : param.getApplyIds()) {

  SeckillApplyDO apply = new QueryChainWrapper<>(seckillApplyMapper)

  //拼接活动id查询条件

  .eq("apply_id", applyId)

  //拼接秒杀活动商品的申请状态查询条件

  .eq("status", SeckillGoodsApplyStatusEnum.APPLY.name())

  //查询单个对象

  .one();

  //申请不存在

  if (apply == null) {

  throw new ServiceException(PromotionErrorCode.E400.code(),

  "商品不是可以审核的状态");

  }

  if (actId == 0) {

  actId = apply.getSeckillId();

  }

  apply.setStatus(applyStatusEnum.name());

  apply.setFailReason(param.getFailReason());

  new UpdateChainWrapper<>(seckillApplyMapper)

  //按活动id修改

  .eq("apply_id", applyId)

  //提交修改

  .update(apply);

  //查询商品

  CacheGoods goods = goodsClient.getFromCache(apply.getGoodsId());

  //将审核通过的商品,存储到活动商品表和缓存中

  if (auditStatus) {

  //将审核通过的商品放入集合中

  goodsList.add(apply);

  //促销商品表

  PromotionGoodsDO promotion = new PromotionGoodsDO();

  promotion.setTitle("限时抢购");

  promotion.setGoodsId(apply.getGoodsId());

  promotion.setSkuId(apply.getSkuId());

  promotion.setPromotionType(PromotionTypeEnum.SECKILL.name());

  promotion.setActivityId(apply.getSeckillId());

  promotion.setNum(apply.getSoldQuantity());

  promotion.setPrice(apply.getPrice());

  promotion.setSellerId(goods.getSellerId());

  //商品活动的开始时间为当前商品的参加时间段

  int timeLine = apply.getTimeLine();

  String date = DateUtil.toString(apply.getStartDay(), "yyyy-MM-dd");

  long startTime = DateUtil.getDateline(

  date + " " + timeLine + ":00:00", "yyyy-MM-dd HH:mm:ss");

  long endTime = DateUtil.getDateline(

  date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");

  promotion.setStartTime(startTime);

  promotion.setEndTime(endTime);

  promotionGoodsDOS.add(promotion);

  //从缓存读取限时抢购的活动的商品

  String redisKey = getRedisKey(apply.getStartDay());

  Map> map = this.cache.getHash(redisKey);

  //如果redis中有当前审核商品参与的限时抢购活动商品信息,就删除掉

  if (map != null && !map.isEmpty()) {

  this.cache.remove(redisKey);

  }

  //设置延迟加载任务,到活动开始时间后将搜索引擎中的优惠价格设置为0

  PromotionPriceDTO promotionPriceDTO = new PromotionPriceDTO();

  promotionPriceDTO.setGoodsId(apply.getGoodsId());

  promotionPriceDTO.setPrice(apply.getPrice());

  timeTrigger.add(TimeExecute.PROMOTION_EXECUTER,

  promotionPriceDTO, startTime, null);

  //此活动结束后将索引的优惠价格重置为0

  promotionPriceDTO.setPrice(0.0);

  timeTrigger.add(TimeExecute.PROMOTION_EXECUTER,

  promotionPriceDTO, endTime, null);

  }

  }

  //如果当前是商品审核通过的操作

  if (auditStatus) {

  SeckillVO seckillVO = this.getModel(actId);

  if (seckillVO != null) {

  String date = DateUtil.toString(seckillVO.getStartDay(), "yyyy-MM-dd");

  long startTime = DateUtil.getDateline(

  date + " 00:00:00", "yyyy-MM-dd HH:mm:ss");

  long endTime = DateUtil.getDateline(

  date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");

  //活动信息DTO

  PromotionDetailDTO detailDTO = new PromotionDetailDTO();

  detailDTO.setActivityId(seckillVO.getSeckillId());

  detailDTO.setStartTime(startTime);

  detailDTO.setEndTime(endTime);

  detailDTO.setPromotionType(PromotionTypeEnum.SECKILL.name());

  detailDTO.setTitle("限时抢购");

  this.promotionGoodsManager.addAndCheck(promotionGoodsDOS, detailDTO);

  }

  //创建审核通过的商品限时抢购促销活动脚本信息

  this.seckillScriptManager.createCacheScript(

  goodsList.get(0).getSeckillId(), goodsList);

  }

  }

  - 创建限时抢购促销活动脚本引擎

  ```java

  @Service

  public class SeckillScriptManagerImpl implements SeckillScriptManager {

  @Override

  public void createCacheScript(Long promotionId, List goodsList) {

  //如果参与促销活动的商品集合不为空并且集合长度不等于0

  if (goodsList != null && goodsList.size() != 0) {

  //批量放入缓存的数据集合

  Map> cacheMap = new HashMap<>();

  //循环skuID集合,将脚本放入缓存中

  for (SeckillApplyDO goods : goodsList) {

  //缓存key

  String cacheKey = CachePrefix.SKU_PROMOTION.getPrefix()

  + goods.getSkuId();

  //获取商品开始的时刻

  String[] time = this.getTime(goods.getTimeLine(), goods.getStartDay());

  //获取拼团活动脚本信息

  PromotionScriptVO scriptVO = new PromotionScriptVO();

  //渲染并读取限时抢购促销活动脚本信息

  String script = renderScript(time[0], time[1], goods.getPrice());

  scriptVO.setPromotionScript(script);

  scriptVO.setPromotionId(promotionId);

  scriptVO.setPromotionType(PromotionTypeEnum.SECKILL.name());

  scriptVO.setIsGrouped(false);

  scriptVO.setPromotionName("限时抢购");

  scriptVO.setSkuId(goods.getSkuId());

  //从缓存中读取脚本信息

  List scriptList = (List)

  cache.get(cacheKey);

  if (scriptList == null) {

  scriptList = new ArrayList<>();

  }

  scriptList.add(scriptVO);

  cacheMap.put(cacheKey, scriptList);

  }

  //将sku促销脚本数据批量放入缓存中

  cache.multiSet(cacheMap);

  }

  }

  /**

  * 获取限时抢购开始和结束时间

  * @param timeLine 开始时刻

  * @param startDay 活动开始当天的起始时间

  * @return

  */

  private String[] getTime(Integer timeLine, Long startDay) {

  String date = DateUtil.toString(startDay, "yyyy-MM-dd");

  Long startTime = DateUtil.getDateline(date + " " + timeLine + ":00:00",

  "yyyy-MM-dd HH:mm:ss");

  Long endTime = DateUtil.getDateline(date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");

  String[] time = new String[2];

  time[0] = startTime.toString();

  time[1] = endTime.toString();

  return time;

  }

  /**

  * 渲染并读取限时抢购促销活动脚本信息

  * @param startTime 活动开始时间

  * @param endTime 活动结束时间

  * @param price 限时抢购商品价格

  * @return

  */

  private String renderScript(String startTime, String endTime, Double price) {

  Map model = new HashMap<>();

  Map params = new HashMap<>();

  params.put("startTime", startTime);

  params.put("endTime", endTime);

  params.put("price", price);

  model.put("promotionActive", params);

  String path = "single_promotion.ftl";

  String script = ScriptUtil.renderScript(path, model);

  logger.debug("生成限时抢购促销活动脚本:" + script);

  return script;

  }

  }

删除限时抢购促销活动脚本引擎

  @Component("seckillScriptTimeTriggerExecuter")

  public class SeckillScriptTimeTriggerExecuter implements TimeTriggerExecuter {

  protected final Logger logger = LoggerFactory.getLogger(this.getClass());

  @Autowired

  private PromotionScriptClient promotionScriptClient;

  @Autowired

  private PromotionGoodsClient promotionGoodsClient;

  @Override

  public void execute(Object object) {

  PromotionScriptMsg promotionScriptMsg = (PromotionScriptMsg) object;

  //如果是限时抢购促销活动结束

  if (ScriptOperationTypeEnum.DELETE.equals(

  promotionScriptMsg.getOperationType())) {

  //获取促销活动ID

  Long promotionId = promotionScriptMsg.getPromotionId();

  //获取所有参与活动审核通过的商品集合

  List goodsList =

  this.promotionGoodsClient.getSeckillGoodsList(

  promotionId, SeckillGoodsApplyStatusEnum.PASS.value());

  //清除促销活动脚本信息

  this.promotionScriptClient.deleteCacheScript(promotionId, goodsList);

  this.logger.debug("促销活动[" + promotionScriptMsg.getPromotionName()

  + "]结束,id=[" + promotionId + "]");

  }

  }

  }

  @Service

  public class SeckillScriptManagerImpl implements SeckillScriptManager {

  @Override

  public void deleteCacheScript(Long promotionId, List goodsList) {

  //如果参与促销活动的商品集合不为空并且集合长度不等于0

  if (goodsList != null && goodsList.size() != 0) {

  //需要批量更新的缓存数据集合

  Map> updateCacheMap = new HashMap<>();

  //需要批量删除的缓存key集合

  List delKeyList = new ArrayList<>();

  for (SeckillApplyDO goods : goodsList) {

  //缓存key

  String cacheKey = CachePrefix.SKU_PROMOTION.getPrefix()

  + goods.getSkuId();

  //从缓存中读取促销脚本缓存

  List scriptCacheList =

  (List) cache.get(cacheKey);

  if (scriptCacheList != null && scriptCacheList.size() != 0) {

  //循环促销脚本缓存数据集合

  for (PromotionScriptVO script : scriptCacheList) {

  //如果脚本数据的促销活动信息与当前修改的促销活动信息一致,那么就将此信息删除

  if (PromotionTypeEnum.SECKILL.name().

  equals(script.getPromotionType())

  && script.getPromotionId().intValue()

  == promotionId.intValue()) {

  scriptCacheList.remove(script);

  break;

  }

  }

  if (scriptCacheList.size() == 0) {

  delKeyList.add(cacheKey);

  } else {

  updateCacheMap.put(cacheKey, scriptCacheList);

  }

  }

  }

  cache.multiDel(delKeyList);

  cache.multiSet(updateCacheMap);

  }

  }

  }

限时抢购促销活动脚本引擎模板文件—single_promotion.ftl

  <#--

  验证促销活动是否在有效期内

  @param promotionActive 活动信息对象(内置常量)

  .startTime 获取开始时间

  .endTime 活动结束时间

  @param $currentTime 当前时间(变量)

  @returns {boolean}

  -->

  function validTime(){

  if (${promotionActive.startTime} <= $currentTime && $currentTime <= ${promotionActive.endTime}) {

  return true;

  }

  return false;

  }

  <#--活动金额计算@param promotionActive 活动信息对象(内置常量)

  .price 商品促销活动价格@param $sku 商品SKU信息对象(变量)

  .$num 商品数量@returns {*}-->

  function countPrice() {

  var resultPrice = $sku.$num * ${promotionActive.price};

  return resultPrice < 0 ? 0 : resultPrice.toString();

  }

  上述就是所有关于限时抢购促销活动的代码设计的内容,有任何问题,欢迎咨询在线客户或给我们留言。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

后台-系统设置-扩展变量-手机广告位-内容正文底部
留言与评论(共有 0 条评论)
   
验证码: