Merge remote-tracking branch 'origin/master'

This commit is contained in:
sin 2019-04-16 10:15:11 +08:00
commit 371eba5537
17 changed files with 445 additions and 29 deletions

View File

@ -6,6 +6,20 @@
<img :src="thumb"> <img :src="thumb">
</van-swipe-item> </van-swipe-item>
</van-swipe> </van-swipe>
<!-- TODO 这里需要优化下芋艿 -->
<div class="limit-dising-banner">
<div class="row no-wrap flex-center limit-price">
<span class="font-13 pusht">¥</span><span class="price">2.8</span>
<div class="pushl">
<div><del>¥14</del></div>
<div><span class="tag">限时抢购</span></div>
</div>
</div>
<div class="counting">
<p>距离结束仅剩</p>
<div class="row no-wrap flex-center counting-clock" style="display: block;"><span class="num">71</span><i class="wxIcon wxIcon-colon"></i><span class="num">42</span><i class="wxIcon wxIcon-colon"></i><span class="num">02</span></div>
</div>
</div>
<van-cell-group> <van-cell-group>
<van-cell> <van-cell>

View File

@ -22,6 +22,11 @@
<artifactId>product-service-api</artifactId> <artifactId>product-service-api</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>promotion-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>javax.validation</groupId> <groupId>javax.validation</groupId>

View File

@ -1,10 +1,7 @@
package cn.iocoder.mall.order.api; package cn.iocoder.mall.order.api;
import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.order.api.bo.CalcOrderPriceBO; import cn.iocoder.mall.order.api.bo.*;
import cn.iocoder.mall.order.api.bo.CartBO;
import cn.iocoder.mall.order.api.bo.CartItemBO;
import cn.iocoder.mall.order.api.bo.OrderCreateBO;
import cn.iocoder.mall.order.api.dto.CalcOrderPriceDTO; import cn.iocoder.mall.order.api.dto.CalcOrderPriceDTO;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -90,6 +87,8 @@ public interface CartService {
*/ */
CommonResult<CalcOrderPriceBO> calcOrderPrice(CalcOrderPriceDTO calcOrderPriceDTO); CommonResult<CalcOrderPriceBO> calcOrderPrice(CalcOrderPriceDTO calcOrderPriceDTO);
CommonResult<CalcSkuPriceBO> calcSkuPrice(Integer skuId);
/** /**
* 获得购物车明细 * 获得购物车明细
* *

View File

@ -1,6 +1,7 @@
package cn.iocoder.mall.order.api.bo; package cn.iocoder.mall.order.api.bo;
import cn.iocoder.mall.product.api.bo.ProductSkuDetailBO; import cn.iocoder.mall.product.api.bo.ProductSkuDetailBO;
import cn.iocoder.mall.promotion.api.bo.PromotionActivityBO;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -35,8 +36,11 @@ public class CalcOrderPriceBO {
@Accessors(chain = true) @Accessors(chain = true)
public static class ItemGroup { public static class ItemGroup {
// TODO 优惠活动 /**
private Object activity; * 优惠活动
*/
// TODO 芋艿目前只会有满减送的情况未来有新的促销方式可能需要改成数组
private PromotionActivityBO activity;
/** /**
* 商品数组 * 商品数组
*/ */
@ -56,6 +60,16 @@ public class CalcOrderPriceBO {
* 购买数量 * 购买数量
*/ */
private Integer buyQuantity; private Integer buyQuantity;
/**
* 优惠活动
*/
private PromotionActivityBO activity;
/**
* 费用
*
* TODO 芋艿这里先偷懒postageTotal 字段用不到
*/
private Fee fee;
} }

View File

@ -0,0 +1,31 @@
package cn.iocoder.mall.order.api.bo;
import cn.iocoder.mall.promotion.api.bo.PromotionActivityBO;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 计算商品 SKU 价格结果 BO
*/
@Data
@Accessors(chain = true)
public class CalcSkuPriceBO {
/**
* 满减送促销活动
*/
private PromotionActivityBO fullPrivilege;
/**
* 电视和折扣促销活动
*/
private PromotionActivityBO timeLimitedDiscount;
/**
* 原价格单位
*/
private Integer originalPrice;
/**
* 最终价格单位
*/
private Integer presentPrice;
}

View File

@ -4,10 +4,7 @@ import cn.iocoder.common.framework.constant.CommonStatusEnum;
import cn.iocoder.common.framework.util.ServiceExceptionUtil; import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.order.api.CartService; import cn.iocoder.mall.order.api.CartService;
import cn.iocoder.mall.order.api.bo.CalcOrderPriceBO; import cn.iocoder.mall.order.api.bo.*;
import cn.iocoder.mall.order.api.bo.CartBO;
import cn.iocoder.mall.order.api.bo.CartItemBO;
import cn.iocoder.mall.order.api.bo.OrderCreateBO;
import cn.iocoder.mall.order.api.constant.CartItemStatusEnum; import cn.iocoder.mall.order.api.constant.CartItemStatusEnum;
import cn.iocoder.mall.order.api.constant.OrderErrorCodeEnum; import cn.iocoder.mall.order.api.constant.OrderErrorCodeEnum;
import cn.iocoder.mall.order.api.dto.CalcOrderPriceDTO; import cn.iocoder.mall.order.api.dto.CalcOrderPriceDTO;
@ -190,6 +187,11 @@ public class CartServiceImpl implements CartService {
return CommonResult.success(calcOrderPriceBO); return CommonResult.success(calcOrderPriceBO);
} }
@Override
public CommonResult<CalcSkuPriceBO> calcSkuPrice(Integer skuId) {
return null;
}
@Override @Override
public CommonResult<CartBO> details(Integer userId) { public CommonResult<CartBO> details(Integer userId) {
return null; return null;

View File

@ -0,0 +1,17 @@
package cn.iocoder.mall.promotion.api;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.bo.PromotionActivityBO;
import java.util.Collection;
import java.util.List;
public interface PromotionActivityService {
CommonResult<List<PromotionActivityBO>> getPromotionActivityListBySpuId(Integer spuId,
Collection<Integer> activityStatuses);
CommonResult<List<PromotionActivityBO>> getPromotionActivityListBySpuIds(Collection<Integer> spuIds,
Collection<Integer> activityStatuses);
}

View File

@ -0,0 +1,134 @@
package cn.iocoder.mall.promotion.api.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
import java.util.Set;
@Data
@Accessors(chain = true)
public class PromotionActivityBO {
/**
* 活动编号
*/
private Integer id;
/**
* 活动标题
*/
private String title;
/**
* 活动类型
*
* 参见 {@link cn.iocoder.mall.promotion.api.constant.PromotionActivityTypeEnum} 枚举
*/
private Integer type;
/**
* 活动状态
*
* 参见 {@link cn.iocoder.mall.promotion.api.constant.PromotionActivityStatusEnum} 枚举
*/
private Integer status;
/**
* 匹配的商品 SPU 编号
*/
private Set<Integer> spuIds;
/**
* 限制折扣
*/
@Data
@Accessors(chain = true)
public static class TimeLimitedDiscount {
/**
* 商品折扣
*/
@Data
@Accessors(chain = true)
public static class Item {
/**
* 商品 SPU 编号
*/
private Integer spuId;
/**
* 优惠类型
*/
private Integer preferentialType;
/**
* 优惠值
*/
private Integer preferentialValue;
}
/**
* 每人每种限购多少
*
* quota = 0 表示不限购
*/
private Integer quota;
/**
* 商品折扣数组
*/
private List<Item> items;
}
/**
* 满减送
*/
@Data
@Accessors(chain = true)
public static class FullPrivilege {
/**
* 优惠
*/
@Data
@Accessors(chain = true)
public static class Privilege {
/**
* 满足类型
*
* 1 - 金额
* 2 - 件数
*/
private Integer meetType;
/**
* 满足值
*/
private Integer meetValue;
/**
* 优惠类型
*/
private Integer preferentialType;
/**
* 优惠值
*/
private Integer preferentialValue;
}
/**
* 可用范围的类型
*
* 参见 {@link cn.iocoder.mall.promotion.api.constant.RangeTypeEnum} 枚举
* 暂时只用 所有可用 + PRODUCT_INCLUDE_PRT
*/
private Integer rangeType;
/**
* 指定可用商品列表
*/
private List<Integer> rangeValues;
/**
* 优惠数组
*/
private List<Privilege> privileges;
}
}

View File

@ -4,13 +4,16 @@ import cn.iocoder.common.framework.core.IntArrayValuable;
import java.util.Arrays; import java.util.Arrays;
public enum CouponTemplatePreferentialTypeEnum implements IntArrayValuable { /**
* 优惠类型枚举
*/
public enum PreferentialTypeEnum implements IntArrayValuable {
PRICE(1, "代金卷"), PRICE(1, "代金卷"),
DISCOUNT(2, "折扣卷"), DISCOUNT(2, "折扣卷"),
; ;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponTemplatePreferentialTypeEnum::getValue).toArray(); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PreferentialTypeEnum::getValue).toArray();
/** /**
* *
@ -21,7 +24,7 @@ public enum CouponTemplatePreferentialTypeEnum implements IntArrayValuable {
*/ */
private final String name; private final String name;
CouponTemplatePreferentialTypeEnum(Integer value, String name) { PreferentialTypeEnum(Integer value, String name) {
this.value = value; this.value = value;
this.name = name; this.name = name;
} }

View File

@ -0,0 +1,41 @@
package cn.iocoder.mall.promotion.api.constant;
/**
* 促销活动状态枚举
*/
public enum PromotionActivityStatusEnum {
WAIT(10, "未开始"),
RUN(20, "进行中"),
END(30, "已结束"),
/**
* 1. WAITRUNEND 可以转换成 INVALID 状态
* 2. INVALID 只可以转换成 DELETED 状态
*/
INVALID(40, "已撤销"),
DELETED(50, "已删除"),
;
/**
* 状态值
*/
private final Integer value;
/**
* 状态名
*/
private final String name;
PromotionActivityStatusEnum(Integer value, String name) {
this.value = value;
this.name = name;
}
public Integer getValue() {
return value;
}
public String getName() {
return name;
}
}

View File

@ -5,8 +5,8 @@ package cn.iocoder.mall.promotion.api.constant;
*/ */
public enum PromotionActivityTypeEnum { public enum PromotionActivityTypeEnum {
LIMIT_DISCOUNT(1, "限时折扣"), TIME_LIMITED_DISCOUNT(1, "限时折扣"),
MEET_REDUCE(2, "满减送"), FULL_PRIVILEGE(2, "满减送"),
; ;
/** /**

View File

@ -4,7 +4,7 @@ import cn.iocoder.common.framework.core.IntArrayValuable;
import java.util.Arrays; import java.util.Arrays;
public enum CouponTemplateRangeTypeEnum implements IntArrayValuable { public enum RangeTypeEnum implements IntArrayValuable {
ALL(10, "所有可用"), ALL(10, "所有可用"),
PRODUCT_INCLUDE_PRT(20, "部分商品可用,或指定商品可用"), PRODUCT_INCLUDE_PRT(20, "部分商品可用,或指定商品可用"),
@ -13,7 +13,7 @@ public enum CouponTemplateRangeTypeEnum implements IntArrayValuable {
CATEGORY_EXCLUDE_PRT(31, "部分分类不可用,或指定分类可用"), CATEGORY_EXCLUDE_PRT(31, "部分分类不可用,或指定分类可用"),
; ;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponTemplateRangeTypeEnum::getValue).toArray(); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(RangeTypeEnum::getValue).toArray();
/** /**
* *
@ -24,7 +24,7 @@ public enum CouponTemplateRangeTypeEnum implements IntArrayValuable {
*/ */
private final String name; private final String name;
CouponTemplateRangeTypeEnum(Integer value, String name) { RangeTypeEnum(Integer value, String name) {
this.value = value; this.value = value;
this.name = name; this.name = name;
} }

View File

@ -2,8 +2,8 @@ package cn.iocoder.mall.promotion.api.dto;
import cn.iocoder.common.framework.validator.InEnum; import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.mall.promotion.api.constant.CouponTemplateDateTypeEnum; import cn.iocoder.mall.promotion.api.constant.CouponTemplateDateTypeEnum;
import cn.iocoder.mall.promotion.api.constant.CouponTemplatePreferentialTypeEnum; import cn.iocoder.mall.promotion.api.constant.PreferentialTypeEnum;
import cn.iocoder.mall.promotion.api.constant.CouponTemplateRangeTypeEnum; import cn.iocoder.mall.promotion.api.constant.RangeTypeEnum;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Length;
@ -70,7 +70,7 @@ public class CouponCardTemplateAddDTO {
* 31-部分PART部分分类不可用或指定分类可用 * 31-部分PART部分分类不可用或指定分类可用
*/ */
@NotNull(message = "可用范围的类型不能为空") @NotNull(message = "可用范围的类型不能为空")
@InEnum(value = CouponTemplateRangeTypeEnum.class, message = "可用范围的类型必须在 {value}") @InEnum(value = RangeTypeEnum.class, message = "可用范围的类型必须在 {value}")
private Integer rangeType; private Integer rangeType;
/** /**
* 指定商品 / 分类列表使用逗号分隔商品编号 * 指定商品 / 分类列表使用逗号分隔商品编号
@ -115,7 +115,7 @@ public class CouponCardTemplateAddDTO {
* 2-折扣卷 * 2-折扣卷
*/ */
@NotNull(message = "优惠类型不能为空") @NotNull(message = "优惠类型不能为空")
@InEnum(value = CouponTemplatePreferentialTypeEnum.class, message = "优惠类型必须在 {value}") @InEnum(value = PreferentialTypeEnum.class, message = "优惠类型必须在 {value}")
private Integer preferentialType; private Integer preferentialType;
/** /**
* 优惠金额单位 * 优惠金额单位

View File

@ -1,7 +1,7 @@
package cn.iocoder.mall.promotion.api.dto; package cn.iocoder.mall.promotion.api.dto;
import cn.iocoder.common.framework.validator.InEnum; import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.mall.promotion.api.constant.CouponTemplateRangeTypeEnum; import cn.iocoder.mall.promotion.api.constant.RangeTypeEnum;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Length;
@ -69,7 +69,7 @@ public class CouponCardTemplateUpdateDTO {
* 31-部分PART部分分类不可用或指定分类可用 * 31-部分PART部分分类不可用或指定分类可用
*/ */
@NotNull(message = "可用范围的类型不能为空") @NotNull(message = "可用范围的类型不能为空")
@InEnum(value = CouponTemplateRangeTypeEnum.class, message = "可用范围的类型必须在 {value}") @InEnum(value = RangeTypeEnum.class, message = "可用范围的类型必须在 {value}")
private Integer rangeType; private Integer rangeType;
/** /**
* 指定商品 / 分类列表使用逗号分隔商品编号 * 指定商品 / 分类列表使用逗号分隔商品编号

View File

@ -4,6 +4,9 @@ import cn.iocoder.common.framework.dataobject.BaseDO;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.util.Date;
import java.util.List;
/** /**
* 促销活动 DO * 促销活动 DO
*/ */
@ -21,7 +24,160 @@ public class PromotionActivityDO extends BaseDO {
private String title; private String title;
/** /**
* 活动类型 * 活动类型
*
* 参见 {@link cn.iocoder.mall.promotion.api.constant.PromotionActivityTypeEnum} 枚举
*/ */
private Integer type; private Integer activityType;
// /**
// * 促销类型
// * // TODO 芋艿 https://jos.jd.com/api/complexTemplate.htm?webPamer=promotion_v_o&groupName=%E4%BF%83%E9%94%80API&id=54&restName=jingdong.seller.promotion.list&isMulti=false 促销类型可选值单品促销1赠品促销4套装促销6总价促销10
// */
// private Integer promotionType;
/**
* 活动状态
*
* 参见 {@link cn.iocoder.mall.promotion.api.constant.PromotionActivityStatusEnum} 枚举
*/
private Integer status;
/**
* 开始时间
*/
private Date startTime;
/**
* 结束时间
*/
private Date endTime;
/**
* 失效时间
*/
private Date invalidTime;
/**
* 删除时间
*/
private Date deleteTime;
/**
* 限制折扣字符串使用 JSON 序列化成字符串存储
*/
private String timeLimitedDiscount;
/**
* 满减送字符串使用 JSON 序列化成字符串存储
*/
private String fullPrivilege;
/**
* 限制折扣
*/
@Data
@Accessors(chain = true)
public static class TimeLimitedDiscount {
/**
* 商品折扣
*/
@Data
@Accessors(chain = true)
public static class Item {
/**
* 商品 SPU 编号
*/
private Integer spuId;
/**
* 优惠类型
*/
private Integer preferentialType;
/**
* 优惠值
*/
private Integer preferentialValue;
}
/**
* 每人每种限购多少
*
* quota = 0 表示不限购
*/
private Integer quota;
/**
* 商品折扣数组
*/
private List<Item> items;
}
/**
* 满减送
*/
@Data
@Accessors(chain = true)
public static class FullPrivilege {
/**
* 优惠
*/
@Data
@Accessors(chain = true)
public static class Privilege {
/**
* 满足类型
*
* 1 - 金额
* 2 - 件数
*/
private Integer meetType;
/**
* 满足值
*/
private Integer meetValue;
/**
* 优惠类型
*/
private Integer preferentialType;
/**
* 优惠值
*/
private Integer preferentialValue;
// /**
// * 是否包邮
// */
// private Boolean isPostage;
// /**
// * 积分
// */
// private Integer score;
// /**
// * 优惠劵分组编号
// */
// private Integer couponTemplateId;
// /**
// * 优惠劵数量
// */
// private Integer couponNum;
// /**
// * 赠品编号
// */
// private Integer presentId;
}
/**
* 可用范围的类型
*
* 参见 {@link cn.iocoder.mall.promotion.api.constant.RangeTypeEnum} 枚举
* 暂时只用 所有可用 + PRODUCT_INCLUDE_PRT
*/
private Integer rangeType;
/**
* 指定可用商品列表
*/
private List<Integer> rangeValues;
/**
* 优惠数组
*/
private List<Privilege> privileges;
}
} }

View File

@ -158,14 +158,14 @@ public class CouponServiceImpl implements CouponService {
private CommonResult<Boolean> checkCouponTemplatePreferentialType(Integer preferentialType, Integer percentOff, private CommonResult<Boolean> checkCouponTemplatePreferentialType(Integer preferentialType, Integer percentOff,
Integer priceOff, Integer priceAvailable) { Integer priceOff, Integer priceAvailable) {
if (CouponTemplatePreferentialTypeEnum.PRICE.getValue().equals(preferentialType)) { if (PreferentialTypeEnum.PRICE.getValue().equals(preferentialType)) {
if (priceOff == null) { if (priceOff == null) {
return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "优惠金额不能为空"); return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "优惠金额不能为空");
} }
if (priceOff >= priceAvailable) { if (priceOff >= priceAvailable) {
return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "优惠金额不能d大于等于使用金额门槛"); return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "优惠金额不能d大于等于使用金额门槛");
} }
} else if (CouponTemplatePreferentialTypeEnum.DISCOUNT.getValue().equals(preferentialType)) { } else if (PreferentialTypeEnum.DISCOUNT.getValue().equals(preferentialType)) {
if (percentOff == null) { if (percentOff == null) {
return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "折扣百分比不能为空"); return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "折扣百分比不能为空");
} }