Commit dc51a9353394e411006548468ff36aac0ae1cba8

Authored by YunaiV
1 parent 3c10058d

promotion:实现部分优惠劵模板的前端列表

yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionDiscountTypeEnum.java
@@ -15,8 +15,8 @@ import java.util.Arrays; @@ -15,8 +15,8 @@ import java.util.Arrays;
15 @AllArgsConstructor 15 @AllArgsConstructor
16 public enum PromotionDiscountTypeEnum implements IntArrayValuable { 16 public enum PromotionDiscountTypeEnum implements IntArrayValuable {
17 17
18 - PRICE(1, "减价"), // 具体金额  
19 - PERCENT(2, "打折"), // 百分比 18 + PRICE(1, "满减"), // 具体金额
  19 + PERCENT(2, "折扣"), // 百分比
20 ; 20 ;
21 21
22 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionDiscountTypeEnum::getType).toArray(); 22 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionDiscountTypeEnum::getType).toArray();
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateRespVO.java
@@ -24,7 +24,7 @@ public class CouponTemplateRespVO extends CouponTemplateBaseVO { @@ -24,7 +24,7 @@ public class CouponTemplateRespVO extends CouponTemplateBaseVO {
24 private Integer status; 24 private Integer status;
25 25
26 @ApiModelProperty(value = "领取优惠券的数量", required = true, example = "1024") 26 @ApiModelProperty(value = "领取优惠券的数量", required = true, example = "1024")
27 - private Integer takeNum; 27 + private Integer takeCount;
28 28
29 @ApiModelProperty(value = "使用优惠券的次数", required = true, example = "2048") 29 @ApiModelProperty(value = "使用优惠券的次数", required = true, example = "2048")
30 private Integer useCount; 30 private Integer useCount;
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java
@@ -106,6 +106,12 @@ public class CouponTemplateDO extends BaseDO { @@ -106,6 +106,12 @@ public class CouponTemplateDO extends BaseDO {
106 */ 106 */
107 private Date validEndTime; 107 private Date validEndTime;
108 /** 108 /**
  109 + * 领取日期 - 开始天数
  110 + *
  111 + * 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#TERM}
  112 + */
  113 + private Integer fixedStartTerm;
  114 + /**
109 * 领取日期 - 结束天数 115 * 领取日期 - 结束天数
110 * 116 *
111 * 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#TERM} 117 * 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#TERM}
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImplTest.java
1 package cn.iocoder.yudao.module.promotion.service.coupon; 1 package cn.iocoder.yudao.module.promotion.service.coupon;
2 2
3 -import org.junit.jupiter.api.Disabled;  
4 -import org.junit.jupiter.api.Test;  
5 -import org.springframework.boot.test.mock.mockito.MockBean;  
6 -  
7 -import javax.annotation.Resource;  
8 - 3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
10 -  
11 -import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.*; 5 +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateCreateReqVO;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplatePageReqVO;
  7 +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateUpdateReqVO;
12 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
13 import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper; 9 import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper;
14 -import cn.iocoder.yudao.framework.common.pojo.PageResult; 10 +import org.junit.jupiter.api.Disabled;
  11 +import org.junit.jupiter.api.Test;
  12 +import org.springframework.context.annotation.Import;
15 13
16 import javax.annotation.Resource; 14 import javax.annotation.Resource;
17 -import org.springframework.context.annotation.Import;  
18 -import java.util.*;  
19 -  
20 -import static cn.hutool.core.util.RandomUtil.*;  
21 -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;  
22 -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;  
23 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;  
24 -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;  
25 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; 15 +import java.util.Date;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  18 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  19 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  20 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  21 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  22 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS;
26 import static org.junit.jupiter.api.Assertions.*; 23 import static org.junit.jupiter.api.Assertions.*;
27 -import static org.mockito.Mockito.*;  
28 24
29 /** 25 /**
30 * {@link CouponTemplateServiceImpl} 的单元测试类 26 * {@link CouponTemplateServiceImpl} 的单元测试类
@@ -110,7 +106,7 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest { @@ -110,7 +106,7 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest {
110 CouponTemplateDO dbCouponTemplate = randomPojo(CouponTemplateDO.class, o -> { // 等会查询到 106 CouponTemplateDO dbCouponTemplate = randomPojo(CouponTemplateDO.class, o -> { // 等会查询到
111 o.setName(null); 107 o.setName(null);
112 o.setStatus(null); 108 o.setStatus(null);
113 - o.setType(null); 109 + o.setDiscountType(null);
114 o.setCreateTime(null); 110 o.setCreateTime(null);
115 }); 111 });
116 couponTemplateMapper.insert(dbCouponTemplate); 112 couponTemplateMapper.insert(dbCouponTemplate);
@@ -119,14 +115,14 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest { @@ -119,14 +115,14 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest {
119 // 测试 status 不匹配 115 // 测试 status 不匹配
120 couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setStatus(null))); 116 couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setStatus(null)));
121 // 测试 type 不匹配 117 // 测试 type 不匹配
122 - couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setType(null))); 118 + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setDiscountType(null)));
123 // 测试 createTime 不匹配 119 // 测试 createTime 不匹配
124 couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setCreateTime(null))); 120 couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setCreateTime(null)));
125 // 准备参数 121 // 准备参数
126 CouponTemplatePageReqVO reqVO = new CouponTemplatePageReqVO(); 122 CouponTemplatePageReqVO reqVO = new CouponTemplatePageReqVO();
127 reqVO.setName(null); 123 reqVO.setName(null);
128 reqVO.setStatus(null); 124 reqVO.setStatus(null);
129 - reqVO.setType(null); 125 + reqVO.setDiscountType(null);
130 reqVO.setCreateTime((new Date[]{})); 126 reqVO.setCreateTime((new Date[]{}));
131 127
132 // 调用 128 // 调用
@@ -137,37 +133,4 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest { @@ -137,37 +133,4 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest {
137 assertPojoEquals(dbCouponTemplate, pageResult.getList().get(0)); 133 assertPojoEquals(dbCouponTemplate, pageResult.getList().get(0));
138 } 134 }
139 135
140 - @Test  
141 - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解  
142 - public void testGetCouponTemplateList() {  
143 - // mock 数据  
144 - CouponTemplateDO dbCouponTemplate = randomPojo(CouponTemplateDO.class, o -> { // 等会查询到  
145 - o.setName(null);  
146 - o.setStatus(null);  
147 - o.setType(null);  
148 - o.setCreateTime(null);  
149 - });  
150 - couponTemplateMapper.insert(dbCouponTemplate);  
151 - // 测试 name 不匹配  
152 - couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setName(null)));  
153 - // 测试 status 不匹配  
154 - couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setStatus(null)));  
155 - // 测试 type 不匹配  
156 - couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setType(null)));  
157 - // 测试 createTime 不匹配  
158 - couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setCreateTime(null)));  
159 - // 准备参数  
160 - CouponTemplateExportReqVO reqVO = new CouponTemplateExportReqVO();  
161 - reqVO.setName(null);  
162 - reqVO.setStatus(null);  
163 - reqVO.setType(null);  
164 - reqVO.setCreateTime((new Date[]{}));  
165 -  
166 - // 调用  
167 - List<CouponTemplateDO> list = couponTemplateService.getCouponTemplateList(reqVO);  
168 - // 断言  
169 - assertEquals(1, list.size());  
170 - assertPojoEquals(dbCouponTemplate, list.get(0));  
171 - }  
172 -  
173 } 136 }
yudao-ui-admin/src/utils/constants.js
@@ -236,3 +236,31 @@ export const ProductSpuStatusEnum = { @@ -236,3 +236,31 @@ export const ProductSpuStatusEnum = {
236 name: '上架' 236 name: '上架'
237 }, 237 },
238 } 238 }
  239 +
  240 +/**
  241 + * 优惠类型枚举
  242 + */
  243 +export const PromotionDiscountTypeEnum = {
  244 + PRICE: {
  245 + type: 1,
  246 + name: '满减'
  247 + },
  248 + PERCENT: {
  249 + type: 2,
  250 + name: '折扣'
  251 + }
  252 +}
  253 +
  254 +/**
  255 + * 优惠劵模板的有限期类型的枚举
  256 + */
  257 +export const CouponTemplateValidityTypeEnum = {
  258 + DATE: {
  259 + type: 1,
  260 + name: '固定日期可用'
  261 + },
  262 + TERM: {
  263 + type: 2,
  264 + name: '领取之后可用'
  265 + }
  266 +}
yudao-ui-admin/src/utils/dict.js
@@ -59,6 +59,9 @@ export const DICT_TYPE = { @@ -59,6 +59,9 @@ export const DICT_TYPE = {
59 59
60 // ========== MALL - PRODUCT 模块 ========== 60 // ========== MALL - PRODUCT 模块 ==========
61 PRODUCT_SPU_STATUS: 'product_spu_status', // 商品 SPU 状态 61 PRODUCT_SPU_STATUS: 'product_spu_status', // 商品 SPU 状态
  62 +
  63 + // ========== MALL - PROMOTION 模块 ==========
  64 + PROMOTION_DISCOUNT_TYPE: 'promotion_discount_type', // 优惠类型
62 } 65 }
63 66
64 /** 67 /**
yudao-ui-admin/src/views/promotion/couponTemplate/index.vue
@@ -2,25 +2,19 @@ @@ -2,25 +2,19 @@
2 <div class="app-container"> 2 <div class="app-container">
3 3
4 <!-- 搜索工作栏 --> 4 <!-- 搜索工作栏 -->
5 - <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">  
6 - <el-form-item label="优惠劵名" prop="name"> 5 + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="82px">
  6 + <el-form-item label="优惠券名称" prop="name">
7 <el-input v-model="queryParams.name" placeholder="请输入优惠劵名" clearable @keyup.enter.native="handleQuery"/> 7 <el-input v-model="queryParams.name" placeholder="请输入优惠劵名" clearable @keyup.enter.native="handleQuery"/>
8 </el-form-item> 8 </el-form-item>
9 - <el-form-item label="状态" prop="status">  
10 - <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">  
11 - <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"  
12 - :key="dict.value" :label="dict.label" :value="dict.value"/> 9 + <el-form-item label="优惠券类型" prop="discountType">
  10 + <el-select v-model="queryParams.discountType" placeholder="请选择优惠券类型" clearable size="small">
  11 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)"
  12 + :key="dict.value" :label="dict.label" :value="dict.value"/>
13 </el-select> 13 </el-select>
14 </el-form-item> 14 </el-form-item>
15 - <el-form-item label="类型  
16 - *  
17 - * 1-优惠劵  
18 - * 2-优惠码" prop="type">  
19 - <el-select v-model="queryParams.type" placeholder="请选择类型  
20 - *  
21 - * 1-优惠劵  
22 - * 2-优惠码" clearable size="small">  
23 - <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PRODUCT_SPU_STATUS)" 15 + <el-form-item label="优惠券状态" prop="status">
  16 + <el-select v-model="queryParams.status" placeholder="请选择优惠券状态" clearable size="small">
  17 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
24 :key="dict.value" :label="dict.label" :value="dict.value"/> 18 :key="dict.value" :label="dict.label" :value="dict.value"/>
25 </el-select> 19 </el-select>
26 </el-form-item> 20 </el-form-item>
@@ -48,45 +42,24 @@ @@ -48,45 +42,24 @@
48 <el-table-column label="优惠券名称" align="center" prop="name" /> 42 <el-table-column label="优惠券名称" align="center" prop="name" />
49 <el-table-column label="优惠券类型" align="center" prop="discountType"> 43 <el-table-column label="优惠券类型" align="center" prop="discountType">
50 <template slot-scope="scope"> 44 <template slot-scope="scope">
51 - <dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.type" /> 45 + <dict-tag :type="DICT_TYPE.PROMOTION_DISCOUNT_TYPE" :value="scope.row.discountType" />
52 </template> 46 </template>
53 </el-table-column> 47 </el-table-column>
54 - <el-table-column label="发行总量" align="center" prop="totalCount" />  
55 - <el-table-column label="每人限领个数  
56 - *  
57 - * null - 则表示不限制" align="center" prop="takeLimitCount" />  
58 - <el-table-column label="领取方式" align="center" prop="takeType" />  
59 - <el-table-column label="是否设置满多少金额可用,单位:分" align="center" prop="usePrice" />  
60 - <el-table-column label="商品范围" align="center" prop="productScope" />  
61 - <el-table-column label="商品 SPU 编号的数组" align="center" prop="productSpuIds" />  
62 - <el-table-column label="生效日期类型" align="center" prop="validityType" />  
63 - <el-table-column label="固定日期-生效开始时间" align="center" prop="validStartTime" width="180"> 48 + <el-table-column label="优惠金额 / 折扣" align="center" prop="discount" :formatter="discountFormat" />
  49 + <el-table-column label="发放数量" align="center" prop="totalCount" />
  50 + <el-table-column label="剩余数量" align="center" prop="totalCount" :formatter="row => (row.totalCount - row.takeCount)" />
  51 + <el-table-column label="领取上限" align="center" prop="takeLimitCount" :formatter="takeLimitCountFormat" />
  52 + <el-table-column label="有效期限" align="center" prop="validityType" width="180" :formatter="validityTypeFormat" />
  53 + <el-table-column label="状态" align="center" prop="status">
64 <template slot-scope="scope"> 54 <template slot-scope="scope">
65 - <span>{{ parseTime(scope.row.validStartTime) }}</span>  
66 - </template>  
67 - </el-table-column>  
68 - <el-table-column label="固定日期-生效结束时间" align="center" prop="validEndTime" width="180">  
69 - <template slot-scope="scope">  
70 - <span>{{ parseTime(scope.row.validEndTime) }}</span> 55 + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
71 </template> 56 </template>
72 </el-table-column> 57 </el-table-column>
73 - <el-table-column label="领取日期-开始天数" align="center" prop="fixedStartTerm" />  
74 - <el-table-column label="领取日期-结束天数" align="center" prop="fixedEndTerm" />  
75 - <el-table-column label="折扣百分比" align="center" prop="discountPercent" />  
76 - <el-table-column label="优惠金额,单位:分" align="center" prop="discountPrice" />  
77 - <el-table-column label="折扣上限" />  
78 - <el-table-column label="领取优惠券的数量" align="center" prop="takeNum" />  
79 - <el-table-column label="使用优惠券的次数" align="center" prop="useCount" />  
80 <el-table-column label="创建时间" align="center" prop="createTime" width="180"> 58 <el-table-column label="创建时间" align="center" prop="createTime" width="180">
81 <template slot-scope="scope"> 59 <template slot-scope="scope">
82 <span>{{ parseTime(scope.row.createTime) }}</span> 60 <span>{{ parseTime(scope.row.createTime) }}</span>
83 </template> 61 </template>
84 </el-table-column> 62 </el-table-column>
85 - <el-table-column label="优惠券类型" align="center" prop="status">  
86 - <template slot-scope="scope">  
87 - <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />  
88 - </template>  
89 - </el-table-column>  
90 <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> 63 <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
91 <template slot-scope="scope"> 64 <template slot-scope="scope">
92 <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" 65 <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
@@ -185,7 +158,8 @@ @@ -185,7 +158,8 @@
185 </template> 158 </template>
186 159
187 <script> 160 <script>
188 -import { createCouponTemplate, updateCouponTemplate, deleteCouponTemplate, getCouponTemplate, getCouponTemplatePage, exportCouponTemplateExcel } from "@/api/promotion/couponTemplate"; 161 +import { createCouponTemplate, updateCouponTemplate, deleteCouponTemplate, getCouponTemplate, getCouponTemplatePage } from "@/api/promotion/couponTemplate";
  162 +import {CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum} from "@/utils/constants";
189 163
190 export default { 164 export default {
191 name: "CouponTemplate", 165 name: "CouponTemplate",
@@ -340,6 +314,33 @@ export default { @@ -340,6 +314,33 @@ export default {
340 this.$modal.msgSuccess("删除成功"); 314 this.$modal.msgSuccess("删除成功");
341 }).catch(() => {}); 315 }).catch(() => {});
342 }, 316 },
  317 + // 格式化【优惠金额/折扣】
  318 + discountFormat(row, column) {
  319 + if (row.discountType === PromotionDiscountTypeEnum.PRICE.type) {
  320 + return `¥${(row.discountPrice / 100.0).toFixed(2)}`;
  321 + }
  322 + if (row.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
  323 + return `¥${(row.discountPrice / 100.0).toFixed(2)}`;
  324 + }
  325 + return '未知【' + row.discountType + '】';
  326 + },
  327 + // 格式化【领取上限】
  328 + takeLimitCountFormat(row, column) {
  329 + if (row.takeLimitCount === -1) {
  330 + return '无领取限制';
  331 + }
  332 + return `${row.takeLimitCount} 张/人`
  333 + },
  334 + // 格式化【有效期限】
  335 + validityTypeFormat(row, column) {
  336 + if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
  337 + return `${parseTime(row.validStartTime)} 至 ${parseTime(row.validEndTime)}`
  338 + }
  339 + if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
  340 + return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
  341 + }
  342 + return '未知【' + row.validityType + '】';
  343 + }
343 } 344 }
344 }; 345 };
345 </script> 346 </script>