跳到主要内容

一、功能说明

1、团购促销活动属于平台发布的促销活动,商家选择商品参与,平台来进行审核。

2、平台在同一时间段内只允许创建一个团购促销活动。

3、团购活动开始后,不允许修改和删除活动信息。

4、平台添加团购活动时,报名截止日期不可以大于活动开始日期。

5、平台可以添加团购分类,发布团购活动时,要选择团购分类,用户可以在团购商品页面按照团购分类筛选商品。

团购分类不等于商品分类,是团购活动商品独立的分类。

团购分类只支持一级分类,平台可以设置分类的排序,排序值越大位置越靠后显示。

6、商家在选择商品参与团购活动时,不可以批量添加,只能一个一个的添加。

7、商家选择商品参与团购活动后,需要平台进行审核。

审核通过可正常售卖;审核不通过的,商家可以编辑商品信息后,再次申请审核。

如果团购活动开始了,商家不允许再次编辑或删除参与团购活动的商品。

8、团购活动属于单品促销活动,用户在购物车中可以选择取消活动,取消后价格恢复为原商品价格。

二、数据库设计

1、表结构设计

  1. 团购促销活动表—es_groupbuy_active

    字段名类型与长度说明
    act_idbigint(20)主键ID
    act_namevarchar(255)活动名称
    start_timebigint(20)活动开始时间(存放的是以秒为单位的时间戳)
    end_timebigint(20)活动结束时间(存放的是以秒为单位的时间戳)
    join_end_timebigint(20)活动报名截止时间(存放的是以秒为单位的时间戳)
    add_timebigint(20)活动创建时间
    act_tag_idint(10)团购活动标签ID(预留字段,暂时无用)
    goods_numint(10)参与团购活动的商品数量
    delete_reasonvarchar(255)团购活动删除原因
    delete_timebigint(20)团购活动删除时间
    delete_namevarchar(50)团购活动删除人
    delete_statusvarchar(20)是否删除 DELETED:已删除,NORMAL:正常
  1. 团购商品分类表—es_groupbuy_cat

    字段名类型与长度说明
    cat_idbigint(20)主键ID
    parent_idbigint(20)父分类ID
    cat_namevarchar(255)分类名称
    cat_pathvarchar(255)分类结构目录(预留字段,暂时无用)
    cat_orderint(8)排序,数值越小排序越靠前
  1. 团购商品表—es_groupbuy_goods

    字段名类型与长度说明
    gb_idbigint(20)主键ID
    sku_idbigint(20)商品SKU(关联es_goods_sku表)
    act_idbigint(20)团购活动ID(关联es_groupbuy_active表)
    cat_idbigint(20)团购分类ID(关联es_groupbuy_cat表)
    area_idint(11)已废弃字段
    gb_namevarchar(1000)团购名称
    gb_titlevarchar(1000)团购标题
    goods_namevarchar(255)商品名称
    goods_idbigint(20)商品ID(关联es_goods表)
    original_pricedecimal(20,2)商品原价
    pricedecimal(20,2)商品团购价
    img_urlvarchar(255)团购商品图片
    goods_numint(11)商品总数
    visual_numint(11)虚拟购买数量
    limit_numint(11)限购数量(预留字段,暂时无用)
    buy_numint(11)已团购数量
    view_numint(11)浏览数量(预留字段,暂时无用)
    remarklongtext团购介绍
    gb_statusint(1)团购商品状态 0:待审核,1:通过审核,2:未通过审核
    add_timebigint(20)商品参与团购活动时间
    wap_thumbnailvarchar(255)WAP端商品缩略图(预留字段,暂时无用)
    thumbnailvarchar(255)PC端商品缩略图(预留字段,暂时无用)
    seller_idbigint(20)商品所属商家(关联es_shop表)
    seller_namevarchar(20)商家名称
    specslongtext商品规格信息
  1. 团购商品库存日志表—es_groupbuy_quantity_log

    字段名类型与长度说明
    log_idbigint(20)主键ID
    order_snvarchar(20)订单编号(关联es_order表)
    goods_idbigint(20)商品ID(关联es_goods表)
    quantityint(10)团购商品售空数量
    op_timebigint(20)操作时间
    log_typevarchar(20)日志类型 BUY:售出,CANCEL:取消
    reasonvarchar(200)操作原因
    gb_idbigint(20)团购活动ID

2、表关联说明

  • 团购相关表与表关联图

    image-20201030154044773

  • 团购相关表与表之间的关联字段对照

    团购促销活动表(es_groupbuy_active)促销活动商品表(es_promotion_goods)
    act_idactivity_id
    无字段,促销类型值为GROUPBUYpromotion_type
    团购促销活动表(es_groupbuy_active)团购商品表(es_groupbuy_goods)
    act_idact_id
    团购商品表(es_groupbuy_goods)团购分类表(es_groupbuy_cat)
    cat_idcat_id
    团购商品表(es_groupbuy_goods)团购商品库存日志表(es_groupbuy_quantity_log)
    act_idgb_id
    goods_idgoods_id

三、缓存设计

1、平台在发布团购促销活动时,在将促销活动信息入库的同时,也会将信息放入缓存中。

缓存key值为:{STOREID_GROUP_BUY_KEY}活动ID。

缓存value值为:GroupbuyActiveVO.java这个实体对象信息。

2、团购促销活动脚本引擎

  • 脚本引擎缓存结构:

    团购促销活动的促销脚本引擎缓存结构只有一种:SKU级别的缓存结构。

  • 脚本引擎生成与删除时机:

    • 生成:团购活动开始时生成。

      如果活动开始后,还有没被平台审核的商品,那么审核商品通过后也会重新生成脚本。

    • 删除:团购活动结束时删除。

关于促销脚本引擎缓存结构可参考《促销活动脚本引擎生成架构》这篇文档。

四、代码设计

1、接口调用流程图

  • 平台发布促销活动

    image-20201102114028745

  • 商家选择商品参与团购活动

    image-20201102112052251

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

    image-20201102114955591

2、相关代码展示

  • 新增团购活动

    @RestController
    @RequestMapping("/admin/promotion/group-buy-actives")
    @Api(description = "团购活动表相关API")
    @Validated
    public class GroupbuyActiveManagerController {

    @ApiOperation(value = "添加团购活动表", response = GroupbuyActiveDO.class)
    @ApiImplicitParam(name = "activeDO", value = "团购信息", required = true,
    dataType = "GroupbuyActiveDO", paramType = "body")
    @PostMapping
    public GroupbuyActiveDO add(@ApiIgnore @Valid @RequestBody GroupbuyActiveDO activeDO) {

    this.verifyParam(activeDO.getStartTime(), activeDO.getEndTime(),
    activeDO.getJoinEndTime());
    this.groupbuyActiveManager.add(activeDO);
    return activeDO;
    }
    }
    @Service
    public class GroupbuyActiveManagerImpl extends AbstractPromotionRuleManagerImpl implements GroupbuyActiveManager {

    @Override
    @Transactional(propagation = Propagation.REQUIRED,
    rollbackFor = {RuntimeException.class})
    public GroupbuyActiveDO add(GroupbuyActiveDO groupbuyActive) {
    //参数验证 1、活动起始时间必须大于当前时间 2、活动开始时间是否大于活动结束时间
    PromotionValid.paramValid(groupbuyActive.getStartTime(),
    groupbuyActive.getEndTime(), 1, null);
    //验证活动时间 同一时间只能有一个活动生效
    this.verifyTime(groupbuyActive.getStartTime(),
    groupbuyActive.getEndTime(), PromotionTypeEnum.GROUPBUY, null);
    //验证活动名称是否重复
    this.verifyName(groupbuyActive.getActName(), false, 0L);

    //设置添加时间为当前时间
    groupbuyActive.setAddTime(DateUtil.getDateline());
    //设置删除状态为正常未删除
    groupbuyActive.setDeleteStatus(DeleteStatusEnum.NORMAL.value());
    //团购活动入库操作
    groupbuyActiveMapper.insert(groupbuyActive);
    //获取团购活动主键ID
    Long id = groupbuyActive.getActId();

    //启用延时任务创建促销活动脚本信息
    PromotionScriptMsg promotionScriptMsg = new PromotionScriptMsg();
    //设置活动ID
    promotionScriptMsg.setPromotionId(id);
    //设置活动名称
    promotionScriptMsg.setPromotionName(groupbuyActive.getActName());
    //设置活动类型
    promotionScriptMsg.setPromotionType(PromotionTypeEnum.GROUPBUY);
    //设置脚本操作类型为创建脚本
    promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.CREATE);
    //设置活动结束时间
    promotionScriptMsg.setEndTime(groupbuyActive.getEndTime());
    //创建延时任务key值
    String uniqueKey = "{TIME_TRIGGER_" + PromotionTypeEnum.GROUPBUY.name()
    + "}_" + id;
    //发送消息创建延时任务
    timeTrigger.add(TimeExecute.GROUPBUY_SCRIPT_EXECUTER,
    promotionScriptMsg, groupbuyActive.getStartTime(), uniqueKey);

    return groupbuyActive;
    }

    }
  • 商家选择商品参与团购活动

    @RestController
    @RequestMapping("/seller/promotion/group-buy-goods")
    @Api(description = "团购商品相关API")
    @Validated
    public class GroupbuyGoodsSellerController {

    @ApiOperation(value = "添加团购商品", response = GroupbuyGoodsDO.class)
    @ApiImplicitParam(name = "groupbuyGoods", value = "团购商品信息",
    required = true, dataType = "GroupbuyGoodsDO", paramType = "body")
    @PostMapping
    public GroupbuyGoodsDO add(@Valid @RequestBody GroupbuyGoodsDO groupbuyGoods) {
    groupbuyGoods.setAddTime(DateUtil.getDateline());
    this.verifyParam(groupbuyGoods);
    Seller seller = UserContext.getSeller();
    groupbuyGoods.setSellerId(seller.getSellerId());
    groupbuyGoods.setSellerName(seller.getSellerName());
    groupbuyGoods.setBuyNum(0);
    groupbuyGoods.setViewNum(0);
    this.groupbuyGoodsManager.add(groupbuyGoods);

    return groupbuyGoods;
    }

    }
    @Service
    public class GroupbuyGoodsManagerImpl extends AbstractPromotionRuleManagerImpl implements GroupbuyGoodsManager {
    @Override
    @Transactional(propagation = Propagation.REQUIRED,
    rollbackFor = {Exception.class, RuntimeException.class})
    public GroupbuyGoodsDO add(GroupbuyGoodsDO goodsDO) {
    //获取团购活动信息并校验
    GroupbuyActiveDO activeDO = groupbuyActiveManager.getModel(goodsDO.getActId());
    if (activeDO == null) {
    throw new ServiceException(PromotionErrorCode.E400.code(), "参与的活动不存在");
    }
    //如果团购价格 大于等于商品原价,则抛出异常
    if (goodsDO.getPrice() >= goodsDO.getOriginalPrice()) {
    throw new ServiceException(PromotionErrorCode.E400.code(),
    "参与活动的商品促销价格不得大于或等于商品原价");
    }
    //校验限购数量是否超过商品总数
    if (goodsDO.getLimitNum() > goodsDO.getGoodsNum()) {
    throw new ServiceException(PromotionErrorCode.E400.code(),
    "商品限购数量不能大于商品总数");
    }

    //新建查询条件包装器
    QueryWrapper<PromotionGoodsDO> wrapper = new QueryWrapper<>();
    //以促销活动类型为限时抢购为条件查询
    wrapper.eq("promotion_type", PromotionTypeEnum.SECKILL.name());
    //以商品SKU为查询条件
    wrapper.eq("sku_id", goodsDO.getSkuId());
    //按(活动开始时间小于等于当前活动开始时间 并且 活动结束时间大于等于当前活动开始时间)或者(活动开始时间小于等于当前活动结束时间 并且 活动结束时间大于等于当前活动结束时间)
    //或者 (活动开始时间小于等于当前活动开始时间 并且 活动结束时间大于等于当前活动结束时间)或者 活动开始时间大于等于当前活动开始时间 并且 活动结束时间小于等于当前活动结束时间)
    wrapper.and(i -> i.le("start_time", activeDO.getStartTime())
    .ge("end_time", activeDO.getStartTime())
    .or().le("start_time", activeDO.getEndTime())
    .ge("end_time", activeDO.getEndTime())
    .or().le("start_time", activeDO.getStartTime())
    .ge("end_time", activeDO.getEndTime())
    .or().ge("start_time", activeDO.getStartTime())
    .le("end_time", activeDO.getEndTime()));

    //获取当前商品参与限时抢购活动的数量
    int count = promotionGoodsMapper.selectCount(wrapper);
    if (count > 0) {
    throw new ServiceException(PromotionErrorCode.E400.code(), "该商品已经在重叠的时间段参加了限时抢购活动,不能参加团购活动");
    }

    //新建促销商品集合
    List<PromotionGoodsDTO> goodsDTOList = new ArrayList<>();
    //新建促销商品对象DTO
    PromotionGoodsDTO goodsDTO = new PromotionGoodsDTO();
    //设置商品ID
    goodsDTO.setGoodsId(goodsDO.getGoodsId());
    //设置商品图片
    goodsDTO.setThumbnail(goodsDO.getThumbnail());
    //设置商品名称
    goodsDTO.setGoodsName(goodsDO.getGoodsName());
    //将商品放入集合中
    goodsDTOList.add(goodsDTO);
    //检测活动商品规则
    this.verifyRule(goodsDTOList);

    //设置团购商品审核状态为待审核
    goodsDO.setGbStatus(GroupBuyGoodsStatusEnum.PENDING.status());
    //获取商品sku
    Long skuId = goodsDO.getSkuId();
    //查询存储相关的规格
    GoodsSkuVO sku = goodsClient.getSkuFromCache(skuId);
    //设置团购商品规格信息
    goodsDO.setSpecs(sku.getSpecs());
    //团购商品信息入库
    groupbuyGoodsMapper.insert(goodsDO);
    return goodsDO;
    }
    }
  • 平台审核参与团购活动的商品

    @RestController
    @RequestMapping("/admin/promotion/group-buy-actives")
    @Api(description = "团购活动表相关API")
    @Validated
    public class GroupbuyActiveManagerController {
    @ApiOperation(value = "批量审核商品")
    @PostMapping(value = "/batch/audit")
    public void batchAudit(@Valid @RequestBody GroupbuyAuditParam param) {
    this.groupbuyActiveManager.batchAuditGoods(param);
    }
    }
    @Service
    public class GroupbuyActiveManagerImpl extends AbstractPromotionRuleManagerImpl implements GroupbuyActiveManager {
    @Override
    @Transactional(propagation = Propagation.REQUIRED,
    rollbackFor = {RuntimeException.class, Exception.class})
    public void batchAuditGoods(GroupbuyAuditParam param) {
    //校验活动id
    if (param.getActId() == null || param.getActId() == 0) {
    throw new ServiceException(PromotionErrorCode.E400.code(), "参数活动ID不正确");
    }
    //校验活动商品
    if (param.getGbIds() == null || param.getGbIds().length == 0) {
    throw new ServiceException(GoodsErrorCode.E301.code(), "请选择要审核的商品");
    }
    //校验审核状态
    if (param.getStatus() == null) {
    throw new ServiceException(PromotionErrorCode.E400.code(),
    "参数审核状态值不能为空");
    }
    //校验参数审核状态值是否服务规范
    if (param.getStatus().intValue() != 1 && param.getStatus().intValue() != 2) {
    throw new ServiceException(PromotionErrorCode.E400.code(),
    "参数审核状态值不正确");
    }

    //获取团购活动信息
    GroupbuyActiveDO activeDO = this.getModel(param.getActId());
    //审核状态 true:审核通过,false:审核未通过
    boolean auditStatus = param.getStatus().intValue()
    == GroupBuyGoodsStatusEnum.APPROVED.status();
    //参与团购促销活动并且已被平台审核通过的商品集合
    List<PromotionGoodsDO> goodsList = new ArrayList<>();
    //循环团购商品ID集合
    for (Long gbId : param.getGbIds()) {
    //读取团购商品信息并校验
    GroupbuyGoodsDO goodsDO = this.groupbuyGoodsManager.getModel(gbId);
    if (goodsDO == null) {
    throw new ServiceException(PromotionErrorCode.E400.code(),
    "商品【" + goodsDO.getGoodsName() + "】不存在");
    }
    if (goodsDO.getGbStatus().intValue() != 0) {
    throw new ServiceException(PromotionErrorCode.E400.code(),
    "商品【" + goodsDO.getGoodsName()
    + "】不是可以审核的状态");
    }

    //修改状态
    this.groupbuyGoodsManager.updateStatus(gbId, param.getStatus());

    //如果通过审核
    if (auditStatus) {
    //新建修改条件包装器
    UpdateWrapper<GroupbuyActiveDO> wrapper = new UpdateWrapper<>();
    //以团购活动ID为修改条件,修改参与团购商品数量+1
    wrapper.setSql("goods_num=goods_num+1").eq("act_id", param.getActId());
    //修改已参与团购活动的商品数量
    groupbuyActiveMapper.update(new GroupbuyActiveDO(), wrapper);

    //商品集合
    List<PromotionGoodsDO> goodsDTOList = new ArrayList<>();
    //初始化促销活动商品数据
    PromotionGoodsDO promotion = new PromotionGoodsDO();
    //设置活动名称
    promotion.setTitle(activeDO.getActName());
    //设置商品ID
    promotion.setGoodsId(goodsDO.getGoodsId());
    //设置商品sku
    promotion.setSkuId(goodsDO.getSkuId());
    //设置促销活动类型为团购活动
    promotion.setPromotionType(PromotionTypeEnum.GROUPBUY.name());
    //设置活动ID
    promotion.setActivityId(activeDO.getActId());
    //设置参与促销活动的商品数量
    promotion.setNum(activeDO.getGoodsNum());
    //设置商品价格
    promotion.setPrice(goodsDO.getPrice());
    //设置商家ID
    promotion.setSellerId(goodsDO.getSellerId());
    //设置活动开始时间
    promotion.setStartTime(activeDO.getStartTime());
    //设置活动结束时间
    promotion.setEndTime(activeDO.getEndTime());
    goodsDTOList.add(promotion);

    //初始化活动信息DTO
    PromotionDetailDTO detailDTO = new PromotionDetailDTO();
    //设置活动ID
    detailDTO.setActivityId(param.getActId());
    //设置活动开始时间
    detailDTO.setStartTime(activeDO.getStartTime());
    //设置活动结束时间
    detailDTO.setEndTime(activeDO.getEndTime());
    //设置促销活动类型为团购活动
    detailDTO.setPromotionType(PromotionTypeEnum.GROUPBUY.name());
    //设置活动名称
    detailDTO.setTitle(activeDO.getActName());

    //入库到活动商品对照表
    this.promotionGoodsManager.addAndCheck(goodsDTOList, detailDTO);

    //将此商品加入延迟加载队列,到指定的时间将索引价格变成最新的优惠价格
    PromotionPriceDTO promotionPriceDTO = new PromotionPriceDTO();
    promotionPriceDTO.setGoodsId(goodsDO.getGoodsId());
    promotionPriceDTO.setPrice(goodsDO.getPrice());
    //检测开始时间和结束时间
    PromotionValid.paramValid(detailDTO.getStartTime(),
    detailDTO.getEndTime(), 1, null);
    timeTrigger.add(TimeExecute.PROMOTION_EXECUTER,
    promotionPriceDTO, activeDO.getStartTime(), null);
    //此活动结束后将索引的优惠价格重置为0
    promotionPriceDTO.setPrice(0.0);
    timeTrigger.add(TimeExecute.PROMOTION_EXECUTER,
    promotionPriceDTO, activeDO.getEndTime(), null);

    //构建要生成脚本的促销商品数据集合
    PromotionGoodsDO promotionGoodsDO = new PromotionGoodsDO();
    promotionGoodsDO.setSkuId(promotion.getSkuId());
    promotionGoodsDO.setPrice(goodsDO.getPrice());
    goodsList.add(promotionGoodsDO);

    }
    }

    //获取当前时间
    long currTime = DateUtil.getDateline();
    //活动是否在进行中
    boolean activeStatus = activeDO.getStartTime().longValue()
    <= currTime && activeDO.getEndTime().longValue() >= currTime;
    //如果当前团购活动正在进行中并且是商品审核通过的操作
    if (activeStatus && auditStatus) {
    //先删除已存在的脚本信息
    this.groupbuyScriptManager.deleteCacheScript(param.getActId(), goodsList);
    //创建审核通过的商品团购促销活动脚本信息
    this.groupbuyScriptManager.createCacheScript(param.getActId(), goodsList);

    }
    }
    }
  • 团购促销活动脚本引擎生成

    @Component("groupBuyScriptTimeTriggerExecuter")
    public class GroupBuyScriptTimeTriggerExecuter implements TimeTriggerExecuter {
    @Override
    public void execute(Object object) {

    PromotionScriptMsg promotionScriptMsg = (PromotionScriptMsg) object;

    //获取促销活动ID
    Long promotionId = promotionScriptMsg.getPromotionId();

    //获取参与团购活动的所有商品信息集合
    List<PromotionGoodsDO> goodsList =
    this.promotionGoodsClient.getPromotionGoods(
    promotionId, PromotionTypeEnum.GROUPBUY.name());

    //如果是团购促销活动开始生效
    if (ScriptOperationTypeEnum.CREATE.equals(
    promotionScriptMsg.getOperationType())) {
    //创建脚本信息
    this.promotionScriptClient.createGroupBuyCacheScript(
    promotionId, goodsList);

    //开启活动后,立马设置一个关闭的流程
    promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.DELETE);

    String uniqueKey = "{TIME_TRIGGER_"
    + promotionScriptMsg.getPromotionType().name() + "}_" + promotionId;

    timeTrigger.add(TimeExecute.GROUPBUY_SCRIPT_EXECUTER, promotionScriptMsg,
    promotionScriptMsg.getEndTime(), uniqueKey);

    this.logger.debug("促销活动[" + promotionScriptMsg.getPromotionName()
    + "]开始,id=[" + promotionId + "]");

    } else {
    //删除脚本信息
    this.promotionScriptClient.deleteGroupBuyCacheScript(
    promotionId, goodsList);

    this.logger.debug("促销活动[" + promotionScriptMsg.getPromotionName()
    + "]结束,id=[" + promotionId + "]");
    }

    }
    }
    @Service
    public class GroupbuyScriptManagerImpl implements GroupbuyScriptManager {
    @Override
    public void createCacheScript(Long promotionId, List<PromotionGoodsDO> goodsList) {
    //如果参与团购促销活动的商品集合不为空并且集合长度不为0
    if (goodsList != null && goodsList.size() != 0) {
    //获取团购活动详细信息
    GroupbuyActiveDO groupbuyActiveDO
    = this.groupbuyActiveManager.getModel(promotionId);

    //批量放入缓存的数据集合
    Map<String, List<PromotionScriptVO>> cacheMap = new HashMap<>();

    //循环参与团购活动的商品集合,将脚本放入缓存中
    for (PromotionGoodsDO goods : goodsList) {

    //缓存key
    String cacheKey = CachePrefix.SKU_PROMOTION.getPrefix()
    + goods.getSkuId();

    //获取拼团活动脚本信息
    PromotionScriptVO scriptVO = new PromotionScriptVO();

    //渲染并读取团购促销活动脚本信息
    String script = renderScript(groupbuyActiveDO.getStartTime().toString(),
    groupbuyActiveDO.getEndTime().toString(),
    goods.getPrice());

    scriptVO.setPromotionScript(script);
    scriptVO.setPromotionId(promotionId);
    scriptVO.setPromotionType(PromotionTypeEnum.GROUPBUY.name());
    scriptVO.setIsGrouped(false);
    scriptVO.setPromotionName("团购");
    scriptVO.setSkuId(goods.getSkuId());

    //从缓存中读取脚本信息
    List<PromotionScriptVO> scriptList = (List<PromotionScriptVO>)
    cache.get(cacheKey);
    if (scriptList == null) {
    scriptList = new ArrayList<>();
    }

    scriptList.add(scriptVO);

    cacheMap.put(cacheKey, scriptList);
    }

    //将sku促销脚本数据批量放入缓存中
    cache.multiSet(cacheMap);
    }
    }

    /**
    * 渲染并读取团购促销活动脚本信息
    * @param startTime 活动开始时间
    * @param endTime 活动结束时间
    * @param price 限时抢购商品价格
    * @return
    */
    private String renderScript(String startTime, String endTime, Double price) {
    Map<String, Object> model = new HashMap<>();

    Map<String, Object> 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;
    }
    }
  • 团购促销活动脚本引擎模板文件—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();
    }