提交 56c5a292 authored 作者: sin's avatar sin

Merge remote-tracking branch 'origin/master'

# Conflicts: # mobile-web/src/api/promotion.js # mobile-web/src/config/request.js
...@@ -26,6 +26,9 @@ public class DateUtil { ...@@ -26,6 +26,9 @@ public class DateUtil {
* @return 计算后的日志 * @return 计算后的日志
*/ */
public static Date addDate(Date date, int field, int amount) { public static Date addDate(Date date, int field, int amount) {
if (amount == 0) {
return date;
}
Calendar c = Calendar.getInstance(); Calendar c = Calendar.getInstance();
if (date != null) { if (date != null) {
c.setTime(date); c.setTime(date);
......
...@@ -15,5 +15,45 @@ export function getProductRecommendList() { ...@@ -15,5 +15,45 @@ export function getProductRecommendList() {
return request({ return request({
url: '/promotion-api/users/product_recommend/list', url: '/promotion-api/users/product_recommend/list',
method: 'get', method: 'get',
params: {
id,
}
});
}
// Coupon Template
export function getCouponTemplate(id) {
return request({
url: '/promotion-api/users/coupon/template/get',
method: 'get',
params: {
id,
}
});
}
export function doAddCouponCard(templateId) {
return request({
url: '/promotion-api/users/coupon/card/add',
method: 'post',
params: {
templateId,
}
});
}
// Coupon Card
export function getCouponPage(status, pageNo, pageSize) {
return request({
url: '/promotion-api/users/coupon/card/page',
method: 'get',
params: {
status,
pageNo,
pageSize
}
}); });
} }
/** /**
* 配置编译环境和线上环境之间的切换 * 配置编译环境和线上环境之间的切换
* *
* baseUrl: 域名地址 * baseUrl: 域名地址
* routerMode: 路由模式 * routerMode: 路由模式
* dataSources:数据源 * dataSources:数据源
*/ */
let baseUrl = ''; let baseUrl = '';
let routerMode = 'hash'; let routerMode = 'hash';
let dataSources='local';//local=本地,其他值代表非本地 let dataSources='local';//local=本地,其他值代表非本地
...@@ -27,4 +27,4 @@ export { ...@@ -27,4 +27,4 @@ export {
baseUrl, baseUrl,
routerMode, routerMode,
dataSources, dataSources,
} }
\ No newline at end of file
...@@ -135,8 +135,8 @@ service.interceptors.request.use( ...@@ -135,8 +135,8 @@ service.interceptors.request.use(
const { target, prefix } = serviceRouter(config.url) const { target, prefix } = serviceRouter(config.url)
let url = config.url = config.url.replace(`${prefix}`, target); let url = config.url = config.url.replace(`${prefix}`, target);
// TODO 芋艿,这些 url 不用增加认证 token 。可能这么写,有点脏,后面看看咋优化下。 // TODO 芋艿,这些 url 不用增加认证 token 。可能这么写,有点脏,后面看看咋优化下。
if (url.indexOf('user-api/users/passport/mobile/send_register_code') != -1 if (url.indexOf('user-api/users/passport/mobile/send_register_code') !== -1
|| url.indexOf('user-api/users/passport/mobile/register') != -1) { || url.indexOf('user-api/users/passport/mobile/register') !== -1) {
return config; return config;
} }
......
import Vue from 'vue'; import Vue from 'vue';
import Router from 'vue-router'; import Router from 'vue-router';
import { getAccessToken } from '../utils/cache';
Vue.use(Router); Vue.use(Router);
const routes = [ const routes = [
...@@ -84,7 +86,8 @@ const routes = [ ...@@ -84,7 +86,8 @@ const routes = [
path: '/user/coupon', path: '/user/coupon',
component: () => import('../page/user/coupon/list'), component: () => import('../page/user/coupon/list'),
meta: { meta: {
title: '我的优惠券' title: '我的优惠券',
requireAuth: true,
} }
}, },
{ {
...@@ -192,6 +195,13 @@ const routes = [ ...@@ -192,6 +195,13 @@ const routes = [
title: '分类' title: '分类'
} }
}, },
{
path: '/coupon/fetch',
component: () => import('../page/coupon/fetch'),
meta: {
title: '优惠劵领取'
}
}
]; ];
// add route path // add route path
...@@ -202,10 +212,23 @@ routes.forEach(route => { ...@@ -202,10 +212,23 @@ routes.forEach(route => {
const router = new Router({ routes }); const router = new Router({ routes });
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
// 判断是否需要认证
const requireAuth = to.meta && to.meta.requireAuth;
if (requireAuth) {
if (!getAccessToken()) { // 未登陆
next({
path: '/login',
query: {redirect: to.fullPath} // 将跳转的路由path作为参数,登录成功后跳转到该路由
});
return;
}
}
// 处理标题
const title = to.meta && to.meta.title; const title = to.meta && to.meta.title;
if (title) { if (title) {
document.title = title; document.title = title;
} }
// 继续路由
next(); next();
}); });
......
...@@ -7,6 +7,8 @@ import VueLazyload from 'vue-lazyload' ...@@ -7,6 +7,8 @@ import VueLazyload from 'vue-lazyload'
import components from './config/components.js'; import components from './config/components.js';
import { Dialog } from 'vant'; import { Dialog } from 'vant';
import { formatDate } from './utils/date.js';
Vue.use(components); Vue.use(components);
Vue.use(VueLazyload); Vue.use(VueLazyload);
...@@ -16,4 +18,10 @@ new Vue({ ...@@ -16,4 +18,10 @@ new Vue({
router, router,
el: '#app', el: '#app',
render: h => h(App) render: h => h(App)
}); });
\ No newline at end of file
Vue.filter('formatDate', function(date, pattern) {
if (date) {
return formatDate(date, pattern);
}
});
...@@ -73,8 +73,9 @@ export default { ...@@ -73,8 +73,9 @@ export default {
message: '登陆成功', message: '登陆成功',
beforeClose: function (action, done) { beforeClose: function (action, done) {
done(); done();
// TODO 芋艿,先暂时不做 callback // TODO 芋艿,简单的 callback 后续完善
that.$router.push('/user/index'); let redirect = that.$route.query.redirect || '/user/index';
that.$router.push(redirect);
} }
}); });
}); });
......
<template>
<div>
<van-cell-group>
<van-cell title="优惠劵编号" :value="couponTemplate.id" />
<van-cell title="优惠劵名" :value="couponTemplate.title"/>
</van-cell-group>
<van-button slot="button" size="small" type="primary" @click="onFetchClick">领取优惠劵</van-button>
</div>
</template>
<script>
import { getCouponTemplate, doAddCouponCard } from '../../api/promotion';
import { Dialog } from 'vant';
import { setLoginToken } from '../../utils/cache';
export default {
data() {
return {
couponTemplate: {
}
}
},
mounted() {
let id = this.$route.query.id;
let response = getCouponTemplate(id);
response.then(data => {
this.couponTemplate = data;
});
},
methods: {
onFetchClick: function () {
let that = this;
let id = this.$route.query.id;
let response = doAddCouponCard(id);
response.then(data => {
Dialog.alert({
title: '系统提示',
message: '领取成功',
beforeClose: function (action, done) {
// 关闭弹窗
done();
// 跳转到我的优惠劵
that.$router.push('/user/coupon');
}
});
});
}
}
}
</script>
...@@ -65,9 +65,9 @@ export default { ...@@ -65,9 +65,9 @@ export default {
} }
}, },
created:function(){ created:function(){
GetPage().then(response=>{ // GetPage().then(response=>{
this.page=response; // this.page=response;
}); // });
}, },
mounted: function() { mounted: function() {
// 加载 Banner // 加载 Banner
......
// TODO 临时代码
export function formatDate(date, pattern) {
if (!(date instanceof Date)) {
date = new Date(date);
}
if (pattern === 'yyyy-MM-dd') {
let d = date.getDate();
let m = date.getMonth() + 1; //Month from 0 to 11
let y = date.getFullYear();
return '' + y + '-' + (m <= 9 ? '0' + m : m) + '-' + (d <= 9 ? '0' + d : d);
} else {
return '暂不支持';
}
}
...@@ -2,6 +2,11 @@ package cn.iocoder.mall.promotion.application.config; ...@@ -2,6 +2,11 @@ package cn.iocoder.mall.promotion.application.config;
import cn.iocoder.common.framework.config.GlobalExceptionHandler; import cn.iocoder.common.framework.config.GlobalExceptionHandler;
import cn.iocoder.common.framework.servlet.CorsFilter; import cn.iocoder.common.framework.servlet.CorsFilter;
import cn.iocoder.mall.admin.sdk.interceptor.AdminAccessLogInterceptor;
import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor;
import cn.iocoder.mall.user.sdk.interceptor.UserAccessLogInterceptor;
import cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -14,23 +19,31 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; ...@@ -14,23 +19,31 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc @EnableWebMvc
@Configuration @Configuration
@Import(value = {GlobalExceptionHandler.class, // 统一全局返回 @Import(value = {GlobalExceptionHandler.class, // 统一全局返回
// AdminSecurityInterceptor.class AdminSecurityInterceptor.class, UserAccessLogInterceptor.class,
UserSecurityInterceptor.class, AdminAccessLogInterceptor.class,
}) })
public class MVCConfiguration implements WebMvcConfigurer { public class MVCConfiguration implements WebMvcConfigurer {
// @Autowired // @Autowired
// private UserSecurityInterceptor securityInterceptor; // private UserSecurityInterceptor securityInterceptor;
// @Autowired @Autowired
// private AdminSecurityInterceptor adminSecurityInterceptor; private UserSecurityInterceptor userSecurityInterceptor;
// @Autowired @Autowired
// private AdminAccessLogInterceptor adminAccessLogInterceptor; private UserAccessLogInterceptor userAccessLogInterceptor;
@Autowired
private AdminSecurityInterceptor adminSecurityInterceptor;
@Autowired
private AdminAccessLogInterceptor adminAccessLogInterceptor;
// //
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(securityInterceptor).addPathPatterns("/user/**", "/admin/**"); // 只拦截我们定义的接口 // 用户
// registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**"); registry.addInterceptor(userAccessLogInterceptor).addPathPatterns("/users/**");
// registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**"); registry.addInterceptor(userSecurityInterceptor).addPathPatterns("/users/**"); // 只拦截我们定义的接口
// 管理员
registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**");
} }
@Override @Override
...@@ -48,4 +61,4 @@ public class MVCConfiguration implements WebMvcConfigurer { ...@@ -48,4 +61,4 @@ public class MVCConfiguration implements WebMvcConfigurer {
return registrationBean; return registrationBean;
} }
} }
\ No newline at end of file
...@@ -19,7 +19,7 @@ import java.util.List; ...@@ -19,7 +19,7 @@ import java.util.List;
@RestController @RestController
@RequestMapping("users/banner") @RequestMapping("users/banner")
@Api("Banner 模块") @Api("Banner 模块")
public class UsersProductCategoryController { public class UsersBannerController {
@Reference(validation = "true") @Reference(validation = "true")
private BannerService bannerService; private BannerService bannerService;
...@@ -35,4 +35,5 @@ public class UsersProductCategoryController { ...@@ -35,4 +35,5 @@ public class UsersProductCategoryController {
return CommonResult.success(BannerConvert.INSTANCE.convertList(result)); return CommonResult.success(BannerConvert.INSTANCE.convertList(result));
} }
} }
\ No newline at end of file
package cn.iocoder.mall.promotion.application.controller.users;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.CouponService;
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO;
import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
import cn.iocoder.mall.promotion.api.dto.CouponCardPageDTO;
import cn.iocoder.mall.promotion.application.convert.CouponCardConvert;
import cn.iocoder.mall.promotion.application.convert.CouponTemplateConvert;
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponCardPageVO;
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponCardVO;
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponTemplateVO;
import cn.iocoder.mall.user.sdk.annotation.PermitAll;
import cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder;
import com.alibaba.dubbo.config.annotation.Reference;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("users/coupon")
@Api("优惠劵(码)模块")
public class UsersCouponController {
@Reference(validation = "true")
private CouponService couponService;
// ========== 优惠劵(码)模板 ==========
@GetMapping("/template/get")
@ApiOperation(value = "优惠劵(码)模板信息")
@ApiImplicitParam(name = "id", value = "优惠劵(码)模板编号", required = true, example = "10")
@PermitAll
public CommonResult<UsersCouponTemplateVO> templateGet(@RequestParam("id") Integer id) {
CouponTemplateBO template = couponService.getCouponTemplate(id).getData();
return CommonResult.success(CouponTemplateConvert.INSTANCE.convert2(template));
}
// ========== 优惠劵 ==========
@GetMapping("/card/page")
@ApiOperation(value = "优惠劵分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "status", value = "状态", example = "参考 CouponCardStatusEnum 枚举"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
})
public CommonResult<UsersCouponCardPageVO> cardPage(@RequestParam(value = "status", required = false) Integer status,
@RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
CommonResult<CouponCardPageBO> result = couponService.getCouponCardPage(new CouponCardPageDTO()
.setStatus(status).setUserId(UserSecurityContextHolder.getContext().getUserId())
.setPageNo(pageNo).setPageSize(pageSize));
return CouponCardConvert.INSTANCE.convert2(result);
}
@PostMapping("/card/add")
@ApiOperation(value = "领取优惠劵")
@ApiImplicitParam(name = "templateId", value = "优惠劵(码)模板编号", required = true, example = "10")
public CommonResult<UsersCouponCardVO> cardAdd(@RequestParam("templateId") Integer templateId) {
CommonResult<CouponCardBO> result = couponService.addCouponCard(UserSecurityContextHolder.getContext().getUserId(), templateId);
return CouponCardConvert.INSTANCE.convert(result);
}
// ========== 优惠码 ==========
}
package cn.iocoder.mall.promotion.application.convert;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO;
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponCardPageVO;
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponCardVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper
public interface CouponCardConvert {
CouponCardConvert INSTANCE = Mappers.getMapper(CouponCardConvert.class);
@Mappings({})
CommonResult<UsersCouponCardVO> convert(CommonResult<CouponCardBO> result);
@Mappings({})
CommonResult<UsersCouponCardPageVO> convert2(CommonResult<CouponCardPageBO> result);
//
// @Mappings({})
// List<UsersCouponTemplateVO> convertList2(List<CouponTemplateBO> banners);
}
...@@ -5,6 +5,7 @@ import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO; ...@@ -5,6 +5,7 @@ import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO; import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO;
import cn.iocoder.mall.promotion.application.vo.admins.AdminsCouponTemplatePageVO; import cn.iocoder.mall.promotion.application.vo.admins.AdminsCouponTemplatePageVO;
import cn.iocoder.mall.promotion.application.vo.admins.AdminsCouponTemplateVO; import cn.iocoder.mall.promotion.application.vo.admins.AdminsCouponTemplateVO;
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponTemplateVO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
...@@ -28,6 +29,9 @@ public interface CouponTemplateConvert { ...@@ -28,6 +29,9 @@ public interface CouponTemplateConvert {
@Mappings({}) @Mappings({})
List<AdminsCouponTemplateVO> convertList(List<CouponTemplateBO> templates); List<AdminsCouponTemplateVO> convertList(List<CouponTemplateBO> templates);
@Mappings({})
UsersCouponTemplateVO convert2(CouponTemplateBO template);
// //
// @Mappings({}) // @Mappings({})
// List<UsersCouponTemplateVO> convertList2(List<CouponTemplateBO> banners); // List<UsersCouponTemplateVO> convertList2(List<CouponTemplateBO> banners);
......
...@@ -59,7 +59,7 @@ public class AdminsCouponTemplateVO { ...@@ -59,7 +59,7 @@ public class AdminsCouponTemplateVO {
// ========== 使用规则 END ========== // ========== 使用规则 END ==========
// ========== 使用效果 BEGIN ========== // ========== 使用效果 BEGIN ==========
@ApiModelProperty(value = "优惠类型", example = "参见 CouponTemplatePreferentialTypeEnum 枚举") @ApiModelProperty(value = "优惠类型", required = true, example = "参见 CouponTemplatePreferentialTypeEnum 枚举")
private Integer preferentialType; private Integer preferentialType;
@ApiModelProperty(value = "折扣百分比") @ApiModelProperty(value = "折扣百分比")
private Integer percentOff; private Integer percentOff;
...@@ -70,11 +70,11 @@ public class AdminsCouponTemplateVO { ...@@ -70,11 +70,11 @@ public class AdminsCouponTemplateVO {
// ========== 使用效果 END ========== // ========== 使用效果 END ==========
// ========== 统计信息 BEGIN ========== // ========== 统计信息 BEGIN ==========
@ApiModelProperty(value = "折扣上限", required = true) @ApiModelProperty(value = "领取优惠券的次数", required = true)
private Integer statFetchNum; private Integer statFetchNum;
// ========== 统计信息 END ========== // ========== 统计信息 END ==========
@ApiModelProperty(value = "折扣上限", required = true) @ApiModelProperty(value = "创建时间", required = true)
private Date createTime; private Date createTime;
} }
package cn.iocoder.mall.promotion.application.vo.users;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@ApiModel("优惠劵分页 VO")
@Data
@Accessors(chain = true)
public class UsersCouponCardPageVO {
@ApiModelProperty(value = "优惠劵数组")
private List<UsersCouponCardVO> list;
@ApiModelProperty(value = "优惠劵总数")
private Integer total;
}
package cn.iocoder.mall.promotion.application.vo.users;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 优惠劵 VO
*/
@Data
@Accessors(chain = true)
public class UsersCouponCardVO {
// ========== 基本信息 BEGIN ==========
@ApiModelProperty(value = "优惠劵编号", required = true, example = "1")
private Integer id;
@ApiModelProperty(value = "模板编号,自增唯一", required = true, example = "1")
private Integer templateId;
@ApiModelProperty(value = "优惠劵名", required = true, example = "大保剑")
private String title;
@ApiModelProperty(value = "优惠码状态", required = true, example = "参见 CouponCardStatusEnum 枚举")
private Integer status;
// ========== 基本信息 END ==========
// ========== 使用规则 BEGIN ==========
@ApiModelProperty(value = "是否设置满多少金额可用,单位:分", required = true)
private Integer priceAvailable;
@ApiModelProperty(value = "固定日期-生效开始时间", required = true)
private Date validStartTime;
@ApiModelProperty(value = "固定日期-生效结束时间", required = true)
private Date validEndTime;
// ========== 使用规则 END ==========
// ========== 使用效果 BEGIN ==========
@ApiModelProperty(value = "优惠类型", required = true, example = "参见 CouponTemplatePreferentialTypeEnum 枚举")
private Integer preferentialType;
@ApiModelProperty(value = "折扣百分比")
private Integer percentOff;
@ApiModelProperty(value = "优惠金额,单位:分")
private Integer priceOff;
@ApiModelProperty(value = "折扣上限")
private Integer discountPriceLimit;
// ========== 使用效果 END ==========
// ========== 使用情况 BEGIN ==========
/**
* 是否使用
*/
@ApiModelProperty(value = "是否使用", required = true)
private Boolean used;
// TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。
// ========== 使用情况 END ==========
}
package cn.iocoder.mall.promotion.application.vo.users;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@ApiModel("CouponTemplate VO")
@Data
@Accessors(chain = true)
public class UsersCouponTemplateVO {
// ========== 基本信息 BEGIN ==========
@ApiModelProperty(value = "模板编号,自增唯一", required = true, example = "1")
private Integer id;
@ApiModelProperty(value = "标题", required = true, example = "优惠劵牛逼")
private String title;
@ApiModelProperty(value = "优惠码状态", required = true, example = "参见 CouponTemplateStatusEnum 枚举")
private Integer status;
// ========== 领取规则 END ==========
// ========== 使用规则 BEGIN ==========
@ApiModelProperty(value = "是否设置满多少金额可用,单位:分", required = true, example = "0-不限制;大于0-多少金额可用")
private Integer priceAvailable;
@ApiModelProperty(value = "可用范围的类型", required = true, example = "参见 CouponTemplateRangeTypeEnum 枚举")
private Integer rangeType;
@ApiModelProperty(value = "指定商品 / 分类列表,使用逗号分隔商品编号", example = "参见 CouponTemplateRangeTypeEnum 枚举")
private String rangeValues;
@ApiModelProperty(value = "生效日期类型", example = "参见 CouponTemplateDateTypeEnum 枚举")
private Integer dateType;
@ApiModelProperty(value = "固定日期-生效开始时间")
private Date validStartTime;
@ApiModelProperty(value = "固定日期-生效结束时间")
private Date validEndTime;
@ApiModelProperty(value = "领取日期-开始天数", example = "例如,0-当天;1-次天")
private Integer fixedStartTerm;
@ApiModelProperty(value = "领取日期-结束天数")
private Integer fixedEndTerm;
// ========== 使用规则 END ==========
// ========== 使用效果 BEGIN ==========
@ApiModelProperty(value = "优惠类型", required = true, example = "参见 CouponTemplatePreferentialTypeEnum 枚举")
private Integer preferentialType;
@ApiModelProperty(value = "折扣百分比")
private Integer percentOff;
@ApiModelProperty(value = "优惠金额,单位:分")
private Integer priceOff;
@ApiModelProperty(value = "折扣上限")
private Integer discountPriceLimit;
// ========== 使用效果 END ==========
}
...@@ -3,6 +3,7 @@ package cn.iocoder.mall.promotion.api; ...@@ -3,6 +3,7 @@ package cn.iocoder.mall.promotion.api;
import cn.iocoder.common.framework.validator.InEnum; import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.bo.CouponCardBO; import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO;
import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO; import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO; import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO;
import cn.iocoder.mall.promotion.api.constant.CouponTemplateStatusEnum; import cn.iocoder.mall.promotion.api.constant.CouponTemplateStatusEnum;
...@@ -12,6 +13,8 @@ public interface CouponService { ...@@ -12,6 +13,8 @@ public interface CouponService {
// ========== 优惠劵(码)模板 ========== // ========== 优惠劵(码)模板 ==========
CommonResult<CouponTemplateBO> getCouponTemplate(Integer couponTemplateId);
CommonResult<CouponTemplatePageBO> getCouponTemplatePage(CouponTemplatePageDTO couponTemplatePageDTO); CommonResult<CouponTemplatePageBO> getCouponTemplatePage(CouponTemplatePageDTO couponTemplatePageDTO);
/** /**
...@@ -59,6 +62,8 @@ public interface CouponService { ...@@ -59,6 +62,8 @@ public interface CouponService {
// ========== 优惠劵 ========== // ========== 优惠劵 ==========
CommonResult<CouponCardPageBO> getCouponCardPage(CouponCardPageDTO couponCardPageDTO);
/** /**
* 基于优惠劵模板,领取优惠劵 * 基于优惠劵模板,领取优惠劵
* *
......
...@@ -3,10 +3,121 @@ package cn.iocoder.mall.promotion.api.bo; ...@@ -3,10 +3,121 @@ package cn.iocoder.mall.promotion.api.bo;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.util.Date;
/** /**
* 优惠劵 BO * 优惠劵 BO
*/ */
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public class CouponCardBO { public class CouponCardBO {
// ========== 基本信息 BEGIN ==========
/**
* 优惠劵编号
*/
private Integer id;
/**
* 优惠劵(码)分组编号
*/
private Integer templateId;
/**
* 优惠劵名
*/
private String title;
// /**
// * 核销码
// */
// private String verifyCode;
/**
* 优惠码状态
*
* 1-未使用
* 2-已使用
* 3-已失效
*/
private Integer status;
// ========== 基本信息 END ==========
// ========== 领取情况 BEGIN ==========
/**
* 用户编号
*/
private Integer userId;
/**
* 领取类型
*
* 1 - 用户主动领取
* 2 - 后台自动发放
*/
private Integer takeType;
// ========== 领取情况 END ==========
// ========== 使用规则 BEGIN ==========
/**
* 是否设置满多少金额可用,单位:分
*/
private Integer priceAvailable;
/**
* 生效开始时间
*/
private Date validStartTime;
/**
* 生效结束时间
*/
private Date validEndTime;
// ========== 使用规则 END ==========
// ========== 使用效果 BEGIN ==========
/**
* 优惠类型
*
* 1-代金卷
* 2-折扣卷
*/
private Integer preferentialType;
/**
* 折扣
*/
private Integer percentOff;
/**
* 优惠金额,单位:分。
*/
private Integer priceOff;
/**
* 折扣上限,仅在 {@link #preferentialType} 等于 2 时生效。
*
* 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80 元。
*/
private Integer discountPriceLimit;
// ========== 使用效果 END ==========
// ========== 使用情况 BEGIN ==========
/**
* 是否使用
*/
private Boolean used;
/**
* 使用订单号
*/
private Integer usedOrderId;
/**
* 订单中优惠面值,单位:分
*/
private Integer usedPrice;
/**
* 使用时间
*/
private Date usedTime;
// TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。
// ========== 使用情况 END ==========
/**
* 创建时间
*/
private Date createTime;
} }
package cn.iocoder.mall.promotion.api.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 优惠劵分页 BO
*/
@Data
@Accessors(chain = true)
public class CouponCardPageBO {
/**
* 优惠劵数组
*/
private List<CouponCardBO> list;
/**
* 总量
*/
private Integer total;
}
package cn.iocoder.mall.promotion.api.constant;
import cn.iocoder.common.framework.core.IntArrayValuable;
import java.util.Arrays;
/**
* 优惠劵状态枚举
*/
public enum CouponCardStatusEnum implements IntArrayValuable {
UNUSED(1, "未使用"),
USED(2, "已使用"),
EXPIRE(3, "已过期"),
;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponCardStatusEnum::getValue).toArray();
/**
* 值
*/
private final Integer value;
/**
* 名字
*/
private final String name;
CouponCardStatusEnum(Integer value, String name) {
this.value = value;
this.name = name;
}
public Integer getValue() {
return value;
}
public String getName() {
return name;
}
@Override
public int[] array() {
return ARRAYS;
}
}
package cn.iocoder.mall.promotion.api.constant;
import cn.iocoder.common.framework.core.IntArrayValuable;
import java.util.Arrays;
/**
* 优惠劵领取方式
*/
public enum CouponCardTakeTypeEnum implements IntArrayValuable {
BY_USER(1, "用户主动领取"),
BY_ADMIN(2, "已使用"),
;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponCardTakeTypeEnum::getValue).toArray();
/**
* 值
*/
private final Integer value;
/**
* 名字
*/
private final String name;
CouponCardTakeTypeEnum(Integer value, String name) {
this.value = value;
this.name = name;
}
public Integer getValue() {
return value;
}
public String getName() {
return name;
}
@Override
public int[] array() {
return ARRAYS;
}
}
...@@ -6,8 +6,8 @@ import java.util.Arrays; ...@@ -6,8 +6,8 @@ import java.util.Arrays;
public enum CouponTemplateStatusEnum implements IntArrayValuable { public enum CouponTemplateStatusEnum implements IntArrayValuable {
ENABLE(1, "开启中"), ENABLE(1, "生效中"),
DISABLE(2, "禁用中"), DISABLE(2, "已失效"),
// EXPIRE(3, "已过期"), TODO 芋艿,暂时不考虑过期的 // EXPIRE(3, "已过期"), TODO 芋艿,暂时不考虑过期的
; ;
......
...@@ -21,7 +21,9 @@ public enum PromotionErrorCodeEnum { ...@@ -21,7 +21,9 @@ public enum PromotionErrorCodeEnum {
PRODUCT_TEMPLATE_NOT_CARD(1006002001, "不是优惠劵模板"), PRODUCT_TEMPLATE_NOT_CARD(1006002001, "不是优惠劵模板"),
PRODUCT_TEMPLATE_NOT_CODE(1006002002, "不是优惠码模板"), PRODUCT_TEMPLATE_NOT_CODE(1006002002, "不是优惠码模板"),
PRODUCT_TEMPLATE_TOTAL_CAN_NOT_REDUCE(1006002003, "优惠劵(码)模板的发放数量不能减小"), PRODUCT_TEMPLATE_TOTAL_CAN_NOT_REDUCE(1006002003, "优惠劵(码)模板的发放数量不能减小"),
PRODUCT_TEMPLATE_STATUS_NOT_ENABLE(1006002004, "优惠劵模板(码)未开启"),
PRODUCT_TEMPLATE_TOTAL_NOT_ENOUGH(1006002005, "优惠劵(码)模板的发放量不足"),
PRODUCT_TEMPLATE_CARD_ADD_EXCEED_QUOTA(1006002006, "优惠劵领取到达上限"),
; ;
private final int code; private final int code;
......
package cn.iocoder.mall.promotion.api.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
/**
* 优惠劵分页 DTO
*/
@Data
@Accessors(chain = true)
public class CouponCardPageDTO {
/**
* 用户编号
*/
private Integer userId;
/**
* 状态
*/
private Integer status;
@NotNull(message = "页码不能为空")
private Integer pageNo;
@NotNull(message = "每页条数不能为空")
private Integer pageSize;
}
package cn.iocoder.mall.promotion.biz.convert;
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface CouponCardConvert {
CouponCardConvert INSTANCE = Mappers.getMapper(CouponCardConvert.class);
// @Mappings({})
// CouponCardBO convertToBO(CouponCardDO banner);
//
@Mappings({})
List<CouponCardBO> convertToBO(List<CouponCardDO> cardList);
@Mappings({})
CouponCardBO convert(CouponCardDO card);
}
package cn.iocoder.mall.promotion.biz.dao;
import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CouponCardMapper {
CouponCardDO selectById(@Param("id") Integer id);
List<CouponCardDO> selectListByPage(@Param("userId") Integer userId,
@Param("status") Integer status,
@Param("offset") Integer offset,
@Param("limit") Integer limit);
Integer selectCountByPage(@Param("userId") Integer userId,
@Param("status") Integer status);
int selectCountByUserIdAndTemplateId(@Param("userId") Integer userId,
@Param("templateId") Integer templateId);
void insert(CouponCardDO couponCardDO);
int update(CouponCardDO couponCardDO);
}
...@@ -27,4 +27,6 @@ public interface CouponTemplateMapper { ...@@ -27,4 +27,6 @@ public interface CouponTemplateMapper {
int update(CouponTemplateDO couponTemplate); int update(CouponTemplateDO couponTemplate);
int updateStatFetchNumIncr(@Param("id") Integer id);
} }
...@@ -22,6 +22,14 @@ public class CouponCardDO extends BaseDO { ...@@ -22,6 +22,14 @@ public class CouponCardDO extends BaseDO {
* 优惠劵(码)分组编号,{@link CouponTemplateDO} 的 id * 优惠劵(码)分组编号,{@link CouponTemplateDO} 的 id
*/ */
private Integer templateId; private Integer templateId;
/**
* 优惠劵名
*
* 冗余自 {@link CouponTemplateDO} 的 title
*
* TODO 芋艿,暂时不考虑冗余的更新
*/
private String title;
// /** // /**
// * 核销码 // * 核销码
// */ // */
...@@ -53,11 +61,15 @@ public class CouponCardDO extends BaseDO { ...@@ -53,11 +61,15 @@ public class CouponCardDO extends BaseDO {
// ========== 使用规则 BEGIN ========== // ========== 使用规则 BEGIN ==========
/** /**
* 固定日期-生效开始时间 * 是否设置满多少金额可用,单位:分
*/
private Integer priceAvailable;
/**
* 生效开始时间
*/ */
private Date validStartTime; private Date validStartTime;
/** /**
* 固定日期-生效结束时间 * 生效结束时间
*/ */
private Date validEndTime; private Date validEndTime;
// ========== 使用规则 END ========== // ========== 使用规则 END ==========
...@@ -73,7 +85,7 @@ public class CouponCardDO extends BaseDO { ...@@ -73,7 +85,7 @@ public class CouponCardDO extends BaseDO {
/** /**
* 折扣 * 折扣
*/ */
private Double percentOff; private Integer percentOff;
/** /**
* 优惠金额,单位:分。 * 优惠金额,单位:分。
*/ */
...@@ -87,14 +99,10 @@ public class CouponCardDO extends BaseDO { ...@@ -87,14 +99,10 @@ public class CouponCardDO extends BaseDO {
// ========== 使用效果 END ========== // ========== 使用效果 END ==========
// ========== 使用情况 BEGIN ========== // ========== 使用情况 BEGIN ==========
/**
* 是否使用
*/
private Boolean used;
/** /**
* 使用订单号 * 使用订单号
*/ */
private String usedOrderId; private Integer usedOrderId;
/** /**
* 订单中优惠面值,单位:分 * 订单中优惠面值,单位:分
*/ */
......
...@@ -38,4 +38,6 @@ public class CouponCodeDO extends BaseDO { ...@@ -38,4 +38,6 @@ public class CouponCodeDO extends BaseDO {
*/ */
private Integer couponId; private Integer couponId;
// TODO 芋艿,后续要考虑状态的追踪
} }
...@@ -35,15 +35,6 @@ public class CouponTemplateDO extends BaseDO { ...@@ -35,15 +35,6 @@ public class CouponTemplateDO extends BaseDO {
* 2-优惠码 * 2-优惠码
*/ */
private Integer type; private Integer type;
/**
* 码类型
*
* 1-一卡一码(UNIQUE)
* 2-通用码(GENERAL)
*
* 【优惠码独有】 @see CouponCodeDO
*/
private Integer codeType;
/** /**
* 优惠码状态 * 优惠码状态
* *
...@@ -212,4 +203,20 @@ public class CouponTemplateDO extends BaseDO { ...@@ -212,4 +203,20 @@ public class CouponTemplateDO extends BaseDO {
// private Integer statUseNum; // private Integer statUseNum;
// ========== 统计信息 END ========== // ========== 统计信息 END ==========
// ========== 优惠码 BEGIN ==========
/**
* 码类型
*
* 1-一卡一码(UNIQUE)
* 2-通用码(GENERAL)
*
* 【优惠码独有】 @see CouponCodeDO
*/
private Integer codeType;
/**
* 通用码
*/
private String commonCode;
// ========== 优惠码 BEGIN ==========
} }
package cn.iocoder.mall.promotion.biz.scheduler;
/**
* 优惠劵过期 Job
*
* TODO 芋艿
*/
public class CouponCardExpireJob {
}
package cn.iocoder.mall.promotion.biz.service; package cn.iocoder.mall.promotion.biz.service;
import cn.iocoder.common.framework.constant.SysErrorCodeEnum; import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
import cn.iocoder.common.framework.util.DateUtil;
import cn.iocoder.common.framework.util.ServiceExceptionUtil; import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.CouponService; import cn.iocoder.mall.promotion.api.CouponService;
import cn.iocoder.mall.promotion.api.bo.CouponCardBO; import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO;
import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO; import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO; import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO;
import cn.iocoder.mall.promotion.api.constant.*; import cn.iocoder.mall.promotion.api.constant.*;
import cn.iocoder.mall.promotion.api.dto.*; import cn.iocoder.mall.promotion.api.dto.*;
import cn.iocoder.mall.promotion.biz.convert.CouponCardConvert;
import cn.iocoder.mall.promotion.biz.convert.CouponTemplateConvert; import cn.iocoder.mall.promotion.biz.convert.CouponTemplateConvert;
import cn.iocoder.mall.promotion.biz.convert.CouponTemplateConvertImpl;
import cn.iocoder.mall.promotion.biz.dao.CouponCardMapper;
import cn.iocoder.mall.promotion.biz.dao.CouponTemplateMapper; import cn.iocoder.mall.promotion.biz.dao.CouponTemplateMapper;
import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO;
import cn.iocoder.mall.promotion.biz.dataobject.CouponTemplateDO; import cn.iocoder.mall.promotion.biz.dataobject.CouponTemplateDO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
@Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示 @Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示
...@@ -23,9 +31,17 @@ public class CouponServiceImpl implements CouponService { ...@@ -23,9 +31,17 @@ public class CouponServiceImpl implements CouponService {
@Autowired @Autowired
private CouponTemplateMapper couponTemplateMapper; private CouponTemplateMapper couponTemplateMapper;
@Autowired
private CouponCardMapper couponCardMapper;
// ========== 优惠劵(码)模板 ========== // ========== 优惠劵(码)模板 ==========
@Override
public CommonResult<CouponTemplateBO> getCouponTemplate(Integer couponTemplateId) {
CouponTemplateDO template = couponTemplateMapper.selectById(couponTemplateId);
return CommonResult.success(CouponTemplateConvertImpl.INSTANCE.convert(template));
}
@Override @Override
public CommonResult<CouponTemplatePageBO> getCouponTemplatePage(CouponTemplatePageDTO couponTemplatePageDTO) { public CommonResult<CouponTemplatePageBO> getCouponTemplatePage(CouponTemplatePageDTO couponTemplatePageDTO) {
CouponTemplatePageBO couponTemplatePageBO = new CouponTemplatePageBO(); CouponTemplatePageBO couponTemplatePageBO = new CouponTemplatePageBO();
...@@ -162,8 +178,68 @@ public class CouponServiceImpl implements CouponService { ...@@ -162,8 +178,68 @@ public class CouponServiceImpl implements CouponService {
// ========== 优惠劵 ========== // ========== 优惠劵 ==========
@Override @Override
public CommonResult<CouponCardPageBO> getCouponCardPage(CouponCardPageDTO couponCardPageDTO) {
CouponCardPageBO pageBO = new CouponCardPageBO();
// 查询分页数据
int offset = (couponCardPageDTO.getPageNo() - 1) * couponCardPageDTO.getPageSize();
pageBO.setList(CouponCardConvert.INSTANCE.convertToBO(couponCardMapper.selectListByPage(
couponCardPageDTO.getUserId(), couponCardPageDTO.getStatus(),
offset, couponCardPageDTO.getPageSize())));
// 查询分页总数
pageBO.setTotal(couponCardMapper.selectCountByPage(
couponCardPageDTO.getUserId(), couponCardPageDTO.getStatus()));
return CommonResult.success(pageBO);
}
@Override
@Transactional
public CommonResult<CouponCardBO> addCouponCard(Integer userId, Integer couponTemplateId) { public CommonResult<CouponCardBO> addCouponCard(Integer userId, Integer couponTemplateId) {
return null; // 校验 CouponCardTemplate 存在
CouponTemplateDO template = couponTemplateMapper.selectById(couponTemplateId);
if (template == null) {
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_NOT_EXISTS.getCode());
}
// 校验 CouponCardTemplate 是 CARD
if (!CouponTemplateTypeEnum.CARD.getValue().equals(template.getType())) {
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_NOT_CARD.getCode());
}
// 校验 CouponCardTemplate 状态是否开启
if (!CouponTemplateStatusEnum.ENABLE.getValue().equals(template.getStatus())) {
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_STATUS_NOT_ENABLE.getCode());
}
// 校验 CouponCardTemplate 是否到达可领取的上限
if (template.getStatFetchNum() > template.getTotal()) {
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_TOTAL_NOT_ENOUGH.getCode());
}
// 校验单人可领取优惠劵是否到达上限
if (couponCardMapper.selectCountByUserIdAndTemplateId(userId, couponTemplateId) > template.getQuota()) {
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode());
}
// 增加优惠劵已领取量
int updateTemplateCount = couponTemplateMapper.updateStatFetchNumIncr(couponTemplateId);
if (updateTemplateCount == 0) { // 超过 CouponCardTemplate 发放量
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode());
}
// 创建优惠劵
// 1. 基本信息 + 领取情况
CouponCardDO card = new CouponCardDO()
.setTemplateId(couponTemplateId)
.setTitle(template.getTitle())
.setStatus(CouponCardStatusEnum.UNUSED.getValue())
.setUserId(userId)
.setTakeType(CouponCardTakeTypeEnum.BY_USER.getValue()); // TODO 需要改
// 2. 使用规则
card.setPriceAvailable(template.getPriceAvailable());
setCouponCardValidTime(card, template);
// 3. 使用效果
card.setPreferentialType(template.getPreferentialType())
.setPriceOff(template.getPriceOff())
.setPercentOff(template.getPercentOff()).setDiscountPriceLimit(template.getDiscountPriceLimit());
// 保存优惠劵模板到数据库
card.setCreateTime(new Date());
couponCardMapper.insert(card);
// 返回成功
return CommonResult.success(CouponCardConvert.INSTANCE.convert(card));
} }
@Override @Override
...@@ -176,6 +252,17 @@ public class CouponServiceImpl implements CouponService { ...@@ -176,6 +252,17 @@ public class CouponServiceImpl implements CouponService {
return null; return null;
} }
private void setCouponCardValidTime(CouponCardDO card, CouponTemplateDO template) {
if (CouponTemplateDateTypeEnum.FIXED_DATE.getValue().equals(template.getDateType())) {
card.setValidStartTime(template.getValidStartTime()).setValidEndTime(template.getValidEndTime());
} else if (CouponTemplateDateTypeEnum.FIXED_TERM.getValue().equals(template.getDateType())) {
Date validStartTime = DateUtil.getDayBegin(new Date());
card.setValidStartTime(DateUtil.addDate(validStartTime, Calendar.DAY_OF_YEAR, template.getFixedStartTerm()));
Date validEndTime = DateUtil.getDayEnd(card.getValidStartTime());
card.setValidEndTime(DateUtil.addDate(validEndTime, Calendar.DAY_OF_YEAR, template.getFixedEndTerm() - 1));
}
}
// ========== 优惠码 ========== // ========== 优惠码 ==========
@Override @Override
......
<?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.iocoder.mall.promotion.biz.dao.CouponCardMapper">
<sql id="FIELDS">
id, template_id, title, status, user_id, take_type,
price_available, valid_start_time, valid_end_time, preferential_type, percent_off, price_off,
discount_price_limit, used_order_id, used_price, used_time,
create_time
</sql>
<!-- <select id="selectListByPidAndStatusOrderBySort" resultType="CouponCardDO">-->
<!-- SELECT-->
<!-- <include refid="FIELDS" />-->
<!-- FROM coupon_card-->
<!-- WHERE pid = #{pid}-->
<!-- AND status = #{status}-->
<!-- AND deleted = 0-->
<!-- ORDER BY sort ASC-->
<!-- </select>-->
<!-- <select id="selectList" resultType="CouponCardDO">-->
<!-- SELECT-->
<!-- <include refid="FIELDS" />-->
<!-- FROM coupon_card-->
<!-- WHERE deleted = 0-->
<!-- </select>-->
<select id="selectById" parameterType="Integer" resultType="CouponCardDO">
SELECT
<include refid="FIELDS" />
FROM coupon_card
WHERE id = #{id}
</select>
<select id="selectListByPage" resultType="CouponCardDO">
SELECT
<include refid="FIELDS" />
FROM coupon_card
<where>
<if test="userId != null">
AND user_id = #{userId}
</if>
<if test="status != null">
AND status = #{status}
</if>
</where>
LIMIT #{offset}, #{limit}
</select>
<select id="selectCountByPage" resultType="Integer">
SELECT
COUNT(1)
FROM coupon_card
<where>
<if test="userId != null">
AND user_id = #{userId}
</if>
<if test="status != null">
AND status = #{status}
</if>
</where>
</select>
<select id="selectCountByUserIdAndTemplateId" resultType="Integer">
SELECT
COUNT(1)
FROM coupon_card
<where>
<if test="userId != null">
AND user_id = #{userId}
</if>
<if test="templateId != null">
AND template_id = #{templateId}
</if>
</where>
</select>
<insert id="insert" parameterType="CouponCardDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
INSERT INTO coupon_card (
template_id, title, status, user_id, take_type,
price_available, valid_start_time, valid_end_time, preferential_type, percent_off, price_off,
discount_price_limit, used_order_id, used_price, used_time,
create_time
) VALUES (
#{templateId}, #{title}, #{status}, #{userId}, #{takeType},
#{priceAvailable}, #{validStartTime}, #{validEndTime}, #{preferentialType}, #{percentOff}, #{priceOff},
#{discountPriceLimit}, #{usedOrderId}, #{usedPrice}, #{usedTime},
#{createTime}
)
</insert>
<update id="update" parameterType="CouponCardDO">
UPDATE coupon_card
<set>
<if test="status != null">
status = #{status},
</if>
<if test="usedOrderId != null">
used_order_id = #{usedOrderId},
</if>
<if test="usedPrice != null">
used_price = #{usedPrice},
</if>
<if test="usedTime != null">
used_time = #{usedTime},
</if>
</set>
WHERE id = #{id}
</update>
</mapper>
...@@ -149,4 +149,11 @@ ...@@ -149,4 +149,11 @@
WHERE id = #{id} WHERE id = #{id}
</update> </update>
<update id="updateStatFetchNumIncr" parameterType="Integer">
UPDATE coupon_template
SET stat_fetch_Num = stat_fetch_Num + 1
WHERE id = #{id}
AND total > stat_fetch_Num
</update>
</mapper> </mapper>
...@@ -49,4 +49,4 @@ public class MVCConfiguration implements WebMvcConfigurer { ...@@ -49,4 +49,4 @@ public class MVCConfiguration implements WebMvcConfigurer {
return registrationBean; return registrationBean;
} }
} }
\ No newline at end of file
...@@ -4,6 +4,7 @@ import lombok.Data; ...@@ -4,6 +4,7 @@ import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date; import java.util.Date;
/** /**
...@@ -11,7 +12,7 @@ import java.util.Date; ...@@ -11,7 +12,7 @@ import java.util.Date;
*/ */
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public class UserAccessLogAddDTO { public class UserAccessLogAddDTO implements Serializable {
/** /**
* 用户编号 - 空 * 用户编号 - 空
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论