Prechádzať zdrojové kódy

feature: add Coupon Service and CouponStrategy Service

tubinyan 5 rokov pred
rodič
commit
5d92d41d9f

+ 9 - 0
src/main/java/cn/seecoder/courselearning/controller/CouponController.java

@@ -0,0 +1,9 @@
+package cn.seecoder.courselearning.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/coupon")
+public class CouponController {
+}

+ 24 - 0
src/main/java/cn/seecoder/courselearning/dto/CourseCouponDTO.java

@@ -0,0 +1,24 @@
+package cn.seecoder.courselearning.dto;
+
+import cn.seecoder.courselearning.enums.CouponType;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 课程优惠活动
+ * 所有用户在优惠券生效期间购买当前课程均可享受优惠
+ */
+@Data
+public class CourseCouponDTO {
+    private CouponType type;
+    private String name;
+    private String description;
+    private Integer courseId;
+    private double discount;
+    private Integer threshold;
+    private Integer cutDown;
+    private LocalDateTime startTime;
+    private LocalDateTime endTime;
+    private Boolean sharable;
+}

+ 23 - 0
src/main/java/cn/seecoder/courselearning/dto/UniversalCouponDTO.java

@@ -0,0 +1,23 @@
+package cn.seecoder.courselearning.dto;
+
+import cn.seecoder.courselearning.enums.CouponType;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 网站优惠活动
+ * 对所有课程、所有用户均有效的、可重复使用的优惠券
+ */
+@Data
+public class UniversalCouponDTO {
+    private CouponType type;
+    private String name;
+    private String description;
+    private double discount;
+    private Integer threshold;
+    private Integer cutDown;
+    private LocalDateTime startTime;
+    private LocalDateTime endTime;
+    private Boolean sharable;
+}

+ 25 - 0
src/main/java/cn/seecoder/courselearning/dto/UserCouponDTO.java

@@ -0,0 +1,25 @@
+package cn.seecoder.courselearning.dto;
+
+import cn.seecoder.courselearning.enums.CouponType;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 对用户发放的定制化优惠券
+ * 仅对某个用户生效的单次优惠券
+ */
+@Data
+public class UserCouponDTO {
+    private CouponType type;
+    private String name;
+    private String description;
+    private Integer courseId;
+    private Integer userId;
+    private double discount;
+    private Integer threshold;
+    private Integer cutDown;
+    private LocalDateTime startTime;
+    private LocalDateTime endTime;
+    private Boolean sharable;
+}

+ 16 - 0
src/main/java/cn/seecoder/courselearning/enums/CouponType.java

@@ -0,0 +1,16 @@
+package cn.seecoder.courselearning.enums;
+
+public enum CouponType {
+    DISCOUNT("折扣型"), CUT_DOWN("减价型");
+
+    private final String value;
+
+    CouponType(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return value;
+    }
+}

+ 22 - 0
src/main/java/cn/seecoder/courselearning/mapperservice/CouponMapper.java

@@ -0,0 +1,22 @@
+package cn.seecoder.courselearning.mapperservice;
+
+import cn.seecoder.courselearning.po.Coupon;
+import java.util.List;
+
+public interface CouponMapper {
+    int deleteByPrimaryKey(Integer id);
+
+    int insert(Coupon record);
+
+    Coupon selectByPrimaryKey(Integer id);
+
+    List<Coupon> selectAll();
+
+    int updateByPrimaryKey(Coupon record);
+
+    // 根据课程Id和用户Id查找优惠券
+    List<Coupon> selectByCourseIdAndUserId(Integer courseId, Integer userId);
+
+    // 根据用户Id查找优惠券
+    List<Coupon> selectByUserId(Integer userId);
+}

+ 92 - 0
src/main/java/cn/seecoder/courselearning/po/Coupon.java

@@ -0,0 +1,92 @@
+package cn.seecoder.courselearning.po;
+
+import cn.seecoder.courselearning.enums.CouponType;
+import cn.seecoder.courselearning.vo.CouponVO;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@NoArgsConstructor
+public class Coupon {
+    /**
+     * 优惠券id
+     */
+    private Integer id;
+
+    /**
+     * 优惠券类型
+     */
+    private CouponType type;
+
+    /**
+     * 优惠券名称
+     */
+    private String name;
+
+    /**
+     * 优惠券描述
+     */
+    private String description;
+
+    /**
+     * 如果为-1,表示对所有课程均有效
+     */
+    private Integer courseId;
+
+    /**
+     * 如果为-1,表示对所有用户均有效
+     */
+    private Integer userId;
+
+    /**
+     * 使用门槛
+     */
+    private Integer threshold;
+
+    /**
+     * 折扣型 - 折扣(介于0~1之间)
+     */
+    private double discount;
+
+    /**
+     * 减价金额
+     */
+    private Integer cutDown;
+
+    /**
+     * 生效时间
+     */
+    private LocalDateTime startTime;
+
+    /**
+     * 失效时间
+     */
+    private LocalDateTime endTime;
+
+    /**
+     * 优惠券是否可用 true可用 false失效(一次性的券使用后就失效 或 网站关闭活动)
+     */
+    private Boolean effective;
+
+    /**
+     * 能否与其他优惠券同时使用 true可同时使用 false不能同时使用
+     */
+    private Boolean sharable;
+
+    public Coupon(CouponVO couponVO) {
+        this.type = CouponType.valueOf(couponVO.getType());
+        this.name = couponVO.getName();
+        this.description = couponVO.getDescription();
+        this.courseId = couponVO.getCourseId();
+        this.userId = couponVO.getUserId();
+        this.threshold = couponVO.getThreshold();
+        this.discount = couponVO.getDiscount();
+        this.cutDown = couponVO.getCutDown();
+        this.startTime = couponVO.getStartTime();
+        this.endTime = couponVO.getEndTime();
+        this.effective = couponVO.getEffective();
+        this.sharable = couponVO.getSharable();
+    }
+}

+ 22 - 0
src/main/java/cn/seecoder/courselearning/service/CouponService.java

@@ -0,0 +1,22 @@
+package cn.seecoder.courselearning.service;
+
+import cn.seecoder.courselearning.dto.CourseCouponDTO;
+import cn.seecoder.courselearning.dto.UniversalCouponDTO;
+import cn.seecoder.courselearning.dto.UserCouponDTO;
+import cn.seecoder.courselearning.vo.CouponVO;
+import cn.seecoder.courselearning.vo.CourseOrderVO;
+import cn.seecoder.courselearning.vo.ResultVO;
+
+import java.util.List;
+
+public interface CouponService {
+    ResultVO<CouponVO> createUniversalCoupon(UniversalCouponDTO universalCouponDTO);
+    ResultVO<CouponVO> createCourseCoupon(CourseCouponDTO courseCouponDTO);
+    ResultVO<CouponVO> createUserCoupon(UserCouponDTO userCouponDTO);
+    // 查看所有的网站通用型优惠券
+    List<CouponVO> getUniversalCoupons();
+    // 查看当前课程所有的课程优惠券(不含网站通用优惠券、用户定制化优惠券) 包含已经失效了的优惠活动
+    List<CouponVO> getCourseCoupons(Integer courseId);
+    // 查看当前用户购买此课程可生效的所有优惠
+    List<CouponVO> getAllEffectiveCouponsForOrder(CourseOrderVO orderVO);
+}

+ 40 - 0
src/main/java/cn/seecoder/courselearning/service/CouponStrategy.java

@@ -0,0 +1,40 @@
+package cn.seecoder.courselearning.service;
+
+import cn.seecoder.courselearning.po.Coupon;
+import cn.seecoder.courselearning.vo.CourseOrderVO;
+
+import java.time.LocalDateTime;
+
+// 优惠券匹配策略
+public interface CouponStrategy {
+
+    /**
+     * 根据当前优惠券匹配策略
+     *   判断当前优惠活动 或 优惠券是否适用于此课程订单
+     * 例如,coupon1 是网站优惠活动产生的通用型优惠券,那么它在通用优惠活动策略下 就适用于任何课程
+     * @param orderVO 课程订单
+     * @param coupon 优惠活动 或 优惠券
+     */
+    boolean isMatch(CourseOrderVO orderVO, Coupon coupon);
+
+    /**
+     * 判断优惠券是否对此订单有效
+     * @param orderVO 课程订单
+     * @param coupon 优惠活动 或 优惠券
+     * @return 优惠券是否有效
+     */
+    default boolean isEffective(CourseOrderVO orderVO, Coupon coupon) {
+        // 获取当前时间
+        LocalDateTime now = LocalDateTime.now();
+        if (isMatch(orderVO, coupon)) {
+            return coupon.getEffective() && coupon.getThreshold()>=orderVO.getCost()
+                    && (coupon.getStartTime()==null || now.isAfter(coupon.getStartTime()))
+                    && (coupon.getEndTime()==null || now.isBefore(coupon.getEndTime()));
+        }
+        return false;
+    }
+
+    default void useCoupon(CourseOrderVO orderVO, Coupon coupon) {
+
+    }
+}

+ 118 - 0
src/main/java/cn/seecoder/courselearning/serviceimpl/CouponServiceImpl.java

@@ -0,0 +1,118 @@
+package cn.seecoder.courselearning.serviceimpl;
+
+import cn.seecoder.courselearning.dto.CourseCouponDTO;
+import cn.seecoder.courselearning.dto.UniversalCouponDTO;
+import cn.seecoder.courselearning.dto.UserCouponDTO;
+import cn.seecoder.courselearning.mapperservice.CouponMapper;
+import cn.seecoder.courselearning.po.Coupon;
+import cn.seecoder.courselearning.service.CouponStrategy;
+import cn.seecoder.courselearning.service.CouponService;
+import cn.seecoder.courselearning.serviceimpl.couponstrategy.CourseCouponStrategyImpl;
+import cn.seecoder.courselearning.serviceimpl.couponstrategy.UniversalCouponStrategyImpl;
+import cn.seecoder.courselearning.serviceimpl.couponstrategy.UserCouponStrategyImpl;
+import cn.seecoder.courselearning.util.Constant;
+import cn.seecoder.courselearning.util.CouponValidator;
+import cn.seecoder.courselearning.vo.CouponVO;
+import cn.seecoder.courselearning.vo.CourseOrderVO;
+import cn.seecoder.courselearning.vo.ResultVO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class CouponServiceImpl implements CouponService {
+    @Resource
+    private CouponMapper couponMapper;
+
+    private final List<CouponStrategy> couponStrategyList;
+
+    @Autowired
+    public CouponServiceImpl(UniversalCouponStrategyImpl universalCouponMatchStrategy, CourseCouponStrategyImpl courseCouponMatchStrategy, UserCouponStrategyImpl userCouponMatchStrategy) {
+        couponStrategyList = new ArrayList<>();
+        couponStrategyList.add(universalCouponMatchStrategy);
+        couponStrategyList.add(courseCouponMatchStrategy);
+        couponStrategyList.add(userCouponMatchStrategy);
+    }
+
+    @Override
+    public ResultVO<CouponVO> createUniversalCoupon(UniversalCouponDTO universalCouponDTO) {
+        Coupon coupon = new Coupon();
+        BeanUtils.copyProperties(universalCouponDTO, coupon);
+        // 网站优惠活动生成的优惠券一定是对所有用户、所有课程均有效的
+        coupon.setUserId(-1);
+        coupon.setCourseId(-1);
+        coupon.setEffective(true);
+        if(CouponValidator.isInvalid(coupon))
+            return new ResultVO<>(Constant.REQUEST_FAIL, "优惠信息填写有误!");
+        if(couponMapper.insert(coupon) > 0)
+            return new ResultVO<>(Constant.REQUEST_SUCCESS, "网站优惠活动创建成功", new CouponVO(coupon));
+        return new ResultVO<>(Constant.REQUEST_FAIL, "网站优惠活动创建失败");
+    }
+
+    @Override
+    public ResultVO<CouponVO> createCourseCoupon(CourseCouponDTO courseCouponDTO) {
+        Coupon coupon = new Coupon();
+        BeanUtils.copyProperties(courseCouponDTO, coupon);
+        // 课程优惠活动生成的优惠券是对所有用户均有效的
+        coupon.setUserId(-1);
+        coupon.setEffective(true);
+        if(CouponValidator.isInvalid(coupon) || coupon.getCourseId() == -1)
+            return new ResultVO<>(Constant.REQUEST_FAIL, "优惠信息填写有误!");
+        if(couponMapper.insert(coupon) > 0)
+            return new ResultVO<>(Constant.REQUEST_SUCCESS, "课程优惠活动创建成功", new CouponVO(coupon));
+        return new ResultVO<>(Constant.REQUEST_FAIL, "课程优惠活动创建失败");
+    }
+
+    @Override
+    public ResultVO<CouponVO> createUserCoupon(UserCouponDTO userCouponDTO) {
+        Coupon coupon = new Coupon();
+        BeanUtils.copyProperties(userCouponDTO, coupon);
+        coupon.setEffective(true);
+        // 用户定制化优惠活动生成的优惠券仅对某个用户有效
+        if(CouponValidator.isInvalid(coupon) || coupon.getUserId() == -1)
+            return new ResultVO<>(Constant.REQUEST_FAIL, "优惠信息填写有误!");
+        if(couponMapper.insert(coupon) > 0)
+            return new ResultVO<>(Constant.REQUEST_SUCCESS, "用户优惠券发放成功", new CouponVO(coupon));
+        return new ResultVO<>(Constant.REQUEST_FAIL, "用户优惠券发放失败");
+    }
+
+    @Override
+    public List<CouponVO> getUniversalCoupons() {
+        List<Coupon> couponList = couponMapper.selectByCourseIdAndUserId(-1, -1);
+        List<CouponVO> ret = new ArrayList<>();
+        couponList.forEach(coupon -> ret.add(new CouponVO(coupon)));
+        return ret;
+    }
+
+    @Override
+    public List<CouponVO> getCourseCoupons(Integer courseId) {
+        List<Coupon> couponList = couponMapper.selectByCourseIdAndUserId(courseId, -1);
+        List<CouponVO> ret = new ArrayList<>();
+        couponList.forEach(coupon -> ret.add(new CouponVO(coupon)));
+        return ret;
+    }
+
+    @Override
+    public List<CouponVO> getAllEffectiveCouponsForOrder(CourseOrderVO orderVO) {
+        List<Coupon> universalCoupons = couponMapper.selectByCourseIdAndUserId(-1, -1);
+        List<Coupon> courseCoupons = couponMapper.selectByCourseIdAndUserId(orderVO.getCourseId(), -1);
+        List<Coupon> userCoupons = couponMapper.selectByUserId(orderVO.getUserId());
+        List<Coupon> temp = new ArrayList<>(universalCoupons);
+        temp.addAll(courseCoupons);
+        temp.addAll(userCoupons);
+        List<CouponVO> ret = new ArrayList<>();
+        temp.forEach(coupon -> {
+            for(CouponStrategy strategy: couponStrategyList) {
+                if (strategy.isEffective(orderVO, coupon)) {
+                    ret.add(new CouponVO(coupon));
+                    break;
+                }
+            }
+        });
+        return ret;
+    }
+}

+ 14 - 0
src/main/java/cn/seecoder/courselearning/serviceimpl/couponstrategy/CourseCouponStrategyImpl.java

@@ -0,0 +1,14 @@
+package cn.seecoder.courselearning.serviceimpl.couponstrategy;
+
+import cn.seecoder.courselearning.po.Coupon;
+import cn.seecoder.courselearning.service.CouponStrategy;
+import cn.seecoder.courselearning.vo.CourseOrderVO;
+import org.springframework.stereotype.Service;
+
+@Service
+public class CourseCouponStrategyImpl implements CouponStrategy {
+    @Override
+    public boolean isMatch(CourseOrderVO orderVO, Coupon coupon) {
+        return coupon.getCourseId().equals(orderVO.getCourseId()) && coupon.getUserId() == -1;
+    }
+}

+ 14 - 0
src/main/java/cn/seecoder/courselearning/serviceimpl/couponstrategy/UniversalCouponStrategyImpl.java

@@ -0,0 +1,14 @@
+package cn.seecoder.courselearning.serviceimpl.couponstrategy;
+
+import cn.seecoder.courselearning.po.Coupon;
+import cn.seecoder.courselearning.service.CouponStrategy;
+import cn.seecoder.courselearning.vo.CourseOrderVO;
+import org.springframework.stereotype.Service;
+
+@Service
+public class UniversalCouponStrategyImpl implements CouponStrategy {
+    @Override
+    public boolean isMatch(CourseOrderVO orderVO, Coupon coupon) {
+        return coupon.getCourseId() == -1 && coupon.getUserId() == -1;
+    }
+}

+ 14 - 0
src/main/java/cn/seecoder/courselearning/serviceimpl/couponstrategy/UserCouponStrategyImpl.java

@@ -0,0 +1,14 @@
+package cn.seecoder.courselearning.serviceimpl.couponstrategy;
+
+import cn.seecoder.courselearning.po.Coupon;
+import cn.seecoder.courselearning.service.CouponStrategy;
+import cn.seecoder.courselearning.vo.CourseOrderVO;
+import org.springframework.stereotype.Service;
+
+@Service
+public class UserCouponStrategyImpl implements CouponStrategy {
+    @Override
+    public boolean isMatch(CourseOrderVO orderVO, Coupon coupon) {
+        return coupon.getCourseId() == -1 || (coupon.getCourseId().equals(orderVO.getCourseId()) && coupon.getUserId().equals(orderVO.getUserId()));
+    }
+}

+ 16 - 0
src/main/java/cn/seecoder/courselearning/util/CouponValidator.java

@@ -0,0 +1,16 @@
+package cn.seecoder.courselearning.util;
+
+import cn.seecoder.courselearning.po.Coupon;
+
+public class CouponValidator {
+    public static boolean isInvalid(Coupon coupon) {
+        if (coupon.getCourseId() < -1 || coupon.getUserId() < -1)
+            return true;
+        if (coupon.getStartTime() != null && coupon.getEndTime() != null
+                && coupon.getStartTime().isAfter(coupon.getEndTime()))
+            return true;
+        if (coupon.getDiscount() > 1 || coupon.getDiscount() < 0)
+            return true;
+        return coupon.getCutDown() < 0;
+    }
+}

+ 91 - 0
src/main/java/cn/seecoder/courselearning/vo/CouponVO.java

@@ -0,0 +1,91 @@
+package cn.seecoder.courselearning.vo;
+
+import cn.seecoder.courselearning.po.Coupon;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@NoArgsConstructor
+public class CouponVO {
+    /**
+     * 优惠券id
+     */
+    private Integer id;
+
+    /**
+     * 优惠券类型(折扣型、减价型)
+     */
+    private String type;
+
+    /**
+     * 优惠券名称
+     */
+    private String name;
+
+    /**
+     * 优惠券描述
+     */
+    private String description;
+
+    /**
+     * 如果为-1,表示对所有课程均有效
+     */
+    private Integer courseId;
+
+    /**
+     * 如果为-1,表示对所有用户均有效
+     */
+    private Integer userId;
+
+    /**
+     * 满减型 - 使用门槛
+     */
+    private Integer threshold;
+
+    /**
+     * 折扣型 - 折扣(介于0~1之间)
+     */
+    private double discount;
+
+    /**
+     * 满减型 - 优惠金额
+     */
+    private Integer cutDown;
+
+    /**
+     * 生效时间
+     */
+    private LocalDateTime startTime;
+
+    /**
+     * 失效时间
+     */
+    private LocalDateTime endTime;
+
+    /**
+     * 优惠券是否可用 true可用 false失效(一次性的券使用后就失效 或 网站关闭活动)
+     */
+    private Boolean effective;
+
+    /**
+     * 能否与其他优惠券同时使用 true可同时使用 false不能同时使用
+     */
+    private Boolean sharable;
+
+    public CouponVO(Coupon coupon) {
+        this.type = coupon.getType().toString();
+        this.name = coupon.getName();
+        this.description = coupon.getDescription();
+        this.courseId = coupon.getCourseId();
+        this.userId = coupon.getUserId();
+        this.threshold = coupon.getThreshold();
+        this.discount = coupon.getDiscount();
+        this.cutDown = coupon.getCutDown();
+        this.startTime = coupon.getStartTime();
+        this.endTime = coupon.getEndTime();
+        this.effective = coupon.getEffective();
+        this.sharable = coupon.getSharable();
+    }
+}

+ 9 - 6
src/main/resources/generatorConfig.xml

@@ -20,10 +20,12 @@
                         connectionURL="jdbc:mysql://localhost:3306/courselearning?useUnicode=true&amp;characterEncoding=UTF-8&amp;userSSL=false&amp;serverTimezone=GMT%2B8"
                         userId="root"
                         password="123456">
+            <!--防止生成其他库同名表-->
+            <property name="nullCatalogMeansCurrent" value="true"/>
         </jdbcConnection>
 
          <!--生成model类的存放位置 -->
-         <javaModelGenerator targetPackage="cn.seecoder.courselearning.po" targetProject="src/main/java">
+         <javaModelGenerator targetPackage="cn.seecoder.courselearning.vo" targetProject="src/main/java">
              <property name="enableSubPackages" value="true"/>
              <property name="trimStrings" value="true"/>
          </javaModelGenerator>
@@ -39,10 +41,11 @@
          </javaClientGenerator>
          
 		 <!-- 生成对应的表及类名 -->
-<!--         <table tableName="course" domainObjectName="Course" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
-<!--         <table tableName="course_ware" domainObjectName="CourseWare" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
-<!--         <table tableName="user_info" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
-         <table tableName="recharge_order" domainObjectName="RechargeOrder" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
-<!--         <table tableName="course_order" domainObjectName="CourseOrder" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
+<!--         <table tableName="course" domainObjectName="Course" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
+<!--         <table tableName="course_ware" domainObjectName="CourseWare" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
+<!--         <table tableName="user_info" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
+<!--         <table tableName="recharge_order" domainObjectName="RechargeOrder" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
+<!--         <table tableName="course_order" domainObjectName="CourseOrder" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
+         <table tableName="coupon" domainObjectName="Coupon" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>
      </context>
  </generatorConfiguration>

+ 80 - 0
src/main/resources/mapper/CouponMapper.xml

@@ -0,0 +1,80 @@
+<?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="cn.seecoder.courselearning.mapperservice.CouponMapper">
+  <resultMap id="BaseResultMap" type="cn.seecoder.courselearning.po.Coupon">
+    <id column="id" jdbcType="INTEGER" property="id" />
+    <result column="type" jdbcType="VARCHAR" property="type" />
+    <result column="name" jdbcType="VARCHAR" property="name" />
+    <result column="description" jdbcType="VARCHAR" property="description" />
+    <result column="course_id" jdbcType="INTEGER" property="courseId" />
+    <result column="user_id" jdbcType="INTEGER" property="userId" />
+    <result column="threshold" jdbcType="INTEGER" property="threshold" />
+    <result column="discount" jdbcType="DOUBLE" property="discount" />
+    <result column="cut_down" jdbcType="INTEGER" property="cutDown" />
+    <result column="start_time" jdbcType="TIMESTAMP" property="startTime" />
+    <result column="end_time" jdbcType="TIMESTAMP" property="endTime" />
+    <result column="effective" jdbcType="BIT" property="effective" />
+    <result column="sharable" jdbcType="BIT" property="sharable" />
+  </resultMap>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
+    delete from coupon
+    where id = #{id,jdbcType=INTEGER}
+  </delete>
+  <insert id="insert" parameterType="cn.seecoder.courselearning.po.Coupon" useGeneratedKeys="true" keyProperty="id">
+    insert into coupon (id, type, name, 
+      description, course_id, user_id, 
+      threshold, discount, cut_down, 
+      start_time, end_time, effective, 
+      sharable)
+    values (#{id,jdbcType=INTEGER}, #{type,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, 
+      #{description,jdbcType=VARCHAR}, #{courseId,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, 
+      #{threshold,jdbcType=INTEGER}, #{discount,jdbcType=DOUBLE}, #{cutDown,jdbcType=INTEGER}, 
+      #{startTime,jdbcType=TIMESTAMP}, #{endTime,jdbcType=TIMESTAMP}, #{effective,jdbcType=BIT}, 
+      #{sharable,jdbcType=BIT})
+  </insert>
+  <update id="updateByPrimaryKey" parameterType="cn.seecoder.courselearning.po.Coupon">
+    update coupon
+    set type = #{type,jdbcType=VARCHAR},
+      name = #{name,jdbcType=VARCHAR},
+      description = #{description,jdbcType=VARCHAR},
+      course_id = #{courseId,jdbcType=INTEGER},
+      user_id = #{userId,jdbcType=INTEGER},
+      threshold = #{threshold,jdbcType=INTEGER},
+      discount = #{discount,jdbcType=DOUBLE},
+      cut_down = #{cutDown,jdbcType=INTEGER},
+      start_time = #{startTime,jdbcType=TIMESTAMP},
+      end_time = #{endTime,jdbcType=TIMESTAMP},
+      effective = #{effective,jdbcType=BIT},
+      sharable = #{sharable,jdbcType=BIT}
+    where id = #{id,jdbcType=INTEGER}
+  </update>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
+    select id, type, name, description, course_id, user_id, threshold, discount, cut_down, 
+    start_time, end_time, effective, sharable
+    from coupon
+    where id = #{id,jdbcType=INTEGER}
+  </select>
+  <select id="selectAll" resultMap="BaseResultMap">
+    select id, type, name, description, course_id, user_id, threshold, discount, cut_down, 
+    start_time, end_time, effective, sharable
+    from coupon
+  </select>
+<!--  <select id="selectAllCourseCoupon" parameterType="java.lang.Integer" resultMap="BaseResultMap">-->
+<!--    select id, type, name, description, course_id, user_id, threshold, discount, cut_down,-->
+<!--           start_time, end_time, effective, sharable-->
+<!--    from coupon-->
+<!--    where (course_id = -1 or course_id = #{courseId,jdbcType=INTEGER}) and user_id = -1-->
+<!--  </select>-->
+  <select id="selectByCourseIdAndUserId" parameterType="java.lang.Integer" resultMap="BaseResultMap">
+    select id, type, name, description, course_id, user_id, threshold, discount, cut_down,
+           start_time, end_time, effective, sharable
+    from coupon
+    where course_id = #{courseId,jdbcType=INTEGER} and user_id = #{userId,jdbcType=INTEGER}
+  </select>
+  <select id="selectByUserId" parameterType="java.lang.Integer" resultMap="BaseResultMap">
+    select id, type, name, description, course_id, user_id, threshold, discount, cut_down,
+           start_time, end_time, effective, sharable
+    from coupon
+    where user_id = #{userId,jdbcType=INTEGER}
+  </select>
+</mapper>