Commit dc51a9353394e411006548468ff36aac0ae1cba8
1 parent
3c10058d
promotion:实现部分优惠劵模板的前端列表
Showing
7 changed files
with
104 additions
and
103 deletions
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 | 15 | @AllArgsConstructor |
| 16 | 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 | 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 | 24 | private Integer status; |
| 25 | 25 | |
| 26 | 26 | @ApiModelProperty(value = "领取优惠券的数量", required = true, example = "1024") |
| 27 | - private Integer takeNum; | |
| 27 | + private Integer takeCount; | |
| 28 | 28 | |
| 29 | 29 | @ApiModelProperty(value = "使用优惠券的次数", required = true, example = "2048") |
| 30 | 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 | 106 | */ |
| 107 | 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 | 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 | 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 | 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 | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; |
| 13 | 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 | 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 | 23 | import static org.junit.jupiter.api.Assertions.*; |
| 27 | -import static org.mockito.Mockito.*; | |
| 28 | 24 | |
| 29 | 25 | /** |
| 30 | 26 | * {@link CouponTemplateServiceImpl} 的单元测试类 |
| ... | ... | @@ -110,7 +106,7 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest { |
| 110 | 106 | CouponTemplateDO dbCouponTemplate = randomPojo(CouponTemplateDO.class, o -> { // 等会查询到 |
| 111 | 107 | o.setName(null); |
| 112 | 108 | o.setStatus(null); |
| 113 | - o.setType(null); | |
| 109 | + o.setDiscountType(null); | |
| 114 | 110 | o.setCreateTime(null); |
| 115 | 111 | }); |
| 116 | 112 | couponTemplateMapper.insert(dbCouponTemplate); |
| ... | ... | @@ -119,14 +115,14 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest { |
| 119 | 115 | // 测试 status 不匹配 |
| 120 | 116 | couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setStatus(null))); |
| 121 | 117 | // 测试 type 不匹配 |
| 122 | - couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setType(null))); | |
| 118 | + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setDiscountType(null))); | |
| 123 | 119 | // 测试 createTime 不匹配 |
| 124 | 120 | couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setCreateTime(null))); |
| 125 | 121 | // 准备参数 |
| 126 | 122 | CouponTemplatePageReqVO reqVO = new CouponTemplatePageReqVO(); |
| 127 | 123 | reqVO.setName(null); |
| 128 | 124 | reqVO.setStatus(null); |
| 129 | - reqVO.setType(null); | |
| 125 | + reqVO.setDiscountType(null); | |
| 130 | 126 | reqVO.setCreateTime((new Date[]{})); |
| 131 | 127 | |
| 132 | 128 | // 调用 |
| ... | ... | @@ -137,37 +133,4 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest { |
| 137 | 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 | 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 | 59 | |
| 60 | 60 | // ========== MALL - PRODUCT 模块 ========== |
| 61 | 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 | 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 | 7 | <el-input v-model="queryParams.name" placeholder="请输入优惠劵名" clearable @keyup.enter.native="handleQuery"/> |
| 8 | 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 | 13 | </el-select> |
| 14 | 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 | 18 | :key="dict.value" :label="dict.label" :value="dict.value"/> |
| 25 | 19 | </el-select> |
| 26 | 20 | </el-form-item> |
| ... | ... | @@ -48,45 +42,24 @@ |
| 48 | 42 | <el-table-column label="优惠券名称" align="center" prop="name" /> |
| 49 | 43 | <el-table-column label="优惠券类型" align="center" prop="discountType"> |
| 50 | 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 | 46 | </template> |
| 53 | 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 | 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 | 56 | </template> |
| 72 | 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 | 58 | <el-table-column label="创建时间" align="center" prop="createTime" width="180"> |
| 81 | 59 | <template slot-scope="scope"> |
| 82 | 60 | <span>{{ parseTime(scope.row.createTime) }}</span> |
| 83 | 61 | </template> |
| 84 | 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 | 63 | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> |
| 91 | 64 | <template slot-scope="scope"> |
| 92 | 65 | <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" |
| ... | ... | @@ -185,7 +158,8 @@ |
| 185 | 158 | </template> |
| 186 | 159 | |
| 187 | 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 | 164 | export default { |
| 191 | 165 | name: "CouponTemplate", |
| ... | ... | @@ -340,6 +314,33 @@ export default { |
| 340 | 314 | this.$modal.msgSuccess("删除成功"); |
| 341 | 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 | 346 | </script> | ... | ... |