Authored by tanling

优惠券使用退还

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;
}
}
... ...
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);
}
}
}
... ...
... ... @@ -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" />
... ... @@ -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
... ...
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.controller;
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;
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 = "couponCodes") List<String> couponCodes,
@RequestParam(value = "orderCode") long orderCode) {
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 = "couponCodes") List<String> couponCodes,
@RequestParam(value = "orderCode") long orderCode) {
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();
}
}
... ...
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.
* 内部接口
... ... @@ -28,88 +18,79 @@ 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 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
public Boolean orderUseCoupon() {
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;
}
// /**
// * 取消订单优惠券的使用
// *
// * @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;
// }
}
... ...
... ... @@ -81,6 +81,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;
... ...
... ... @@ -20,4 +20,24 @@ 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);
}
... ...
... ... @@ -6,15 +6,14 @@ import com.yoho.error.exception.ServiceException;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.dal.promotion.CouponMapper;
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.convert.CouponConvert;
import com.yohoufo.promotion.model.response.CouponInfo;
import com.yohoufo.promotion.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -88,6 +87,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;
}
});
}
/**
* 优惠券数量校验
... ...