Authored by chenchao

Merge branch 'dev-promotion' into test6.8.2

Showing 20 changed files with 230 additions and 478 deletions
... ... @@ -157,7 +157,6 @@ public class RedisGwCacheClient implements CacheClient {
} else {
redisValue = JSON.toJSONString(value);
}
long beginTime = System.currentTimeMillis();
try {
valueOperations.set(key, redisValue, timeout, TimeUnit.SECONDS);
} catch (Exception e) {
... ... @@ -281,7 +280,6 @@ public class RedisGwCacheClient implements CacheClient {
cacheMap.put(key, JSON.toJSONString(value));
}
}
long beginTime = System.currentTimeMillis();
try {
redis.mset(cacheMap,timeout);
} catch (Exception e) {
... ...
... ... @@ -8,10 +8,10 @@
<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" />
<result column="coupon_cut_amount" jdbcType="DECIMAL" property="couponCutAmount" />
</resultMap>
<sql id="Base_Column_List">
id, order_code, skup, goods_price, goods_amount, uid
id, order_code, skup, goods_price, goods_amount, uid,coupon_cut_amount
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
... ... @@ -85,7 +85,7 @@
uid,
</if>
<if test="couponCutAmount != null">
coupons_cut_amount,
coupon_cut_amount,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
... ...
... ... @@ -127,7 +127,7 @@ public class ChargeService {
chargeResult.setFinalAmount(newFinalAmount);
CouponPayResult couponPayResult = CouponPayResult.builder().couponCode(userCouponsBo.getCouponCode())
.couponAmount(couponPayAmount).couponTitle(userCouponsBo.getCouponName()).build();
.couponAmount(couponPayAmount).couponTitle(userCouponsBo.getCouponName()).couponCount(1).build();
chargeResult.setCouponPayResult(couponPayResult);
... ... @@ -139,7 +139,7 @@ public class ChargeService {
private UserCouponsBo getOneUsableUserCouponBo(ChargeContext chargeContext) {
ChargeParam chargeParam = chargeContext.getChargeParam();
List<UserCouponsBo> couponsBos = couponProxyService.checkUseCouponsAndGet(chargeParam.getUid(), chargeParam.getCouponCodes());
List<UserCouponsBo> couponsBos = couponProxyService.checkAndGetCoupons(chargeParam.getUid(), chargeParam.getCouponCodes());
if (CollectionUtils.isEmpty(couponsBos)) {
logger.info("[{}] not find any coupons by couponCodes:{}", chargeParam.getUid(), chargeParam.getCouponCodes());
throw new ServiceException(ServiceError.PROMOTION_COUPON_IS_NOT_VAILD);
... ... @@ -150,6 +150,7 @@ public class ChargeService {
//找到可用的券
List<UserCouponsBo> usableCoupons = couponMatchResults.stream().filter(result -> result.isUsable()).map(result -> result.getUserCouponsBo()).collect(Collectors.toList());
//当前只有使用一张券
if (CollectionUtils.isEmpty(usableCoupons) || usableCoupons.size() != 1) {
logger.info("[{}] get coupons by couponCodes:{} is invalid", chargeParam.getUid(), chargeParam.getCouponCodes());
throw new ServiceException(ServiceError.PROMOTION_COUPON_IS_NOT_VAILD);
... ...
... ... @@ -3,9 +3,11 @@ 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.YHTxCoordinator;
import com.yoho.core.transaction.annoation.YHTransaction;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohoufo.common.alarm.CommonAlarmEventPublisher;
import com.yohoufo.dal.order.*;
import com.yohoufo.dal.order.model.*;
import com.yohoufo.order.common.ClientType;
... ... @@ -39,47 +41,55 @@ public class SubmitOrderServiceImpl implements ISubmitOrderService {
@Autowired
private CouponProxyService couponProxyService;
@Autowired
YHTxCoordinator tx;
@YHTransaction
public BuyerOrderSubmitResult doSumbitOrder(OrderBuilder orderBuilder){
BuyerOrderSubmitResult result = null;
try {
// 减库存
if(productProxyService.subtractStorage(orderBuilder.getProductId(), orderBuilder.getSkup())) {
productProxyService.subtractStorage(orderBuilder.getProductId(), orderBuilder.getSkup());
try{
//使用优惠券
if (orderBuilder.getCouponBo().getCouponAmount().doubleValue() > 0) {
couponProxyService.orderUseCoupon(orderBuilder.getUid(), orderBuilder.getOrderCode(), orderBuilder.getCouponBo());
}
// 创建订单
return orderCreateService.createOrder(orderBuilder);
}catch (Exception e){
tx.rollback();
returnStrorageEx(orderBuilder);
throw e;
}
}catch (Exception ex){
try{
boolean returnStorageFlag = productProxyService.returnStorage(orderBuilder.getSkup());
logger.warn("in buyer createOrder fail, need return storage SaleSkup, uid {},ordercode {},Skup {} ",
orderBuilder.getUid(), orderBuilder.getOrderCode(), orderBuilder.getSkup(), ex);
if (!(ex instanceof ServiceException)) {
//上报告警事件
//EventBusPublisher.publishEvent(new SmsAlarmEvent(OrderHanders.submit, "submit", "订单(" + order.getOrderCode() + ")创建失败"));
throw new ServiceException(ServiceError.SHOPPING_SUBMIT_ORDER_FAIL, ex);
}
throw ex;
}
}
// 补库存失败,需要报警手动补库存 TODO
if (!returnStorageFlag){
logger.warn("in buyer createOrder fail, need return storage SaleSkup, uid {},ordercode {},Skup {} ",
orderBuilder.getUid(), orderBuilder.getOrderCode(), orderBuilder.getSkup());
}
private void returnStrorageEx(OrderBuilder orderBuilder) {
try{
productProxyService.returnStorage(orderBuilder.getSkup());
}catch (Exception ex0){
CommonAlarmEventPublisher.publish("还库存失败", "ufo.product.cancelSaleSkup", "sku:["+orderBuilder.getSkup()+"]");
// 还库存失败,上报到influxdb
logger.warn("in buyer createOrder fail, return storage fail, uid {},ordercode {},Skup {}",
orderBuilder.getUid(), orderBuilder.getOrderCode(), orderBuilder.getSkup(), ex0);
}catch (Exception ex0){
logger.warn("in buyer createOrder fail, return storage fail, uid {},ordercode {},Skup {}",
orderBuilder.getUid(), orderBuilder.getOrderCode(), orderBuilder.getSkup(), ex0);
}finally {
logger.warn("in buyer createOrder fail, need return storage SaleSkup, uid {},ordercode {},Skup {} ",
orderBuilder.getUid(), orderBuilder.getOrderCode(), orderBuilder.getSkup(), ex);
if (!(ex instanceof ServiceException)) {
//上报告警事件
//EventBusPublisher.publishEvent(new SmsAlarmEvent(OrderHanders.submit, "submit", "订单(" + order.getOrderCode() + ")创建失败"));
throw new ServiceException(ServiceError.SHOPPING_SUBMIT_ORDER_FAIL, ex);
}
throw ex;
}
}
return result;
}
... ...
... ... @@ -9,16 +9,19 @@ 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.yohobuy.ufo.model.promotion.UserCouponsListBo;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.common.caller.UfoServiceCaller;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.order.model.bo.CouponBo;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* Created by jiexiang.wu on 2018/11/19.
... ... @@ -38,40 +41,27 @@ public class CouponProxyService implements Compensator {
* @return
*/
public List<UserCouponsBo> getUserAvailableCoupons(int uid) {
UserCouponsBo userCouponsBo = new UserCouponsBo();
userCouponsBo.setCouponCode("a100");
userCouponsBo.setCouponAmount(BigDecimal.valueOf(20));
userCouponsBo.setUseLimitType("2");
userCouponsBo.setUseLimitValue("299");
userCouponsBo.setProductLimitType("1");
userCouponsBo.setProductIdInclude(Lists.newArrayList(88888900));
userCouponsBo.setUseRule("满299可用");
userCouponsBo.setStartTime(1514739661L);
userCouponsBo.setEndTime(1546275661L);
UserCouponsBo userCouponsBo1 = new UserCouponsBo();
userCouponsBo1.setCouponCode("a200");
userCouponsBo1.setCouponAmount(BigDecimal.valueOf(100));
userCouponsBo1.setUseLimitType("0");
userCouponsBo1.setUseLimitValue("");
userCouponsBo1.setProductLimitType("1");
userCouponsBo1.setProductIdInclude(Lists.newArrayList(88888900));
userCouponsBo1.setStartTime(1514739661L);
userCouponsBo1.setEndTime(1546275661L);
return Lists.newArrayList(userCouponsBo, userCouponsBo1);
logger.info("[{}] getUserAvailableCoupons", uid);
//未使用的优惠券,包括还未生效的券
ApiResponse resp = serviceCaller.call("app.coupons.listNoUsed", uid);
UserCouponsListBo result = getResultFromApiResponse(resp);
if (Objects.isNull(result) || CollectionUtils.isEmpty(result.getCoupons())) {
return Lists.newArrayList();
}
//过滤未生效的券
int currentTime = DateUtil.getCurrentTimeSecond();
return result.getCoupons().stream().filter(e -> e.getStartTime() < currentTime && e.getEndTime() > currentTime).collect(Collectors.toList());
}
public List<UserCouponsBo> checkUseCouponsAndGet(int uid, List<String> couponCodes) {
UserCouponsBo userCouponsBo = new UserCouponsBo();
userCouponsBo.setCouponCode("a100");
userCouponsBo.setCouponAmount(BigDecimal.valueOf(20));
userCouponsBo.setUseLimitType("2");
userCouponsBo.setUseLimitValue("299");
userCouponsBo.setProductLimitType("1");
userCouponsBo.setProductIdInclude(Lists.newArrayList(88888900));
userCouponsBo.setStartTime(1514739661L);
userCouponsBo.setEndTime(1546275661L);
return Lists.newArrayList(userCouponsBo);
public List<UserCouponsBo> checkAndGetCoupons(int uid, List<String> couponCodes) {
logger.info("[{}] checkAndGetCoupons:{}", uid, couponCodes);
//未使用的优惠券,包括还未生效的券
ApiResponse resp = serviceCaller.call("app.coupons.checkAndGet", uid, couponCodes);
UserCouponsListBo result = getResultFromApiResponse(resp);
if (Objects.isNull(result) || CollectionUtils.isEmpty(result.getCoupons())) {
return Lists.newArrayList();
}
return result.getCoupons();
}
... ... @@ -87,7 +77,8 @@ public class CouponProxyService implements Compensator {
@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) {
Boolean result = getResultFromApiResponse(resp);
if (result == null || result.booleanValue() == false) {
logger.warn("[{}] use couponBo fail,coupons is {}", orderCode, coupon);
throw new ServiceException(ServiceError.PROMOTION_COUPON_IS_NOT_VAILD);
}
... ... @@ -105,21 +96,22 @@ public class CouponProxyService implements Compensator {
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) {
Boolean result = getResultFromApiResponse(resp);
if (result == null || result.booleanValue() == 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) {
private <T> T getResultFromApiResponse(ApiResponse resp) {
if (resp == null) {
return false;
return null;
}
if (resp.getCode() != 200 || resp.getData() == null) {
return false;
return null;
}
return (boolean) resp.getData();
return (T) resp.getData();
}
/**
... ... @@ -137,7 +129,7 @@ public class CouponProxyService implements Compensator {
JSONObject json = JSON.parseObject(message);
uid = json.getIntValue("uid");
orderCode = json.getLongValue("orderCode");
couponBo = json.getObject("coupons", CouponBo.class);
couponBo = json.getObject("couponBo", CouponBo.class);
} catch (Exception ex) {
logger.warn("parse message to json error,message is {}", message, ex);
}
... ...
... ... @@ -3,12 +3,12 @@ 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.common.utils.DateUtil;
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;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
... ... @@ -39,8 +39,8 @@ public class CouponSupport {
shoppingCoupon.setCouponCode(userCouponsBo.getCouponCode());
shoppingCoupon.setCouponName(userCouponsBo.getCouponName());
shoppingCoupon.setCouponValueStr(userCouponsBo.getCouponAmount().intValue() + "");
shoppingCoupon.setCouponValidity(DateUtil.format(DateUtil.getDateFromLong(userCouponsBo.getStartTime()), "yyyy.MM.dd") + "-" +
DateUtil.format(DateUtil.getDateFromLong(userCouponsBo.getEndTime()), "yyyy.MM.dd"));
shoppingCoupon.setCouponValidity(DateUtil.getDateFormat(userCouponsBo.getStartTime()) + "-" +
DateUtil.getDateFormat(userCouponsBo.getEndTime()));
shoppingCoupon.setUseRuleStr(userCouponsBo.getUseRule());
shoppingCoupon.setSelected(OrderConstant.N_STR);
... ...
package com.yohoufo.order.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by jiexiang.wu on 2018/11/20.
*/
public class DateUtil {
public static final String yyyy_MM_dd_HH_mm_SS = "yyyy-MM-dd HH:mm:ss";
public static final String yyyy$MM$dd = "yyyy.MM.dd";
/**
* 将Date类型转换为字符串
*
* @param date 日期类型
* @param pattern 字符串格式
* @return 日期字符串
*/
public static String format(Date date, String pattern) {
if (date == null) {
return "null";
}
if (pattern == null || pattern.equals("") || pattern.equals("null")) {
pattern = yyyy$MM$dd;
}
return new SimpleDateFormat(pattern).format(date);
}
/**
* @param time
* @return java.lang.String
*/
public static Date getDateFromLong(long time) {
Long timestamp = time*1000;
String date = new java.text.SimpleDateFormat(yyyy_MM_dd_HH_mm_SS).format(new java.util.Date(timestamp));
return format(date);
}
/**
* 将字符串转换为Date类型
*
* @param date 字符串类型
* @return 日期类型
*/
public static Date format(String date) {
return format(date, null);
}
/**
* 将字符串转换为Date类型
*
* @param date 字符串类型
* @param pattern 格式
* @return 日期类型
*/
public static Date format(String date, String pattern) {
if (pattern == null || pattern.equals("") || pattern.equals("null")) {
pattern = yyyy_MM_dd_HH_mm_SS;
}
if (date == null || date.equals("") || date.equals("null")) {
return new Date();
}
Date d = null;
try {
d = new SimpleDateFormat(pattern).parse(date);
} catch (ParseException pe) {
}
return d;
}
}
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
package com.yohoufo.promotion.common;
public enum CouponsStatusEnum {
//ERP中老的状态为: 0:未启用 1:启用 3:作废
/**
待审核:通过、驳回、查看详情
通过:查看详情、作废
驳回:修改
作废:查看详情
*/
/**
* 新建之后是待审核
*/
NEED_REVIEW(0, "待审核"),
/**
* 审核通过之后是有效的(对应原来的启用状态)
*/
VALID(1, "有效"),
/**
* 审核通过之后可作废
*/
INVALID(3, "作废"),
/**
* 审批未通过的是驳回状态,驳回状态可编辑,编辑之后变成待审核
*/
REJECT(2, "审核驳回");
/**
* 编码
*/
private int code;
/**
* 描述
*/
private String desc;
/**
* 操作列表
*
* @param code
* @param desc
* @return
*/
CouponsStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
package com.yohoufo.promotion.common;
public enum ProductLimitType {
PRODUCT(1, "特定商品", "限特定商品");
int code ;
String desc;
/**
* 显示给前端的文案
*/
String text;
ProductLimitType(int code, String desc, String text) {
this.code = code;
this.desc = desc;
this.text = text;
}
public int getCode() {
return code;
}
public String getText() {
return text;
}
}
\ No newline at end of file
package com.yohoufo.promotion.common;
public enum UseLimitType {
NO_LIMIT(0, "无限制", ""),
AMOUNT_LIMIT(1, "金额", "满{0}可用");
int code ;
String desc;
/**
* 给前端的显示文案
*/
String text;
UseLimitType(int code, String desc, String text) {
this.code = code;
this.desc = desc;
this.text = text;
}
public String getText() {
return text;
}
public int getCode() {
return code;
}
}
package com.yohoufo.promotion.common;
public enum UserCouponsStatusEnum {
NO_USE(0, "未使用"),
USED(1, "已使用");
/**
* 编码
*/
private int code;
/**
* 描述
*/
private String desc;
/**
* 操作列表
*
* @param code
* @param desc
* @return
*/
UserCouponsStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
package com.yohoufo.promotion.controller;
import com.yohobuy.ufo.model.promotion.response.CouponInfo;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.promotion.model.response.CouponInfo;
import com.yohoufo.promotion.service.ICouponService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
... ...
package com.yohoufo.promotion.controller;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohobuy.ufo.model.promotion.UserCouponsListBo;
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.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -73,15 +75,34 @@ public class OrderCouponController {
* @param uid
* @return
*/
@RequestMapping(params = "method=app.coupons.list")
@RequestMapping(params = "method=app.coupons.listNoUsed")
@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());
UserCouponsListBo couponBoList = couponService.queryUserNoUsedCoupons(uid);
logger.info("use coupons, uid: {}, success", uid);
return new ApiResponse.ApiResponseBuilder().code(200).data(couponBoList).build();
}
/**
* 优惠券列表(订单使用)
*
* @param uid
* @return
*/
@RequestMapping(params = "method=app.coupons.checkAndGet")
@ResponseBody
public ApiResponse checkAndGetCoupons(@RequestParam(value = "uid") int uid,
@RequestParam(value = "couponCodes") List<String> couponCodes) {
logger.info("checkAndGet coupons, uid: {},couponCodes:{}", uid, couponCodes);
if (uid <= 0 || CollectionUtils.isEmpty(couponCodes)) {
throw new ServiceException(ServiceError.PROMOTION_REQUEST_PAREMENT_ERROR);
}
UserCouponsListBo couponBoList = couponService.checkAndGetCoupons(uid, couponCodes);
logger.info("checkAndGet coupons, uid: {},couponCodes:{},success", uid, couponCodes);
return new ApiResponse.ApiResponseBuilder().code(200).data(couponBoList).build();
}
}
... ...
package com.yohoufo.promotion.convert;
import com.yohobuy.ufo.model.promotion.UserCouponsBo;
import com.yohobuy.ufo.model.promotion.constant.CouponProductLimitTypeEnum;
import com.yohobuy.ufo.model.promotion.constant.CouponUseLimitTypeEnum;
import com.yohobuy.ufo.model.promotion.constant.UserCouponsStatusEnum;
import com.yohobuy.ufo.model.promotion.response.CouponInfo;
import com.yohoufo.common.utils.DateUtil;
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;
public class CouponConvert {
public static CouponBo covertCouponBo(UserCoupon userCoupon, Coupon coupon){
public static UserCouponsBo covertCouponBo(UserCoupon userCoupon, Coupon coupon){
CouponBo couponBo = new CouponBo();
UserCouponsBo couponBo = new UserCouponsBo();
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());
couponBo.setProductLimitType(coupon.getProductLimitType()!=null ? String.valueOf(coupon.getProductLimitType()):"");
couponBo.setUseLimitType(coupon.getUseLimitType()!=null ? String.valueOf(coupon.getUseLimitType()) : "");
couponBo.setUseLimitValue(coupon.getUseLimitValue()!=null ? String.valueOf(coupon.getUseLimitValue()) : "");
couponBo.setStartTime(userCoupon.getStartTime());
couponBo.setEndTime(userCoupon.getEndTime());
couponBo.setStatus(userCoupon.getStatus());
// use_limit_type use_limit_value 满多少元可用
if (coupon.getUseLimitType()!=null && CouponUseLimitTypeEnum.AMOUNT_LIMIT.getLimitType().equals(String.valueOf(coupon.getUseLimitType()))){
couponBo.setUseRule(MessageFormat.format(CouponUseLimitTypeEnum.AMOUNT_LIMIT.getText(),coupon.getUseLimitValue().intValue()));
}
return couponBo;
}
... ... @@ -62,13 +65,13 @@ public class CouponConvert {
couponInfo.setCoupon_value(coupon.getCouponAmount());
// use_limit_type use_limit_value 满多少元可用
if (coupon.getUseLimitType()!=null && coupon.getUseLimitType().intValue() == UseLimitType.AMOUNT_LIMIT.getCode()){
couponInfo.setUse_rule(MessageFormat.format(UseLimitType.AMOUNT_LIMIT.getText(),coupon.getUseLimitValue().intValue()));
if (coupon.getUseLimitType()!=null && CouponUseLimitTypeEnum.AMOUNT_LIMIT.getLimitType().equals(String.valueOf(coupon.getUseLimitType()))){
couponInfo.setUse_rule(MessageFormat.format(CouponUseLimitTypeEnum.AMOUNT_LIMIT.getText(),coupon.getUseLimitValue().intValue()));
}
// product_limit_type product_limit_value 特定商品
if (coupon.getProductLimitType()!=null && coupon.getProductLimitType().intValue() == ProductLimitType.PRODUCT.getCode()){
couponInfo.setNotes(Arrays.asList(ProductLimitType.PRODUCT.getText()));
if (coupon.getProductLimitType()!=null && CouponProductLimitTypeEnum.SPECIFIC_PRODUCT.getLimitType().equals(String.valueOf(coupon.getProductLimitType()))){
couponInfo.setNotes(Arrays.asList(CouponProductLimitTypeEnum.SPECIFIC_PRODUCT.getText()));
}
}
... ... @@ -97,7 +100,6 @@ public class CouponConvert {
userCoupon.setCouponCode(couponCode);
int now = DateUtil.getCurrentTimeSecond();
userCoupon.setStartTime(now);
// TODO
userCoupon.setEndTime(couponAndType.getCoupon().getEndTime());
userCoupon.setCreateTime(now);
userCoupon.setOrderCode(0l);
... ...
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.math.BigDecimal;
import java.util.List;
import lombok.Data;
@Data
public class CouponInfo {
private String coupon_token;
private String coupon_name;
private String coupon_code;
private BigDecimal coupon_value;
private String use_rule;
private String coupon_validity;
private Integer coupon_type; //大类
private String coupon_type_name;
List<String> notes;
}
package com.yohoufo.promotion.service;
import com.yohoufo.promotion.model.response.CouponBo;
import com.yohoufo.promotion.model.response.CouponInfo;
import com.yohobuy.ufo.model.promotion.UserCouponsListBo;
import com.yohobuy.ufo.model.promotion.response.CouponInfo;
import java.util.List;
... ... @@ -44,7 +45,15 @@ public interface ICouponService {
* @param uid
* @return
*/
public List<CouponBo> queryUserNoUsedCoupons(Integer uid);
public UserCouponsListBo queryUserNoUsedCoupons(Integer uid);
/**
* 校验券并返回券信息
*
* @param uid
* @param couponCodes
* @return
*/
UserCouponsListBo checkAndGetCoupons(int uid, List<String> couponCodes);
}
... ...
... ... @@ -3,17 +3,17 @@ package com.yohoufo.promotion.service.impl;
import com.google.common.collect.Lists;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohobuy.ufo.model.promotion.UserCouponsBo;
import com.yohobuy.ufo.model.promotion.UserCouponsListBo;
import com.yohobuy.ufo.model.promotion.constant.CouponProductLimitTypeEnum;
import com.yohobuy.ufo.model.promotion.constant.CouponUseStatusEnum;
import com.yohobuy.ufo.model.promotion.constant.CouponsStatusEnum;
import com.yohobuy.ufo.model.promotion.response.CouponInfo;
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.*;
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;
... ... @@ -206,7 +206,7 @@ public class CouponServiceImpl implements ICouponService {
* @param uid
* @return
*/
public List<CouponBo> queryUserNoUsedCoupons(Integer uid){
public UserCouponsListBo queryUserNoUsedCoupons(Integer uid){
if (uid == null || uid <=0){
logger.warn("query coupon list param invalidate");
... ... @@ -217,35 +217,44 @@ public class CouponServiceImpl implements ICouponService {
List<UserCoupon> list = userCouponMapper.selectUsableCouponByUid(uid, DateUtil.getCurrentTimeSecond());
if (CollectionUtils.isEmpty(list)){
return Lists.newArrayList();
return UserCouponsListBo.builder().build();
}
// 批量获取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()));
Map<Integer, Coupon> couponMap = couponList.stream().filter(coupon -> {
if (coupon.getStatus() != null && coupon.getStatus().intValue() == CouponsStatusEnum.VALID.getCode()) {
return true;
} else {
return false;
}
}).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 -> {
List<UserCouponsBo> couponBoList = list.stream().filter(userCoupon -> {
return couponMap.containsKey(userCoupon.getCouponId());
}).map(userCoupon -> {
Coupon coupon = couponMap.get(userCoupon.getCouponId());
List<Integer> productIds = couponProductIdMap.get(userCoupon.getCouponId());
CouponBo couponBo = CouponConvert.covertCouponBo(userCoupon, coupon);
couponBo.setMatchProducts(productIds);
UserCouponsBo couponBo = CouponConvert.covertCouponBo(userCoupon, coupon);
couponBo.setProductIdInclude(productIds);
return couponBo;
}).collect(Collectors.toList());
return couponBoList;
return UserCouponsListBo.builder().coupons(couponBoList).build();
}
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()){
if (coupon.getProductLimitType()!=null && CouponProductLimitTypeEnum.SPECIFIC_PRODUCT.getLimitType().equals(String.valueOf(coupon.getProductLimitType()))){
return true;
}else{
return false;
... ... @@ -276,15 +285,22 @@ public class CouponServiceImpl implements ICouponService {
// 批量获取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()));
Map<Integer, Coupon> couponMap = couponList.stream().filter(coupon -> {
if (coupon.getStatus()!=null && coupon.getStatus().intValue() == CouponsStatusEnum.VALID.getCode()){
return true;
}else{
return false;
}
}).collect(Collectors.toMap(Coupon::getId, Function.identity()));
List<CouponInfo> couponInfoList = list.stream().map(userCoupon -> {
List<CouponInfo> couponInfoList = list.stream().filter(userCoupon -> {
return couponMap.containsKey(userCoupon.getCouponId());
}).map(userCoupon -> {
Coupon coupon = couponMap.get(userCoupon.getCouponId());
// 单个获取couponType
CouponType couponType = couponCacheService.getCouponTypeWithCache(userCoupon.getCouponType()!=null ? userCoupon.getCouponType().intValue() : null);
CouponType couponType = couponCacheService.getCouponTypeWithCache(userCoupon.getCouponType() != null ? userCoupon.getCouponType().intValue() : null);
return CouponConvert.convertCouponInfo(userCoupon, coupon, couponType);
... ... @@ -302,5 +318,62 @@ public class CouponServiceImpl implements ICouponService {
int cnt = userCouponMapper.selectCntUsableCouponByUid(uid, DateUtil.getCurrentTimeSecond());
return cnt;
}
@Override
public UserCouponsListBo checkAndGetCoupons(int uid, List<String> couponCodes) {
//数据校验
if (uid <= 0 || CollectionUtils.isEmpty(couponCodes)) {
logger.warn("check coupon use param error:{}, {}", uid, couponCodes);
throw new ServiceException(ServiceError.PROMOTION_PARAM_IS_ERROR);
}
// 获取用户券记录
List<UserCoupon> userCoupons = userCouponMapper.selectByUidAndCouponCodes(uid, couponCodes);
int time = DateUtil.getCurrentTimeSecond();
List<UserCouponsBo> couponBoList = couponCodes.stream().map(couponCode -> {
UserCoupon userCoupon = userCoupons.stream().filter(e -> couponCode.equals(e.getCouponCode())).findAny().orElse(null);
logger.info("user coupon {},{},{}", uid, couponCode, userCoupon);
if (userCoupon == null) {
logger.warn("not find user coupon by{},{}", uid, couponCode);
throw new ServiceException(ServiceError.PROMOTION_COUPON_IS_NOT_YOUS);
}
//判断券状态
if (userCoupon.getStatus().intValue() != CouponUseStatusEnum.NOT_USED.getCode()) {
logger.warn("user this coupon is used:{},{}", userCoupon.getUid(), userCoupon.getCouponCode());
throw new ServiceException(ServiceError.PROMOTION_COUPON_NOT_USE_DOUBLE);
}
//判断生失效时间
if (userCoupon.getStartTime() > time || userCoupon.getEndTime() < time) {
logger.warn("coupon has expire or not arrive time:{},{},{}", userCoupon.getStartTime(), userCoupon.getEndTime(), time);
throw new ServiceException(ServiceError.PROMOTION_COUPON_NOT_ALLOW_OR_EXPIRE);
}
//券模板的状态
Coupon coupon = couponCacheService.getCouponWithCache(userCoupon.getCouponToken());
if (coupon == null) {
logger.warn("coupons is null");
throw new ServiceException(ServiceError.PROMOTION_COUPON_NOT_EXISTS);
}
if (coupon.getStatus() != CouponsStatusEnum.VALID.getCode()) {
logger.warn("coupon status can't be use:{},{}", coupon.getId(), coupon.getStatus());
throw new ServiceException(ServiceError.PROMOTION_COUPON_IS_NOT_VAILD);
}
//所有的校验都通过了,生成bo
Map<Integer, List<Integer>> couponProductIdMap = getProductIdListMap(Lists.newArrayList(coupon));
List<Integer> productIds = couponProductIdMap.get(userCoupon.getCouponId());
UserCouponsBo couponBo = CouponConvert.covertCouponBo(userCoupon, coupon);
couponBo.setProductIdInclude(productIds);
return couponBo;
}).collect(Collectors.toList());
return UserCouponsListBo.builder().coupons(couponBoList).build();
}
}
... ...
... ... @@ -84,6 +84,6 @@ 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
rabbit_host=${rabbit_ufo}
rabbit_user=${rabbit_ufo_user}
rabbit_password=${rabbit_ufo_password}
\ No newline at end of file
... ...