Authored by wujiexiang

Merge branch 'dev-promotion' into test6.8.2

Showing 41 changed files with 1039 additions and 184 deletions
... ... @@ -71,4 +71,9 @@ public interface CacheClient {
public <T> T get(RedisKeyBuilder key, Class<T> clazz);
public <T> List<T> range(RedisKeyBuilder redisKeyBuilder, Class<T> clazz, long start, long end);
public <T> void rightPushAll(RedisKeyBuilder redisKeyBuilder, Collection<T> values, long timeout);
}
... ...
... ... @@ -4,6 +4,9 @@ import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.alibaba.fastjson.JSONObject;
import com.yoho.core.redis.cluster.operations.nosync.YHListOperations;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
... ... @@ -31,6 +34,9 @@ public class RedisGwCacheClient implements CacheClient {
@Redis("gwNoSyncRedis")
private YHHashOperations hashOperations;
@Redis("gwNoSyncRedis")
private YHListOperations listOperations;
public <T> Map<String, T> mget(List<RedisKeyBuilder> keys, Class<T> clazz) {
long beginTime = System.currentTimeMillis();
... ... @@ -81,6 +87,63 @@ public class RedisGwCacheClient implements CacheClient {
}
public <T> void rightPushAll(RedisKeyBuilder redisKeyBuilder, Collection<T> values, long timeout) {
// 如果是空列表,直接返回
if (CollectionUtils.isEmpty(values)) {
return;
}
try {
Collection<String> strValues = new ArrayList<String>(10);
for (T t : values) {
String strValue = JSON.toJSONString(t);
if (org.apache.commons.lang3.StringUtils.isEmpty(strValue)) {
continue;
}
strValues.add(strValue);
}
listOperations.rightPushAll(redisKeyBuilder, strValues);
} catch (Exception e) {
LOGGER.warn("rightPushAll redis list operation failed. key is {}", redisKeyBuilder, e);
}
try{
redis.longExpire(redisKeyBuilder, timeout, TimeUnit.SECONDS);
}catch (Exception e){
try{
redis.longExpire(redisKeyBuilder, timeout, TimeUnit.SECONDS);
}catch (Exception e1){
LOGGER.warn("rightPushAll expires redis list operation failed. key is {}", redisKeyBuilder, e1);
}
}
}
public <T> List<T> range(RedisKeyBuilder redisKeyBuilder, Class<T> clazz, long start, long end) {
try {
List<String> strList = listOperations.range(redisKeyBuilder, start, end);
LOGGER.info("range redis value. value size {}", strList == null ? 0 : strList.size());
if (CollectionUtils.isEmpty(strList)) {
return null;
}
// 遍历,组装对象
List<T> list = new ArrayList<T>(10);
for (String str : strList) {
list.add(JSONObject.parseObject(str, clazz));
}
return list;
} catch (Exception e) {
LOGGER.warn("get redis value operation failed. key is {}", redisKeyBuilder, e);
}
return null;
}
/**
* @param key
* @param value
... ...
package com.yohoufo.dal.order;
import com.yohoufo.dal.order.model.OrderCoupon;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Created by jiexiang.wu on 2018/11/20.
*/
public interface OrderCouponMapper {
int insert(OrderCoupon orderCoupon);
List<OrderCoupon> selectByUidAndOrderCode(@Param("uid") int uid, @Param("orderCode") long orderCode);
}
... ...
... ... @@ -15,6 +15,11 @@ public class BuyerOrderGoods {
private BigDecimal goodsAmount;
/**
* 优惠券减免金额
*/
private BigDecimal couponCutAmount;
public Integer getUid() {
return uid;
}
... ... @@ -62,4 +67,12 @@ public class BuyerOrderGoods {
public void setGoodsAmount(BigDecimal goodsAmount) {
this.goodsAmount = goodsAmount;
}
public BigDecimal getCouponCutAmount() {
return couponCutAmount;
}
public void setCouponCutAmount(BigDecimal couponCutAmount) {
this.couponCutAmount = couponCutAmount;
}
}
\ No newline at end of file
... ...
package com.yohoufo.dal.order.model;
/**
* Created by jiexiang.wu on 2018/11/20.
*/
public class OrderCoupon {
private int uid;
private long orderCode;
private String couponCode;
private int createTime;
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public long getOrderCode() {
return orderCode;
}
public void setOrderCode(long orderCode) {
this.orderCode = orderCode;
}
public String getCouponCode() {
return couponCode;
}
public void setCouponCode(String couponCode) {
this.couponCode = couponCode;
}
public int getCreateTime() {
return createTime;
}
public void setCreateTime(int createTime) {
this.createTime = createTime;
}
}
... ...
... ... @@ -2,6 +2,9 @@ package com.yohoufo.dal.promotion;
import com.yohoufo.dal.promotion.model.CouponProductLimit;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface CouponProductLimitMapper {
int deleteByPrimaryKey(Integer id);
... ... @@ -12,6 +15,8 @@ public interface CouponProductLimitMapper {
CouponProductLimit selectByPrimaryKey(Integer id);
List<CouponProductLimit> selectByCouponIds(@Param("list") List<Integer> couponList);
int updateByPrimaryKeySelective(CouponProductLimit record);
int updateByPrimaryKey(CouponProductLimit record);
... ...
package com.yohoufo.dal.promotion;
import com.yohoufo.dal.promotion.model.CouponCancelUseDO;
import com.yohoufo.dal.promotion.model.CouponUseDO;
import com.yohoufo.dal.promotion.model.UserCoupon;
import org.apache.ibatis.annotations.Param;
... ... @@ -17,6 +19,16 @@ public interface UserCouponMapper {
UserCoupon selectByPrimaryKey(Integer id);
int updateCoupon2Use(CouponUseDO couponUseDO);
int updateCouponNotUse(CouponCancelUseDO cancelUseDO);
List<UserCoupon> selectByUidAndCouponCodes(@Param("uid") Integer uid, @Param("couponCodes") List<String> couponCode);
List<UserCoupon> selectUsableCouponByUid(@Param("uid") Integer uid, @Param("now") int now);
int selectCntUsableCouponByUid(@Param("uid") Integer uid, @Param("now") int now);
... ...
package com.yohoufo.dal.promotion.model;
import java.util.List;
public class CouponCancelUseDO {
private int uid;
private List<String> couponCodes;
private long orderCode;
public CouponCancelUseDO(int uid, List<String> couponCodes, long orderCode) {
this.uid = uid;
this.couponCodes = couponCodes;
this.orderCode = orderCode;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public List<String> getCouponCodes() {
return couponCodes;
}
public void setCouponCodes(List<String> couponCodes) {
this.couponCodes = couponCodes;
}
public long getOrderCode() {
return orderCode;
}
public void setOrderCode(long orderCode) {
this.orderCode = orderCode;
}
}
... ...
... ... @@ -7,7 +7,7 @@ public class CouponProductLimit {
private Byte limitType;
private Integer productSkn;
private Integer productId;
public Integer getId() {
return id;
... ... @@ -33,11 +33,11 @@ public class CouponProductLimit {
this.limitType = limitType;
}
public Integer getProductSkn() {
return productSkn;
public Integer getProductId() {
return productId;
}
public void setProductSkn(Integer productSkn) {
this.productSkn = productSkn;
public void setProductId(Integer productId) {
this.productId = productId;
}
}
\ No newline at end of file
... ...
package com.yohoufo.dal.promotion.model;
import java.util.List;
public class CouponUseDO {
private int uid;
private List<String> couponCodes;
private long orderCode;
private int useTime;
private CouponUseDO(Builder builder) {
setUid(builder.uid);
setCouponCodes(builder.couponCodes);
setOrderCode(builder.orderCode);
setUseTime(builder.useTime);
}
public static Builder newBuilder() {
return new Builder();
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public List<String> getCouponCodes() {
return couponCodes;
}
public void setCouponCodes(List<String> couponCodes) {
this.couponCodes = couponCodes;
}
public long getOrderCode() {
return orderCode;
}
public void setOrderCode(long orderCode) {
this.orderCode = orderCode;
}
public int getUseTime() {
return useTime;
}
public void setUseTime(int useTime) {
this.useTime = useTime;
}
public static final class Builder {
private int uid;
private List<String> couponCodes;
private long orderCode;
private int useTime;
private Builder() {
}
public Builder uid(int val) {
uid = val;
return this;
}
public Builder couponCodes(List<String> val) {
couponCodes = val;
return this;
}
public Builder orderCode(long val) {
orderCode = val;
return this;
}
public Builder useTime(int val) {
useTime = val;
return this;
}
public CouponUseDO build() {
return new CouponUseDO(this);
}
}
}
... ...
... ... @@ -8,6 +8,7 @@
<result column="skup" jdbcType="INTEGER" property="skup" />
<result column="goods_price" jdbcType="DECIMAL" property="goodsPrice" />
<result column="goods_amount" jdbcType="DECIMAL" property="goodsAmount" />
<result column="coupons_cut_amount" jdbcType="DECIMAL" property="couponCutAmount" />
</resultMap>
<sql id="Base_Column_List">
id, order_code, skup, goods_price, goods_amount, uid
... ... @@ -83,6 +84,9 @@
<if test="uid != null">
uid,
</if>
<if test="couponCutAmount != null">
coupons_cut_amount,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="orderCode != null">
... ... @@ -100,6 +104,9 @@
<if test="uid != null">
#{uid,jdbcType=INTEGER},
</if>
<if test="couponCutAmount != null">
#{couponCutAmount,jdbcType=DECIMAL},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.yohoufo.dal.order.model.BuyerOrderGoods">
... ...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yohoufo.dal.order.OrderCouponMapper">
<resultMap id="BaseResultMap" type="com.yohoufo.dal.order.model.OrderCoupon">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="uid" jdbcType="INTEGER" property="uid"/>
<result column="order_code" jdbcType="BIGINT" property="orderCode"/>
<result column="coupon_code" jdbcType="VARCHAR" property="couponCode"/>
<result column="create_time" jdbcType="INTEGER" property="createTime"/>
</resultMap>
<sql id="Base_Column_List">
id, uid, order_code, coupon_code, create_time
</sql>
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.yohoufo.dal.order.model.OrderCoupon" useGeneratedKeys="true">
insert into order_coupon (uid, order_code, coupon_code,create_time)
values (#{uid,jdbcType=INTEGER}, #{orderCode,jdbcType=BIGINT}, #{couponCode,jdbcType=VARCHAR}, #{createTime,jdbcType=INTEGER})
</insert>
<select id="selectByUidAndOrderCode" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from buyer_order
where order_code = #{orderCode,jdbcType=BIGINT}
and uid = #{uid,jdbcType=INTEGER}
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -5,10 +5,10 @@
<id column="id" property="id" jdbcType="INTEGER" />
<result column="coupon_id" property="couponId" jdbcType="INTEGER" />
<result column="limit_type" property="limitType" jdbcType="TINYINT" />
<result column="product_skn" property="productSkn" jdbcType="INTEGER" />
<result column="product_id" property="productId" jdbcType="INTEGER" />
</resultMap>
<sql id="Base_Column_List" >
id, coupon_id, limit_type, product_skn
id, coupon_id, limit_type, product_id
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
... ... @@ -22,9 +22,9 @@
</delete>
<insert id="insert" parameterType="com.yohoufo.dal.promotion.model.CouponProductLimit" >
insert into coupon_product_limit (id, coupon_id, limit_type,
product_skn)
product_id)
values (#{id,jdbcType=INTEGER}, #{couponId,jdbcType=INTEGER}, #{limitType,jdbcType=TINYINT},
#{productSkn,jdbcType=INTEGER})
#{productId,jdbcType=INTEGER})
</insert>
<insert id="insertSelective" parameterType="com.yohoufo.dal.promotion.model.CouponProductLimit" >
insert into coupon_product_limit
... ... @@ -38,8 +38,8 @@
<if test="limitType != null" >
limit_type,
</if>
<if test="productSkn != null" >
product_skn,
<if test="productId != null" >
product_id,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
... ... @@ -52,8 +52,8 @@
<if test="limitType != null" >
#{limitType,jdbcType=TINYINT},
</if>
<if test="productSkn != null" >
#{productSkn,jdbcType=INTEGER},
<if test="productId != null" >
#{productId,jdbcType=INTEGER},
</if>
</trim>
</insert>
... ... @@ -66,8 +66,8 @@
<if test="limitType != null" >
limit_type = #{limitType,jdbcType=TINYINT},
</if>
<if test="productSkn != null" >
product_skn = #{productSkn,jdbcType=INTEGER},
<if test="productId != null" >
product_id = #{productId,jdbcType=INTEGER},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
... ... @@ -76,7 +76,21 @@
update coupon_product_limit
set coupon_id = #{couponId,jdbcType=INTEGER},
limit_type = #{limitType,jdbcType=TINYINT},
product_skn = #{productSkn,jdbcType=INTEGER}
product_id = #{productId,jdbcType=INTEGER}
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectByCouponIds" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from coupon_product_limit
where 1=1
AND coupon_id IN
<foreach item="id" index="index" collection="list"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -28,6 +28,20 @@
</select>
<select id="selectByUidAndCouponCodes" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user_coupon
where uid = #{uid}
AND coupon_code IN
<foreach collection="couponCodes" item="couponCode" open="(" separator="," close=")">
#{couponCode,jdbcType=VARCHAR}
</foreach>
</select>
<select id="selectByUidAndToken" resultMap="BaseResultMap" >
select
<include refid="Base_Column_List" />
... ... @@ -44,12 +58,12 @@
from user_coupon
where uid = #{uid,jdbcType=INTEGER}
<include refid="CouponsLogsQueryUsable" />
order by end_time
</select>
<sql id="CouponsLogsQueryUsable" >
<!-- 在有效时间范围内 -->
and <![CDATA[ start_time < #{now, jdbcType=INTEGER} ]]>
and <![CDATA[ end_time > #{now, jdbcType=INTEGER} ]]>
<!-- 未使用-->
and status = 0
... ... @@ -200,4 +214,42 @@
create_time = #{createTime,jdbcType=INTEGER}
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateCouponNotUse" parameterType="com.yohoufo.dal.promotion.model.CouponCancelUseDO">
update user_coupon
<set>
status = 0,use_time = 0, order_code =0
</set>
where uid= #{uid}
and order_code= #{orderCode}
and status = 1
and coupon_code in
<foreach collection="couponCodes" index="index" item="couponCode"
open="(" separator="," close=")">
#{couponCode}
</foreach>
</update>
<update id="updateCoupon2Use" parameterType="com.yohoufo.dal.promotion.model.CouponUseDO">
update user_coupon
<set>
<if test="orderCode != null">
order_code= #{orderCode},
</if>
<if test="useTime != null">
use_time= #{useTime},
</if>
status=1
</set>
where uid= #{uid}
and coupon_code in
<foreach collection="couponCodes" index="index" item="couponCode"
open="(" separator="," close=")">
#{couponCode}
</foreach>
and status = 0
and order_code= 0
</update>
</mapper>
\ No newline at end of file
... ...
... ... @@ -78,5 +78,9 @@
<groupId>com.yoho.ufo.model</groupId>
<artifactId>promotion-ufo-model</artifactId>
</dependency>
<dependency>
<groupId>com.yoho.core</groupId>
<artifactId>yoho-core-transaction</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
... ...
... ... @@ -31,4 +31,9 @@ public class ChargeResult {
*/
private double finalAmount;
public ChargeResult() {
//init
this.couponPayResult = CouponPayResult.builder().build();
}
}
... ...
... ... @@ -32,4 +32,9 @@ public class CouponPayResult {
*/
private double couponAmount = 0;
/**
* 券数量
*/
private int couponCount = 0;
}
... ...
package com.yohoufo.order.model.bo;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Builder;
import java.math.BigDecimal;
/**
* Created by jiexiang.wu on 2018/11/20.
*/
@Data
@ToString
@Builder
public class CouponBo {
//券code
private String couponCode;
//券金额
private BigDecimal couponAmount;
}
... ...
... ... @@ -3,11 +3,13 @@ package com.yohoufo.order.model.dto;
import com.yoho.service.model.response.UserAddressRspBO;
import com.yohoufo.order.model.AddressInfo;
import com.yohoufo.order.model.bo.CouponBo;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Builder;
import java.math.BigDecimal;
import java.util.List;
@Data
@Builder
... ... @@ -39,4 +41,9 @@ public class OrderBuilder {
AddressInfo addressInfo;
AddressInfo hiddenAddressInfo;
/**
* 使用的优惠券
*/
CouponBo couponBo;
}
... ...
... ... @@ -142,6 +142,11 @@ public class OrderDetailInfo {
String feePrice;
/**
* 优惠券金额
*/
String couponCutPrice;
/**
* 实付金额
*/
String realPayPrice;
... ...
... ... @@ -150,6 +150,7 @@ public abstract class AbsOrderDetailService implements IOrderDetailService{
OrderDetailInfo.PriceInfo priceInfo = OrderDetailInfo.PriceInfo.builder()
.goodPrice(buyerOrderGoods.getGoodsPrice() == null ? "0" : buyerOrderGoods.getGoodsPrice().toPlainString() )
.feePrice(buyerOrder.getShipFee() == null ? "0" : buyerOrder.getShipFee().toPlainString())
.couponCutPrice(buyerOrderGoods.getCouponCutAmount() == null ? "0":buyerOrderGoods.getCouponCutAmount().toPlainString())
.realPayPrice(buyerOrder.getAmount() == null ? "0" : buyerOrder.getAmount().toPlainString())
.build();
orderDetailInfo.setPriceInfo(priceInfo);
... ...
... ... @@ -23,6 +23,7 @@ import com.yohoufo.order.charge.model.CouponMatchResult;
import com.yohoufo.order.event.BuyerCancelEvent;
import com.yohoufo.order.event.NotPaidNoticeEvent;
import com.yohoufo.order.model.AddressInfo;
import com.yohoufo.order.model.bo.CouponBo;
import com.yohoufo.order.model.dto.BuyerOrderSubmitResult;
import com.yohoufo.order.model.dto.OrderBuilder;
import com.yohoufo.order.model.request.ShoppingRequest;
... ... @@ -209,7 +210,7 @@ public class ShoppingServiceImpl implements IShoppingService {
ChargeResult chargeResult = chargeContext.getChargeResult();
ComputeResponse response = new ComputeResponse();
response.setCouponInfo(shoppingSupport.getCouponInfo(chargeResult));
response.setCouponInfo(couponSupport.getCouponInfo(chargeResult));
response.setPromotionFormulaList(shoppingSupport.getPromotionFormula(chargeResult));
response.setAmount(MathUtils.formatStr(chargeResult.getFinalAmount()));
... ... @@ -272,6 +273,10 @@ public class ShoppingServiceImpl implements IShoppingService {
.channelNo(shoppingRequest.getChannelNo())
.amount(BigDecimal.valueOf(chargeResult.getFinalAmount()))
.shipFee(BigDecimal.valueOf(chargeResult.getExpressDeliveryAmount()))
.couponBo(CouponBo.builder().couponCode(chargeResult.getCouponPayResult().getCouponCode())
.couponAmount(BigDecimal.valueOf(chargeResult.getCouponPayResult().getCouponAmount()))
.build()
)
.hiddenAddressInfo(hiddenAddress)
.addressInfo(addressInfo)
.clientType(shoppingRequest.getClientType())
... ...
... ... @@ -3,6 +3,7 @@ package com.yohoufo.order.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.yoho.core.common.utils.DateUtil;
import com.yoho.core.dal.datasource.annotation.Database;
import com.yoho.core.transaction.annoation.YHTransaction;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohoufo.dal.order.*;
... ... @@ -15,6 +16,7 @@ import com.yohoufo.order.constants.MetaKey;
import com.yohoufo.order.model.dto.BuyerOrderSubmitResult;
import com.yohoufo.order.model.dto.OrderBuilder;
import com.yohoufo.order.service.ISubmitOrderService;
import com.yohoufo.order.service.proxy.CouponProxyService;
import com.yohoufo.order.service.proxy.ProductProxyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
... ... @@ -34,13 +36,21 @@ public class SubmitOrderServiceImpl implements ISubmitOrderService {
@Autowired
private ProductProxyService productProxyService;
@Autowired
private CouponProxyService couponProxyService;
@YHTransaction
public BuyerOrderSubmitResult doSumbitOrder(OrderBuilder orderBuilder){
BuyerOrderSubmitResult result = null;
try {
// 减库存
if(productProxyService.subtractStorage(orderBuilder.getProductId(), orderBuilder.getSkup())) {
//使用优惠券
if (orderBuilder.getCouponBo().getCouponAmount().doubleValue() > 0) {
couponProxyService.orderUseCoupon(orderBuilder.getUid(), orderBuilder.getOrderCode(), orderBuilder.getCouponBo());
}
// 创建订单
return orderCreateService.createOrder(orderBuilder);
}
... ... @@ -91,7 +101,8 @@ public class SubmitOrderServiceImpl implements ISubmitOrderService {
@Autowired
BuyerOrderMetaMapper buyerOrderMetaMapper;
@Autowired
OrderCouponMapper orderCouponMapper;
@Autowired
private ProductProxyService productProxyService;
... ... @@ -110,6 +121,7 @@ public class SubmitOrderServiceImpl implements ISubmitOrderService {
* 3.插入订单 表buyer_order
* 4.插入订单商品 buyer_order_goods
* 5.插入收货地址 buyer_order_meta
* 6.插入优惠券 order_coupon
*/
// 1.表seller_order_goods ==> 不可售
... ... @@ -127,6 +139,9 @@ public class SubmitOrderServiceImpl implements ISubmitOrderService {
// 5.插入收货地址 buyer_order_meta 买家收货地址
insertOrderMeta(orderBuilder);
//6.插入优惠券 order_coupon
insertOrderCouponIfNeed(orderBuilder);
BuyerOrderSubmitResult result = BuyerOrderSubmitResult.builder()
.orderCode(orderBuilder.getOrderCode())
.sellerOrder(sellerOrder).sellerOrderGoods(sellerOrderGoods).build();
... ... @@ -159,6 +174,7 @@ public class SubmitOrderServiceImpl implements ISubmitOrderService {
buyerOrderGoods.setGoodsPrice(sellerOrderGoods.getGoodsPrice());
buyerOrderGoods.setGoodsAmount(sellerOrderGoods.getGoodsPrice());
buyerOrderGoods.setUid(orderBuilder.getUid());
buyerOrderGoods.setCouponCutAmount(orderBuilder.getCouponBo().getCouponAmount());
buyerOrderGoodsMapper.insertSelective(buyerOrderGoods);
}
... ... @@ -181,6 +197,18 @@ public class SubmitOrderServiceImpl implements ISubmitOrderService {
buyerOrderMapper.insert(buyerOrder);
}
private void insertOrderCouponIfNeed(OrderBuilder orderBuilder) {
if (orderBuilder.getCouponBo().getCouponAmount().doubleValue() > 0) {
OrderCoupon orderCoupon = new OrderCoupon();
orderCoupon.setUid(orderBuilder.getUid());
orderCoupon.setOrderCode(orderBuilder.getOrderCode());
orderCoupon.setCouponCode(orderBuilder.getCouponBo().getCouponCode());
orderCoupon.setCreateTime(DateUtil.getCurrentTimeSecond());
orderCouponMapper.insert(orderCoupon);
}
}
private SellerOrder selectSellerOrder(OrderBuilder orderBuilder) {
SellerOrder sellerOrder = sellerOrderMapper.selectBySkup(orderBuilder.getSkup());
return sellerOrder;
... ...
package com.yohoufo.order.service.proxy;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.yoho.core.transaction.Compensator;
import com.yoho.core.transaction.annoation.TxCompensatable;
import com.yoho.core.transaction.annoation.TxCompensateArgs;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohobuy.ufo.model.promotion.UserCouponsBo;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.common.caller.UfoServiceCaller;
import com.yohoufo.order.model.bo.CouponBo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
... ... @@ -11,7 +24,13 @@ import java.util.List;
* Created by jiexiang.wu on 2018/11/19.
*/
@Service
public class CouponProxyService {
public class CouponProxyService implements Compensator {
private final static Logger logger = LoggerFactory.getLogger(CouponProxyService.class);
@Autowired
private UfoServiceCaller serviceCaller;
/**
* 查询用户可以使用的券
*
... ... @@ -54,4 +73,75 @@ public class CouponProxyService {
userCouponsBo.setEndTime(1546275661L);
return Lists.newArrayList(userCouponsBo);
}
/**
* 使用优惠券,有补偿功能
*
* @param uid
* @param orderCode
* @param coupon
*/
@TxCompensatable(value = CouponProxyService.class)
public void orderUseCoupon(@TxCompensateArgs("uid") int uid, @TxCompensateArgs("orderCode") long orderCode,
@TxCompensateArgs("couponBo") CouponBo coupon) {
logger.info("[{}] request to use coupon,couponBo is {}", orderCode, coupon);
ApiResponse resp = serviceCaller.call("app.coupons.use", uid, orderCode, Lists.newArrayList(coupon.getCouponCode()));
if (getResultFromApiResponse(resp) == false) {
logger.warn("[{}] use couponBo fail,coupons is {}", orderCode, coupon);
throw new ServiceException(ServiceError.PROMOTION_COUPON_IS_NOT_VAILD);
}
logger.info("[{}] use coupon success", orderCode);
}
/**
* 取消券使用
*
* @param uid
* @param orderCode
* @param coupon
*/
public void orderCancelCoupon(int uid, long orderCode, CouponBo coupon) {
logger.info("[{}] request to cancel coupon,couponBo is {}", orderCode, coupon);
ApiResponse resp = serviceCaller.call("app.coupons.cancel", uid, orderCode, Lists.newArrayList(coupon.getCouponCode()));
if (getResultFromApiResponse(resp) == false) {
logger.warn("[{}] cancel couponBo fail,coupons is {}", orderCode, coupon);
throw new ServiceException(ServiceError.PROMOTION_COUPON_IS_NOT_VAILD);
}
logger.info("[{}] cancel coupon success", orderCode);
}
private boolean getResultFromApiResponse(ApiResponse resp) {
if (resp == null) {
return false;
}
if (resp.getCode() != 200 || resp.getData() == null) {
return false;
}
return (boolean) resp.getData();
}
/**
* 补偿
*
* @param message json格式的字符串
*/
@Override
public void compensate(String message) {
logger.info("CouponProxyService begin to compensate : {}", message);
int uid = 0;
long orderCode = 0;
CouponBo couponBo = null;
try {
JSONObject json = JSON.parseObject(message);
uid = json.getIntValue("uid");
orderCode = json.getLongValue("orderCode");
couponBo = json.getObject("coupons", CouponBo.class);
} catch (Exception ex) {
logger.warn("parse message to json error,message is {}", message, ex);
}
orderCancelCoupon(uid, orderCode, couponBo);
logger.info("CouponProxyService compensate end,uid is {},orderCode is {}", uid, orderCode);
}
}
... ...
... ... @@ -3,7 +3,10 @@ package com.yohoufo.order.service.support;
import com.google.common.collect.Lists;
import com.yohobuy.ufo.model.order.constants.OrderConstant;
import com.yohobuy.ufo.model.promotion.UserCouponsBo;
import com.yohoufo.order.charge.model.ChargeResult;
import com.yohoufo.order.charge.model.CouponMatchResult;
import com.yohoufo.order.charge.model.CouponPayResult;
import com.yohoufo.order.model.response.CouponInfo;
import com.yohoufo.order.model.response.ShoppingCoupon;
import com.yohoufo.order.utils.DateUtil;
import com.yohoufo.order.utils.MathUtils;
... ... @@ -48,4 +51,18 @@ public class CouponSupport {
return result;
}
/**
* 使用的优惠券信息
* @param chargeResult
* @return
*/
public CouponInfo getCouponInfo(ChargeResult chargeResult) {
CouponPayResult couponPayResult = chargeResult.getCouponPayResult();
return CouponInfo.builder().couponCode(couponPayResult.getCouponCode())
.couponTitle(couponPayResult.getCouponTitle())
.couponAmountStr(MathUtils.formatCurrencyStr(couponPayResult.getCouponAmount()))
.couponCount(couponPayResult.getCouponCount())
.build();
}
}
... ...
package com.yohoufo.order.service.support;
import com.fasterxml.jackson.databind.deser.DataFormatReaders;
import com.google.common.collect.Lists;
import com.yohoufo.common.helper.ImageUrlAssist;
import com.yohoufo.common.utils.BigDecimalHelper;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohobuy.ufo.model.order.constants.OrderConstant;
import com.yohoufo.order.charge.ChargeContext;
import com.yohoufo.order.charge.model.ChargeResult;
import com.yohoufo.order.charge.model.CouponPayResult;
import com.yohoufo.order.model.response.CouponInfo;
import com.yohoufo.order.model.response.CouponInfo;
import com.yohoufo.order.model.response.GoodsInfo;
import com.yohoufo.order.model.response.PaymentResponse;
import com.yohoufo.order.model.response.PromotionFormula;
... ... @@ -19,7 +14,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
@Service
... ... @@ -98,7 +92,7 @@ public class ShoppingSupport {
//优惠券
CouponPayResult couponPayResult = chargeResult.getCouponPayResult();
if (couponPayResult != null) {
if (couponPayResult.getCouponAmount() > 0) {
PromotionFormula couponFormula = new PromotionFormula();
couponFormula.setPromotion(OrderConstant.COUPON_DESC);
couponFormula.setPromotionAmount(OrderConstant.SUB_SIGN + MathUtils.formatCurrencyStr(couponPayResult.getCouponAmount()));
... ... @@ -133,17 +127,4 @@ public class ShoppingSupport {
return damagesDesc.toString();
}
public CouponInfo getCouponInfo(ChargeResult chargeResult) {
CouponPayResult couponPayResult = chargeResult.getCouponPayResult();
if (couponPayResult == null) {
return null;
}
return CouponInfo.builder().couponCode(couponPayResult.getCouponCode())
.couponTitle(couponPayResult.getCouponTitle())
.couponAmountStr(MathUtils.formatCurrencyStr(couponPayResult.getCouponAmount()))
.couponCount(1)
.build();
}
}
... ...
... ... @@ -16,6 +16,12 @@ public interface ExpiredTime {
/**
* coupon_product_limit ---缓存时间
*/
int COUPON_PRODUCT_LIMIT_CACHE_TIME = 3600;
/**
* 券发放数量缓存
*/
int COUPON_SEND_NUM_CACHE_TIME = 7 * 24 * 3600;
... ...
... ... @@ -9,8 +9,12 @@ public class KeyBuilder {
return RedisKeyBuilder.newInstance().appendFixed("ufo:promotion:coupons:couponToken:").appendVar(couponToken);
}
public static RedisKeyBuilder buildCouponLimitProductCacheKey(Integer couponId) {
return RedisKeyBuilder.newInstance().appendFixed("ufo:promotion:couponLimitProduct:id:").appendVar(couponId);
}
public static RedisKeyBuilder buildCouponTypeCacheKey(int id) {
return RedisKeyBuilder.newInstance().appendFixed("ufo:promotion:coupontype:id:").appendVar(id);
return RedisKeyBuilder.newInstance().appendFixed("ufo:promotion:couponType:id:").appendVar(id);
}
/**
... ...
package com.yohoufo.promotion.common;
public enum CouponUseStatusEnum {
NOT_USED(0, "未使用"),
USED(1, "已使用"),
/**
* 已作废
*
* @使用场景 1、生日礼包最多使用一张其它会作废
* 2、新客礼包最多使用一张它会作废
*/
INVALID(2, "已作废");
/**
* 编码
*/
private int code;
/**
* 描述
*/
private String desc;
CouponUseStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
\ No newline at end of file
... ...
... ... @@ -2,7 +2,6 @@ package com.yohoufo.promotion.controller;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.promotion.model.response.CouponInfo;
import com.yohoufo.promotion.model.response.CouponInfoListBO;
import com.yohoufo.promotion.service.ICouponService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
... ...
package com.yohoufo.promotion.controller;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.promotion.model.response.CouponBo;
import com.yohoufo.promotion.model.response.CouponInfo;
import com.yohoufo.promotion.service.ICouponService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 全部是给订单的接口
*/
@RestController
@RequestMapping(value = "/orderCoupon")
public class OrderCouponController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
ICouponService couponService;
/**
* 使用优惠券(订单使用)
* @param uid
* @param couponCodes
* @param orderCode
* @return
*/
@RequestMapping(params = "method=app.coupons.use")
@ResponseBody
public ApiResponse useCoupon(@RequestParam(value = "uid") Integer uid,
@RequestParam(value = "orderCode") long orderCode,
@RequestParam(value = "couponCodes") List<String> couponCodes) {
logger.info("use coupons, uid: {},couponCodes: {}, orderCode :{}", uid, couponCodes, orderCode);
boolean useSuccess = couponService.useCoupon(uid, couponCodes, orderCode);
logger.info("use coupons, uid: {},couponCodes: {}, orderCode :{},result: {}", uid, couponCodes, orderCode, useSuccess);
return new ApiResponse.ApiResponseBuilder().code(200).data(useSuccess).build();
}
/**
* 使用优惠券(订单退还)
* @param uid
* @param couponCodes
* @param orderCode
* @return
*/
@RequestMapping(params = "method=app.coupons.cancel")
@ResponseBody
public ApiResponse cancelCoupon(@RequestParam(value = "uid") Integer uid,
@RequestParam(value = "orderCode") long orderCode,
@RequestParam(value = "couponCodes") List<String> couponCodes) {
logger.info("cancel coupons, uid: {},couponCodes: {}, orderCode :{}", uid, couponCodes, orderCode);
boolean cancelSuccess = couponService.cancelCoupon(uid, couponCodes, orderCode);
logger.info("cancel coupons, uid: {},couponCodes: {}, orderCode :{},result: {}", uid, couponCodes, orderCode, cancelSuccess);
return new ApiResponse.ApiResponseBuilder().code(200).data(cancelSuccess).build();
}
/**
* 优惠券列表(订单使用)
* @param uid
* @return
*/
@RequestMapping(params = "method=app.coupons.list")
@ResponseBody
public ApiResponse queryUserNoUsedCoupons(@RequestParam(value = "uid") Integer uid) {
logger.info("use coupons, uid: {}", uid);
List<CouponBo> couponBoList = couponService.queryUserNoUsedCoupons(uid);
logger.info("use coupons, uid: {}, size:{}, success", uid, couponBoList.size());
return new ApiResponse.ApiResponseBuilder().code(200).data(couponBoList).build();
}
}
... ...
package com.yohoufo.promotion.controller;
import com.yoho.core.rest.annotation.ServiceDesc;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohobuy.ufo.model.promotion.request.CouponCancelUseReq;
import com.yohobuy.ufo.model.promotion.request.CouponUseReq;
import com.yohobuy.ufo.model.promotion.request.UserCouponListReq;
import com.yohobuy.ufo.model.promotion.UserCouponsListBo;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/**
* Created by jiexiang.wu on 2018/11/19.
* 内部接口
*/
@Controller
@RequestMapping("/userCoupon")
@ServiceDesc(value = "promotion")
public class UserCouponController {
private static Logger logger = LoggerFactory.getLogger(UserCouponController.class);
/**
* 新获取可用的优惠券接口,包括基本信息,以及优惠规则。(供购物车使用)
*
* @param req 包含用户id的请求
* @return
* @see [类、类#方法、类#成员]
*/
@RequestMapping(value = "/getUserAvailableCoupons")
@ResponseBody
public UserCouponsListBo getUserAvailableCoupons(@RequestBody UserCouponListReq req) {
logger.info("queryUserNoUsedCoupons request is {}", req);
if (req == null || (req.getUid() <= 0)) {
logger.warn("queryUserNoUsedCoupons RequestBody is wrong , the request is {} ", req);
throw new ServiceException(ServiceError.PROMOTION_REQUEST_PAREMENT_ERROR);
}
//todo
return null;
}
/**
* 查询并校验优惠券是否能用
* 提供给order模块调用判断优惠券是否可以使用
* 订单使用前调用校验优惠券是否可用
*
* @param req
* @return
*/
@RequestMapping(value = "/checkUseCouponsAndGet")
@ResponseBody
public UserCouponsListBo checkUseCouponsAndGet(@RequestBody UserCouponListReq req) {
logger.info("checkUseCouponsAndGet req is:{}", req);
if (req == null || req.getUid() <= 0 || CollectionUtils.isEmpty(req.getCouponCodes())) {
throw new ServiceException(ServiceError.PROMOTION_REQUEST_PAREMENT_ERROR);
}
//todo
return null;
}
/**
* 订单使用优惠券(订单中心调用)
*
* @param useReq
* @return
*/
@RequestMapping(value = "/orderUseCoupon")
@ResponseBody
public Boolean orderUseCoupon(@RequestBody CouponUseReq useReq) {
logger.info("use coupon request is {}", useReq);
if (useReq.getUid() <= 0 || CollectionUtils.isEmpty(useReq.getCouponCodes()) || useReq.getOrderCode() <= 0) {
logger.info("use coupon request params error {}", useReq);
throw new ServiceException(ServiceError.PROMOTION_REQUEST_PAREMENT_ERROR);
}
// UseCouponBo useCouponBo = new UseCouponBo(useReq.getUid(), useReq.getOrderCode(), useReq.getCouponCodes());
// return iCouponService.useCoupons(useCouponBo);
//todo
return null;
}
/**
* 取消订单优惠券的使用
*
* @param couponOrderCancelUseReq
* @return
*/
@RequestMapping(value = "/cancelCouponUse")
@ResponseBody
public boolean cancelOrderUseCoupon(@RequestBody CouponCancelUseReq couponOrderCancelUseReq) {
int uid = couponOrderCancelUseReq.getUid();
long orderCode = couponOrderCancelUseReq.getOrderCode();
List<String> couponCodes = couponOrderCancelUseReq.getCouponCodes();
if (uid <= 0 || orderCode <= 0 || CollectionUtils.isEmpty(couponCodes)) {
logger.warn("cancel order use coupons req param err:{}", couponOrderCancelUseReq);
throw new ServiceException(ServiceError.PROMOTION_REQUEST_PAREMENT_ERROR);
}
// CancelUseCouponBo cancelUseCouponBo = new CancelUseCouponBo(uid, orderCode, couponCodes);
// return iCouponService.cancelOrderUseCoupon(cancelUseCouponBo);
//todo
return false;
}
}
package com.yohoufo.promotion.convert;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.dal.promotion.model.Coupon;
import com.yohoufo.dal.promotion.model.CouponAndType;
import com.yohoufo.dal.promotion.model.CouponType;
import com.yohoufo.dal.promotion.model.UserCoupon;
import com.yohoufo.dal.promotion.model.*;
import com.yohoufo.promotion.common.ProductLimitType;
import com.yohoufo.promotion.common.UseLimitType;
import com.yohoufo.promotion.common.UserCouponsStatusEnum;
import com.yohoufo.promotion.model.response.CouponInfo;
import com.yohoufo.promotion.model.response.CouponBo;
import java.text.MessageFormat;
import java.util.Arrays;
... ... @@ -16,6 +14,27 @@ import java.util.Arrays;
public class CouponConvert {
public static CouponBo covertCouponBo(UserCoupon userCoupon, Coupon coupon){
CouponBo couponBo = new CouponBo();
couponBo.setUid(userCoupon.getUid());
couponBo.setCouponId(userCoupon.getCouponId());
couponBo.setCouponCode(userCoupon.getCouponCode());
couponBo.setCouponToken(userCoupon.getCouponToken());
couponBo.setCouponType(userCoupon.getCouponType());
couponBo.setCouponAmount(coupon.getCouponAmount());
couponBo.setCouponName(coupon.getCouponName());
couponBo.setProductLimitType(coupon.getProductLimitType());
couponBo.setProductLimitValue(coupon.getProductLimitValue());
couponBo.setUseLimitType(coupon.getUseLimitType());
couponBo.setUseLimitValue(coupon.getUseLimitValue());
return couponBo;
}
/**
* 用户优惠券信息
* @param userCoupon 用户优惠券
... ... @@ -81,6 +100,7 @@ public class CouponConvert {
// TODO
userCoupon.setEndTime(couponAndType.getCoupon().getEndTime());
userCoupon.setCreateTime(now);
userCoupon.setOrderCode(0l);
userCoupon.setStatus(UserCouponsStatusEnum.NO_USE.getCode());
userCoupon.setCouponToken(couponAndType.getCoupon().getCouponToken());
return userCoupon;
... ...
package com.yohoufo.promotion.model.response;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class CouponBo {
private Integer uid;
private Integer couponId;
private String couponCode;
private String couponToken;
private String couponName;
private BigDecimal couponAmount;
private Integer couponType;
private Byte useLimitType;
private Short useLimitValue;
private Byte productLimitType;
private String productLimitValue;
private List<Integer> matchProducts;
}
... ...
package com.yohoufo.promotion.model.response;
import java.util.List;
import lombok.Data;
import lombok.experimental.Builder;
@Data
@Builder
public class CouponInfoListBO {
private List<CouponInfo> couponList;
}
... ... @@ -5,6 +5,7 @@ import com.yohoufo.dal.promotion.model.CouponAndType;
import com.yohoufo.dal.promotion.model.CouponType;
import java.util.List;
import java.util.Map;
public interface ICouponCacheService {
... ... @@ -28,4 +29,12 @@ public interface ICouponCacheService {
* @return
*/
public Coupon getCouponWithCache(String couponToken);
/**
* 获取couponId对应的productIds
* @param productLimitCouponIds
* @return
*/
public Map<Integer, List<Integer>> getLimitProductWithCache(List<Integer> productLimitCouponIds);
}
... ...
package com.yohoufo.promotion.service;
import com.yohoufo.promotion.model.response.CouponBo;
import com.yohoufo.promotion.model.response.CouponInfo;
import com.yohoufo.promotion.model.response.CouponInfoListBO;
import java.util.List;
... ... @@ -20,4 +20,31 @@ public interface ICouponService {
* @return
*/
public String senCoupon(Integer uid, String couponToken);
/**
* 使用优惠券
* @param uid
* @param couponCodes
* @param orderCode
* @return
*/
public boolean useCoupon(Integer uid, List<String> couponCodes, long orderCode);
/**
* 退还优惠券
* @param uid
* @param couponCodes
* @param orderCode
* @return
*/
public boolean cancelCoupon(Integer uid, List<String> couponCodes, long orderCode);
/**
* 获取优惠券列表(订单)
* @param uid
* @return
*/
public List<CouponBo> queryUserNoUsedCoupons(Integer uid);
}
... ...
... ... @@ -6,9 +6,11 @@ import com.google.common.collect.Maps;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yohoufo.common.cache.CacheClient;
import com.yohoufo.dal.promotion.CouponMapper;
import com.yohoufo.dal.promotion.CouponProductLimitMapper;
import com.yohoufo.dal.promotion.CouponTypeMapper;
import com.yohoufo.dal.promotion.model.Coupon;
import com.yohoufo.dal.promotion.model.CouponAndType;
import com.yohoufo.dal.promotion.model.CouponProductLimit;
import com.yohoufo.dal.promotion.model.CouponType;
import com.yohoufo.promotion.cache.ExpiredTime;
import com.yohoufo.promotion.cache.KeyBuilder;
... ... @@ -35,6 +37,10 @@ public class CouponCacheServiceImpl implements ICouponCacheService {
@Autowired
CouponProductLimitMapper couponProductLimitMapper;
@Autowired
private CacheClient cacheClient;
private final Logger logger = LoggerFactory.getLogger(getClass());
... ... @@ -105,6 +111,53 @@ public class CouponCacheServiceImpl implements ICouponCacheService {
return coupon;
}
/**
* 获取couponId对应的productIds
* @param productLimitCouponIds
* @return
*/
public Map<Integer, List<Integer>> getLimitProductWithCache(List<Integer> productLimitCouponIds) {
Map<Integer, List<Integer>> result = Maps.newHashMap();
List<Integer> missCouponIdList = Lists.newArrayList();
for (Integer couponId : productLimitCouponIds){
List<Integer> productIds = cacheClient.range(KeyBuilder.buildCouponLimitProductCacheKey(couponId), Integer.class,0, -1);
if (CollectionUtils.isEmpty(productIds)){
missCouponIdList.add(couponId);
}else{
result.put(couponId, productIds);
}
}
if (CollectionUtils.isEmpty(missCouponIdList)){
return result;
}
List<CouponProductLimit> couponProductLimitList = couponProductLimitMapper.selectByCouponIds(missCouponIdList);
Map<Integer, List<Integer>> resultCache = couponProductLimitList.stream().collect(Collectors.toMap(CouponProductLimit::getCouponId,
s -> {
List<Integer> skns = Lists.newArrayList();
skns.add(s.getProductId());
return skns;
},
(List<Integer> v1, List<Integer> v2) -> {
v1.addAll(v2);
return v1;
}));
result.putAll(resultCache);
for (Integer key : resultCache.keySet()){
cacheClient.rightPushAll(KeyBuilder.buildCouponLimitProductCacheKey(key), resultCache.get(key), ExpiredTime.COUPON_PRODUCT_LIMIT_CACHE_TIME);
}
return result;
}
/**
* 批量获取coupon
... ...
... ... @@ -5,14 +5,15 @@ import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.dal.promotion.CouponMapper;
import com.yohoufo.dal.promotion.CouponProductLimitMapper;
import com.yohoufo.dal.promotion.UserCouponMapper;
import com.yohoufo.dal.promotion.model.Coupon;
import com.yohoufo.dal.promotion.model.CouponAndType;
import com.yohoufo.dal.promotion.model.CouponType;
import com.yohoufo.dal.promotion.model.UserCoupon;
import com.yohoufo.dal.promotion.model.*;
import com.yohoufo.promotion.common.CouponUseStatusEnum;
import com.yohoufo.promotion.common.CouponsStatusEnum;
import com.yohoufo.promotion.common.ProductLimitType;
import com.yohoufo.promotion.convert.CouponConvert;
import com.yohoufo.promotion.model.response.CouponInfo;
import com.yohoufo.promotion.model.response.CouponBo;
import com.yohoufo.promotion.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
... ... @@ -88,6 +89,75 @@ public class CouponServiceImpl implements ICouponService {
return couponCode;
}
@Override
public boolean useCoupon(Integer uid, List<String> couponCodes, long orderCode) {
if (uid == null || uid.intValue() <=0
|| CollectionUtils.isEmpty(couponCodes)
|| orderCode < 0){
logger.warn("useCoupon param invalidate");
throw new ServiceException(ServiceError.PROMOTION_REQUEST_PAREMENT_ERROR);
}
if (checkUserCoupon(uid, couponCodes, orderCode)){
return false;
}
CouponUseDO couponUseDO = CouponUseDO.newBuilder()
.uid(uid)
.orderCode(orderCode)
.useTime(DateUtil.getCurrentTimeSecond())
.couponCodes(couponCodes)
.build();
int updateRow = userCouponMapper.updateCoupon2Use(couponUseDO);
if (updateRow >= couponCodes.size()) {
logger.info("order use coupons success:{},{},{}",uid, couponCodes, orderCode);
return true;
} else {
logger.warn("order use coupons fail:{},{},{}", uid, couponCodes, orderCode);
return false;
}
}
@Override
public boolean cancelCoupon(Integer uid, List<String> couponCodes, long orderCode) {
if (uid == null || uid.intValue() <=0
|| CollectionUtils.isEmpty(couponCodes)
|| orderCode < 0){
logger.warn("cancelCoupon param invalidate");
throw new ServiceException(ServiceError.PROMOTION_REQUEST_PAREMENT_ERROR);
}
CouponCancelUseDO cancelUseDO = new CouponCancelUseDO(uid, couponCodes, orderCode);
int row = userCouponMapper.updateCouponNotUse(cancelUseDO);
if (row >= couponCodes.size()) {
logger.info("cancel order use coupon succ {},{},{}:{}", uid, couponCodes, orderCode, row);
return true;
} else {
logger.info("cancel order use coupon fail {},{},{}:{}", uid, couponCodes, orderCode, row);
return false;
}
}
private boolean checkUserCoupon(Integer uid, List<String> couponCodes, long orderCode) {
List<UserCoupon> userCoupons = userCouponMapper.selectByUidAndCouponCodes(uid, couponCodes);
if (CollectionUtils.isEmpty(userCoupons) || userCoupons.size() != couponCodes.size()){
logger.warn("user {},{} coupon not enough {},{} ", uid,orderCode, couponCodes.size(), userCoupons.size());
return true;
}
return userCoupons.stream().anyMatch(userCoupon -> {
if (userCoupon.getStatus().intValue() != CouponUseStatusEnum.NOT_USED.getCode()){
return true;
}else{
return false;
}
});
}
/**
* 优惠券数量校验
... ... @@ -130,9 +200,72 @@ public class CouponServiceImpl implements ICouponService {
}
}
/**
*
* @param uid
* @return
*/
public List<CouponBo> queryUserNoUsedCoupons(Integer uid){
if (uid == null || uid <=0){
logger.warn("query coupon list param invalidate");
throw new ServiceException(ServiceError.PROMOTION_REQUEST_PAREMENT_ERROR);
}
// 获取未使用未过期的优惠券
List<UserCoupon> list = userCouponMapper.selectUsableCouponByUid(uid, DateUtil.getCurrentTimeSecond());
if (CollectionUtils.isEmpty(list)){
return Lists.newArrayList();
}
// 批量获取coupon
List<String> couponIdList = list.stream().map(UserCoupon::getCouponToken).collect(Collectors.toList());
List<Coupon> couponList = couponCacheService.getCouponsWithCache(couponIdList);
Map<Integer, Coupon> couponMap = couponList.stream().collect(Collectors.toMap(Coupon::getId, Function.identity()));
// 优惠券商品限制 key=couponId, value=ProductId集合
Map<Integer, List<Integer>> couponProductIdMap = getProductIdListMap(couponList);
List<CouponBo> couponBoList = list.stream().map(userCoupon -> {
Coupon coupon = couponMap.get(userCoupon.getCouponId());
List<Integer> productIds = couponProductIdMap.get(userCoupon.getCouponId());
CouponBo couponBo = CouponConvert.covertCouponBo(userCoupon, coupon);
couponBo.setMatchProducts(productIds);
return couponBo;
}).collect(Collectors.toList());
return couponBoList;
}
private Map<Integer, List<Integer>> getProductIdListMap(List<Coupon> couponList) {
// 批量获取 coupon_product_limt 过滤出商品限制的优惠券id
List<Integer> productLimitCouponIds = couponList.stream().filter(coupon -> {
if (coupon.getProductLimitType()!=null && ProductLimitType.PRODUCT.getCode() == coupon.getProductLimitType().intValue()){
return true;
}else{
return false;
}
}).map(Coupon::getId).collect(Collectors.toList());
return couponCacheService.getLimitProductWithCache(productLimitCouponIds);
}
@Override
public List<CouponInfo> queryCouponList(Integer uid) {
if (uid == null || uid <=0){
logger.warn("query coupon list param invalidate");
throw new ServiceException(ServiceError.PROMOTION_REQUEST_PAREMENT_ERROR);
}
// 获取未使用未过期的优惠券
List<UserCoupon> list = userCouponMapper.selectUsableCouponByUid(uid, DateUtil.getCurrentTimeSecond());
... ... @@ -152,9 +285,8 @@ public class CouponServiceImpl implements ICouponService {
// 单个获取couponType
CouponType couponType = couponCacheService.getCouponTypeWithCache(userCoupon.getCouponType()!=null ? userCoupon.getCouponType().intValue() : null);
CouponInfo couponInfo = CouponConvert.convertCouponInfo(userCoupon, coupon, couponType);
return couponInfo;
return CouponConvert.convertCouponInfo(userCoupon, coupon, couponType);
}).collect(Collectors.toList());
... ...
... ... @@ -107,4 +107,9 @@ order.buyer.cancelWhenSellerUnDelivery.sellerGetMoneyRate=0.8
uic.url=http://java-yoho-uic.test3.ingress.dev.yohocorp.com/uic
yoho.message.controller.url=http://message-controller.yohoops.org/yoho-message-controller
\ No newline at end of file
yoho.message.controller.url=http://message-controller.yohoops.org/yoho-message-controller
#rabbit address for transaction compensate
rabbit_host=192.168.102.45:5672
rabbit_user=yoho
rabbit_password=yoho
... ...
... ... @@ -81,3 +81,9 @@ order.buyer.cancelWhenSellerUnDelivery.sellerGetMoneyRate=${order.buyer.cancelWh
erp-gateway.url=${erp-gateway.url}
uic.url=${uic.url}
yoho.message.controller.url=${yoho.message.controller.url}
#rabbit address for transaction compensate
rabbit_host=${rabbit_order}
rabbit_user=${rabbit_order_user}
rabbit_password=${rabbit_order_password}
\ No newline at end of file
... ...