Merge remote-tracking branch 'origin/master' into feature/vue3

This commit is contained in:
xingyu4j 2022-11-14 09:15:19 +08:00
commit 042c4e8390
307 changed files with 12436 additions and 5278 deletions

View File

@ -248,7 +248,7 @@ DROP TABLE IF EXISTS `product_spu`;
CREATE TABLE `product_spu` ( CREATE TABLE `product_spu` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
`brand_id` int DEFAULT NULL COMMENT '商品品牌编号', `brand_id` bigint DEFAULT NULL COMMENT '商品品牌编号',
`category_id` bigint NOT NULL COMMENT '分类id', `category_id` bigint NOT NULL COMMENT '分类id',
`spec_type` int NOT NULL COMMENT '规格类型0 单规格 1 多规格', `spec_type` int NOT NULL COMMENT '规格类型0 单规格 1 多规格',
`code` varchar(128) DEFAULT NULL COMMENT '商品编码', `code` varchar(128) DEFAULT NULL COMMENT '商品编码',

View File

@ -1,4 +1,5 @@
/**todo cancelType 设置默认值 0?*/ /**todo cancelType 设置默认值 0?*/
DROP TABLE IF EXISTS `trade_order`;
CREATE TABLE `trade_order` CREATE TABLE `trade_order`
( (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID', `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
@ -10,9 +11,10 @@ CREATE TABLE `trade_order`
`user_remark` varchar(200) DEFAULT NULL COMMENT '用户备注', `user_remark` varchar(200) DEFAULT NULL COMMENT '用户备注',
`status` int NOT NULL DEFAULT '0' COMMENT '订单状态[0:待付款 1:待发货 2:待收货 3:已完成 4:已关闭]', `status` int NOT NULL DEFAULT '0' COMMENT '订单状态[0:待付款 1:待发货 2:待收货 3:已完成 4:已关闭]',
`product_count` int NOT NULL COMMENT '购买的商品数量', `product_count` int NOT NULL COMMENT '购买的商品数量',
`cancel_type` int NOT NULL COMMENT '取消类型[10:超时未支付 20:退款关闭 30:买家取消 40:已通过货到付款交易]', `cancel_type` int DEFAULT NULL COMMENT '取消类型[10:超时未支付 20:退款关闭 30:买家取消 40:已通过货到付款交易]',
`remark` varchar(200) DEFAULT NULL COMMENT '商家备注', `remark` varchar(200) DEFAULT NULL COMMENT '商家备注',
`payed` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否已支付[0:未支付 1:已经支付过]', `payed` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否已支付[0:未支付 1:已经支付过]',
`pay_time` datetime DEFAULT NULL COMMENT '订单支付时间',
`finish_time` datetime DEFAULT NULL COMMENT '订单完成时间', `finish_time` datetime DEFAULT NULL COMMENT '订单完成时间',
`cancel_time` datetime DEFAULT NULL COMMENT '订单取消时间', `cancel_time` datetime DEFAULT NULL COMMENT '订单取消时间',
`sku_original_price` int NOT NULL DEFAULT '0' COMMENT '商品原价单位', `sku_original_price` int NOT NULL DEFAULT '0' COMMENT '商品原价单位',
@ -20,11 +22,11 @@ CREATE TABLE `trade_order`
`order_promotion_price` int NOT NULL DEFAULT '0' COMMENT '订单优惠单位', `order_promotion_price` int NOT NULL DEFAULT '0' COMMENT '订单优惠单位',
`delivery_price` int NOT NULL DEFAULT '0' COMMENT '运费金额单位', `delivery_price` int NOT NULL DEFAULT '0' COMMENT '运费金额单位',
`pay_price` int NOT NULL DEFAULT '0' COMMENT '应付金额单位', `pay_price` int NOT NULL DEFAULT '0' COMMENT '应付金额单位',
`pay_order_id` int NOT NULL COMMENT '支付订单编号', `pay_order_id` int DEFAULT NULL COMMENT '支付订单编号',
`pay_channel` int NOT NULL COMMENT '支付成功的支付渠道', `pay_channel` int DEFAULT NULL COMMENT '支付成功的支付渠道',
`delivery_type` int NOT NULL DEFAULT '1' COMMENT '配送方式:[1:快递发货 2:自提]', `delivery_type` int DEFAULT NULL DEFAULT '1' COMMENT '配送方式:[1:快递发货 2:自提]',
`actual_delivery_type` int NOT NULL DEFAULT '1' COMMENT '实际的配送方式:[1:快递发货 2:自提]', `actual_delivery_type` int DEFAULT NULL DEFAULT '1' COMMENT '实际的配送方式:[1:快递发货 2:自提]',
`delivery_templateid` int DEFAULT NULL COMMENT '配置模板的编号', `delivery_template_id` int DEFAULT NULL COMMENT '配置模板的编号',
`express_no` int DEFAULT NULL COMMENT '物流公司单号', `express_no` int DEFAULT NULL COMMENT '物流公司单号',
`delivery_status` bit(1) NOT NULL DEFAULT b'0' COMMENT '发货状态[0:未发货 1:已发货]', `delivery_status` bit(1) NOT NULL DEFAULT b'0' COMMENT '发货状态[0:未发货 1:已发货]',
`delivery_time` datetime DEFAULT NULL COMMENT '发货时间', `delivery_time` datetime DEFAULT NULL COMMENT '发货时间',
@ -73,4 +75,4 @@ CREATE TABLE `trade_order_item`
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT ='交易订单明细表'; ) ENGINE = InnoDB COMMENT ='交易订单明细表';

View File

@ -12,7 +12,8 @@ import lombok.Getter;
@AllArgsConstructor @AllArgsConstructor
public enum DocumentEnum { public enum DocumentEnum {
REDIS_INSTALL("https://gitee.com/zhijiantianya/ruoyi-vue-pro/issues/I4VCSJ", "Redis 安装文档"); REDIS_INSTALL("https://gitee.com/zhijiantianya/ruoyi-vue-pro/issues/I4VCSJ", "Redis 安装文档"),
TENANT("https://doc.iocoder.cn", "SaaS 多租户文档");
private final String url; private final String url;
private final String memo; private final String memo;

View File

@ -1,13 +1,8 @@
package cn.iocoder.yudao.framework.common.util.date; package cn.iocoder.yudao.framework.common.util.date;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.date.LocalDateTimeUtil;
import java.time.Duration; import java.time.*;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
@ -58,6 +53,7 @@ public class DateUtils {
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
} }
@Deprecated
public static Date addTime(Duration duration) { public static Date addTime(Duration duration) {
return new Date(System.currentTimeMillis() + duration.toMillis()); return new Date(System.currentTimeMillis() + duration.toMillis());
} }
@ -87,6 +83,7 @@ public class DateUtils {
return buildTime(year, mouth, day, 0, 0, 0); return buildTime(year, mouth, day, 0, 0, 0);
} }
@Deprecated
public static LocalDateTime buildLocalDateTime(int year, int mouth, int day) { public static LocalDateTime buildLocalDateTime(int year, int mouth, int day) {
return LocalDateTime.of(year, mouth, day, 0, 0, 0); return LocalDateTime.of(year, mouth, day, 0, 0, 0);
} }
@ -135,14 +132,7 @@ public class DateUtils {
return a.isAfter(b) ? a : b; return a.isAfter(b) ? a : b;
} }
public static boolean beforeNow(Date date) { @Deprecated
return date.getTime() < System.currentTimeMillis();
}
public static boolean afterNow(Date date) {
return date.getTime() >= System.currentTimeMillis();
}
public static boolean afterNow(LocalDateTime localDateTime) { public static boolean afterNow(LocalDateTime localDateTime) {
return localDateTime.isAfter(LocalDateTime.now()); return localDateTime.isAfter(LocalDateTime.now());
} }
@ -178,19 +168,6 @@ public class DateUtils {
return c.getTime(); return c.getTime();
} }
/**
* 是否今天
*
* @param date 日期
* @return 是否
*/
public static boolean isToday(Date date) {
if (date == null) {
return false;
}
return DateUtil.isSameDay(date, new Date());
}
/** /**
* 是否今天 * 是否今天
* *

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.framework.common.util.date;
import cn.hutool.core.date.LocalDateTimeUtil;
import java.time.Duration;
import java.time.LocalDateTime;
/**
* 时间工具类用于 {@link java.time.LocalDateTime}
*
* @author 芋道源码
*/
public class LocalDateTimeUtils {
public static LocalDateTime addTime(Duration duration) {
return LocalDateTime.now().plus(duration);
}
public static boolean beforeNow(LocalDateTime date) {
return date.isBefore(LocalDateTime.now());
}
public static boolean afterNow(LocalDateTime date) {
return date.isAfter(LocalDateTime.now());
}
/**
* 创建指定时间
*
* @param year
* @param mouth
* @param day
* @return 指定时间
*/
public static LocalDateTime buildTime(int year, int mouth, int day) {
return LocalDateTime.of(year, mouth, day, 0, 0, 0);
}
/**
* 判断当前时间是否在该时间范围内
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 是否
*/
public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime) {
if (startTime == null || endTime == null) {
return false;
}
return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime);
}
}

View File

@ -3,7 +3,10 @@ package cn.iocoder.yudao.framework.common.util.string;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/** /**
* 字符串工具类 * 字符串工具类
@ -37,4 +40,9 @@ public class StrUtils {
return false; return false;
} }
public static List<Long> splitToLong(String value, CharSequence separator) {
long[] longs = StrUtil.splitToLong(value, separator);
return Arrays.stream(longs).boxed().collect(Collectors.toList());
}
} }

View File

@ -124,7 +124,7 @@ public class YunpianSmsClientTest extends BaseMockitoUnitTest {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testDoGetSmsTemplate() throws Throwable { public void testDoGetSmsTemplate() throws Throwable {
// 准备参数 // 准备参数
String apiTemplateId = randomString(); String apiTemplateId = String.valueOf(randomLongId());
// mock tpl 方法 // mock tpl 方法
TplApi tplApi = mock(TplApi.class); TplApi tplApi = mock(TplApi.class);
when(client.tpl()).thenReturn(tplApi); when(client.tpl()).thenReturn(tplApi);

View File

@ -119,6 +119,8 @@ public class YudaoTenantAutoConfiguration {
}; };
} }
// ========== Redis ==========
@Bean @Bean
@Primary // 引入租户时tenantRedisCacheManager 为主 Bean @Primary // 引入租户时tenantRedisCacheManager 为主 Bean
public RedisCacheManager tenantRedisCacheManager(RedisTemplate<String, Object> redisTemplate, public RedisCacheManager tenantRedisCacheManager(RedisTemplate<String, Object> redisTemplate,

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.tenant.core.context; package cn.iocoder.yudao.framework.tenant.core.context;
import cn.iocoder.yudao.framework.common.enums.DocumentEnum;
import com.alibaba.ttl.TransmittableThreadLocal; import com.alibaba.ttl.TransmittableThreadLocal;
/** /**
@ -36,7 +37,8 @@ public class TenantContextHolder {
public static Long getRequiredTenantId() { public static Long getRequiredTenantId() {
Long tenantId = getTenantId(); Long tenantId = getTenantId();
if (tenantId == null) { if (tenantId == null) {
throw new NullPointerException("TenantContextHolder 不存在租户编号"); // TODO 芋艿增加文档链接 throw new NullPointerException("TenantContextHolder 不存在租户编号!可参考文档:"
+ DocumentEnum.TENANT.getUrl());
} }
return tenantId; return tenantId;
} }

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.tenant.core.redis;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheManager;
@ -11,7 +10,7 @@ import org.springframework.data.redis.cache.RedisCacheWriter;
/** /**
* 多租户的 {@link RedisCacheManager} 实现类 * 多租户的 {@link RedisCacheManager} 实现类
* *
* 操作指定 name {@link Cache} 自动拼接租户后缀格式为 name + ":" + tenantId * 操作指定 name {@link Cache} 自动拼接租户后缀格式为 name + ":" + tenantId + 后缀
* *
* @author airhead * @author airhead
*/ */
@ -24,7 +23,7 @@ public class TenantRedisCacheManager extends RedisCacheManager {
} }
@Override @Override
public Cache getCache(@NotNull String name) { public Cache getCache(String name) {
// 如果开启多租户 name 拼接租户后缀 // 如果开启多租户 name 拼接租户后缀
if (!TenantContextHolder.isIgnore() if (!TenantContextHolder.isIgnore()
&& TenantContextHolder.getTenantId() != null) { && TenantContextHolder.getTenantId() != null) {

View File

@ -28,8 +28,6 @@ import java.util.Objects;
* 2. 如果请求未带租户的编号检查是否是忽略的 URL否则也不允许访问 * 2. 如果请求未带租户的编号检查是否是忽略的 URL否则也不允许访问
* 3. 校验租户是合法例如说被禁用到期 * 3. 校验租户是合法例如说被禁用到期
* *
* 校验用户访问的租户是否是其所在的租户
*
* @author 芋道源码 * @author 芋道源码
*/ */
@Slf4j @Slf4j

View File

@ -0,0 +1,57 @@
package cn.iocoder.yudao.framework.mybatis.core.type;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
* List<Long> 的类型转换器实现类对应数据库的 varchar 类型
*
* @author 芋道源码
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class LongListTypeHandler implements TypeHandler<List<Long>> {
private static final String COMMA = ",";
@Override
public void setParameter(PreparedStatement ps, int i, List<Long> strings, JdbcType jdbcType) throws SQLException {
// 设置占位符
ps.setString(i, CollUtil.join(strings, COMMA));
}
@Override
public List<Long> getResult(ResultSet rs, String columnName) throws SQLException {
String value = rs.getString(columnName);
return getResult(value);
}
@Override
public List<Long> getResult(ResultSet rs, int columnIndex) throws SQLException {
String value = rs.getString(columnIndex);
return getResult(value);
}
@Override
public List<Long> getResult(CallableStatement cs, int columnIndex) throws SQLException {
String value = cs.getString(columnIndex);
return getResult(value);
}
private List<Long> getResult(String value) {
if (value == null) {
return null;
}
return StrUtils.splitToLong(value, COMMA);
}
}

View File

@ -15,13 +15,13 @@
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
<description> <description>
商城大模块,由 product 商品、market 营销、trade 交易 coupon等组成 商城大模块,由 product 商品、promotion 营销、trade 交易 coupon等组成
</description> </description>
<modules> <modules>
<module>yudao-module-coupon-api</module> <!-- <module>yudao-module-coupon-api</module>-->
<module>yudao-module-coupon-biz</module> <!-- <module>yudao-module-coupon-biz</module>-->
<module>yudao-module-market-api</module> <module>yudao-module-promotion-api</module>
<module>yudao-module-market-biz</module> <module>yudao-module-promotion-biz</module>
<module>yudao-module-product-api</module> <module>yudao-module-product-api</module>
<module>yudao-module-product-biz</module> <module>yudao-module-product-biz</module>
<module>yudao-module-trade-api</module> <module>yudao-module-trade-api</module>

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-mall</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-coupon-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
coupon 模块 API暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -1,29 +0,0 @@
package cn.iocoder.yudao.module.CouponTemplete.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 优惠券 - 是否开启过期提醒
*
* @author Sin
*/
@RequiredArgsConstructor
@Getter
public enum CouponExpireTimeTypeEnum {
OPEN(1,"不开启"),
CLOSE(0,"开启"),;
/**
* 是否开启过期提醒
*/
private final Integer type;
/**
* 是否开启过期提醒
*/
private final String name;
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.yudao.module.CouponTemplete.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 优惠券 - 领取是否无限制 0
*
* @author Sin
*/
@RequiredArgsConstructor
@Getter
public enum CouponFetchTypeEnum {
LIMIT(1,"限制"),
NOT_LIMIT(0,"不限制"),;
/**
* 是否开启过期提醒
*/
private final Integer type;
/**
* 是否开启过期提醒
*/
private final String name;
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.yudao.module.CouponTemplete.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 优惠券 - 优惠叠加类型
*
* @author Sin
*/
@RequiredArgsConstructor
@Getter
public enum CouponForbidPreferenceEnum {
UN_FORBID(0,"不限制"),
FORBID(1,"优惠券仅原价购买商品时可用");
/**
* 优惠券类型
*/
private final Integer type;
/**
* 优惠券类型名
*/
private final String name;
}

View File

@ -1,30 +0,0 @@
package cn.iocoder.yudao.module.CouponTemplete.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 优惠券 - 优惠券商品使用类型
*
* @author Sin
*/
@RequiredArgsConstructor
@Getter
public enum CouponGoodsTypeEnum {
ALL(1,"全部商品可用"),
POINT_PRODUCT(2,"指定商品可用"),
POINT_PRODUCT_NOT(3,"指定商品不可用"),;
/**
* 优惠券商品使用类型
*/
private final Integer type;
/**
* 优惠券商品使用类型名
*/
private final String name;
}

View File

@ -1,30 +0,0 @@
package cn.iocoder.yudao.module.CouponTemplete.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 优惠券 - 优惠券状态类型
*
* @author Sin
*/
@RequiredArgsConstructor
@Getter
public enum CouponStatusTypeEnum {
PROCESSING(1,"进行中"),
END(2,"已结束"),
CLOSE(3,"已关闭"),;
/**
* 优惠券类型
*/
private final Integer type;
/**
* 优惠券类型名
*/
private final String name;
}

View File

@ -1,30 +0,0 @@
package cn.iocoder.yudao.module.CouponTemplete.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 优惠券 - 优惠券类型
*
* @author Sin
*/
@RequiredArgsConstructor
@Getter
public enum CouponTypeEnum {
REWARD(1,"满减"),
DISCOUNT(2,"折扣"),
RANDOW(3,"随机"),;
/**
* 优惠券类型
*/
private final Integer type;
/**
* 优惠券类型名
*/
private final String name;
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.yudao.module.CouponTemplete.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 优惠券使用类型 - 优惠券使用类型类型
*
* @author Sin
*/
@RequiredArgsConstructor
@Getter
public enum CouponUseLimitEnum {
HAS_LIMIT(1,"无门槛"),
NO_LIMIT(2,"有门槛"),;
/**
* 优惠券使用类型
*/
private final Integer type;
/**
* 优惠券使用类型名
*/
private final String name;
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.yudao.module.CouponTemplete.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 过期类型 - 状态
*
* @author Sin
*/
@RequiredArgsConstructor
@Getter
public enum CouponValidityTypeEnum {
TIME_RANGE_EXPIRTED(1,"时间范围过期"),
EXPIRES_AFTER_FIXED_DATE(2,"领取之日固定日期后过期"),
EXPIRES_DATE_NEXT_FIEXD_DATE(3,"领取次日固定日期后过期"),;
/**
* 状态值
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.yudao.module.CouponTemplete.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* coupon 优惠券错误码枚举类
*
* coupon 优惠券系统使用 1-010-000-000
*/
public interface ErrorCodeConstants {
// ========== COUPON分类相关 1010001000 ============
ErrorCode COUPON_TEMPLETE_NOT_EXISTS = new ErrorCode(1010001000, "优惠券模板不存在");
ErrorCode MONEY_NOT_NULL = new ErrorCode(1010001001, "当type为reward时需要添加发放面额不能为空");
ErrorCode DISCOUNT_NOT_NULL = new ErrorCode(1010001001, "当type为discount时需要添加折扣不能为空");
ErrorCode DISCOUNT_LIMIT_NOT_NULL = new ErrorCode(1010001001, "当type为discount时可选择性添加最多折扣金额不能为空");
ErrorCode MIN_MAX_NOT_NULL = new ErrorCode(1010001001, "当type为radom时需要添加最低金额");
ErrorCode START_END_TIME_NOT_NULL = new ErrorCode(1010001001, "使用开始日期,使用结束日期不能为空");
ErrorCode FIXED_TERM_NOT_NULL = new ErrorCode(1010001001, "领取之日起或者次日N天内有效不能为空");
// ========== COUPON分类相关 1010002000 ============
ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1010001000, "优惠券模板不存在");
}

View File

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-mall</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>yudao-module-coupon-biz</artifactId>
<name>${project.artifactId}</name>
<description>
coupon模块主要负责优惠券的一些业务含发布优惠券模板分发优惠券等
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-coupon-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,88 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.coupon;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;
import javax.validation.*;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo.*;
import cn.iocoder.yudao.module.coupon.dal.dataobject.coupon.CouponDO;
import cn.iocoder.yudao.module.coupon.convert.coupon.CouponConvert;
import cn.iocoder.yudao.module.coupon.service.coupon.CouponService;
@Api(tags = "管理后台 - 优惠券")
@RestController
@RequestMapping("/coupon/item")
@Validated
public class CouponController {
@Resource
private CouponService couponService;
//todo 用户优惠券
@PostMapping("/create")
@ApiOperation("用户领取优惠券")
@PreAuthorize("@ss.hasPermission('coupon::create')")
public CommonResult<Long> create(@RequestParam("couponTemplateId") Long couponTemplateId) {
return success(couponService.create(couponTemplateId));
}
@PutMapping("/update")
@ApiOperation("更新优惠券")
@PreAuthorize("@ss.hasPermission('coupon::update')")
public CommonResult<Boolean> update(@Valid @RequestBody CouponUpdateReqVO updateReqVO) {
couponService.update(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除优惠券")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('coupon::delete')")
public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
couponService.delete(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得优惠券")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('coupon::query')")
public CommonResult<CouponRespVO> get(@RequestParam("id") Long id) {
CouponDO couponDO = couponService.get(id);
return success(CouponConvert.INSTANCE.convert(couponDO));
}
@GetMapping("/list")
@ApiOperation("获得优惠券列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('coupon::query')")
public CommonResult<List<CouponRespVO>> getList(@RequestParam("ids") Collection<Long> ids) {
List<CouponDO> list = couponService.getList(ids);
return success(CouponConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得优惠券分页")
@PreAuthorize("@ss.hasPermission('coupon::query')")
public CommonResult<PageResult<CouponRespVO>> getPage(@Valid CouponPageReqVO pageVO) {
PageResult<CouponDO> pageResult = couponService.getPage(pageVO);
return success(CouponConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@ -1,111 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
import lombok.*;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 优惠券 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class CouponBaseVO {
@ApiModelProperty(value = "优惠券类型 reward-满减 discount-折扣 random-随机", required = true)
@NotNull(message = "优惠券类型 reward-满减 discount-折扣 random-随机不能为空")
private String type;
@ApiModelProperty(value = "优惠券名称", required = true)
@NotNull(message = "优惠券名称不能为空")
private String name;
@ApiModelProperty(value = "优惠券类型id")
private Long couponTypeId;
@ApiModelProperty(value = "优惠券编码", required = true)
@NotNull(message = "优惠券编码不能为空")
private String couponCode;
@ApiModelProperty(value = "领用人", required = true)
@NotNull(message = "领用人不能为空")
private Long memberId;
@ApiModelProperty(value = "优惠券使用订单id", required = true)
@NotNull(message = "优惠券使用订单id不能为空")
private Long useOrderId;
@ApiModelProperty(value = "适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用", required = true)
@NotNull(message = "适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用不能为空")
private Boolean goodsType;
@ApiModelProperty(value = "适用商品id", required = true)
@NotNull(message = "适用商品id不能为空")
private String goodsIds;
@ApiModelProperty(value = "最小金额", required = true)
@NotNull(message = "最小金额不能为空")
private BigDecimal atLeast;
@ApiModelProperty(value = "面额", required = true)
@NotNull(message = "面额不能为空")
private BigDecimal money;
@ApiModelProperty(value = "1 =< 折扣 <= 9.9 当type为discount时需要添加", required = true)
@NotNull(message = "1 =< 折扣 <= 9.9 当type为discount时需要添加不能为空")
private BigDecimal discount;
@ApiModelProperty(value = "最多折扣金额 当type为discount时可选择性添加", required = true)
@NotNull(message = "最多折扣金额 当type为discount时可选择性添加不能为空")
private BigDecimal discountLimit;
@ApiModelProperty(value = "优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用", required = true)
@NotNull(message = "优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用不能为空")
private Boolean whetherForbidPreference;
@ApiModelProperty(value = "是否开启过期提醒0-不开启 1-开启", required = true)
@NotNull(message = "是否开启过期提醒0-不开启 1-开启")
private Boolean whetherExpireNotice;
@ApiModelProperty(value = "过期前N天提醒", required = true)
@NotNull(message = "过期前N天提醒不能为空")
private Integer expireNoticeFixedTerm;
@ApiModelProperty(value = "是否已提醒", required = true)
@NotNull(message = "是否已提醒不能为空")
private Boolean whetherNoticed;
@ApiModelProperty(value = "优惠券状态 1已领用未使用 2已使用 3已过期", required = true)
@NotNull(message = "优惠券状态 1已领用未使用 2已使用 3已过期不能为空")
private Integer state;
@ApiModelProperty(value = "获取方式1订单2.直接领取3.活动领取 4转赠 5分享获取", required = true)
@NotNull(message = "获取方式1订单2.直接领取3.活动领取 4转赠 5分享获取不能为空")
private Boolean getType;
@ApiModelProperty(value = "领取时间", required = true)
@NotNull(message = "领取时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime fetchTime;
@ApiModelProperty(value = "使用时间", required = true)
@NotNull(message = "使用时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime useTime;
@ApiModelProperty(value = "可使用的开始时间", required = true)
@NotNull(message = "可使用的开始时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime startTime;
@ApiModelProperty(value = "有效期结束时间", required = true)
@NotNull(message = "有效期结束时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime endTime;
}

View File

@ -1,14 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 优惠券创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CouponCreateReqVO extends CouponBaseVO {
}

View File

@ -1,90 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
import lombok.*;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 优惠券 Excel VO
*
* @author wxr
*/
@Data
public class CouponExcelVO {
@ExcelProperty("用户ID")
private Long id;
@ExcelProperty("优惠券类型 reward-满减 discount-折扣 random-随机")
private String type;
@ExcelProperty("优惠券名称")
private String name;
@ExcelProperty("优惠券类型id")
private Long couponTypeId;
@ExcelProperty("优惠券编码")
private String couponCode;
@ExcelProperty("领用人")
private Long memberId;
@ExcelProperty("优惠券使用订单id")
private Long useOrderId;
@ExcelProperty("适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用")
private Boolean goodsType;
@ExcelProperty("适用商品id")
private String goodsIds;
@ExcelProperty("最小金额")
private BigDecimal atLeast;
@ExcelProperty("面额")
private BigDecimal money;
@ExcelProperty("1 =< 折扣 <= 9.9 当type为discount时需要添加")
private BigDecimal discount;
@ExcelProperty("最多折扣金额 当type为discount时可选择性添加")
private BigDecimal discountLimit;
@ExcelProperty("优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用")
private Boolean whetherForbidPreference;
@ExcelProperty("是否开启过期提醒0-不开启 1-开启")
private Boolean whetherExpireNotice;
@ExcelProperty("过期前N天提醒")
private Integer expireNoticeFixedTerm;
@ExcelProperty("是否已提醒")
private Boolean whetherNoticed;
@ExcelProperty("优惠券状态 1已领用未使用 2已使用 3已过期")
private Integer state;
@ExcelProperty("获取方式1订单2.直接领取3.活动领取 4转赠 5分享获取")
private Boolean getType;
@ExcelProperty("领取时间")
private LocalDateTime fetchTime;
@ExcelProperty("使用时间")
private LocalDateTime useTime;
@ExcelProperty("可使用的开始时间")
private LocalDateTime startTime;
@ExcelProperty("有效期结束时间")
private LocalDateTime endTime;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -1,90 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import io.swagger.annotations.*;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 优惠券 Excel 导出 Request VO", description = "参数和 CouponPageReqVO 是一致的")
@Data
public class CouponExportReqVO {
@ApiModelProperty(value = "优惠券类型 reward-满减 discount-折扣 random-随机")
private String type;
@ApiModelProperty(value = "优惠券名称")
private String name;
@ApiModelProperty(value = "优惠券类型id")
private Long couponTypeId;
@ApiModelProperty(value = "优惠券编码")
private String couponCode;
@ApiModelProperty(value = "领用人")
private Long memberId;
@ApiModelProperty(value = "优惠券使用订单id")
private Long useOrderId;
@ApiModelProperty(value = "适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用")
private Boolean goodsType;
@ApiModelProperty(value = "适用商品id")
private String goodsIds;
@ApiModelProperty(value = "最小金额")
private BigDecimal atLeast;
@ApiModelProperty(value = "面额")
private BigDecimal money;
@ApiModelProperty(value = "1 =< 折扣 <= 9.9 当type为discount时需要添加")
private BigDecimal discount;
@ApiModelProperty(value = "最多折扣金额 当type为discount时可选择性添加")
private BigDecimal discountLimit;
@ApiModelProperty(value = "优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用")
private Boolean whetherForbidPreference;
@ApiModelProperty(value = "是否开启过期提醒0-不开启 1-开启")
private Boolean whetherExpireNotice;
@ApiModelProperty(value = "过期前N天提醒")
private Integer expireNoticeFixedTerm;
@ApiModelProperty(value = "是否已提醒")
private Boolean whetherNoticed;
@ApiModelProperty(value = "优惠券状态 1已领用未使用 2已使用 3已过期")
private Integer state;
@ApiModelProperty(value = "获取方式1订单2.直接领取3.活动领取 4转赠 5分享获取")
private Boolean getType;
@ApiModelProperty(value = "领取时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] fetchTime;
@ApiModelProperty(value = "使用时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] useTime;
@ApiModelProperty(value = "可使用的开始时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] startTime;
@ApiModelProperty(value = "有效期结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] endTime;
@ApiModelProperty(value = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -1,93 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 优惠券分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CouponPageReqVO extends PageParam {
@ApiModelProperty(value = "优惠券类型 reward-满减 discount-折扣 random-随机")
private String type;
@ApiModelProperty(value = "优惠券名称")
private String name;
@ApiModelProperty(value = "优惠券类型id")
private Long couponTypeId;
@ApiModelProperty(value = "优惠券编码")
private String couponCode;
@ApiModelProperty(value = "领用人")
private Long memberId;
@ApiModelProperty(value = "优惠券使用订单id")
private Long useOrderId;
@ApiModelProperty(value = "适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用")
private Boolean goodsType;
@ApiModelProperty(value = "适用商品id")
private String goodsIds;
@ApiModelProperty(value = "最小金额")
private BigDecimal atLeast;
@ApiModelProperty(value = "面额")
private BigDecimal money;
@ApiModelProperty(value = "1 =< 折扣 <= 9.9 当type为discount时需要添加")
private BigDecimal discount;
@ApiModelProperty(value = "最多折扣金额 当type为discount时可选择性添加")
private BigDecimal discountLimit;
@ApiModelProperty(value = "优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用")
private Boolean whetherForbidPreference;
@ApiModelProperty(value = "是否开启过期提醒0-不开启 1-开启")
private Boolean whetherExpireNotice;
@ApiModelProperty(value = "过期前N天提醒")
private Integer expireNoticeFixedTerm;
@ApiModelProperty(value = "是否已提醒")
private Boolean whetherNoticed;
@ApiModelProperty(value = "优惠券状态 1已领用未使用 2已使用 3已过期")
private Integer state;
@ApiModelProperty(value = "获取方式1订单2.直接领取3.活动领取 4转赠 5分享获取")
private Boolean getType;
@ApiModelProperty(value = "领取时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] fetchTime;
@ApiModelProperty(value = "使用时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] useTime;
@ApiModelProperty(value = "可使用的开始时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] startTime;
@ApiModelProperty(value = "有效期结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] endTime;
@ApiModelProperty(value = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
import lombok.*;
import java.time.LocalDateTime;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 优惠券 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CouponRespVO extends CouponBaseVO {
@ApiModelProperty(value = "用户ID", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private LocalDateTime createTime;
}

View File

@ -1,18 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 优惠券更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CouponUpdateReqVO extends CouponBaseVO {
@ApiModelProperty(value = "用户ID", required = true)
@NotNull(message = "用户ID不能为空")
private Long id;
}

View File

@ -1,81 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.templete;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.*;
import cn.iocoder.yudao.module.coupon.convert.CouponTemplete.CouponTempleteConvert;
import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
import cn.iocoder.yudao.module.coupon.service.CouponTemplete.CouponTempleteService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;
import javax.validation.*;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - 优惠券模板")
@RestController
@RequestMapping("/coupon/template")
@Validated
public class CouponTempleteController {
@Resource
private CouponTempleteService couponTempleteServiceService;
@PostMapping("/create")
@ApiOperation("创建优惠券模板")
@PreAuthorize("@ss.hasPermission('CouponTemplete::create')")
public CommonResult<Long> create(@Valid @RequestBody CouponTempleteCreateReqVO createReqVO) {
return success(couponTempleteServiceService.create(createReqVO));
}
// @PutMapping("/update")
// @ApiOperation("更新优惠券模板")
// @PreAuthorize("@ss.hasPermission('CouponTemplete::update')")
// public CommonResult<Boolean> update(@Valid @RequestBody CouponTempleteUpdateReqVO updateReqVO) {
// couponTempleteServiceService.update(updateReqVO);
// return success(true);
// }
//
// @DeleteMapping("/delete")
// @ApiOperation("删除优惠券模板")
// @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
// @PreAuthorize("@ss.hasPermission('CouponTemplete::delete')")
// public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
// couponTempleteServiceService.delete(id);
// return success(true);
// }
//
// @GetMapping("/get")
// @ApiOperation("获得优惠券模板")
// @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
// @PreAuthorize("@ss.hasPermission('CouponTemplete::query')")
// public CommonResult<CouponTempleteRespVO> get(@RequestParam("id") Long id) {
// CouponTempleteDO couponTempleteDO = couponTempleteServiceService.get(id);
// return success(CouponTempleteConvert.INSTANCE.convert(couponTempleteDO));
// }
//
// @GetMapping("/list")
// @ApiOperation("获得优惠券模板列表")
// @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
// @PreAuthorize("@ss.hasPermission('CouponTemplete::query')")
// public CommonResult<List<CouponTempleteRespVO>> getList(@RequestParam("ids") Collection<Long> ids) {
// List<CouponTempleteDO> list = couponTempleteServiceService.getList(ids);
// return success(CouponTempleteConvert.INSTANCE.convertList(list));
// }
//
@GetMapping("/page")
@ApiOperation("获得优惠券模板分页")
@PreAuthorize("@ss.hasPermission('CouponTemplete::query')")
public CommonResult<PageResult<CouponTempleteRespVO>> getPage(@Valid CouponTempletePageReqVO pageVO) {
PageResult<CouponTempleteDO> pageResult = couponTempleteServiceService.getPage(pageVO);
return success(CouponTempleteConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@ -1,173 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
import lombok.*;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 优惠券模板 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class CouponTempleteBaseVO {
//基本信息
@ApiModelProperty(value = "优惠券名称", required = true)
@NotNull(message = "优惠券名称不能为空")
private String name;
@ApiModelProperty(value = "名称备注")
private String couponNameRemark;
@ApiModelProperty(value = "优惠券图片")
private String image;
/* ============判断适用商品——开始============= */
@ApiModelProperty(value = "适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用", required = true)
@NotNull(message = "适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用不能为空")
private Integer goodsType;
@ApiModelProperty(value = "适用商品id")
private String productIds;
@ApiModelProperty(value = "使用门槛0-无门槛 1-有门槛", required = true)
@NotNull(message = "使用门槛0-无门槛 1-有门槛不能为空")
private Boolean hasUseLimit;
@ApiModelProperty(value = "满多少元使用 0代表无限制", required = true)
@NotNull(message = "满多少元使用 0代表无限制不能为空")
private BigDecimal atLeast;
/* ============折扣类型——开始============= */
@ApiModelProperty(value = "优惠券类型 reward-满减 discount-折扣 random-随机", required = true)
@NotNull(message = "优惠券类型 reward-满减 discount-折扣 random-随机不能为空")
private String type;
@ApiModelProperty(value = "发放面额 当type为reward时需要添加")
@NotNull(message = "发放面额 当type为reward时需要添加不能为空")
private BigDecimal money;
@ApiModelProperty(value = "1 =< 折扣 <= 9.9 当type为discount时需要添加")
@NotNull(message = "1 =< 折扣 <= 9.9 当type为discount时需要添加不能为空")
private BigDecimal discount;
@ApiModelProperty(value = "最多折扣金额 当type为discount时可选择性添加")
@NotNull(message = "最多折扣金额 当type为discount时可选择性添加不能为空")
private BigDecimal discountLimit;
@ApiModelProperty(value = "最低金额 当type为radom时需要添加", required = true)
@NotNull(message = "最低金额 当type为radom时需要添加不能为空")
private BigDecimal minMoney;
@ApiModelProperty(value = "最大金额 当type为radom时需要添加", required = true)
@NotNull(message = "最大金额 当type为radom时需要添加不能为空")
private BigDecimal maxMoney;
/* ============折扣类型——结束============= */
/* ============过期类型——开始============= */
@ApiModelProperty(value = "过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期", required = true)
@NotNull(message = "过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期 不能为空")
private Integer validityType;
@ApiModelProperty(value = "使用开始日期 过期类型1时必填")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime startUseTime;
@ApiModelProperty(value = "使用结束日期 过期类型1时必填")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime endUseTime;
@ApiModelProperty(value = "当validity_type为2或者3时需要添加 领取之日起或者次日N天内有效")
@NotNull(message = "当validity_type为2或者3时需要添加 领取之日起或者次日N天内有效不能为空")
private Integer fixedTerm;
@ApiModelProperty(value = "有效日期结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime endTime;
/* ============过期类型——结束============= */
@ApiModelProperty(value = "领取是否无限制0-否 1是", required = true)
@NotNull(message = "是否无限制0-否 1是")
private Boolean whetherLimitless;
@ApiModelProperty(value = "每人最大领取个数", required = true)
@NotNull(message = "每人最大领取个数不能为空")
private Integer maxFetch;
@ApiModelProperty(value = "是否开启过期提醒 0-不开启 1-开启", required = true)
@NotNull(message = "是否开启过期提醒0-不开启 1-开启不能为空")
private Boolean whetherExpireNotice;
@ApiModelProperty(value = "过期前N天提醒", required = true)
@NotNull(message = "过期前N天提醒不能为空")
private Integer expireNoticeFixedTerm;
@ApiModelProperty(value = "优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用", required = true)
@NotNull(message = "优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用不能为空")
private Boolean whetherForbidPreference;
@ApiModelProperty(value = "是否显示", required = true)
@NotNull(message = "是否显示不能为空")
private Integer whetherShow;
@ApiModelProperty(value = "是否禁止发放0-否 1-是", required = true)
@NotNull(message = "是否禁止发放0-否 1-是不能为空")
private Boolean whetherForbidden;
/* ============汇总计算——开始============= */
@ApiModelProperty(value = "使用优惠券购买的商品数量", required = true)
@NotNull(message = "使用优惠券购买的商品数量不能为空")
private Integer orderGoodsNum;
@ApiModelProperty(value = "订单的优惠总金额", required = true)
@NotNull(message = "订单的优惠总金额不能为空")
private BigDecimal discountOrderMoney;
@ApiModelProperty(value = "用券总成交额", required = true)
@NotNull(message = "用券总成交额不能为空")
private BigDecimal orderMoney;
@ApiModelProperty(value = "发放数量", required = true)
@NotNull(message = "发放数量不能为空")
private Integer count;
@ApiModelProperty(value = "已领取数量", required = true)
@NotNull(message = "已领取数量不能为空")
private Integer leadCount;
@ApiModelProperty(value = "已使用数量", required = true)
@NotNull(message = "已使用数量不能为空")
private Integer usedCount;
/* ============汇总计算——结束============= */
@ApiModelProperty(value = "状态1进行中2已结束3已关闭", required = true)
@NotNull(message = "状态1进行中2已结束-1已关闭不能为空")
private Integer status;
}

View File

@ -1,12 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
import lombok.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 优惠券模板创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CouponTempleteCreateReqVO extends CouponTempleteBaseVO {
}

View File

@ -1,120 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
import lombok.*;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 优惠券模板 Excel VO
*
* @author wxr
*/
@Data
public class CouponTempleteExcelVO {
@ExcelProperty("用户ID")
private Long id;
@ExcelProperty("优惠券类型 reward-满减 discount-折扣 random-随机")
private String type;
@ExcelProperty("优惠券名称")
private String name;
@ExcelProperty("名称备注")
private String couponNameRemark;
@ExcelProperty("优惠券图片")
private String image;
@ExcelProperty("发放数量")
private Integer count;
@ExcelProperty("已领取数量")
private Integer leadCount;
@ExcelProperty("已使用数量")
private Integer usedCount;
@ExcelProperty("适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用")
private Integer goodsType;
@ExcelProperty("适用商品id")
private String productIds;
@ExcelProperty("使用门槛0-无门槛 1-有门槛")
private Boolean hasUseLimit;
@ExcelProperty("满多少元使用 0代表无限制")
private BigDecimal atLeast;
@ExcelProperty("发放面额 当type为reward时需要添加")
private BigDecimal money;
@ExcelProperty("1 =< 折扣 <= 9.9 当type为discount时需要添加")
private BigDecimal discount;
@ExcelProperty("最多折扣金额 当type为discount时可选择性添加")
private BigDecimal discountLimit;
@ExcelProperty("最低金额 当type为radom时需要添加")
private BigDecimal minMoney;
@ExcelProperty("最大金额 当type为radom时需要添加")
private BigDecimal maxMoney;
@ExcelProperty("过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期")
private Integer validityType;
@ExcelProperty("使用开始日期 过期类型1时必填")
private LocalDateTime startUseTime;
@ExcelProperty("使用结束日期 过期类型1时必填")
private LocalDateTime endUseTime;
@ExcelProperty("当validity_type为2或者3时需要添加 领取之日起或者次日N天内有效")
private Integer fixedTerm;
@ExcelProperty("是否无限制0-否 1是")
private Boolean whetherLimitless;
@ExcelProperty("每人最大领取个数")
private Integer maxFetch;
@ExcelProperty("是否开启过期提醒0-不开启 1-开启")
private Boolean whetherExpireNotice;
@ExcelProperty("过期前N天提醒")
private Integer expireNoticeFixedTerm;
@ExcelProperty("优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用")
private Boolean whetherForbidPreference;
@ExcelProperty("是否显示")
private Integer whetherShow;
@ExcelProperty("订单的优惠总金额")
private BigDecimal discountOrderMoney;
@ExcelProperty("用券总成交额")
private BigDecimal orderMoney;
@ExcelProperty("是否禁止发放0-否 1-是")
private Boolean whetherForbidden;
@ExcelProperty("使用优惠券购买的商品数量")
private Integer orderGoodsNum;
@ExcelProperty("状态1进行中2已结束-1已关闭")
private Integer status;
@ExcelProperty("有效日期结束时间")
private LocalDateTime endTime;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -1,119 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import io.swagger.annotations.*;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 优惠券模板 Excel 导出 Request VO", description = "参数和 CouponTempletePageReqVO 是一致的")
@Data
public class CouponTempleteExportReqVO {
@ApiModelProperty(value = "优惠券类型 reward-满减 discount-折扣 random-随机")
private String type;
@ApiModelProperty(value = "优惠券名称")
private String name;
@ApiModelProperty(value = "名称备注")
private String couponNameRemark;
@ApiModelProperty(value = "优惠券图片")
private String image;
@ApiModelProperty(value = "发放数量")
private Integer count;
@ApiModelProperty(value = "已领取数量")
private Integer leadCount;
@ApiModelProperty(value = "已使用数量")
private Integer usedCount;
@ApiModelProperty(value = "适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用")
private Boolean goodsType;
@ApiModelProperty(value = "适用商品id")
private String productIds;
@ApiModelProperty(value = "使用门槛0-无门槛 1-有门槛")
private Boolean hasUseLimit;
@ApiModelProperty(value = "满多少元使用 0代表无限制")
private BigDecimal atLeast;
@ApiModelProperty(value = "发放面额 当type为reward时需要添加")
private BigDecimal money;
@ApiModelProperty(value = "1 =< 折扣 <= 9.9 当type为discount时需要添加")
private BigDecimal discount;
@ApiModelProperty(value = "最多折扣金额 当type为discount时可选择性添加")
private BigDecimal discountLimit;
@ApiModelProperty(value = "最低金额 当type为radom时需要添加")
private BigDecimal minMoney;
@ApiModelProperty(value = "最大金额 当type为radom时需要添加")
private BigDecimal maxMoney;
@ApiModelProperty(value = "过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期")
private Boolean validityType;
@ApiModelProperty(value = "使用开始日期 过期类型1时必填")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] startUseTime;
@ApiModelProperty(value = "使用结束日期 过期类型1时必填")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] endUseTime;
@ApiModelProperty(value = "当validity_type为2或者3时需要添加 领取之日起或者次日N天内有效")
private Integer fixedTerm;
@ApiModelProperty(value = "是否无限制0-否 1是")
private Boolean whetherLimitless;
@ApiModelProperty(value = "每人最大领取个数")
private Integer maxFetch;
@ApiModelProperty(value = "是否开启过期提醒0-不开启 1-开启")
private Boolean whetherExpireNotice;
@ApiModelProperty(value = "过期前N天提醒")
private Integer expireNoticeFixedTerm;
@ApiModelProperty(value = "优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用")
private Boolean whetherForbidPreference;
@ApiModelProperty(value = "是否显示")
private Integer whetherShow;
@ApiModelProperty(value = "订单的优惠总金额")
private BigDecimal discountOrderMoney;
@ApiModelProperty(value = "用券总成交额")
private BigDecimal orderMoney;
@ApiModelProperty(value = "是否禁止发放0-否 1-是")
private Boolean whetherForbidden;
@ApiModelProperty(value = "使用优惠券购买的商品数量")
private Integer orderGoodsNum;
@ApiModelProperty(value = "状态1进行中2已结束-1已关闭")
private Integer status;
@ApiModelProperty(value = "有效日期结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] endTime;
@ApiModelProperty(value = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -1,122 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 优惠券模板分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CouponTempletePageReqVO extends PageParam {
@ApiModelProperty(value = "优惠券类型 reward-满减 discount-折扣 random-随机")
private String type;
@ApiModelProperty(value = "优惠券名称")
private String name;
@ApiModelProperty(value = "名称备注")
private String couponNameRemark;
@ApiModelProperty(value = "优惠券图片")
private String image;
@ApiModelProperty(value = "发放数量")
private Integer count;
@ApiModelProperty(value = "已领取数量")
private Integer leadCount;
@ApiModelProperty(value = "已使用数量")
private Integer usedCount;
@ApiModelProperty(value = "适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用")
private Boolean goodsType;
@ApiModelProperty(value = "适用商品id")
private String productIds;
@ApiModelProperty(value = "使用门槛0-无门槛 1-有门槛")
private Boolean hasUseLimit;
@ApiModelProperty(value = "满多少元使用 0代表无限制")
private BigDecimal atLeast;
@ApiModelProperty(value = "发放面额 当type为reward时需要添加")
private BigDecimal money;
@ApiModelProperty(value = "1 =< 折扣 <= 9.9 当type为discount时需要添加")
private BigDecimal discount;
@ApiModelProperty(value = "最多折扣金额 当type为discount时可选择性添加")
private BigDecimal discountLimit;
@ApiModelProperty(value = "最低金额 当type为radom时需要添加")
private BigDecimal minMoney;
@ApiModelProperty(value = "最大金额 当type为radom时需要添加")
private BigDecimal maxMoney;
@ApiModelProperty(value = "过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期")
private Boolean validityType;
@ApiModelProperty(value = "使用开始日期 过期类型1时必填")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] startUseTime;
@ApiModelProperty(value = "使用结束日期 过期类型1时必填")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] endUseTime;
@ApiModelProperty(value = "当validity_type为2或者3时需要添加 领取之日起或者次日N天内有效")
private Integer fixedTerm;
@ApiModelProperty(value = "是否无限制0-否 1是")
private Boolean whetherLimitless;
@ApiModelProperty(value = "每人最大领取个数")
private Integer maxFetch;
@ApiModelProperty(value = "是否开启过期提醒0-不开启 1-开启")
private Boolean whetherExpireNotice;
@ApiModelProperty(value = "过期前N天提醒")
private Integer expireNoticeFixedTerm;
@ApiModelProperty(value = "优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用")
private Boolean whetherForbidPreference;
@ApiModelProperty(value = "是否显示")
private Integer whetherShow;
@ApiModelProperty(value = "订单的优惠总金额")
private BigDecimal discountOrderMoney;
@ApiModelProperty(value = "用券总成交额")
private BigDecimal orderMoney;
@ApiModelProperty(value = "是否禁止发放0-否 1-是")
private Boolean whetherForbidden;
@ApiModelProperty(value = "使用优惠券购买的商品数量")
private Integer orderGoodsNum;
@ApiModelProperty(value = "状态1进行中2已结束-1已关闭")
private Integer status;
@ApiModelProperty(value = "有效日期结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] endTime;
@ApiModelProperty(value = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
import lombok.*;
import java.time.LocalDateTime;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 优惠券模板 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CouponTempleteRespVO extends CouponTempleteBaseVO {
@ApiModelProperty(value = "用户ID", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private LocalDateTime createTime;
}

View File

@ -1,17 +0,0 @@
package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
import lombok.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 优惠券模板更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CouponTempleteUpdateReqVO extends CouponTempleteBaseVO {
@ApiModelProperty(value = "用户ID", required = true)
@NotNull(message = "用户ID不能为空")
private Long id;
}

View File

@ -1,38 +0,0 @@
package cn.iocoder.yudao.module.coupon.convert.CouponTemplete;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteCreateReqVO;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteExcelVO;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteRespVO;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteUpdateReqVO;
import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 优惠券模板 Convert
*
* @author wxr
*/
@Mapper
public interface CouponTempleteConvert {
CouponTempleteConvert INSTANCE = Mappers.getMapper(CouponTempleteConvert.class);
CouponTempleteDO convert(CouponTempleteCreateReqVO bean);
CouponTempleteDO convert(CouponTempleteUpdateReqVO bean);
CouponTempleteRespVO convert(CouponTempleteDO bean);
List<CouponTempleteRespVO> convertList(List<CouponTempleteDO> list);
PageResult<CouponTempleteRespVO> convertPage(PageResult<CouponTempleteDO> page);
List<CouponTempleteExcelVO> convertList02(List<CouponTempleteDO> list);
}

View File

@ -1,34 +0,0 @@
package cn.iocoder.yudao.module.coupon.convert.coupon;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo.*;
import cn.iocoder.yudao.module.coupon.dal.dataobject.coupon.CouponDO;
/**
* 优惠券 Convert
*
* @author wxr
*/
@Mapper
public interface CouponConvert {
CouponConvert INSTANCE = Mappers.getMapper(CouponConvert.class);
CouponDO convert(CouponCreateReqVO bean);
CouponDO convert(CouponUpdateReqVO bean);
CouponRespVO convert(CouponDO bean);
List<CouponRespVO> convertList(List<CouponDO> list);
PageResult<CouponRespVO> convertPage(PageResult<CouponDO> page);
List<CouponExcelVO> convertList02(List<CouponDO> list);
}

View File

@ -1,159 +0,0 @@
package cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete;
import lombok.*;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 优惠券模板 DO
*
* @author wxr
*/
@TableName("coupon_templete")
@KeySequence("coupon_templete_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CouponTempleteDO extends BaseDO {
/**
* 用户ID
*/
@TableId
private Long id;
/**
* 优惠券类型 reward-满减 discount-折扣 random-随机
*/
private String type;
/**
* 优惠券名称
*/
private String name;
/**
* 名称备注
*/
private String couponNameRemark;
/**
* 优惠券图片
*/
private String image;
/**
* 发放数量
*/
private Integer count;
/**
* 已领取数量
*/
private Integer leadCount;
/**
* 已使用数量
*/
private Integer usedCount;
/**
* 适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用
*/
private Integer goodsType;
/**
* 适用商品id
*/
private String productIds;
/**
* 使用门槛0-无门槛 1-有门槛
*/
private Boolean hasUseLimit;
/**
* 满多少元使用 0代表无限制
*/
private BigDecimal atLeast;
/**
* 发放面额 当type为reward时需要添加
*/
private BigDecimal money;
/**
* 1 =< 折扣 <= 9.9 当type为discount时需要添加
*/
private BigDecimal discount;
/**
* 最多折扣金额 当type为discount时可选择性添加
*/
private BigDecimal discountLimit;
/**
* 最低金额 当type为radom时需要添加
*/
private BigDecimal minMoney;
/**
* 最大金额 当type为radom时需要添加
*/
private BigDecimal maxMoney;
/**
* 过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期
*/
private Integer validityType;
/**
* 使用开始日期 过期类型1时必填
*/
private LocalDateTime startUseTime;
/**
* 使用结束日期 过期类型1时必填
*/
private LocalDateTime endUseTime;
/**
* 当validity_type为2或者3时需要添加 领取之日起或者次日N天内有效
*/
private Integer fixedTerm;
/**
* 是否无限制0- 1是
*/
private Boolean whetherLimitless;
/**
* 每人最大领取个数
*/
private Integer maxFetch;
/**
* 是否开启过期提醒0-不开启 1-开启
*/
private Boolean whetherExpireNotice;
/**
* 过期前N天提醒
*/
private Integer expireNoticeFixedTerm;
/**
* 优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用
*/
private Boolean whetherForbidPreference;
/**
* 是否显示
*/
private Integer whetherShow;
/**
* 订单的优惠总金额
*/
private BigDecimal discountOrderMoney;
/**
* 用券总成交额
*/
private BigDecimal orderMoney;
/**
* 是否禁止发放0- 1-
*/
private Boolean whetherForbidden;
/**
* 使用优惠券购买的商品数量
*/
private Integer orderGoodsNum;
/**
* 状态1进行中2已结束-1已关闭
*/
private Integer status;
/**
* 有效日期结束时间
*/
private LocalDateTime endTime;
}

View File

@ -1,119 +0,0 @@
package cn.iocoder.yudao.module.coupon.dal.dataobject.coupon;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import lombok.*;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.*;
/**
* 优惠券 DO
*
* @author wxr
*/
@TableName("coupon")
@KeySequence("coupon_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CouponDO extends BaseDO {
/**
* 用户ID
*/
@TableId
private Long id;
/**
* 优惠券类型 reward-满减 discount-折扣 random-随机
*/
private String type;
/**
* 优惠券名称
*/
private String name;
/**
* 优惠券类型id
*/
private Long couponTypeId;
/**
* 优惠券编码
*/
private String couponCode;
/**
* 领用人
*/
private Long memberId;
/**
* 优惠券使用订单id
*/
private Long useOrderId;
/**
* 适用商品类型1-全部商品可用2-指定商品可用3-指定商品不可用
*/
private Boolean goodsType;
/**
* 适用商品id
*/
private String goodsIds;
/**
* 最小金额
*/
private BigDecimal atLeast;
/**
* 面额
*/
private BigDecimal money;
/**
* 1 =< 折扣 <= 9.9 当type为discount时需要添加
*/
private BigDecimal discount;
/**
* 最多折扣金额 当type为discount时可选择性添加
*/
private BigDecimal discountLimit;
/**
* 优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用
*/
private Boolean whetherForbidPreference;
/**
* 是否开启过期提醒0-不开启 1-开启
*/
private Boolean whetherExpireNotice;
/**
* 过期前N天提醒
*/
private Integer expireNoticeFixedTerm;
/**
* 是否已提醒
*/
private Boolean whetherNoticed;
/**
* 优惠券状态 1已领用未使用 2已使用 3已过期
*/
private Integer state;
/**
* 获取方式1订单2.直接领取3.活动领取 4转赠 5分享获取
*/
private Boolean getType;
/**
* 领取时间
*/
private LocalDateTime fetchTime;
/**
* 使用时间
*/
private LocalDateTime useTime;
/**
* 可使用的开始时间
*/
private LocalDateTime startTime;
/**
* 有效期结束时间
*/
private LocalDateTime endTime;
}

View File

@ -1,98 +0,0 @@
package cn.iocoder.yudao.module.coupon.dal.mysql.CouponTemplete;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteExportReqVO;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempletePageReqVO;
import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 优惠券模板 Mapper
*
* @author wxr
*/
@Mapper
public interface CouponTempleteMapper extends BaseMapperX<CouponTempleteDO> {
default PageResult<CouponTempleteDO> selectPage(CouponTempletePageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<CouponTempleteDO>()
.eqIfPresent(CouponTempleteDO::getType, reqVO.getType())
.likeIfPresent(CouponTempleteDO::getName, reqVO.getName())
.eqIfPresent(CouponTempleteDO::getCouponNameRemark, reqVO.getCouponNameRemark())
.eqIfPresent(CouponTempleteDO::getImage, reqVO.getImage())
.eqIfPresent(CouponTempleteDO::getCount, reqVO.getCount())
.eqIfPresent(CouponTempleteDO::getLeadCount, reqVO.getLeadCount())
.eqIfPresent(CouponTempleteDO::getUsedCount, reqVO.getUsedCount())
.eqIfPresent(CouponTempleteDO::getGoodsType, reqVO.getGoodsType())
.eqIfPresent(CouponTempleteDO::getProductIds, reqVO.getProductIds())
.eqIfPresent(CouponTempleteDO::getHasUseLimit, reqVO.getHasUseLimit())
.eqIfPresent(CouponTempleteDO::getAtLeast, reqVO.getAtLeast())
.eqIfPresent(CouponTempleteDO::getMoney, reqVO.getMoney())
.eqIfPresent(CouponTempleteDO::getDiscount, reqVO.getDiscount())
.eqIfPresent(CouponTempleteDO::getDiscountLimit, reqVO.getDiscountLimit())
.eqIfPresent(CouponTempleteDO::getMinMoney, reqVO.getMinMoney())
.eqIfPresent(CouponTempleteDO::getMaxMoney, reqVO.getMaxMoney())
.eqIfPresent(CouponTempleteDO::getValidityType, reqVO.getValidityType())
.betweenIfPresent(CouponTempleteDO::getStartUseTime, reqVO.getStartUseTime())
.betweenIfPresent(CouponTempleteDO::getEndUseTime, reqVO.getEndUseTime())
.eqIfPresent(CouponTempleteDO::getFixedTerm, reqVO.getFixedTerm())
.eqIfPresent(CouponTempleteDO::getWhetherLimitless, reqVO.getWhetherLimitless())
.eqIfPresent(CouponTempleteDO::getMaxFetch, reqVO.getMaxFetch())
.eqIfPresent(CouponTempleteDO::getWhetherExpireNotice, reqVO.getWhetherExpireNotice())
.eqIfPresent(CouponTempleteDO::getExpireNoticeFixedTerm, reqVO.getExpireNoticeFixedTerm())
.eqIfPresent(CouponTempleteDO::getWhetherForbidPreference, reqVO.getWhetherForbidPreference())
.eqIfPresent(CouponTempleteDO::getWhetherShow, reqVO.getWhetherShow())
.eqIfPresent(CouponTempleteDO::getDiscountOrderMoney, reqVO.getDiscountOrderMoney())
.eqIfPresent(CouponTempleteDO::getOrderMoney, reqVO.getOrderMoney())
.eqIfPresent(CouponTempleteDO::getWhetherForbidden, reqVO.getWhetherForbidden())
.eqIfPresent(CouponTempleteDO::getOrderGoodsNum, reqVO.getOrderGoodsNum())
.eqIfPresent(CouponTempleteDO::getStatus, reqVO.getStatus())
.betweenIfPresent(CouponTempleteDO::getEndTime, reqVO.getEndTime())
.betweenIfPresent(CouponTempleteDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(CouponTempleteDO::getId));
}
default List<CouponTempleteDO> selectList(CouponTempleteExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<CouponTempleteDO>()
.eqIfPresent(CouponTempleteDO::getType, reqVO.getType())
.likeIfPresent(CouponTempleteDO::getName, reqVO.getName())
.eqIfPresent(CouponTempleteDO::getCouponNameRemark, reqVO.getCouponNameRemark())
.eqIfPresent(CouponTempleteDO::getImage, reqVO.getImage())
.eqIfPresent(CouponTempleteDO::getCount, reqVO.getCount())
.eqIfPresent(CouponTempleteDO::getLeadCount, reqVO.getLeadCount())
.eqIfPresent(CouponTempleteDO::getUsedCount, reqVO.getUsedCount())
.eqIfPresent(CouponTempleteDO::getGoodsType, reqVO.getGoodsType())
.eqIfPresent(CouponTempleteDO::getProductIds, reqVO.getProductIds())
.eqIfPresent(CouponTempleteDO::getHasUseLimit, reqVO.getHasUseLimit())
.eqIfPresent(CouponTempleteDO::getAtLeast, reqVO.getAtLeast())
.eqIfPresent(CouponTempleteDO::getMoney, reqVO.getMoney())
.eqIfPresent(CouponTempleteDO::getDiscount, reqVO.getDiscount())
.eqIfPresent(CouponTempleteDO::getDiscountLimit, reqVO.getDiscountLimit())
.eqIfPresent(CouponTempleteDO::getMinMoney, reqVO.getMinMoney())
.eqIfPresent(CouponTempleteDO::getMaxMoney, reqVO.getMaxMoney())
.eqIfPresent(CouponTempleteDO::getValidityType, reqVO.getValidityType())
.betweenIfPresent(CouponTempleteDO::getStartUseTime, reqVO.getStartUseTime())
.betweenIfPresent(CouponTempleteDO::getEndUseTime, reqVO.getEndUseTime())
.eqIfPresent(CouponTempleteDO::getFixedTerm, reqVO.getFixedTerm())
.eqIfPresent(CouponTempleteDO::getWhetherLimitless, reqVO.getWhetherLimitless())
.eqIfPresent(CouponTempleteDO::getMaxFetch, reqVO.getMaxFetch())
.eqIfPresent(CouponTempleteDO::getWhetherExpireNotice, reqVO.getWhetherExpireNotice())
.eqIfPresent(CouponTempleteDO::getExpireNoticeFixedTerm, reqVO.getExpireNoticeFixedTerm())
.eqIfPresent(CouponTempleteDO::getWhetherForbidPreference, reqVO.getWhetherForbidPreference())
.eqIfPresent(CouponTempleteDO::getWhetherShow, reqVO.getWhetherShow())
.eqIfPresent(CouponTempleteDO::getDiscountOrderMoney, reqVO.getDiscountOrderMoney())
.eqIfPresent(CouponTempleteDO::getOrderMoney, reqVO.getOrderMoney())
.eqIfPresent(CouponTempleteDO::getWhetherForbidden, reqVO.getWhetherForbidden())
.eqIfPresent(CouponTempleteDO::getOrderGoodsNum, reqVO.getOrderGoodsNum())
.eqIfPresent(CouponTempleteDO::getStatus, reqVO.getStatus())
.betweenIfPresent(CouponTempleteDO::getEndTime, reqVO.getEndTime())
.betweenIfPresent(CouponTempleteDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(CouponTempleteDO::getId));
}
}

View File

@ -1,76 +0,0 @@
package cn.iocoder.yudao.module.coupon.dal.mysql.coupon;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.coupon.dal.dataobject.coupon.CouponDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo.*;
/**
* 优惠券 Mapper
*
* @author wxr
*/
@Mapper
public interface CouponMapper extends BaseMapperX<CouponDO> {
default PageResult<CouponDO> selectPage(CouponPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<CouponDO>()
.eqIfPresent(CouponDO::getType, reqVO.getType())
.likeIfPresent(CouponDO::getName, reqVO.getName())
.eqIfPresent(CouponDO::getCouponTypeId, reqVO.getCouponTypeId())
.eqIfPresent(CouponDO::getCouponCode, reqVO.getCouponCode())
.eqIfPresent(CouponDO::getMemberId, reqVO.getMemberId())
.eqIfPresent(CouponDO::getUseOrderId, reqVO.getUseOrderId())
.eqIfPresent(CouponDO::getGoodsType, reqVO.getGoodsType())
.eqIfPresent(CouponDO::getGoodsIds, reqVO.getGoodsIds())
.eqIfPresent(CouponDO::getAtLeast, reqVO.getAtLeast())
.eqIfPresent(CouponDO::getMoney, reqVO.getMoney())
.eqIfPresent(CouponDO::getDiscount, reqVO.getDiscount())
.eqIfPresent(CouponDO::getDiscountLimit, reqVO.getDiscountLimit())
.eqIfPresent(CouponDO::getWhetherForbidPreference, reqVO.getWhetherForbidPreference())
.eqIfPresent(CouponDO::getWhetherExpireNotice, reqVO.getWhetherExpireNotice())
.eqIfPresent(CouponDO::getExpireNoticeFixedTerm, reqVO.getExpireNoticeFixedTerm())
.eqIfPresent(CouponDO::getWhetherNoticed, reqVO.getWhetherNoticed())
.eqIfPresent(CouponDO::getState, reqVO.getState())
.eqIfPresent(CouponDO::getGetType, reqVO.getGetType())
.betweenIfPresent(CouponDO::getFetchTime, reqVO.getFetchTime())
.betweenIfPresent(CouponDO::getUseTime, reqVO.getUseTime())
.betweenIfPresent(CouponDO::getStartTime, reqVO.getStartTime())
.betweenIfPresent(CouponDO::getEndTime, reqVO.getEndTime())
.betweenIfPresent(CouponDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(CouponDO::getId));
}
default List<CouponDO> selectList(CouponExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<CouponDO>()
.eqIfPresent(CouponDO::getType, reqVO.getType())
.likeIfPresent(CouponDO::getName, reqVO.getName())
.eqIfPresent(CouponDO::getCouponTypeId, reqVO.getCouponTypeId())
.eqIfPresent(CouponDO::getCouponCode, reqVO.getCouponCode())
.eqIfPresent(CouponDO::getMemberId, reqVO.getMemberId())
.eqIfPresent(CouponDO::getUseOrderId, reqVO.getUseOrderId())
.eqIfPresent(CouponDO::getGoodsType, reqVO.getGoodsType())
.eqIfPresent(CouponDO::getGoodsIds, reqVO.getGoodsIds())
.eqIfPresent(CouponDO::getAtLeast, reqVO.getAtLeast())
.eqIfPresent(CouponDO::getMoney, reqVO.getMoney())
.eqIfPresent(CouponDO::getDiscount, reqVO.getDiscount())
.eqIfPresent(CouponDO::getDiscountLimit, reqVO.getDiscountLimit())
.eqIfPresent(CouponDO::getWhetherForbidPreference, reqVO.getWhetherForbidPreference())
.eqIfPresent(CouponDO::getWhetherExpireNotice, reqVO.getWhetherExpireNotice())
.eqIfPresent(CouponDO::getExpireNoticeFixedTerm, reqVO.getExpireNoticeFixedTerm())
.eqIfPresent(CouponDO::getWhetherNoticed, reqVO.getWhetherNoticed())
.eqIfPresent(CouponDO::getState, reqVO.getState())
.eqIfPresent(CouponDO::getGetType, reqVO.getGetType())
.betweenIfPresent(CouponDO::getFetchTime, reqVO.getFetchTime())
.betweenIfPresent(CouponDO::getUseTime, reqVO.getUseTime())
.betweenIfPresent(CouponDO::getStartTime, reqVO.getStartTime())
.betweenIfPresent(CouponDO::getEndTime, reqVO.getEndTime())
.betweenIfPresent(CouponDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(CouponDO::getId));
}
}

View File

@ -1,6 +0,0 @@
/**
* coupon模块主要负责麦一些优惠券的额增删
*
* 1. Controller URL /coumon/ 开头避免和其它 Module 冲突
*/
package cn.iocoder.yudao.module.coupon;

View File

@ -1,70 +0,0 @@
package cn.iocoder.yudao.module.coupon.service.CouponTemplete;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
/**
* 优惠券模板 Service 接口
*
* @author wxr
*/
public interface CouponTempleteService {
/**
* 创建优惠券模板
*
* @param createReqVO 创建信息
* @return 编号
*/
Long create(@Valid CouponTempleteCreateReqVO createReqVO);
/**
* 更新优惠券模板
*
* @param updateReqVO 更新信息
*/
void update(@Valid CouponTempleteUpdateReqVO updateReqVO);
/**
* 删除优惠券模板
*
* @param id 编号
*/
void delete(Long id);
/**
* 获得优惠券模板
*
* @param id 编号
* @return 优惠券模板
*/
CouponTempleteDO get(Long id);
/**
* 获得优惠券模板列表
*
* @param ids 编号
* @return 优惠券模板列表
*/
List<CouponTempleteDO> getList(Collection<Long> ids);
/**
* 获得优惠券模板分页
*
* @param pageReqVO 分页查询
* @return 优惠券模板分页
*/
PageResult<CouponTempleteDO> getPage(CouponTempletePageReqVO pageReqVO);
/**
* 获得优惠券模板列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 优惠券模板列表
*/
List<CouponTempleteDO> getList(CouponTempleteExportReqVO exportReqVO);
}

View File

@ -1,134 +0,0 @@
package cn.iocoder.yudao.module.coupon.service.CouponTemplete;
import cn.iocoder.yudao.module.CouponTemplete.enums.CouponTypeEnum;
import cn.iocoder.yudao.module.CouponTemplete.enums.CouponValidityTypeEnum;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteCreateReqVO;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteExportReqVO;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempletePageReqVO;
import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteUpdateReqVO;
import cn.iocoder.yudao.module.coupon.convert.CouponTemplete.CouponTempleteConvert;
import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
import cn.iocoder.yudao.module.coupon.dal.mysql.CouponTemplete.CouponTempleteMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.CouponTemplete.enums.ErrorCodeConstants.*;
/**
* 优惠券模板 Service 实现类
*
* @author wxr
*/
@Service
@Validated
public class CouponTempleteServiceImpl implements CouponTempleteService {
@Resource
private CouponTempleteMapper couponTempleteMapper;
@Override
public Long create(CouponTempleteCreateReqVO createReqVO) {
// 插入
CouponTempleteDO couponTempleteDO = CouponTempleteConvert.INSTANCE.convert(createReqVO);
/* 验证类型、判断必填*/
checkCouponType(createReqVO);
/*验证过期类型、判断必填*/
checkValidityType(createReqVO);
couponTempleteMapper.insert(couponTempleteDO);
// 返回
return couponTempleteDO.getId();
}
/*确认优惠券类型*/
private void checkValidityType(CouponTempleteCreateReqVO createReqVO) {
Integer validtyType = createReqVO.getValidityType();
if(CouponValidityTypeEnum.TIME_RANGE_EXPIRTED.getStatus().equals(validtyType)){
if(createReqVO.getStartUseTime() == null||createReqVO.getEndUseTime() == null){
throw exception(START_END_TIME_NOT_NULL);
}
}else{
if(createReqVO.getFixedTerm() == null){
throw exception(FIXED_TERM_NOT_NULL);
}
}
}
private void checkCouponType(CouponTempleteCreateReqVO createReqVO) {
String couponType = createReqVO.getType();
//当type=reward时候需要添加
if(couponType.equals(CouponTypeEnum.REWARD.getName())){
if(createReqVO.getMoney()==null){
throw exception(MONEY_NOT_NULL);
}
}else if(couponType.equals(CouponTypeEnum.DISCOUNT.getName())){
if(createReqVO.getDiscount()==null){
throw exception(DISCOUNT_NOT_NULL);
}
if(createReqVO.getDiscountLimit()==null){
throw exception(DISCOUNT_LIMIT_NOT_NULL);
}
}else if (couponType.equals(CouponTypeEnum.RANDOW.getName())){
//当type为radom时需要添加不能为空
if(createReqVO.getMinMoney()==null||createReqVO.getMaxMoney()==null){
throw exception(MIN_MAX_NOT_NULL);
}
}
}
@Override
public void update(CouponTempleteUpdateReqVO updateReqVO) {
// 校验存在
this.validateExists(updateReqVO.getId());
// 更新
CouponTempleteDO updateObj = CouponTempleteConvert.INSTANCE.convert(updateReqVO);
couponTempleteMapper.updateById(updateObj);
}
@Override
public void delete(Long id) {
// 校验存在
this.validateExists(id);
// 删除
couponTempleteMapper.deleteById(id);
}
private void validateExists(Long id) {
if (couponTempleteMapper.selectById(id) == null) {
throw exception(COUPON_TEMPLETE_NOT_EXISTS);
}
}
@Override
public CouponTempleteDO get(Long id) {
return couponTempleteMapper.selectById(id);
}
@Override
public List<CouponTempleteDO> getList(Collection<Long> ids) {
return couponTempleteMapper.selectBatchIds(ids);
}
@Override
public PageResult<CouponTempleteDO> getPage(CouponTempletePageReqVO pageReqVO) {
return couponTempleteMapper.selectPage(pageReqVO);
}
@Override
public List<CouponTempleteDO> getList(CouponTempleteExportReqVO exportReqVO) {
return couponTempleteMapper.selectList(exportReqVO);
}
}

View File

@ -1,70 +0,0 @@
package cn.iocoder.yudao.module.coupon.service.coupon;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo.*;
import cn.iocoder.yudao.module.coupon.dal.dataobject.coupon.CouponDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
/**
* 优惠券 Service 接口
*
* @author wxr
*/
public interface CouponService {
/**
* 创建优惠券
*
* @param templateId 优惠券模板id
* @return 编号
*/
Long create(Long templateId);
/**
* 更新优惠券
*
* @param updateReqVO 更新信息
*/
void update(@Valid CouponUpdateReqVO updateReqVO);
/**
* 删除优惠券
*
* @param id 编号
*/
void delete(Long id);
/**
* 获得优惠券
*
* @param id 编号
* @return 优惠券
*/
CouponDO get(Long id);
/**
* 获得优惠券列表
*
* @param ids 编号
* @return 优惠券列表
*/
List<CouponDO> getList(Collection<Long> ids);
/**
* 获得优惠券分页
*
* @param pageReqVO 分页查询
* @return 优惠券分页
*/
PageResult<CouponDO> getPage(CouponPageReqVO pageReqVO);
/**
* 获得优惠券列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 优惠券列表
*/
List<CouponDO> getList(CouponExportReqVO exportReqVO);
}

View File

@ -1,106 +0,0 @@
package cn.iocoder.yudao.module.coupon.service.coupon;
import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
import cn.iocoder.yudao.module.coupon.dal.mysql.CouponTemplete.CouponTempleteMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo.*;
import cn.iocoder.yudao.module.coupon.dal.dataobject.coupon.CouponDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.coupon.convert.coupon.CouponConvert;
import cn.iocoder.yudao.module.coupon.dal.mysql.coupon.CouponMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.CouponTemplete.enums.ErrorCodeConstants.COUPON_NOT_EXISTS;
/**
* 优惠券 Service 实现类
*
* @author wxr
*/
@Service
@Validated
public class CouponServiceImpl implements CouponService {
@Resource
private CouponMapper couponMapper;
@Resource
private CouponTempleteMapper couponTempleteMapper;
public Long create(CouponCreateReqVO createReqVO) {
// 插入
CouponDO couponDO = CouponConvert.INSTANCE.convert(createReqVO);
couponMapper.insert(couponDO);
// 返回
return couponDO.getId();
}
/**
*todo 获取用户id收获优惠券
*@author:wxr
*@date:2022-08-13 3:11
*@Description
*/
@Override
public Long create(Long templateId) {
Long userid = SecurityFrameworkUtils.getLoginUserId();
CouponDO couponDO = CouponDO.builder().memberId(userid).build();
CouponTempleteDO couponTempleteDO = couponTempleteMapper.selectById(templateId);
//todo 缺少判空
BeanUtil.copyProperties(couponTempleteDO,couponTempleteDO);
couponMapper.insert(couponDO);
return couponDO.getId();
}
@Override
public void update(CouponUpdateReqVO updateReqVO) {
// 校验存在
this.validateExists(updateReqVO.getId());
// 更新
CouponDO updateObj = CouponConvert.INSTANCE.convert(updateReqVO);
couponMapper.updateById(updateObj);
}
@Override
public void delete(Long id) {
// 校验存在
this.validateExists(id);
// 删除
couponMapper.deleteById(id);
}
private void validateExists(Long id) {
if (couponMapper.selectById(id) == null) {
throw exception(COUPON_NOT_EXISTS);
}
}
@Override
public CouponDO get(Long id) {
return couponMapper.selectById(id);
}
@Override
public List<CouponDO> getList(Collection<Long> ids) {
return couponMapper.selectBatchIds(ids);
}
@Override
public PageResult<CouponDO> getPage(CouponPageReqVO pageReqVO) {
return couponMapper.selectPage(pageReqVO);
}
@Override
public List<CouponDO> getList(CouponExportReqVO exportReqVO) {
return couponMapper.selectList(exportReqVO);
}
}

View File

@ -1,12 +0,0 @@
<?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.yudao.module.coupon.dal.mysql.CouponTemplete.CouponTempleteMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@ -1,12 +0,0 @@
<?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.yudao.module.coupon.dal.mysql.coupon.CouponMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@ -1,4 +0,0 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.market.api;

View File

@ -1,202 +0,0 @@
package cn.iocoder.yudao.module.market.api.price.dto;
import cn.iocoder.yudao.module.market.enums.common.PromotionLevelEnum;
import cn.iocoder.yudao.module.market.enums.common.PromotionTypeEnum;
import lombok.Data;
import java.util.List;
/**
* 价格计算 Response DTO
*
* @author 芋道源码
*/
@Data
public class PriceCalculateRespDTO {
/**
* 订单
*/
private Order order;
/**
* 商品 SKU 数组
*/
private List<Item> items;
/**
* 营销活动数组
*
* 只对应 {@link #items} 商品匹配的活动
*/
private List<Promotion> promotions;
/**
* 订单
*/
@Data
public static class Order {
/**
* 商品原价单位
*
* 基于 {@link Item#getTotalOriginalPrice()} 求和
*/
private Integer skuOriginalPrice;
/**
* 商品优惠单位
*
* 基于 {@link Item#getTotalPromotionPrice()} 求和
*/
private Integer skuPromotionPrice;
/**
* 订单优惠单位
*
* 例如说满减折扣不包括优惠劵商品优惠
*/
private Integer orderPromotionPrice;
/**
* 运费金额单位
*/
private Integer deliveryPrice;
/**
* 应付金额单位
*
* = {@link #skuOriginalPrice}
* + {@link #deliveryPrice}
* - {@link #skuPromotionPrice}
* - {@link #orderPromotionPrice}
*/
// * - {@link #couponPrice} // TODO 芋艿靠营销表记录
private Integer payPrice;
// ========== 营销基本信息 ==========
/**
* 优惠劵编号
*/
private Long couponId;
// /**
// * 优惠劵减免金额单位
// *
// * // TODO 芋艿靠营销表记录
// */
// private Integer couponPrice;
}
/**
* 商品 SKU
*/
@Data
public static class Item extends PriceCalculateReqDTO.Item {
/**
* 商品原价单位
*
* 对应 ProductSkuDO price 字段
*/
private Integer originalPrice;
/**
* 商品原价单位
*
* = {@link #originalPrice} * {@link #getCount()}
*/
private Integer totalOriginalPrice;
/**
* 商品级优惠单位
*
* 例如说限时折扣商品原价的 8 商品原价的减 50
*/
private Integer totalPromotionPrice;
/**
* 最终购买金额单位
*
* = {@link #totalOriginalPrice}
* - {@link #totalPromotionPrice}
*/
private Integer totalPresentPrice;
/**
* 最终购买金额单位
*
* = {@link #totalPresentPrice} / {@link #getCount()}
*/
private Integer presentPrice;
/**
* 应付金额单位
*/
private Integer totalPayPrice;
}
/**
* 营销活动
*/
@Data
public static class Promotion {
/**
* 营销编号
*
* 例如说营销活动的编号优惠劵的编号
*/
private Long id;
/**
* 营销类型
*
* 枚举 {@link PromotionTypeEnum}
*/
private Integer type;
/**
* 营销级别
*
* 枚举 {@link PromotionLevelEnum}
*/
private Integer level;
/**
* 匹配的商品 SKU 数组
*/
private List<Item> items;
/**
* 计算时的原价单位
*/
private Integer totalOriginalPrice;
/**
* 计算时的优惠单位
*/
private Integer totalPromotionPrice;
/**
* 是否满足优惠条件
*/
private Boolean meet;
/**
* 满足条件的提示
*
* 如果 {@link #meet} = true 满足则提示圣诞价: 150.00
* 如果 {@link #meet} = false 不满足则提示购满 85 可减 40
*/
private String meetTip;
/**
* 匹配的商品 SKU
*/
@Data
public static class Item {
/**
* 商品 SKU 编号
*/
private Long skuId;
/**
* 计算时的原价单位
*/
private Integer totalOriginalPrice;
/**
* 计算时的优惠单位
*/
private Integer totalPromotionPrice;
}
}
}

View File

@ -1,18 +0,0 @@
package cn.iocoder.yudao.module.market.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* market 错误码枚举类
* <p>
* market 系统使用 1-003-000-000
*/
public interface ErrorCodeConstants {
// ========== 促销活动相关 1003001000============
ErrorCode ACTIVITY_NOT_EXISTS = new ErrorCode(1003001000, "促销活动不存在");
// ========== banner相关 1003002000============
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1003002000, "Banner不存在");
}

View File

@ -1,4 +0,0 @@
/**
* TODO 占位
*/
package cn.iocoder.yudao.module.market.controller.admin.discount;

View File

@ -1,4 +0,0 @@
/**
* TODO 占位
*/
package cn.iocoder.yudao.module.market.convert.discount;

View File

@ -1,4 +0,0 @@
/**
* TODO 占位
*/
package cn.iocoder.yudao.module.market.dal.mysql.discount;

View File

@ -1,4 +0,0 @@
/**
* TODO 占位
*/
package cn.iocoder.yudao.module.market.service.discount;

View File

@ -1,24 +0,0 @@
package cn.iocoder.yudao.module.market.service.price;
import cn.iocoder.yudao.module.market.api.price.PriceApi;
import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateReqDTO;
import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateRespDTO;
import org.springframework.stereotype.Service;
/**
* 价格 API 实现类
*
* TODO 完善注释
*
* @author TODO
*/
@Service
public class PriceApiImpl implements PriceApi {
@Override
public PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO) {
// TODO fixme实现逻辑
return new PriceCalculateRespDTO();
}
}

View File

@ -1 +0,0 @@
DELETE FROM "market_activity";

View File

@ -1,19 +0,0 @@
CREATE TABLE IF NOT EXISTS "market_activity" (
"id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"title" varchar(50) NOT NULL,
"activity_type" tinyint(4) NOT NULL,
"status" tinyint(4) NOT NULL,
"start_time" datetime NOT NULL,
"end_time" datetime NOT NULL,
"invalid_time" datetime,
"delete_time" datetime,
"time_limited_discount" varchar(2000),
"full_privilege" varchar(2000),
"creator" varchar(64) DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint(20) NOT NULL,
PRIMARY KEY ("id")
) COMMENT '促销活动';

View File

@ -22,6 +22,13 @@
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId> <artifactId>yudao-common</artifactId>
</dependency> </dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,30 +1,40 @@
package cn.iocoder.yudao.module.product.api.sku; package cn.iocoder.yudao.module.product.api.sku;
import cn.iocoder.yudao.module.product.api.sku.dto.SkuDecrementStockBatchReqDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.SkuInfoRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
* 商品 SKU API 接口
*
* @author LeeYan9 * @author LeeYan9
* @since 2022-08-26 * @since 2022-08-26
*/ */
public interface ProductSkuApi { public interface ProductSkuApi {
/**
* 查询 SKU 信息
*
* @param id SKU 编号
* @return SKU 信息
*/
ProductSkuRespDTO getSku(Long id);
/** /**
* 根据skuId列表 查询sku信息 * 批量查询 SKU 数组
* *
* @param skuIds sku ID列表 * @param ids SKU 编号列表
* @return sku信息列表 * @return SKU 数组
*/ */
List<SkuInfoRespDTO> getSkusByIds(Collection<Long> skuIds); List<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
/** /**
* 批量扣减sku库存 * 更新 SKU 库存
* *
* @param batchReqDTO sku库存信息列表 * @param updateStockReqDTO 更新请求
*/ */
void decrementStockBatch(SkuDecrementStockBatchReqDTO batchReqDTO); void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO);
} }

View File

@ -6,11 +6,13 @@ import lombok.Data;
import java.util.List; import java.util.List;
/** /**
* 商品 SKU 信息 Response DTO
*
* @author LeeYan9 * @author LeeYan9
* @since 2022-08-26 * @since 2022-08-26
*/ */
@Data @Data
public class SkuInfoRespDTO { public class ProductSkuRespDTO {
/** /**
* 商品 SKU 编号自增 * 商品 SKU 编号自增

View File

@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.product.api.sku.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 商品 SKU 更新库存 Request DTO
*
* @author LeeYan9
* @since 2022-08-26
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductSkuUpdateStockReqDTO {
/**
* 商品 SKU
*/
@NotNull(message = "商品 SKU 不能为空")
private List<Item> items;
@Data
public static class Item {
/**
* 商品 SKU 编号
*/
@NotNull(message = "商品 SKU 编号不能为空")
private Long id;
/**
* 库存变化数量
*
* 正数增加库存
* 负数扣减库存
*/
@NotNull(message = "库存变化数量不能为空")
private Integer incrCount;
}
}

View File

@ -1,45 +0,0 @@
package cn.iocoder.yudao.module.product.api.sku.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author LeeYan9
* @since 2022-08-26
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SkuDecrementStockBatchReqDTO {
private List<Item> items;
@Data
public static class Item {
/**
* 商品 SPU 编号自增
*/
private Long productId;
/**
* 商品 SKU 编号自增
*/
private Long skuId;
/**
* 数量
*/
private Integer count;
}
public static SkuDecrementStockBatchReqDTO of(List<Item> items) {
return new SkuDecrementStockBatchReqDTO(items);
}
}

View File

@ -1,23 +1,24 @@
package cn.iocoder.yudao.module.product.api.spu; package cn.iocoder.yudao.module.product.api.spu;
import cn.iocoder.yudao.module.product.api.sku.dto.SkuInfoRespDTO; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
* 商品 SPU API 接口
*
* @author LeeYan9 * @author LeeYan9
* @since 2022-08-26 * @since 2022-08-26
*/ */
public interface ProductSpuApi { public interface ProductSpuApi {
/** /**
* 根据spuId列表 查询spu信息 * 批量查询 SPU 数组
* *
* @param spuIds spu ID列表 * @param ids SPU 编号列表
* @return spu信息列表 * @return SPU 数组
*/ */
List<SpuInfoRespDTO> getSpusByIds(Collection<Long> spuIds); List<ProductSpuRespDTO> getSpuList(Collection<Long> ids);
} }

View File

@ -1,18 +1,21 @@
package cn.iocoder.yudao.module.product.api.spu.dto; package cn.iocoder.yudao.module.product.api.spu.dto;
import cn.iocoder.yudao.module.product.api.sku.dto.SkuInfoRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
// TODO @LeeYan9: ProductSpuRespDTO
/** /**
* 商品 SPU 信息 Response DTO
*
* @author LeeYan9 * @author LeeYan9
* @since 2022-08-26 * @since 2022-08-26
*/ */
@Data @Data
public class SpuInfoRespDTO { public class ProductSpuRespDTO {
/** /**
* 商品 SPU 编号自增 * 商品 SPU 编号自增
@ -30,7 +33,7 @@ public class SpuInfoRespDTO {
*/ */
private String code; private String code;
/** /**
* 商品卖点 * 促销语
*/ */
private String sellPoint; private String sellPoint;
/** /**
@ -80,25 +83,25 @@ public class SpuInfoRespDTO {
/** /**
* 最小价格单位使用 * 最小价格单位使用
* <p> * <p>
* 基于其对应的 {@link SkuInfoRespDTO#getPrice()} 最小值 * 基于其对应的 {@link ProductSkuRespDTO#getPrice()} 最小值
*/ */
private Integer minPrice; private Integer minPrice;
/** /**
* 最大价格单位使用 * 最大价格单位使用
* <p> * <p>
* 基于其对应的 {@link SkuInfoRespDTO#getPrice()} 最大值 * 基于其对应的 {@link ProductSkuRespDTO#getPrice()} 最大值
*/ */
private Integer maxPrice; private Integer maxPrice;
/** /**
* 市场价单位使用 * 市场价单位使用
* <p> * <p>
* 基于其对应的 {@link SkuInfoRespDTO#getMarketPrice()} 最大值 * 基于其对应的 {@link ProductSkuRespDTO#getMarketPrice()} 最大值
*/ */
private Integer marketPrice; private Integer marketPrice;
/** /**
* 总库存 * 总库存
* <p> * <p>
* 基于其对应的 {@link SkuInfoRespDTO#getStock()} 求和 * 基于其对应的 {@link ProductSkuRespDTO#getStock()} 求和
*/ */
private Integer totalStock; private Integer totalStock;
/** /**

View File

@ -24,9 +24,11 @@ public interface ErrorCodeConstants {
// ========== 商品规格名称 1008003000 ========== // ========== 商品规格名称 1008003000 ==========
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在"); ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在");
ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "规格名称已存在");
// ========== 规格值 1008004000 ========== // ========== 规格值 1008004000 ==========
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在"); ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在");
ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "规格值已存在");
// ========== 商品 SPU 1008005000 ========== // ========== 商品 SPU 1008005000 ==========
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在"); ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
@ -36,5 +38,6 @@ public interface ErrorCodeConstants {
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复"); ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU其规格数必须一致"); ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU其规格数必须一致");
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU必须不重复"); ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU必须不重复");
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
} }

View File

@ -19,12 +19,12 @@ public enum ProductSpuStatusEnum implements IntArrayValuable {
DISABLE(0, "下架"), DISABLE(0, "下架"),
ENABLE(1, "上架"),; ENABLE(1, "上架"),;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuStatusEnum::getStyle).toArray(); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuStatusEnum::getStatus).toArray();
/** /**
* 状态 * 状态
*/ */
private final Integer style; private final Integer status;
/** /**
* 状态名 * 状态名
*/ */

View File

@ -1,26 +1,49 @@
package cn.iocoder.yudao.module.product.api.sku; package cn.iocoder.yudao.module.product.api.sku;
import cn.iocoder.yudao.module.product.api.sku.dto.SkuDecrementStockBatchReqDTO; import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.product.api.sku.dto.SkuInfoRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
* todo 注释 * TODO LeeYan9: 类注释;
* @author LeeYan9
* @since 2022-09-06
*/ */
@Service @Service
@Validated
public class ProductSkuApiImpl implements ProductSkuApi { public class ProductSkuApiImpl implements ProductSkuApi {
@Resource
private ProductSkuService productSkuService;
@Override @Override
public List<SkuInfoRespDTO> getSkusByIds(Collection<Long> skuIds) { public ProductSkuRespDTO getSku(Long id) {
// TODO TODO LeeYan9: 需要实现
return null; return null;
} }
@Override @Override
public void decrementStockBatch(SkuDecrementStockBatchReqDTO batchReqDTO) { public List<ProductSkuRespDTO> getSkuList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
List<ProductSkuDO> skus = productSkuService.getSkuList(ids);
return ProductSkuConvert.INSTANCE.convertList04(skus);
}
@Override
public void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO) {
productSkuService.updateSkuStock(updateStockReqDTO);
} }
} }

View File

@ -1,20 +1,38 @@
package cn.iocoder.yudao.module.product.api.spu; package cn.iocoder.yudao.module.product.api.spu;
import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
* todo 注释 * TODO LeeYan9: 类注释;
*
* @author LeeYan9
* @since 2022-09-06
*/ */
@Service @Service
@Validated
public class ProductSpuApiImpl implements ProductSpuApi { public class ProductSpuApiImpl implements ProductSpuApi {
@Override @Resource
public List<SpuInfoRespDTO> getSpusByIds(Collection<Long> spuIds) { private ProductSpuMapper productSpuMapper;
return null;
}
@Override
public List<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) {
// TODO TODO LeeYan9: AllEmpty?
if (CollectionUtils.isAnyEmpty(spuIds)) {
return Collections.emptyList();
}
List<ProductSpuDO> productSpuDOList = productSpuMapper.selectBatchIds(spuIds);
return ProductSpuConvert.INSTANCE.convertList2(productSpuDOList);
}
} }

View File

@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.product.controller.admin.property;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
@ -17,6 +14,8 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - 规格名称") @Api(tags = "管理后台 - 规格名称")
@ -56,15 +55,29 @@ public class ProductPropertyController {
@ApiOperation("获得规格名称") @ApiOperation("获得规格名称")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:query')") @PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<ProductPropertyAndValueRespVO> getProperty(@RequestParam("id") Long id) { public CommonResult<ProductPropertyRespVO> getProperty(@RequestParam("id") Long id) {
return success(productPropertyService.getPropertyResp(id)); return success(productPropertyService.getProperty(id));
}
@GetMapping("/list")
@ApiOperation("获得规格名称列表")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<List<ProductPropertyRespVO>> getPropertyList(@Valid ProductPropertyListReqVO listReqVO) {
return success(productPropertyService.getPropertyList(listReqVO));
} }
@GetMapping("/page") @GetMapping("/page")
@ApiOperation("获得规格名称分页") @ApiOperation("获得规格名称分页")
@PreAuthorize("@ss.hasPermission('product:property:query')") @PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<PageResult<ProductPropertyAndValueRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) { public CommonResult<PageResult<ProductPropertyRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
return success(productPropertyService.getPropertyListPage(pageVO)); return success(productPropertyService.getPropertyPage(pageVO));
}
@GetMapping("/listAndValue")
@ApiOperation("获得规格名称列表")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) {
return success(productPropertyService.getPropertyAndValueList(listReqVO));
} }
} }

View File

@ -0,0 +1,70 @@
package cn.iocoder.yudao.module.product.controller.admin.property;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - 规格值名称")
@RestController
@RequestMapping("/product/property/value")
@Validated
public class ProductPropertyValueController {
@Resource
private ProductPropertyValueService productPropertyValueService;
@PostMapping("/create")
@ApiOperation("创建规格名称")
@PreAuthorize("@ss.hasPermission('product:property:create')")
public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) {
return success(productPropertyValueService.createPropertyValue(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新规格名称")
@PreAuthorize("@ss.hasPermission('product:property:update')")
public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) {
productPropertyValueService.updatePropertyValue(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除规格名称")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:delete')")
public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) {
productPropertyValueService.deletePropertyValue(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得规格名称")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<ProductPropertyValueRespVO> getProperty(@RequestParam("id") Long id) {
return success(productPropertyValueService.getPropertyValue(id));
}
@GetMapping("/page")
@ApiOperation("获得规格名称分页")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<PageResult<ProductPropertyValueRespVO>> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) {
return success(productPropertyValueService.getPropertyValueListPage(pageVO));
}
}

View File

@ -3,21 +3,25 @@ package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/** /**
* 规格名称 Base VO提供给添加修改详细的子 VO 使用 * 规格名称 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成 * 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/ */
@Data @Data
public class ProductPropertyBaseVO { public class ProductPropertyBaseVO {
@ApiModelProperty(value = "规格名称", required = true, example = "颜色") @ApiModelProperty(value = "规格名称", required = true, example = "颜色")
@NotEmpty(message = "规格名称不能为空") @NotBlank(message = "规格名称不能为空")
private String name; private String name;
@ApiModelProperty(value = "备注", example = "颜色")
private String remark;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
@NotEmpty(message = "状态不能为空") @NotNull(message = "状态不能为空")
private Integer status; private Integer status;
} }

View File

@ -1,11 +1,9 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; import io.swagger.annotations.ApiModel;
import lombok.*; import lombok.Data;
import io.swagger.annotations.*; import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.List;
@ApiModel("管理后台 - 规格名称创建 Request VO") @ApiModel("管理后台 - 规格名称创建 Request VO")
@Data @Data
@ -13,9 +11,5 @@ import java.util.List;
@ToString(callSuper = true) @ToString(callSuper = true)
public class ProductPropertyCreateReqVO extends ProductPropertyBaseVO { public class ProductPropertyCreateReqVO extends ProductPropertyBaseVO {
// TODO @Luowenfeng规格值的 CRUD 可以单独前端 + 后端改成类似字典类型字典数据的这种交互在加一个 ProductPropertyValueController
@ApiModelProperty(value = "属性值")
@NotNull(message = "属性值不能为空")
List<ProductPropertyValueCreateReqVO> propertyValueList;
} }

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
@ApiModel("管理后台 - 规格名称 List Request VO")
@Data
@ToString(callSuper = true)
public class ProductPropertyListReqVO {
@ApiModelProperty(value = "规格名称", example = "颜色")
private String name;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
private Integer status;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@ApiModel("管理后台 - 规格 + 规格值 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyRespVO extends ProductPropertyBaseVO {
@ApiModelProperty(value = "规格的编号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private LocalDateTime createTime;
}

View File

@ -16,8 +16,4 @@ public class ProductPropertyUpdateReqVO extends ProductPropertyBaseVO {
@NotNull(message = "主键不能为空") @NotNull(message = "主键不能为空")
private Long id; private Long id;
@ApiModelProperty(value = "属性值")
@NotNull(message = "属性值不能为空")
List<ProductPropertyValueCreateReqVO> propertyValueList;
} }

View File

@ -22,7 +22,10 @@ public class ProductPropertyValueBaseVO {
private String name; private String name;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
@NotEmpty(message = "状态不能为空") @NotNull(message = "状态不能为空")
private Integer status; private Integer status;
@ApiModelProperty(value = "备注", example = "颜色")
private String remark;
} }

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotEmpty;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 规格名称值分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyValuePageReqVO extends PageParam {
@ApiModelProperty(value = "规格id", example = "1024")
private String propertyId;
@ApiModelProperty(value = "规格值", example = "红色")
private String name;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
private Integer status;
}

View File

@ -12,6 +12,6 @@ public class ProductPropertyValueUpdateReqVO extends ProductPropertyValueBaseVO
@ApiModelProperty(value = "主键", required = true, example = "1024") @ApiModelProperty(value = "主键", required = true, example = "1024")
@NotNull(message = "主键不能为空") @NotNull(message = "主键不能为空")
private Integer id; private Long id;
} }

View File

@ -1,14 +1,57 @@
package cn.iocoder.yudao.module.product.controller.admin.sku; package cn.iocoder.yudao.module.product.controller.admin.sku;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuOptionRespVO;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Api(tags = "管理后台 - 商品 sku") @Api(tags = "管理后台 - 商品 sku")
@RestController @RestController
@RequestMapping("/product/sku") @RequestMapping("/product/sku")
@Validated @Validated
public class ProductSkuController { public class ProductSkuController {
@Resource
private ProductSkuService productSkuService;
@Resource
private ProductSpuService productSpuService;
@GetMapping("/get-option-list")
@ApiOperation("获得商品 SKU 选项的列表")
// @PreAuthorize("@ss.hasPermission('product:sku:query')")
public CommonResult<List<ProductSkuOptionRespVO>> getSkuOptionList() {
// 获得 SKU 列表
List<ProductSkuDO> skus = productSkuService.getSkuList();
if (CollUtil.isEmpty(skus)) {
return success(Collections.emptyList());
}
// 获得对应的 SPU 映射
Map<Long, ProductSpuDO> spuMap = productSpuService.getSpuMap(convertSet(skus, ProductSkuDO::getSpuId));
// 转换为返回结果
List<ProductSkuOptionRespVO> skuVOs = ProductSkuConvert.INSTANCE.convertList05(skus);
skuVOs.forEach(sku -> MapUtils.findAndThen(spuMap, sku.getSpuId(),
spu -> sku.setSpuId(spu.getId()).setSpuName(spu.getName())));
return success(skuVOs);
}
} }

View File

@ -33,7 +33,7 @@ public class ProductSkuBaseVO {
@ApiModelProperty(value = "条形码", example = "haha") @ApiModelProperty(value = "条形码", example = "haha")
private String barCode; private String barCode;
@ApiModelProperty(value = "图片地址") @ApiModelProperty(value = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
@NotNull(message = "图片地址不能为空") @NotNull(message = "图片地址不能为空")
private String picUrl; private String picUrl;

View File

@ -14,8 +14,7 @@ import java.util.List;
@ToString(callSuper = true) @ToString(callSuper = true)
public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO { public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
// TODO @Luowenfeng可以不用哈如果基于规格匹配 @ApiModelProperty(value = "商品 SKU 编号", example = "1")
@ApiModelProperty(value = "商品 id 更新时须有", example = "1")
private Long id; private Long id;
/** /**

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "管理后台 - 商品 SKU 选项 Response VO", description = "用于前端 SELECT 选项")
@Data
public class ProductSkuOptionRespVO {
@ApiModelProperty(value = "主键", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "商品 SKU 名字", example = "红色")
private String name;
@ApiModelProperty(value = "销售价格", required = true, example = "100", notes = "单位:分")
private String price;
@ApiModelProperty(value = "库存", required = true, example = "100")
private Integer stock;
// ========== 商品 SPU 信息 ==========
@ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
private Long spuId;
@ApiModelProperty(value = "商品 SPU 名字", required = true, example = "iPhone 11")
private String spuName;
}

View File

@ -9,7 +9,7 @@ import lombok.ToString;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@ApiModel("管理后台 - 商品sku Response VO") @ApiModel("管理后台 - 商品 SKU Response VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)

View File

@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
@ -56,6 +53,15 @@ public class ProductSpuController {
return success(true); return success(true);
} }
// TODO 芋艿修改接口
@GetMapping("/get/detail")
@ApiOperation("获得商品 SPU")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<ProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
return success(spuService.getSpuDetail(id));
}
@GetMapping("/get") @GetMapping("/get")
@ApiOperation("获得商品 SPU") @ApiOperation("获得商品 SPU")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@ -64,7 +70,6 @@ public class ProductSpuController {
return success(spuService.getSpu(id)); return success(spuService.getSpu(id));
} }
// TODO @luowenfeng新增 get-detail返回 SpuDetailRespVO
@GetMapping("/list") @GetMapping("/list")
@ApiOperation("获得商品 SPU 列表") @ApiOperation("获得商品 SPU 列表")
@ -75,6 +80,14 @@ public class ProductSpuController {
return success(ProductSpuConvert.INSTANCE.convertList(list)); return success(ProductSpuConvert.INSTANCE.convertList(list));
} }
@GetMapping("/get-simple-list")
@ApiOperation("获得商品 SPU 精简列表")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<List<ProductSpuSimpleRespVO>> getSpuSimpleList() {
List<ProductSpuDO> list = spuService.getSpuList();
return success(ProductSpuConvert.INSTANCE.convertList02(list));
}
@GetMapping("/page") @GetMapping("/page")
@ApiOperation("获得商品 SPU 分页") @ApiOperation("获得商品 SPU 分页")
@PreAuthorize("@ss.hasPermission('product:spu:query')") @PreAuthorize("@ss.hasPermission('product:spu:query')")

View File

@ -24,7 +24,7 @@ public class ProductSpuBaseVO {
@ApiModelProperty(value = "商品编码", example = "yudaoyuanma") @ApiModelProperty(value = "商品编码", example = "yudaoyuanma")
private String code; private String code;
@ApiModelProperty(value = "商品卖点", example = "好吃!") @ApiModelProperty(value = "促销语", example = "好吃!")
private String sellPoint; private String sellPoint;
@ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述") @ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述")
@ -67,6 +67,9 @@ public class ProductSpuBaseVO {
@ApiModelProperty(value = "库存", required = true, example = "true") @ApiModelProperty(value = "库存", required = true, example = "true")
private Integer totalStock; private Integer totalStock;
@ApiModelProperty(value = "市场价", example = "1024")
private Integer marketPrice;
@ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024") @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
private Integer minPrice; private Integer minPrice;
@ -75,10 +78,14 @@ public class ProductSpuBaseVO {
// ========== 统计相关字段 ========= // ========== 统计相关字段 =========
@ApiModelProperty(value = "商品销量", example = "1024")
private Integer salesCount;
@ApiModelProperty(value = "虚拟销量", required = true, example = "1024") @ApiModelProperty(value = "虚拟销量", required = true, example = "1024")
@NotNull(message = "虚拟销量不能为空") @NotNull(message = "虚拟销量不能为空")
private Integer virtualSalesCount; private Integer virtualSalesCount;
@ApiModelProperty(value = "点击量", example = "1024") @ApiModelProperty(value = "点击量", example = "1024")
private Integer clickCount; private Integer clickCount;
} }

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo; package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
@ -54,4 +55,11 @@ public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
} }
@ApiModelProperty(value = "分类 id 数组,一直递归到一级父节点", example = "4")
private Long categoryId;
// TODO @芋艿在瞅瞅~
@ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]")
private List<ProductPropertyViewRespVO> productPropertyViews;
} }

View File

@ -1,13 +1,11 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo; package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import lombok.*;
import java.time.LocalDateTime;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ApiModel("管理后台 - 商品 SPU 分页 Request VO") @ApiModel("管理后台 - 商品 SPU 分页 Request VO")
@Data @Data
@ -15,38 +13,34 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@ToString(callSuper = true) @ToString(callSuper = true)
public class ProductSpuPageReqVO extends PageParam { public class ProductSpuPageReqVO extends PageParam {
@ApiModelProperty(value = "商品名称") @ApiModelProperty(value = "商品名称", example = "yutou")
private String name; private String name;
@ApiModelProperty(value = "卖点") @ApiModelProperty(value = "商品编码", example = "yudaoyuanma")
private String sellPoint; private String code;
@ApiModelProperty(value = "描述") @ApiModelProperty(value = "分类id", example = "1")
private String description;
@ApiModelProperty(value = "分类id")
private Long categoryId; private Long categoryId;
@ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张") @ApiModelProperty(value = "商品品牌编号", example = "1")
private String picUrls; private Long brandId;
@ApiModelProperty(value = "排序字段") @ApiModelProperty(value = "上下架状态", example = "1", notes = "参见 ProductSpuStatusEnum 枚举值")
private Integer sort;
@ApiModelProperty(value = "点赞初始人数")
private Integer likeCount;
@ApiModelProperty(value = "价格 单位使用:分")
private Integer price;
@ApiModelProperty(value = "库存数量")
private Integer quantity;
@ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
private Integer status; private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ApiModelProperty(value = "销量最小值", example = "1")
@ApiModelProperty(value = "创建时间") private Integer salesCountMin;
private LocalDateTime[] createTime;
@ApiModelProperty(value = "销量最大值", example = "1024")
private Integer salesCountMax;
@ApiModelProperty(value = "市场价最小值", example = "1")
private Integer marketPriceMin;
@ApiModelProperty(value = "市场价最大值", example = "1024")
private Integer marketPriceMax;
@ApiModelProperty(value = "是否库存告警", example = "true")
private Boolean alarmStock;
} }

View File

@ -1,7 +1,5 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo; package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@ -11,7 +9,6 @@ import lombok.ToString;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
// TODO @Luowenfeng这个类只返回 SPU 相关的信息删除 skuscategoryIdsproductPropertyViews明细使用 SpuDetailRespVO 替代
@ApiModel("管理后台 - 商品 SPU Response VO") @ApiModel("管理后台 - 商品 SPU Response VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -24,18 +21,4 @@ public class ProductSpuRespVO extends ProductSpuBaseVO {
@ApiModelProperty(value = "创建时间") @ApiModelProperty(value = "创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
/**
* SKU 数组
*/
@ApiModelProperty(value = "sku 数组", example = "[{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":15},{\"propertyId\":2,\"valueId\":10}],\"price\":12,\"originalPrice\":32,\"costPrice\":22,\"barCode\":\"765670123123\",\"picUrl\":\"http://test.yudao.iocoder.cn/72938088f1ca8438837c3b51394aea43.jpg\",\"status\":0,\"id\":7,\"createTime\":1656683270000},{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":15},{\"propertyId\":2,\"valueId\":11}],\"price\":13,\"originalPrice\":33,\"costPrice\":23,\"barCode\":\"888788770999\",\"picUrl\":\"http://test.yudao.iocoder.cn/6b902c700e5d32e862b6fd9af2e1c0e4.jpg\",\"status\":0,\"id\":8,\"createTime\":1656683270000},{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":16},{\"propertyId\":2,\"valueId\":10}],\"price\":14,\"originalPrice\":34,\"costPrice\":24,\"barCode\":\"9999981212\",\"picUrl\":\"http://test.yudao.iocoder.cn/eddf3c79b1917160d94d05244e1f47da.jpg\",\"status\":0,\"id\":9,\"createTime\":1656683270000},{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":16},{\"propertyId\":2,\"valueId\":11}],\"price\":15,\"originalPrice\":35,\"costPrice\":25,\"barCode\":\"4444121212\",\"picUrl\":\"http://test.yudao.iocoder.cn/88ac3eb068ea9cfac4726879b2776ccf.jpg\",\"status\":0,\"id\":10,\"createTime\":1656683270000}]")
private List<ProductSkuRespVO> skus;
@ApiModelProperty(value = "分类id数组一直递归到一级父节点", example = "[1,2,4]")
private List<Long> categoryIds;
// TODO @芋艿再琢磨下 这个 VO 其实变成 SpuRespVO 内嵌的 VO 类会更好一点然后把 SpuRespVO 改成 SpuDetailSpuVO
@ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]")
private List<ProductPropertyViewRespVO> productPropertyViews;
} }

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ApiModel("管理后台 - 商品 SPU 精简 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuSimpleRespVO extends ProductSpuBaseVO {
@ApiModelProperty(value = "主键", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "商品名称", required = true, example = "芋道")
private String name;
@ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
private Integer minPrice;
@ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
private Integer maxPrice;
}

View File

@ -3,8 +3,11 @@ package cn.iocoder.yudao.module.product.convert.property;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -24,10 +27,12 @@ public interface ProductPropertyConvert {
ProductPropertyDO convert(ProductPropertyUpdateReqVO bean); ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
ProductPropertyAndValueRespVO convert(ProductPropertyDO bean); ProductPropertyAndValueRespVO convert(ProductPropertyRespVO bean);
List<ProductPropertyAndValueRespVO> convertList(List<ProductPropertyDO> list); ProductPropertyRespVO convert(ProductPropertyDO bean);
PageResult<ProductPropertyAndValueRespVO> convertPage(PageResult<ProductPropertyDO> page); List<ProductPropertyRespVO> convertList(List<ProductPropertyDO> list);
PageResult<ProductPropertyRespVO> convertPage(PageResult<ProductPropertyDO> page);
} }

View File

@ -1,16 +1,23 @@
package cn.iocoder.yudao.module.product.convert.sku; package cn.iocoder.yudao.module.product.convert.sku;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuOptionRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuDetailRespVO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/** /**
* 商品sku Convert * 商品 SKU Convert
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@ -21,11 +28,42 @@ public interface ProductSkuConvert {
ProductSkuDO convert(ProductSkuCreateOrUpdateReqVO bean); ProductSkuDO convert(ProductSkuCreateOrUpdateReqVO bean);
@Mapping(source = "properties", target = "properties")
ProductSkuRespVO convert(ProductSkuDO bean); ProductSkuRespVO convert(ProductSkuDO bean);
List<ProductSkuRespVO> convertList(List<ProductSkuDO> list); List<ProductSkuRespVO> convertList(List<ProductSkuDO> list);
List<ProductSkuDO> convertSkuDOList(List<ProductSkuCreateOrUpdateReqVO> list); List<ProductSkuDO> convertSkuDOList(List<ProductSkuCreateOrUpdateReqVO> list);
ProductSkuRespDTO convert02(ProductSkuDO bean);
List<ProductSkuRespDTO> convertList02(List<ProductSkuDO> list);
List<ProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> list);
List<ProductSkuRespDTO> convertList04(List<ProductSkuDO> list);
List<ProductSkuOptionRespVO> convertList05(List<ProductSkuDO> skus);
/**
* 获得 SPU 的库存变化 Map
*
* @param items SKU 库存变化
* @param skus SKU 列表
* @return SPU 的库存变化 Map
*/
default Map<Long, Integer> convertSpuStockMap(List<ProductSkuUpdateStockReqDTO.Item> items,
List<ProductSkuDO> skus) {
Map<Long, Long> skuIdAndSpuIdMap = convertMap(skus, ProductSkuDO::getId, ProductSkuDO::getSpuId); // SKU SKU 编号的 Map 关系
Map<Long, Integer> spuIdAndStockMap = new HashMap<>(); // SPU 的库存变化 Map 关系
items.forEach(item -> {
Long spuId = skuIdAndSpuIdMap.get(item.getId());
if (spuId == null) {
return;
}
Integer stock = spuIdAndStockMap.getOrDefault(spuId, 0) + item.getIncrCount();
spuIdAndStockMap.put(spuId, stock);
});
return spuIdAndStockMap;
}
} }

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.product.convert.spu; package cn.iocoder.yudao.module.product.convert.spu;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
@ -34,4 +35,8 @@ public interface ProductSpuConvert {
AppSpuPageRespVO convertAppResp(ProductSpuDO list); AppSpuPageRespVO convertAppResp(ProductSpuDO list);
List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list);
List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
} }

View File

@ -64,6 +64,4 @@ public class ProductCategoryDO extends BaseDO {
*/ */
private Integer status; private Integer status;
// TODO 芋艿is_recommend 是否首页推荐1-0-
} }

View File

@ -37,6 +37,10 @@ public class ProductPropertyDO extends BaseDO {
* 枚举 {@link CommonStatusEnum} * 枚举 {@link CommonStatusEnum}
*/ */
private Integer status; private Integer status;
/**
* 备注
*/
private String remark;
// TODO 芋艿rule规格属性 (发布商品时 SKU 关联)规格参数(搜索商品时 Category 关联搜索) // TODO 芋艿rule规格属性 (发布商品时 SKU 关联)规格参数(搜索商品时 Category 关联搜索)

Some files were not shown because too many files have changed in this diff Show More