diff --git a/sql/optional/mall/coupon.sql b/sql/optional/mall/coupon.sql
new file mode 100644
index 000000000..4ab7b1ff9
--- /dev/null
+++ b/sql/optional/mall/coupon.sql
@@ -0,0 +1,85 @@
+DROP TABLE IF EXISTS `coupon`;
+CREATE TABLE `coupon`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+ `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '优惠券类型 reward-满减 discount-折扣 random-随机',
+ `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '优惠券名称',
+ `coupon_type_id` bigint UNSIGNED DEFAULT 0 COMMENT '优惠券类型id',
+ `coupon_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '优惠券编码',
+ `member_id` bigint UNSIGNED NOT NULL DEFAULT 0 COMMENT '领用人',
+ `use_order_id` bigint UNSIGNED NOT NULL DEFAULT 0 COMMENT '优惠券使用订单id',
+ `goods_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用',
+ `goods_ids` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '适用商品id',
+ `at_least` decimal(10, 2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最小金额',
+ `money` decimal(10, 2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '面额',
+ `discount` decimal(10, 2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '1 =< 折扣 <= 9.9 当type为discount时需要添加',
+ `discount_limit` decimal(10, 2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最多折扣金额 当type为discount时可选择性添加',
+ `whether_forbid_preference` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用',
+ `whether_expire_notice` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否开启过期提醒0-不开启 1-开启',
+ `expire_notice_fixed_term` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '过期前N天提醒',
+ `whether_noticed` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否已提醒',
+ `state` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '优惠券状态 1已领用(未使用) 2已使用 3已过期',
+ `get_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '获取方式1订单2.直接领取3.活动领取 4转赠 5分享获取',
+ `fetch_time` datetime NOT NULL DEFAULT 0 COMMENT '领取时间',
+ `use_time` datetime NOT NULL DEFAULT 0 COMMENT '使用时间',
+ `start_time` datetime NOT NULL DEFAULT 0 COMMENT '可使用的开始时间',
+ `end_time` datetime NOT NULL DEFAULT 0 COMMENT '有效期结束时间',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 119
+ CHARACTER SET = utf8mb4
+ COLLATE = utf8mb4_unicode_ci COMMENT = '优惠券';
+
+DROP TABLE IF EXISTS `coupon_templete`;
+CREATE TABLE `coupon_templete`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+ `type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '优惠券类型 reward-满减 discount-折扣 random-随机',
+ `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '优惠券名称',
+ `coupon_name_remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '名称备注',
+ `image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '优惠券图片',
+ `count` int(11) NOT NULL DEFAULT 0 COMMENT '发放数量',
+ `lead_count` int(11) NOT NULL DEFAULT 0 COMMENT '已领取数量',
+ `used_count` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '已使用数量',
+ `goods_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用',
+ `product_ids` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '适用商品id',
+ `has_use_limit` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用门槛0-无门槛 1-有门槛',
+ `at_least` decimal(10, 2) NOT NULL DEFAULT 0 COMMENT '满多少元使用 0代表无限制',
+ `money` decimal(10, 2) NOT NULL DEFAULT 0 COMMENT '发放面额 当type为reward时需要添加',
+ `discount` decimal(10, 2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '1 =< 折扣 <= 9.9 当type为discount时需要添加',
+ `discount_limit` decimal(10, 2) NOT NULL DEFAULT 0 COMMENT '最多折扣金额 当type为discount时可选择性添加',
+ `min_money` decimal(10, 2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最低金额 当type为radom时需要添加',
+ `max_money` decimal(10, 2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最大金额 当type为radom时需要添加',
+ `validity_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期',
+ `start_use_time` datetime COMMENT '使用开始日期 过期类型1时必填',
+ `end_use_time` datetime COMMENT '使用结束日期 过期类型1时必填',
+ `fixed_term` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '当validity_type为2或者3时需要添加 领取之日起或者次日N天内有效',
+ `whether_limitless` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否无限制0-否 1是',
+ `max_fetch` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '每人最大领取个数',
+ `whether_expire_notice` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否开启过期提醒0-不开启 1-开启',
+ `expire_notice_fixed_term` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '过期前N天提醒',
+ `whether_forbid_preference` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '优惠叠加 0-不限制 1- 优惠券仅原价购买商品时可用',
+ `whether_show` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否显示',
+ `discount_order_money` decimal(10, 2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '订单的优惠总金额',
+ `order_money` decimal(10, 2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用券总成交额',
+ `whether_forbidden` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否禁止发放0-否 1-是',
+ `order_goods_num` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用优惠券购买的商品数量',
+ `status` tinyint(11) NOT NULL DEFAULT 0 COMMENT '状态(1进行中2已结束-1已关闭)',
+ `end_time` datetime COMMENT '有效日期结束时间',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 119
+ CHARACTER SET = utf8mb4
+ COLLATE = utf8mb4_unicode_ci COMMENT = '优惠券模板';
\ No newline at end of file
diff --git a/sql/optional/mall/mall.sql b/sql/optional/mall/mall.sql
index 9a090c9e4..486b6f2fc 100644
--- a/sql/optional/mall/mall.sql
+++ b/sql/optional/mall/mall.sql
@@ -1,7 +1,7 @@
/*
Navicat Premium Data Transfer
- Source Server : 127.0.0.1
+ Source Server : 127.0.0.1 MySQL
Source Server Type : MySQL
Source Server Version : 80026
Source Host : localhost:3306
@@ -11,277 +11,305 @@
Target Server Version : 80026
File Encoding : 65001
- Date: 05/02/2022 00:50:30
+ Date: 01/08/2022 23:01:36
*/
-SET
-FOREIGN_KEY_CHECKS = 0;
+
SET NAMES utf8mb4;
-
--- ----------------------------
--- Table structure for product_category
--- ----------------------------
-DROP TABLE IF EXISTS `product_category`;
-CREATE TABLE `product_category`
-(
- `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号',
- `parent_id` bigint NOT NULL COMMENT '父分类编号',
- `name` varchar(255) NOT NULL COMMENT '分类名称',
- `icon` varchar(100) NOT NULL DEFAULT '#' COMMENT '分类图标',
- `banner_url` varchar(255) NOT NULL COMMENT '分类图片',
- `sort` int DEFAULT '0' COMMENT '分类排序',
- `description` varchar(1024) DEFAULT NULL COMMENT '分类描述',
- `status` tinyint NOT NULL COMMENT '开启状态',
- `creator` varchar(64) DEFAULT '' COMMENT '创建者',
- `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
- `updater` varchar(64) DEFAULT '' COMMENT '更新者',
- `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
- `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
- `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
- PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB COMMENT='商品分类';
-
--- ----------------------------
--- Table structure for product_brand
--- ----------------------------
-DROP TABLE IF EXISTS `product_brand`;
-CREATE TABLE `product_brand`
-(
- `id` bigint NOT NULL AUTO_INCREMENT COMMENT '品牌编号',
- `category_id` bigint NOT NULL COMMENT '分类编号',
- `name` varchar(255) NOT NULL COMMENT '品牌名称',
- `banner_url` varchar(255) NOT NULL COMMENT '品牌图片',
- `sort` int DEFAULT '0' COMMENT '品牌排序',
- `description` varchar(1024) DEFAULT NULL COMMENT '品牌描述',
- `status` tinyint NOT NULL COMMENT '状态',
- `creator` varchar(64) DEFAULT '' COMMENT '创建者',
- `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
- `updater` varchar(64) DEFAULT '' COMMENT '更新者',
- `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
- `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
- `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
- PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB COMMENT='品牌';
-
--- TODO 父级菜单的 id 处理: 2000 、 2001
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES (2000, '商城', '', 1, 1, 0, '/mall', 'merchant', NULL, 0);
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES (2001, '商品', '', 1, 1, 2000, 'product', 'dict', NULL, 0);
--- 商品分类 菜单 SQL
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('分类管理', '', 2, 0, 2001, 'category', '', 'mall/product/category/index', 0);
--- 按钮父菜单ID
-SELECT @parentId := LAST_INSERT_ID();
--- 按钮 SQL
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('分类查询', 'product:category:query', 3, 1, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('分类创建', 'product:category:create', 3, 2, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('分类更新', 'product:category:update', 3, 3, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('分类删除', 'product:category:delete', 3, 4, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('分类导出', 'product:category:export', 3, 5, @parentId, '', '', '', 0);
--- 品牌管理 菜单 SQL
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('品牌管理', '', 2, 1, 2001, 'brand', '', 'mall/product/brand/index', 0);
--- 按钮父菜单ID
-SELECT @parentId := LAST_INSERT_ID();
--- 按钮 SQL
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('品牌查询', 'product:brand:query', 3, 1, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('品牌创建', 'product:brand:create', 3, 2, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('品牌更新', 'product:brand:update', 3, 3, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('品牌删除', 'product:brand:delete', 3, 4, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('品牌导出', 'product:brand:export', 3, 5, @parentId, '', '', '', 0);
-
+SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for market_activity
-- ----------------------------
DROP TABLE IF EXISTS `market_activity`;
-CREATE TABLE `market_activity`
-(
- `id` bigint NOT NULL AUTO_INCREMENT COMMENT '活动编号',
- `title` varchar(50) NOT NULL DEFAULT '' COMMENT '活动标题',
- `activity_type` tinyint(4) NOT NULL COMMENT '活动类型',
- `status` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '活动状态',
- `start_time` datetime NOT NULL COMMENT '开始时间',
- `end_time` datetime NOT NULL COMMENT '结束时间',
- `invalid_time` datetime DEFAULT NULL COMMENT '失效时间',
- `delete_time` datetime DEFAULT NULL COMMENT '删除时间',
- `time_limited_discount` varchar(2000) DEFAULT NULL COMMENT '限制折扣字符串,使用 JSON 序列化成字符串存储',
- `full_privilege` varchar(2000) DEFAULT NULL COMMENT '限制折扣字符串,使用 JSON 序列化成字符串存储',
- `creator` varchar(64) DEFAULT '' COMMENT '创建者',
- `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
- `updater` varchar(64) DEFAULT '' COMMENT '更新者',
- `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
- `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
- `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
- PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='促销活动';
+CREATE TABLE `market_activity` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '活动编号',
+ `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '活动标题',
+ `activity_type` tinyint NOT NULL COMMENT '活动类型',
+ `status` tinyint NOT NULL DEFAULT -1 COMMENT '活动状态',
+ `start_time` datetime NOT NULL COMMENT '开始时间',
+ `end_time` datetime NOT NULL COMMENT '结束时间',
+ `invalid_time` datetime NULL DEFAULT NULL COMMENT '失效时间',
+ `delete_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
+ `time_limited_discount` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '限制折扣字符串,使用 JSON 序列化成字符串存储',
+ `full_privilege` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '限制折扣字符串,使用 JSON 序列化成字符串存储',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '促销活动';
+-- ----------------------------
+-- Records of market_activity
+-- ----------------------------
+BEGIN;
+COMMIT;
--- 规格菜单 SQL
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('规格管理', '', 2, 3, 2001, 'property', '', 'mall/product/property/index', 0);
+-- ----------------------------
+-- Table structure for market_banner
+-- ----------------------------
+DROP TABLE IF EXISTS `market_banner`;
+CREATE TABLE `market_banner` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Banner编号',
+ `title` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT 'Banner标题',
+ `pic_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '图片URL',
+ `status` tinyint NOT NULL DEFAULT -1 COMMENT '活动状态',
+ `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '跳转地址',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ `sort` tinyint NULL DEFAULT NULL COMMENT '排序',
+ `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '描述',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Banner管理';
--- 按钮父菜单ID
-SELECT @parentId := LAST_INSERT_ID();
+-- ----------------------------
+-- Records of market_banner
+-- ----------------------------
+BEGIN;
+COMMIT;
--- 按钮 SQL
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('规格查询', 'product:property:query', 3, 1, @parentId, '', '', '', 0);
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('规格创建', 'product:property:create', 3, 2, @parentId, '', '', '', 0);
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('规格更新', 'product:property:update', 3, 3, @parentId, '', '', '', 0);
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('规格删除', 'product:property:delete', 3, 4, @parentId, '', '', '', 0);
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('规格导出', 'product:property:export', 3, 5, @parentId, '', '', '', 0);
+-- ----------------------------
+-- Table structure for member_address
+-- ----------------------------
+DROP TABLE IF EXISTS `member_address`;
+CREATE TABLE `member_address` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '收件地址编号',
+ `user_id` bigint NOT NULL COMMENT '用户编号',
+ `name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '收件人名称',
+ `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '手机号',
+ `area_id` bigint NOT NULL COMMENT '地区编码',
+ `post_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '邮编',
+ `detail_address` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '收件详细地址',
+ `defaulted` bit(1) NOT NULL COMMENT '是否默认',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_userId`(`user_id` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户收件地址';
+-- ----------------------------
+-- Records of member_address
+-- ----------------------------
+BEGIN;
+INSERT INTO `member_address` (`id`, `user_id`, `name`, `mobile`, `area_id`, `post_code`, `detail_address`, `defaulted`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (21, 1, 'yunai', '15601691300', 610632, '200000', '芋道源码 233 号 666 室', b'1', '1', '2022-08-01 22:46:35', '1', '2022-08-01 22:46:35', b'0', 1);
+COMMIT;
--- 商品菜单 SQL
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('商品管理', '', 2, 2, 2001, 'spu', '', 'mall/product/spu/index', 0);
+-- ----------------------------
+-- Table structure for product_brand
+-- ----------------------------
+DROP TABLE IF EXISTS `product_brand`;
+CREATE TABLE `product_brand` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '品牌编号',
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '品牌名称',
+ `pic_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '品牌图片',
+ `sort` int NULL DEFAULT 0 COMMENT '品牌排序',
+ `description` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '品牌描述',
+ `status` tinyint NOT NULL COMMENT '状态',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商品品牌';
--- 按钮父菜单ID
-SELECT @parentId := LAST_INSERT_ID();
+-- ----------------------------
+-- Records of product_brand
+-- ----------------------------
+BEGIN;
+INSERT INTO `product_brand` (`id`, `name`, `pic_url`, `sort`, `description`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '苹果', 'http://test.yudao.iocoder.cn/e3726713fa56db5717c78c011762fcc7a251db12735c3581470638b8e1fa17e2.jpeg', 0, '是上市', 0, '1', '2022-07-30 22:12:18', '1', '2022-07-30 22:13:55', b'0', 1);
+COMMIT;
--- 按钮 SQL
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('商品查询', 'product:spu:query', 3, 1, @parentId, '', '', '', 0);
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('商品创建', 'product:spu:create', 3, 2, @parentId, '', '', '', 0);
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('商品更新', 'product:spu:update', 3, 3, @parentId, '', '', '', 0);
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('商品删除', 'product:spu:delete', 3, 4, @parentId, '', '', '', 0);
-INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('商品导出', 'product:spu:export', 3, 5, @parentId, '', '', '', 0);
+-- ----------------------------
+-- Table structure for product_category
+-- ----------------------------
+DROP TABLE IF EXISTS `product_category`;
+CREATE TABLE `product_category` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号',
+ `parent_id` bigint NOT NULL COMMENT '父分类编号',
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类名称',
+ `pic_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类图片',
+ `sort` int NULL DEFAULT 0 COMMENT '分类排序',
+ `description` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '分类描述',
+ `status` tinyint NOT NULL COMMENT '开启状态',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商品分类';
+-- ----------------------------
+-- Records of product_category
+-- ----------------------------
+BEGIN;
+INSERT INTO `product_category` (`id`, `parent_id`, `name`, `pic_url`, `sort`, `description`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 0, '电脑办公', 'http://test.yudao.iocoder.cn/122d548e1b3cd5dec72fe8075c6977a70f9cc13541a684ab3685f1b5df42f6bd.jpeg', 1, '1234', 0, '1', '2022-07-30 16:36:35', '1', '2022-07-30 20:27:16', b'0', 1), (2, 1, '笔记本', 'http://test.yudao.iocoder.cn/72713ac7b947600a019a18786ed0e6562e8692e253dbd35110a0a85c2469bbec.jpg', 1, '
测试一下
', 0, '1', '2022-07-30 16:38:09', '1', '2022-07-30 16:38:09', b'0', 1), (3, 1, '游戏本', 'http://test.yudao.iocoder.cn/287c50dd9f5f575f57329a0c57b2095be6d1aeba83867b905fe549f54a296feb.jpg', 2, '测试一下
', 0, '1', '2022-07-30 16:39:09', '1', '2022-07-30 20:26:59', b'0', 1), (4, 0, '手机', 'http://test.yudao.iocoder.cn/e1b63900c78dbb661b3e383960cee5cfea7e1dd2fb22cff2e317ff025faaf8b2.jpeg', 2, '123
', 0, '1', '2022-07-30 16:40:00', '1', '2022-07-30 16:40:09', b'0', 1), (5, 4, '5G手机', 'http://test.yudao.iocoder.cn/3af6557ac7def6423f046f5b2e920b644793420b466959aaa996a2e19068bbde.jpeg', 1, '
', 0, '1', '2022-07-30 16:43:00', '1', '2022-07-30 16:43:00', b'0', 1), (6, 4, '游戏手机', 'http://test.yudao.iocoder.cn/964fe9ccd1710d64ede261dc36d231918a017641986c15293c367f9f66d94d05.jpeg', 2, NULL, 0, '1', '2022-07-30 16:43:44', '1', '2022-07-30 16:43:44', b'0', 1), (7, 5, '厉害的 5G 手机', 'http://test.yudao.iocoder.cn/b287122f277838e8de368769b96217918605743bc45f3a29bda3cc7359dc66e1.png', 0, '123', 0, '1', '2022-07-30 20:38:09', '1', '2022-07-30 20:38:09', b'0', 1);
+COMMIT;
--- 规格名称表
-drop table if exists product_property;
-create table product_property
-(
- id bigint NOT NULL AUTO_INCREMENT comment '主键',
- name varchar(64) comment '规格名称',
- status tinyint comment '状态: 0 开启 ,1 禁用',
- create_time datetime default current_timestamp comment '创建时间',
- update_time datetime default current_timestamp on update current_timestamp comment '更新时间',
- creator varchar(64) comment '创建人',
- updater varchar(64) comment '更新人',
- tenant_id bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
- deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
- primary key (id),
- key idx_name ( name (32)) comment '规格名称索引'
-) comment '规格名称' character set utf8mb4
- collate utf8mb4_general_ci;
+-- ----------------------------
+-- Table structure for product_property
+-- ----------------------------
+DROP TABLE IF EXISTS `product_property`;
+CREATE TABLE `product_property` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规格名称',
+ `status` tinyint NULL DEFAULT NULL COMMENT '状态: 0 开启 ,1 禁用',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_name`(`name`(32) ASC) USING BTREE COMMENT '规格名称索引'
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格名称';
--- 规格值表
-drop table if exists product_property_value;
-create table product_property_value
-(
- id bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
- property_id bigint comment '规格键id',
- name varchar(128) comment '规格值名字',
- status tinyint comment '状态: 1 开启 ,2 禁用',
- create_time datetime default current_timestamp comment '创建时间',
- update_time datetime default current_timestamp on update current_timestamp comment '更新时间',
- creator varchar(64) comment '创建人',
- updater varchar(64) comment '更新人',
- tenant_id bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
- deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
- primary key (id)
-) comment '规格值' character set utf8mb4
- collate utf8mb4_general_ci;
+-- ----------------------------
+-- Records of product_property
+-- ----------------------------
+BEGIN;
+COMMIT;
--- spu
-drop table if exists product_spu;
-create table product_spu
-(
- id bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
- name varchar(128) comment '商品名称',
- sell_point varchar(128) not null comment '卖点',
- description text not null comment '描述',
- category_id bigint not null comment '分类id',
- pic_urls varchar(1024) not null default '' comment '商品主图地址\n *\n * 数组,以逗号分隔\n 最多上传15张',
- sort int not null default 0 comment '排序字段',
- like_count int comment '点赞初始人数',
- price int comment '价格 单位使用:分',
- quantity int comment '库存数量',
- status bit(1) comment '上下架状态: 0 上架(开启) 1 下架(禁用)',
- create_time datetime default current_timestamp comment '创建时间',
- update_time datetime default current_timestamp on update current_timestamp comment '更新时间',
- creator varchar(64) comment '创建人',
- updater varchar(64) comment '更新人',
- tenant_id bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
- deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
- primary key (id)
-) comment '商品spu' character set utf8mb4
- collate utf8mb4_general_ci;
+-- ----------------------------
+-- Table structure for product_property_value
+-- ----------------------------
+DROP TABLE IF EXISTS `product_property_value`;
+CREATE TABLE `product_property_value` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `property_id` bigint NULL DEFAULT NULL COMMENT '规格键id',
+ `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规格值名字',
+ `status` tinyint NULL DEFAULT NULL COMMENT '状态: 1 开启 ,2 禁用',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格值';
+-- ----------------------------
+-- Records of product_property_value
+-- ----------------------------
+BEGIN;
+COMMIT;
--- sku
-drop table if exists product_sku;
-create table product_sku
-(
- id bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
- spu_id bigint not null comment 'spu编号',
- properties varchar(64) not null comment '规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]',
- price int not null DEFAULT -1 comment '销售价格,单位:分',
- original_price int not null DEFAULT -1 comment '原价, 单位: 分',
- cost_price int not null DEFAULT -1 comment '成本价,单位: 分',
- bar_code varchar(64) not null comment '条形码',
- pic_url VARCHAR(128) not null comment '图片地址',
- status tinyint comment '状态: 0-正常 1-禁用',
- create_time datetime default current_timestamp comment '创建时间',
- update_time datetime default current_timestamp on update current_timestamp comment '更新时间',
- creator varchar(64) comment '创建人',
- updater varchar(64) comment '更新人',
- tenant_id bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
- deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
- primary key (id)
-) comment '商品sku' character set utf8mb4
- collate utf8mb4_general_ci;
+-- ----------------------------
+-- Table structure for product_sku
+-- ----------------------------
+DROP TABLE IF EXISTS `product_sku`;
+CREATE TABLE `product_sku` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `spu_id` bigint NOT NULL COMMENT 'spu编号',
+ `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
+ `name` varchar(128) DEFAULT NULL COMMENT '商品 SKU 名字',
+ `properties` varchar(128) DEFAULT NULL COMMENT '规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]',
+ `price` int NOT NULL DEFAULT '-1' COMMENT '销售价格,单位:分',
+ `market_price` int DEFAULT NULL COMMENT '市场价',
+ `cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价,单位: 分',
+ `pic_url` varchar(128) NOT NULL COMMENT '图片地址',
+ `stock` int DEFAULT NULL COMMENT '库存',
+ `warn_stock` int DEFAULT NULL COMMENT '预警库存',
+ `volume` double DEFAULT NULL COMMENT '商品体积',
+ `weight` double DEFAULT NULL COMMENT '商品重量',
+ `bar_code` varchar(64) DEFAULT NULL COMMENT '条形码',
+ `status` tinyint DEFAULT NULL COMMENT '状态: 0-正常 1-禁用',
+ `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `creator` varchar(64) DEFAULT NULL COMMENT '创建人',
+ `updater` double(64,0) DEFAULT NULL COMMENT '更新人',
+`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB COMMENT='商品sku';
+-- ----------------------------
+-- Records of product_sku
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for product_spu
+-- ----------------------------
+DROP TABLE IF EXISTS `product_spu`;
+CREATE TABLE `product_spu` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
+ `brand_id` int DEFAULT NULL COMMENT '商品品牌编号',
+ `category_id` bigint NOT NULL COMMENT '分类id',
+ `spec_type` int NOT NULL COMMENT '规格类型:0 单规格 1 多规格',
+ `code` varchar(128) DEFAULT NULL COMMENT '商品编码',
+ `name` varchar(128) NOT NULL COMMENT '商品名称',
+ `sell_point` varchar(128) DEFAULT NULL COMMENT '卖点',
+ `description` text COMMENT '描述',
+ `pic_urls` varchar(1024) DEFAULT '' COMMENT '商品轮播图地址\n 数组,以逗号分隔\n 最多上传15张',
+ `video_url` varchar(128) DEFAULT NULL COMMENT '商品视频',
+ `market_price` int DEFAULT NULL COMMENT '市场价,单位使用:分',
+ `min_price` int DEFAULT NULL COMMENT '最小价格,单位使用:分',
+ `max_price` int DEFAULT NULL COMMENT '最大价格,单位使用:分',
+ `total_stock` int NOT NULL DEFAULT '0' COMMENT '总库存',
+ `show_stock` int DEFAULT '0' COMMENT '是否展示库存',
+ `sales_count` int DEFAULT '0' COMMENT '商品销量',
+ `virtual_sales_count` int DEFAULT '0' COMMENT '虚拟销量',
+ `click_count` int DEFAULT '0' COMMENT '商品点击量',
+ `status` bit(1) DEFAULT NULL COMMENT '上下架状态: 0 上架(开启) 1 下架(禁用)-1 回收',
+ `sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',
+ `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `creator` varchar(64) DEFAULT NULL COMMENT '创建人',
+ `updater` varchar(64) DEFAULT NULL COMMENT '更新人',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB COMMENT='商品spu';
+
+-- ----------------------------
+-- Records of product_spu
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+SET FOREIGN_KEY_CHECKS = 1;
+
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2000, '商品中心', '', 1, 60, 0, '/product', 'merchant', NULL, 0, b'1', b'1', '', '2022-07-29 15:53:53', '1', '2022-07-30 22:26:19', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2002, '商品分类', '', 2, 2, 2000, 'category', 'dict', 'mall/product/category/index', 0, b'1', b'1', '', '2022-07-29 15:53:53', '1', '2022-07-30 22:23:37', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2003, '分类查询', 'product:category:query', 3, 1, 2002, '', '', '', 0, b'1', b'1', '', '2022-07-29 15:53:53', '', '2022-07-29 15:53:53', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2004, '分类创建', 'product:category:create', 3, 2, 2002, '', '', '', 0, b'1', b'1', '', '2022-07-29 15:53:53', '', '2022-07-29 15:53:53', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2005, '分类更新', 'product:category:update', 3, 3, 2002, '', '', '', 0, b'1', b'1', '', '2022-07-29 15:53:53', '', '2022-07-29 15:53:53', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2006, '分类删除', 'product:category:delete', 3, 4, 2002, '', '', '', 0, b'1', b'1', '', '2022-07-29 15:53:53', '', '2022-07-29 15:53:53', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2007, '分类导出', 'product:category:export', 3, 5, 2002, '', '', '', 0, b'1', b'1', '', '2022-07-29 15:53:53', '', '2022-07-30 13:52:13', b'1');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2008, '商品品牌', '', 2, 1, 2000, 'brand', 'dashboard', 'mall/product/brand/index', 0, b'1', b'1', '', '2022-07-30 13:52:44', '1', '2022-07-30 22:23:43', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2009, '品牌查询', 'product:brand:query', 3, 1, 2008, '', '', '', 0, b'1', b'1', '', '2022-07-30 13:52:44', '', '2022-07-30 13:52:44', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2010, '品牌创建', 'product:brand:create', 3, 2, 2008, '', '', '', 0, b'1', b'1', '', '2022-07-30 13:52:44', '', '2022-07-30 13:52:44', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2011, '品牌更新', 'product:brand:update', 3, 3, 2008, '', '', '', 0, b'1', b'1', '', '2022-07-30 13:52:44', '', '2022-07-30 13:52:44', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2012, '品牌删除', 'product:brand:delete', 3, 4, 2008, '', '', '', 0, b'1', b'1', '', '2022-07-30 13:52:44', '', '2022-07-30 13:52:44', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2013, '品牌导出', 'product:brand:export', 3, 5, 2008, '', '', '', 0, b'1', b'1', '', '2022-07-30 13:52:44', '', '2022-07-30 14:15:00', b'1');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2014, '商品管理', '', 2, 0, 2000, 'spu', 'link', 'mall/product/spu/index', 0, b'1', b'1', '', '2022-07-30 14:22:58', '1', '2022-07-30 22:26:35', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2015, '商品查询', 'product:spu:query', 3, 1, 2014, '', '', '', 0, b'1', b'1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2016, '商品创建', 'product:spu:create', 3, 2, 2014, '', '', '', 0, b'1', b'1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2017, '商品更新', 'product:spu:update', 3, 3, 2014, '', '', '', 0, b'1', b'1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2018, '商品删除', 'product:spu:delete', 3, 4, 2014, '', '', '', 0, b'1', b'1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2019, '规格管理', '', 2, 3, 2000, 'property', '', 'mall/product/property/index', 0, b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-08-01 14:55:35', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2020, '规格查询', 'product:property:query', 3, 1, 2019, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-08-01 14:55:35', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2021, '规格创建', 'product:property:create', 3, 2, 2019, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-08-01 14:55:35', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2022, '规格更新', 'product:property:update', 3, 3, 2019, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-08-01 14:55:35', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2023, '规格删除', 'product:property:delete', 3, 4, 2019, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-08-01 14:55:35', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2024, '规格导出', 'product:property:export', 3, 5, 2019, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-08-01 14:55:35', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2025, 'Banner管理', '', 2, 1, 2000, 'brand', '', 'mall/market/banner/index', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2026, 'Banner查询', 'market:banner:query', 3, 1, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2027, 'Banner创建', 'market:banner:create', 3, 2, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2028, 'Banner更新', 'market:banner:update', 3, 3, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
+INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2029, 'Banner删除', 'market:banner:delete', 3, 4, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
--- Market-Banner管理SQL
-drop table if exists market_banner;
-CREATE TABLE `market_banner` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Banner编号',
- `title` varchar(64) NOT NULL DEFAULT '' COMMENT 'Banner标题',
- `pic_url` varchar(255) NOT NULL COMMENT '图片URL',
- `status` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '活动状态',
- `url` varchar(255) NOT NULL COMMENT '跳转地址',
- `creator` varchar(64) DEFAULT '' COMMENT '创建者',
- `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
- `updater` varchar(64) DEFAULT '' COMMENT '更新者',
- `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
- `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
- `tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '租户编号',
- `sort` tinyint(4) DEFAULT NULL COMMENT '排序',
- `memo` varchar(255) DEFAULT NULL COMMENT '描述',
- PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='Banner管理';
--- 菜单 SQL
-INSERT INTO `system_menu`(`id`,`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES (2026, 'Banner管理', '', 2, 1, 2000, 'brand', '', 'mall/market/banner/index', 0);
--- 按钮父菜单ID
-SELECT @parentId := LAST_INSERT_ID();
--- 按钮 SQL
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('Banner查询', 'market:banner:query', 3, 1, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('Banner创建', 'market:banner:create', 3, 2, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('Banner更新', 'market:banner:update', 3, 3, @parentId, '', '', '', 0);
-INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
-VALUES ('Banner删除', 'market:banner:delete', 3, 4, @parentId, '', '', '', 0);
diff --git a/sql/optional/mall/order.sql b/sql/optional/mall/order.sql
new file mode 100644
index 000000000..21e60200d
--- /dev/null
+++ b/sql/optional/mall/order.sql
@@ -0,0 +1,76 @@
+/**todo cancelType 设置默认值 0?*/
+CREATE TABLE `trade_order`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+ `sn` varchar(32) NOT NULL COMMENT '订单流水号',
+ `type` int NOT NULL DEFAULT '0' COMMENT '订单类型:[0:普通订单 1:秒杀订单 2:拼团订单 3:砍价订单]',
+ `terminal` int NOT NULL COMMENT '订单来源终端:[1:小程序 2:H5 3:iOS 4:安卓]',
+ `user_id` bigint unsigned NOT NULL COMMENT '用户编号',
+ `user_ip` varchar(30) NOT NULL DEFAULT '' COMMENT '用户 IP',
+ `user_remark` varchar(200) DEFAULT NULL COMMENT '用户备注',
+ `status` int NOT NULL DEFAULT '0' COMMENT '订单状态:[0:待付款 1:待发货 2:待收货 3:已完成 4:已关闭]',
+ `product_count` int NOT NULL COMMENT '购买的商品数量',
+ `cancel_type` int NOT NULL COMMENT '取消类型:[10:超时未支付 20:退款关闭 30:买家取消 40:已通过货到付款交易]',
+ `remark` varchar(200) DEFAULT NULL COMMENT '商家备注',
+ `payed` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否已支付:[0:未支付 1:已经支付过]',
+ `finish_time` datetime DEFAULT NULL COMMENT '订单完成时间',
+ `cancel_time` datetime DEFAULT NULL COMMENT '订单取消时间',
+ `sku_original_price` int NOT NULL DEFAULT '0' COMMENT '商品原价(总),单位:分',
+ `sku_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 '运费金额,单位:分',
+ `pay_price` int NOT NULL DEFAULT '0' COMMENT '应付金额(总),单位:分',
+ `pay_order_id` int NOT NULL COMMENT '支付订单编号',
+ `pay_channel` int NOT NULL COMMENT '支付成功的支付渠道',
+ `delivery_type` int NOT NULL DEFAULT '1' COMMENT '配送方式:[1:快递发货 2:自提]',
+ `actual_delivery_type` int NOT NULL DEFAULT '1' COMMENT '实际的配送方式:[1:快递发货 2:自提]',
+ `delivery_templateid` int DEFAULT NULL COMMENT '配置模板的编号',
+ `express_no` int DEFAULT NULL COMMENT '物流公司单号',
+ `delivery_status` bit(1) NOT NULL DEFAULT b'0' COMMENT '发货状态[0:未发货 1:已发货]',
+ `delivery_time` datetime DEFAULT NULL COMMENT '发货时间',
+ `receive_time` datetime DEFAULT NULL COMMENT '收货时间',
+ `receiver_name` varchar(20) NOT NULL COMMENT '收件人名称',
+ `receiver_mobile` varchar(20) NOT NULL COMMENT '收件人手机',
+ `receiver_area_id` int NOT NULL COMMENT '收件人地区编号',
+ `receiver_post_code` int DEFAULT NULL COMMENT '收件人邮编',
+ `receiver_detail_address` varchar(255) NOT NULL COMMENT '收件人详细地址',
+ `refund_status` int NOT NULL DEFAULT '0' COMMENT '订单状态:[0:未退款 1:部分退款 2:全部退款]',
+ `refund_price` int NOT NULL DEFAULT '0' COMMENT '退款金额,单位:分',
+ `coupon_id` bigint unsigned NOT NULL COMMENT '优惠劵编号',
+ `creator` varchar(64) DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB COMMENT ='交易订单表';
+
+
+DROP TABLE IF EXISTS `trade_order_item`;
+CREATE TABLE `trade_order_item`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+ `user_id` bigint unsigned NOT NULL COMMENT '用户编号',
+ `order_Id` bigint unsigned NOT NULL COMMENT '订单编号',
+ `spu_id` bigint unsigned NOT NULL COMMENT '商品 SPU 编号',
+ `sku_id` bigint unsigned NOT NULL COMMENT '商品 SKU 编号',
+ `properties` json DEFAULT NULL COMMENT '规格值数组,JSON 格式',
+ `name` varchar(128) NOT NULL DEFAULT '' COMMENT '商品名称',
+ `pic_url` varchar(200) DEFAULT NULL COMMENT '商品图片',
+ `count` int NOT NULL COMMENT '购买数量',
+ `commented` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否评论:[0:未评论 1:已评论]',
+ `original_price` int NOT NULL DEFAULT '0' COMMENT '商品原价(单),单位:分',
+ `total_original_price` int NOT NULL DEFAULT '0' COMMENT '商品原价(总),单位:分',
+ `total_promotion_price` int NOT NULL DEFAULT '0' COMMENT '商品级优惠(总),单位:分',
+ `present_price` int NOT NULL DEFAULT '0' COMMENT '最终购买金额(单),单位:分。',
+ `total_present_price` int NOT NULL DEFAULT '0' COMMENT '最终购买金额(总),单位:分。',
+ `total_pay_price` int NOT NULL DEFAULT '0' COMMENT '应付金额(总),单位:分',
+ `refund_status` int NOT NULL DEFAULT '0' COMMENT '退款状态:[0:未申请退款 1:申请退款 2:等待退款 3:退款成功]',
+ `refund_total` int NOT NULL DEFAULT '0' COMMENT '退款总金额,单位:分',
+ `creator` varchar(64) DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB COMMENT ='交易订单明细表';
\ No newline at end of file
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java
new file mode 100644
index 000000000..cb9e530b7
--- /dev/null
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.framework.common.enums;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+/**
+ * 终端的枚举
+ *
+ * @author 芋道源码
+ */
+@RequiredArgsConstructor
+@Getter
+public enum TerminalEnum implements IntArrayValuable {
+
+ //TODO terminal 重复,请参考 '订单来源终端:[1:小程序 2:H5 3:iOS 4:安卓]'
+ MINI_PROGRAM(1, "小程序"),
+ H5(2, "H5"),
+ IOS(3, "iOS"),
+ ANDROID(3, "安卓"),;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TerminalEnum::getTerminal).toArray();
+
+ /**
+ * 终端
+ */
+ private final Integer terminal;
+ /**
+ * 终端名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
index 6b83bb3d6..d57fb21b9 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
@@ -173,6 +173,23 @@ public class CollectionUtils {
return valueFunc.apply(t);
}
+ public static > V getMinValue(List from, Function valueFunc) {
+ if (CollUtil.isEmpty(from)) {
+ return null;
+ }
+ assert from.size() > 0; // 断言,避免告警
+ T t = from.stream().min(Comparator.comparing(valueFunc)).get();
+ return valueFunc.apply(t);
+ }
+
+ public static > V getSumValue(List from, Function valueFunc, BinaryOperator accumulator) {
+ if (CollUtil.isEmpty(from)) {
+ return null;
+ }
+ assert from.size() > 0; // 断言,避免告警
+ return from.stream().map(valueFunc).reduce(accumulator).get();
+ }
+
public static void addIfNotNull(Collection coll, T item) {
if (item == null) {
return;
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java
index a9a4d24d4..5fc4e55d0 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java
@@ -18,7 +18,6 @@ import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
-import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.select.*;
@@ -37,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* 数据权限拦截器,通过 {@link DataPermissionRule} 数据权限规则,重写 SQL 的方式来实现
- * 主要的 SQL 重写方法,可见 {@link #builderExpression(Expression, Table)} 方法
+ * 主要的 SQL 重写方法,可见 {@link #builderExpression(Expression, List)} 方法
*
* 整体的代码实现上,参考 {@link com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor} 实现。
* 所以每次 MyBatis Plus 升级时,需要 Review 下其具体的实现是否有变更!
@@ -53,8 +52,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
private final MappedStatementCache mappedStatementCache = new MappedStatementCache();
@Override // SELECT 场景
- public void beforeQuery(Executor executor, MappedStatement ms, Object parameter,
- RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
+ public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
// 获得 Mapper 对应的数据权限的规则
List rules = ruleFactory.getDataPermissionRule(ms.getId());
if (mappedStatementCache.noRewritable(ms, rules)) { // 如果无需重写,则跳过
@@ -68,12 +66,14 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
// 处理 SQL
mpBs.sql(parserSingle(mpBs.sql(), null));
} finally {
+ // 添加是否需要重写的缓存
addMappedStatementCache(ms);
+ // 清空上下文
ContextHolder.clear();
}
}
- @Override // 只处理 UPDATE / DELETE 场景,不处理 INSERT 场景
+ @Override // 只处理 UPDATE / DELETE 场景,不处理 INSERT 场景(因为 INSERT 不需要数据权限)
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
MappedStatement ms = mpSh.mappedStatement();
@@ -92,7 +92,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
// 处理 SQL
mpBs.sql(parserMulti(mpBs.sql(), null));
} finally {
+ // 添加是否需要重写的缓存
addMappedStatementCache(ms);
+ // 清空上下文
ContextHolder.clear();
}
}
@@ -107,24 +109,6 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
}
}
- protected void processSelectBody(SelectBody selectBody) {
- if (selectBody == null) {
- return;
- }
- if (selectBody instanceof PlainSelect) {
- processPlainSelect((PlainSelect) selectBody);
- } else if (selectBody instanceof WithItem) {
- WithItem withItem = (WithItem) selectBody;
- processSelectBody(withItem.getSubSelect().getSelectBody());
- } else {
- SetOperationList operationList = (SetOperationList) selectBody;
- List selectBodys = operationList.getSelects();
- if (CollectionUtils.isNotEmpty(selectBodys)) {
- selectBodys.forEach(this::processSelectBody);
- }
- }
- }
-
/**
* update 语句处理
*/
@@ -142,28 +126,77 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
delete.setWhere(this.builderExpression(delete.getWhere(), delete.getTable()));
}
+ // ========== 和 TenantLineInnerInterceptor 一致的逻辑 ==========
+
+ protected void processSelectBody(SelectBody selectBody) {
+ if (selectBody == null) {
+ return;
+ }
+ if (selectBody instanceof PlainSelect) {
+ processPlainSelect((PlainSelect) selectBody);
+ } else if (selectBody instanceof WithItem) {
+ WithItem withItem = (WithItem) selectBody;
+ processSelectBody(withItem.getSubSelect().getSelectBody());
+ } else {
+ SetOperationList operationList = (SetOperationList) selectBody;
+ List selectBodyList = operationList.getSelects();
+ if (CollectionUtils.isNotEmpty(selectBodyList)) {
+ selectBodyList.forEach(this::processSelectBody);
+ }
+ }
+ }
+
/**
* 处理 PlainSelect
*/
protected void processPlainSelect(PlainSelect plainSelect) {
- FromItem fromItem = plainSelect.getFromItem();
- Expression where = plainSelect.getWhere();
- processWhereSubSelect(where);
- if (fromItem instanceof Table) {
- Table fromTable = (Table) fromItem;
- plainSelect.setWhere(builderExpression(where, fromTable));
- } else {
- processFromItem(fromItem);
- }
//#3087 github
List selectItems = plainSelect.getSelectItems();
if (CollectionUtils.isNotEmpty(selectItems)) {
selectItems.forEach(this::processSelectItem);
}
+
+ // 处理 where 中的子查询
+ Expression where = plainSelect.getWhere();
+ processWhereSubSelect(where);
+
+ // 处理 fromItem
+ FromItem fromItem = plainSelect.getFromItem();
+ List list = processFromItem(fromItem);
+ List mainTables = new ArrayList<>(list);
+
+ // 处理 join
List joins = plainSelect.getJoins();
if (CollectionUtils.isNotEmpty(joins)) {
- processJoins(joins);
+ mainTables = processJoins(mainTables, joins);
}
+
+ // 当有 mainTable 时,进行 where 条件追加
+ if (CollectionUtils.isNotEmpty(mainTables)) {
+ plainSelect.setWhere(builderExpression(where, mainTables));
+ }
+ }
+
+ private List processFromItem(FromItem fromItem) {
+ // 处理括号括起来的表达式
+ while (fromItem instanceof ParenthesisFromItem) {
+ fromItem = ((ParenthesisFromItem) fromItem).getFromItem();
+ }
+
+ List mainTables = new ArrayList<>();
+ // 无 join 时的处理逻辑
+ if (fromItem instanceof Table) {
+ Table fromTable = (Table) fromItem;
+ mainTables.add(fromTable);
+ } else if (fromItem instanceof SubJoin) {
+ // SubJoin 类型则还需要添加上 where 条件
+ List tables = processSubJoin((SubJoin) fromItem);
+ mainTables.addAll(tables);
+ } else {
+ // 处理下 fromItem
+ processOtherFromItem(fromItem);
+ }
+ return mainTables;
}
/**
@@ -191,7 +224,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
return;
}
if (where instanceof FromItem) {
- processFromItem((FromItem) where);
+ processOtherFromItem((FromItem) where);
return;
}
if (where.toString().indexOf("SELECT") > 0) {
@@ -204,9 +237,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
} else if (where instanceof InExpression) {
// in
InExpression expression = (InExpression) where;
- ItemsList itemsList = expression.getRightItemsList();
- if (itemsList instanceof SubSelect) {
- processSelectBody(((SubSelect) itemsList).getSelectBody());
+ Expression inExpression = expression.getRightExpression();
+ if (inExpression instanceof SubSelect) {
+ processSelectBody(((SubSelect) inExpression).getSelectBody());
}
} else if (where instanceof ExistsExpression) {
// exists
@@ -239,7 +272,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
* 支持: 1. select fun(args..) 2. select fun1(fun2(args..),args..)
*
fixed gitee pulls/141
*
- * @param function 函数
+ * @param function
*/
protected void processFunction(Function function) {
ExpressionList parameters = function.getParameters();
@@ -257,22 +290,19 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
/**
* 处理子查询等
*/
- protected void processFromItem(FromItem fromItem) {
- if (fromItem instanceof SubJoin) {
- SubJoin subJoin = (SubJoin) fromItem;
- if (subJoin.getJoinList() != null) {
- processJoins(subJoin.getJoinList());
- }
- if (subJoin.getLeft() != null) {
- processFromItem(subJoin.getLeft());
- }
- } else if (fromItem instanceof SubSelect) {
+ protected void processOtherFromItem(FromItem fromItem) {
+ // 去除括号
+ while (fromItem instanceof ParenthesisFromItem) {
+ fromItem = ((ParenthesisFromItem) fromItem).getFromItem();
+ }
+
+ if (fromItem instanceof SubSelect) {
SubSelect subSelect = (SubSelect) fromItem;
if (subSelect.getSelectBody() != null) {
processSelectBody(subSelect.getSelectBody());
}
} else if (fromItem instanceof ValuesList) {
- logger.debug("Perform a subquery, if you do not give us feedback");
+ logger.debug("Perform a subQuery, if you do not give us feedback");
} else if (fromItem instanceof LateralSubSelect) {
LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem;
if (lateralSubSelect.getSubSelect() != null) {
@@ -284,75 +314,176 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
}
}
+ /**
+ * 处理 sub join
+ *
+ * @param subJoin subJoin
+ * @return Table subJoin 中的主表
+ */
+ private List processSubJoin(SubJoin subJoin) {
+ List mainTables = new ArrayList<>();
+ if (subJoin.getJoinList() != null) {
+ List list = processFromItem(subJoin.getLeft());
+ mainTables.addAll(list);
+ mainTables = processJoins(mainTables, subJoin.getJoinList());
+ }
+ return mainTables;
+ }
+
/**
* 处理 joins
*
- * @param joins join 集合
+ * @param mainTables 可以为 null
+ * @param joins join 集合
+ * @return List 右连接查询的 Table 列表
*/
- private void processJoins(List joins) {
+ private List processJoins(List mainTables, List joins) {
+ // join 表达式中最终的主表
+ Table mainTable = null;
+ // 当前 join 的左表
+ Table leftTable = null;
+
+ if (mainTables == null) {
+ mainTables = new ArrayList<>();
+ } else if (mainTables.size() == 1) {
+ mainTable = mainTables.get(0);
+ leftTable = mainTable;
+ }
+
//对于 on 表达式写在最后的 join,需要记录下前面多个 on 的表名
- Deque tables = new LinkedList<>();
+ Deque> onTableDeque = new LinkedList<>();
for (Join join : joins) {
// 处理 on 表达式
- FromItem fromItem = join.getRightItem();
- if (fromItem instanceof Table) {
- Table fromTable = (Table) fromItem;
+ FromItem joinItem = join.getRightItem();
+
+ // 获取当前 join 的表,subJoint 可以看作是一张表
+ List joinTables = null;
+ if (joinItem instanceof Table) {
+ joinTables = new ArrayList<>();
+ joinTables.add((Table) joinItem);
+ } else if (joinItem instanceof SubJoin) {
+ joinTables = processSubJoin((SubJoin) joinItem);
+ }
+
+ if (joinTables != null) {
+
+ // 如果是隐式内连接
+ if (join.isSimple()) {
+ mainTables.addAll(joinTables);
+ continue;
+ }
+
+ // 当前表是否忽略
+ Table joinTable = joinTables.get(0);
+
+ List onTables = null;
+ // 如果不要忽略,且是右连接,则记录下当前表
+ if (join.isRight()) {
+ mainTable = joinTable;
+ if (leftTable != null) {
+ onTables = Collections.singletonList(leftTable);
+ }
+ } else if (join.isLeft()) {
+ onTables = Collections.singletonList(joinTable);
+ } else if (join.isInner()) {
+ if (mainTable == null) {
+ onTables = Collections.singletonList(joinTable);
+ } else {
+ onTables = Arrays.asList(mainTable, joinTable);
+ }
+ mainTable = null;
+ }
+
+ mainTables = new ArrayList<>();
+ if (mainTable != null) {
+ mainTables.add(mainTable);
+ }
+
// 获取 join 尾缀的 on 表达式列表
Collection originOnExpressions = join.getOnExpressions();
// 正常 join on 表达式只有一个,立刻处理
- if (originOnExpressions.size() == 1) {
- processJoin(join);
+ if (originOnExpressions.size() == 1 && onTables != null) {
+ List onExpressions = new LinkedList<>();
+ onExpressions.add(builderExpression(originOnExpressions.iterator().next(), onTables));
+ join.setOnExpressions(onExpressions);
+ leftTable = joinTable;
continue;
}
- tables.push(fromTable);
+ // 表名压栈,忽略的表压入 null,以便后续不处理
+ onTableDeque.push(onTables);
// 尾缀多个 on 表达式的时候统一处理
if (originOnExpressions.size() > 1) {
Collection onExpressions = new LinkedList<>();
for (Expression originOnExpression : originOnExpressions) {
- Table currentTable = tables.poll();
- onExpressions.add(builderExpression(originOnExpression, currentTable));
+ List currentTableList = onTableDeque.poll();
+ if (CollectionUtils.isEmpty(currentTableList)) {
+ onExpressions.add(originOnExpression);
+ } else {
+ onExpressions.add(builderExpression(originOnExpression, currentTableList));
+ }
}
join.setOnExpressions(onExpressions);
}
+ leftTable = joinTable;
} else {
- // 处理右边连接的子表达式
- processFromItem(fromItem);
+ processOtherFromItem(joinItem);
+ leftTable = null;
}
}
+
+ return mainTables;
}
+ // ========== 和 TenantLineInnerInterceptor 存在差异的逻辑:关键,实现权限条件的拼接 ==========
+
/**
- * 处理联接语句
+ * 处理条件
+ *
+ * @param currentExpression 当前 where 条件
+ * @param table 单个表
*/
- protected void processJoin(Join join) {
- if (join.getRightItem() instanceof Table) {
- Table fromTable = (Table) join.getRightItem();
- Expression originOnExpression = CollUtil.getFirst(join.getOnExpressions());
- originOnExpression = builderExpression(originOnExpression, fromTable);
- join.setOnExpressions(CollUtil.newArrayList(originOnExpression));
- }
+ protected Expression builderExpression(Expression currentExpression, Table table) {
+ return this.builderExpression(currentExpression, Collections.singletonList(table));
}
/**
* 处理条件
+ *
+ * @param currentExpression 当前 where 条件
+ * @param tables 多个表
*/
- protected Expression builderExpression(Expression currentExpression, Table table) {
- // 获得 Table 对应的数据权限条件
- Expression equalsTo = buildDataPermissionExpression(table);
- if (equalsTo == null) { // 如果没条件,则返回 currentExpression 默认
+ protected Expression builderExpression(Expression currentExpression, List tables) {
+ // 没有表需要处理直接返回
+ if (CollectionUtils.isEmpty(tables)) {
return currentExpression;
}
- // 表达式为空,则直接返回 equalsTo
+ // 第一步,获得 Table 对应的数据权限条件
+ Expression dataPermissionExpression = null;
+ for (Table table : tables) {
+ // 构建每个表的权限 Expression 条件
+ Expression expression = buildDataPermissionExpression(table);
+ if (expression == null) {
+ continue;
+ }
+ // 合并到 dataPermissionExpression 中
+ dataPermissionExpression = dataPermissionExpression == null ? expression
+ : new AndExpression(dataPermissionExpression, expression);
+ }
+
+ // 第二步,合并多个 Expression 条件
+ if (dataPermissionExpression == null) {
+ return currentExpression;
+ }
if (currentExpression == null) {
- return equalsTo;
+ return dataPermissionExpression;
}
- // 如果表达式为 Or,则需要 (currentExpression) AND equalsTo
+ // ① 如果表达式为 Or,则需要 (currentExpression) AND dataPermissionExpression
if (currentExpression instanceof OrExpression) {
- return new AndExpression(new Parenthesis(currentExpression), equalsTo);
+ return new AndExpression(new Parenthesis(currentExpression), dataPermissionExpression);
}
- // 如果表达式为 And,则直接返回 currentExpression AND equalsTo
- return new AndExpression(currentExpression, equalsTo);
+ // ② 如果表达式为 And,则直接返回 where AND dataPermissionExpression
+ return new AndExpression(currentExpression, dataPermissionExpression);
}
/**
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java
index 8c0772f1a..b8cad13cf 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java
@@ -46,7 +46,7 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
@Override
public Set getTableNames() {
- return asSet("entity", "entity1", "entity2", "t1", "t2", // 支持 MyBatis Plus 的单元测试
+ return asSet("entity", "entity1", "entity2", "entity3", "t1", "t2", "sys_dict_item", // 支持 MyBatis Plus 的单元测试
"t_user", "t_role"); // 满足自己的单元测试
}
@@ -84,30 +84,30 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
@Test
void delete() {
assertSql("delete from entity where id = ?",
- "DELETE FROM entity WHERE id = ? AND tenant_id = 1");
+ "DELETE FROM entity WHERE id = ? AND entity.tenant_id = 1");
}
@Test
void update() {
assertSql("update entity set name = ? where id = ?",
- "UPDATE entity SET name = ? WHERE id = ? AND tenant_id = 1");
+ "UPDATE entity SET name = ? WHERE id = ? AND entity.tenant_id = 1");
}
@Test
void selectSingle() {
// 单表
assertSql("select * from entity where id = ?",
- "SELECT * FROM entity WHERE id = ? AND tenant_id = 1");
+ "SELECT * FROM entity WHERE id = ? AND entity.tenant_id = 1");
assertSql("select * from entity where id = ? or name = ?",
- "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1");
+ "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1");
assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)",
- "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1");
+ "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1");
/* not */
assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)",
- "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND tenant_id = 1");
+ "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND entity.tenant_id = 1");
}
@Test
@@ -167,10 +167,12 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
assertSql("SELECT * FROM entity e WHERE e.id >= (select e1.id from entity1 e1 where e1.id = ?)",
"SELECT * FROM entity e WHERE e.id >= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
+
/* <= */
assertSql("SELECT * FROM entity e WHERE e.id <= (select e1.id from entity1 e1 where e1.id = ?)",
"SELECT * FROM entity e WHERE e.id <= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
+
/* <> */
assertSql("SELECT * FROM entity e WHERE e.id <> (select e1.id from entity1 e1 where e1.id = ?)",
"SELECT * FROM entity e WHERE e.id <> (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
@@ -204,6 +206,14 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
"SELECT * FROM entity e " +
"LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
"WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
+
+ assertSql("SELECT * FROM entity e " +
+ "left join entity1 e1 on e1.id = e.id " +
+ "left join entity2 e2 on e1.id = e2.id",
+ "SELECT * FROM entity e " +
+ "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
+ "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " +
+ "WHERE e.tenant_id = 1");
}
@Test
@@ -212,17 +222,125 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
assertSql("SELECT * FROM entity e " +
"right join entity1 e1 on e1.id = e.id",
"SELECT * FROM entity e " +
- "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
- "WHERE e.tenant_id = 1");
+ "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
+ "WHERE e1.tenant_id = 1");
+
+ assertSql("SELECT * FROM with_as_1 e " +
+ "right join entity1 e1 on e1.id = e.id",
+ "SELECT * FROM with_as_1 e " +
+ "RIGHT JOIN entity1 e1 ON e1.id = e.id " +
+ "WHERE e1.tenant_id = 1");
assertSql("SELECT * FROM entity e " +
"right join entity1 e1 on e1.id = e.id " +
"WHERE e.id = ? OR e.name = ?",
"SELECT * FROM entity e " +
- "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
- "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
+ "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
+ "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
+
+ assertSql("SELECT * FROM entity e " +
+ "right join entity1 e1 on e1.id = e.id " +
+ "right join entity2 e2 on e1.id = e2.id ",
+ "SELECT * FROM entity e " +
+ "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
+ "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " +
+ "WHERE e2.tenant_id = 1");
}
+ @Test
+ void selectMixJoin() {
+ assertSql("SELECT * FROM entity e " +
+ "right join entity1 e1 on e1.id = e.id " +
+ "left join entity2 e2 on e1.id = e2.id",
+ "SELECT * FROM entity e " +
+ "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
+ "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " +
+ "WHERE e1.tenant_id = 1");
+
+ assertSql("SELECT * FROM entity e " +
+ "left join entity1 e1 on e1.id = e.id " +
+ "right join entity2 e2 on e1.id = e2.id",
+ "SELECT * FROM entity e " +
+ "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
+ "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " +
+ "WHERE e2.tenant_id = 1");
+
+ assertSql("SELECT * FROM entity e " +
+ "left join entity1 e1 on e1.id = e.id " +
+ "inner join entity2 e2 on e1.id = e2.id",
+ "SELECT * FROM entity e " +
+ "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
+ "INNER JOIN entity2 e2 ON e1.id = e2.id AND e.tenant_id = 1 AND e2.tenant_id = 1");
+ }
+
+
+ @Test
+ void selectJoinSubSelect() {
+ assertSql("select * from (select * from entity) e1 " +
+ "left join entity2 e2 on e1.id = e2.id",
+ "SELECT * FROM (SELECT * FROM entity WHERE entity.tenant_id = 1) e1 " +
+ "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1");
+
+ assertSql("select * from entity1 e1 " +
+ "left join (select * from entity2) e2 " +
+ "on e1.id = e2.id",
+ "SELECT * FROM entity1 e1 " +
+ "LEFT JOIN (SELECT * FROM entity2 WHERE entity2.tenant_id = 1) e2 " +
+ "ON e1.id = e2.id " +
+ "WHERE e1.tenant_id = 1");
+ }
+
+ @Test
+ void selectSubJoin() {
+
+ assertSql("select * FROM " +
+ "(entity1 e1 right JOIN entity2 e2 ON e1.id = e2.id)",
+ "SELECT * FROM " +
+ "(entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " +
+ "WHERE e2.tenant_id = 1");
+
+ assertSql("select * FROM " +
+ "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id)",
+ "SELECT * FROM " +
+ "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
+ "WHERE e1.tenant_id = 1");
+
+
+ assertSql("select * FROM " +
+ "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id) " +
+ "right join entity3 e3 on e1.id = e3.id",
+ "SELECT * FROM " +
+ "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
+ "RIGHT JOIN entity3 e3 ON e1.id = e3.id AND e1.tenant_id = 1 " +
+ "WHERE e3.tenant_id = 1");
+
+
+ assertSql("select * FROM entity e " +
+ "LEFT JOIN (entity1 e1 right join entity2 e2 ON e1.id = e2.id) " +
+ "on e.id = e2.id",
+ "SELECT * FROM entity e " +
+ "LEFT JOIN (entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " +
+ "ON e.id = e2.id AND e2.tenant_id = 1 " +
+ "WHERE e.tenant_id = 1");
+
+ assertSql("select * FROM entity e " +
+ "LEFT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " +
+ "on e.id = e2.id",
+ "SELECT * FROM entity e " +
+ "LEFT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
+ "ON e.id = e2.id AND e1.tenant_id = 1 " +
+ "WHERE e.tenant_id = 1");
+
+ assertSql("select * FROM entity e " +
+ "RIGHT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " +
+ "on e.id = e2.id",
+ "SELECT * FROM entity e " +
+ "RIGHT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
+ "ON e.id = e2.id AND e.tenant_id = 1 " +
+ "WHERE e1.tenant_id = 1");
+ }
+
+
@Test
void selectLeftJoinMultipleTrailingOn() {
// 多个 on 尾缀的
@@ -256,51 +374,97 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
"inner join entity1 e1 on e1.id = e.id " +
"WHERE e.id = ? OR e.name = ?",
"SELECT * FROM entity e " +
- "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
- "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
+ "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " +
+ "WHERE e.id = ? OR e.name = ?");
assertSql("SELECT * FROM entity e " +
"inner join entity1 e1 on e1.id = e.id " +
"WHERE (e.id = ? OR e.name = ?)",
"SELECT * FROM entity e " +
- "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
- "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
+ "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " +
+ "WHERE (e.id = ? OR e.name = ?)");
+
+ // 隐式内连接
+ assertSql("SELECT * FROM entity,entity1 " +
+ "WHERE entity.id = entity1.id",
+ "SELECT * FROM entity, entity1 " +
+ "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
+
+ // 隐式内连接
+ assertSql("SELECT * FROM entity a, with_as_entity1 b " +
+ "WHERE a.id = b.id",
+ "SELECT * FROM entity a, with_as_entity1 b " +
+ "WHERE a.id = b.id AND a.tenant_id = 1");
+
+ assertSql("SELECT * FROM with_as_entity a, with_as_entity1 b " +
+ "WHERE a.id = b.id",
+ "SELECT * FROM with_as_entity a, with_as_entity1 b " +
+ "WHERE a.id = b.id");
+
+ // SubJoin with 隐式内连接
+ assertSql("SELECT * FROM (entity,entity1) " +
+ "WHERE entity.id = entity1.id",
+ "SELECT * FROM (entity, entity1) " +
+ "WHERE entity.id = entity1.id " +
+ "AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
+
+ assertSql("SELECT * FROM ((entity,entity1),entity2) " +
+ "WHERE entity.id = entity1.id and entity.id = entity2.id",
+ "SELECT * FROM ((entity, entity1), entity2) " +
+ "WHERE entity.id = entity1.id AND entity.id = entity2.id " +
+ "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1");
+
+ assertSql("SELECT * FROM (entity,(entity1,entity2)) " +
+ "WHERE entity.id = entity1.id and entity.id = entity2.id",
+ "SELECT * FROM (entity, (entity1, entity2)) " +
+ "WHERE entity.id = entity1.id AND entity.id = entity2.id " +
+ "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1");
+
+ // 沙雕的括号写法
+ assertSql("SELECT * FROM (((entity,entity1))) " +
+ "WHERE entity.id = entity1.id",
+ "SELECT * FROM (((entity, entity1))) " +
+ "WHERE entity.id = entity1.id " +
+ "AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
- // 垃圾 inner join todo
-// assertSql("SELECT * FROM entity,entity1 " +
-// "WHERE entity.id = entity1.id",
-// "SELECT * FROM entity e " +
-// "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-// "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
}
+
@Test
void selectWithAs() {
assertSql("with with_as_A as (select * from entity) select * from with_as_A",
- "WITH with_as_A AS (SELECT * FROM entity WHERE tenant_id = 1) SELECT * FROM with_as_A");
+ "WITH with_as_A AS (SELECT * FROM entity WHERE entity.tenant_id = 1) SELECT * FROM with_as_A");
+ }
+
+
+ @Test
+ void selectIgnoreTable() {
+ assertSql(" SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)",
+ "SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id AND item.tenant_id = 1 WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)");
}
private void assertSql(String sql, String targetSql) {
assertEquals(targetSql, interceptor.parserSingle(sql, null));
}
+
// ========== 额外的测试 ==========
@Test
public void testSelectSingle() {
// 单表
assertSql("select * from t_user where id = ?",
- "SELECT * FROM t_user WHERE id = ? AND tenant_id = 1 AND dept_id IN (10, 20)");
+ "SELECT * FROM t_user WHERE id = ? AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
assertSql("select * from t_user where id = ? or name = ?",
- "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND tenant_id = 1 AND dept_id IN (10, 20)");
+ "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
assertSql("SELECT * FROM t_user WHERE (id = ? OR name = ?)",
- "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND tenant_id = 1 AND dept_id IN (10, 20)");
+ "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
/* not */
assertSql("SELECT * FROM t_user WHERE not (id = ? OR name = ?)",
- "SELECT * FROM t_user WHERE NOT (id = ? OR name = ?) AND tenant_id = 1 AND dept_id IN (10, 20)");
+ "SELECT * FROM t_user WHERE NOT (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
}
@Test
@@ -329,16 +493,16 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
"right join t_role e1 on e1.id = e.id " +
"WHERE e.id = ? OR e.name = ?",
"SELECT * FROM t_user e " +
- "RIGHT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
- "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)");
+ "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " +
+ "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
// 条件 e.id = ? OR e.name = ? 带括号
assertSql("SELECT * FROM t_user e " +
"right join t_role e1 on e1.id = e.id " +
"WHERE (e.id = ? OR e.name = ?)",
"SELECT * FROM t_user e " +
- "RIGHT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
- "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)");
+ "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " +
+ "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
}
@Test
@@ -348,23 +512,22 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
"inner join entity1 e1 on e1.id = e.id " +
"WHERE e.id = ? OR e.name = ?",
"SELECT * FROM t_user e " +
- "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
- "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)");
+ "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " +
+ "WHERE e.id = ? OR e.name = ?");
// 条件 e.id = ? OR e.name = ? 带括号
assertSql("SELECT * FROM t_user e " +
- "inner join t_role e1 on e1.id = e.id " +
+ "inner join entity1 e1 on e1.id = e.id " +
"WHERE (e.id = ? OR e.name = ?)",
"SELECT * FROM t_user e " +
- "INNER JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
- "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)");
+ "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " +
+ "WHERE (e.id = ? OR e.name = ?)");
- // 垃圾 inner join todo
-// assertSql("SELECT * FROM entity,entity1 " +
-// "WHERE entity.id = entity1.id",
-// "SELECT * FROM entity e " +
-// "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-// "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
+ // 没有 On 的 inner join
+ assertSql("SELECT * FROM entity,entity1 " +
+ "WHERE entity.id = entity1.id",
+ "SELECT * FROM entity, entity1 " +
+ "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
}
}
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java
index 16d3b29b1..0b1b01b08 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.SortingField;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -78,7 +79,10 @@ public class MyBatisUtils {
* @return Column 对象
*/
public static Column buildColumn(String tableName, Alias tableAlias, String column) {
- return new Column(tableAlias != null ? tableAlias.getName() + "." + column : column);
+ if (tableAlias != null) {
+ tableName = tableAlias.getName();
+ }
+ return new Column(tableName + StringPool.DOT + column);
}
}
diff --git a/yudao-module-mall/pom.xml b/yudao-module-mall/pom.xml
index 866874852..68c1825cc 100644
--- a/yudao-module-mall/pom.xml
+++ b/yudao-module-mall/pom.xml
@@ -15,14 +15,18 @@
${project.artifactId}
- market模块,主要实现营销相关功能
- 例如:营销活动、banner广告、优惠券、优惠码等功能。
+ 商城大模块,由 product 商品、market 营销、trade 交易 coupon等组成
+ yudao-module-coupon-api
+ yudao-module-coupon-biz
yudao-module-market-api
yudao-module-market-biz
yudao-module-product-api
yudao-module-product-biz
+ yudao-module-trade-api
+ yudao-module-trade-biz
+
diff --git a/yudao-module-mall/yudao-module-coupon-api/pom.xml b/yudao-module-mall/yudao-module-coupon-api/pom.xml
new file mode 100644
index 000000000..6dab80613
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/pom.xml
@@ -0,0 +1,35 @@
+
+
+
+ cn.iocoder.boot
+ yudao-module-mall
+ ${revision}
+
+
+ 4.0.0
+ yudao-module-coupon-api
+ jar
+
+
+ ${project.artifactId}
+
+ coupon 模块 API,暴露给其它模块调用
+
+
+
+
+ cn.iocoder.boot
+ yudao-common
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ true
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponExpireTimeTypeEnum.java b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponExpireTimeTypeEnum.java
new file mode 100644
index 000000000..0e1e17ece
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponExpireTimeTypeEnum.java
@@ -0,0 +1,29 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponFetchTypeEnum.java b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponFetchTypeEnum.java
new file mode 100644
index 000000000..66a86bc84
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponFetchTypeEnum.java
@@ -0,0 +1,29 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponForbidPreferenceEnum.java b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponForbidPreferenceEnum.java
new file mode 100644
index 000000000..1ac9e9f68
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponForbidPreferenceEnum.java
@@ -0,0 +1,29 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponGoodsTypeEnum.java b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponGoodsTypeEnum.java
new file mode 100644
index 000000000..e0946b7a0
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponGoodsTypeEnum.java
@@ -0,0 +1,30 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponStatusTypeEnum.java b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponStatusTypeEnum.java
new file mode 100644
index 000000000..813084731
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponStatusTypeEnum.java
@@ -0,0 +1,30 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponTypeEnum.java b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponTypeEnum.java
new file mode 100644
index 000000000..639d5080d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponTypeEnum.java
@@ -0,0 +1,30 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponUseLimitEnum.java b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponUseLimitEnum.java
new file mode 100644
index 000000000..beb530f0c
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponUseLimitEnum.java
@@ -0,0 +1,29 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponValidityTypeEnum.java b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponValidityTypeEnum.java
new file mode 100644
index 000000000..798cf1e0f
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponValidityTypeEnum.java
@@ -0,0 +1,29 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/ErrorCodeConstants.java
new file mode 100644
index 000000000..fced9d140
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/ErrorCodeConstants.java
@@ -0,0 +1,27 @@
+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, "优惠券模板不存在");
+
+
+}
+
diff --git a/yudao-module-mall/yudao-module-coupon-biz/pom.xml b/yudao-module-mall/yudao-module-coupon-biz/pom.xml
new file mode 100644
index 000000000..eda16bd16
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/pom.xml
@@ -0,0 +1,62 @@
+
+
+
+ cn.iocoder.boot
+ yudao-module-mall
+ ${revision}
+
+ 4.0.0
+ jar
+ yudao-module-coupon-biz
+
+ ${project.artifactId}
+
+
+ coupon模块,主要负责优惠券的一些业务,含发布优惠券模板,分发优惠券等
+
+
+
+
+
+ cn.iocoder.boot
+ yudao-module-coupon-api
+ ${revision}
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-biz-operatelog
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-biz-tenant
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-web
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-excel
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-mybatis
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-test
+
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/CouponController.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/CouponController.java
new file mode 100644
index 000000000..8ee02c366
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/CouponController.java
@@ -0,0 +1,88 @@
+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 create(@RequestParam("couponTemplateId") Long couponTemplateId) {
+
+ return success(couponService.create(couponTemplateId));
+ }
+
+
+ @PutMapping("/update")
+ @ApiOperation("更新优惠券")
+ @PreAuthorize("@ss.hasPermission('coupon::update')")
+ public CommonResult 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 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 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> getList(@RequestParam("ids") Collection ids) {
+ List list = couponService.getList(ids);
+ return success(CouponConvert.INSTANCE.convertList(list));
+ }
+
+ @GetMapping("/page")
+ @ApiOperation("获得优惠券分页")
+ @PreAuthorize("@ss.hasPermission('coupon::query')")
+ public CommonResult> getPage(@Valid CouponPageReqVO pageVO) {
+ PageResult pageResult = couponService.getPage(pageVO);
+ return success(CouponConvert.INSTANCE.convertPage(pageResult));
+ }
+
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponBaseVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponBaseVO.java
new file mode 100644
index 000000000..31cc828f7
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponBaseVO.java
@@ -0,0 +1,110 @@
+package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
+
+import lombok.*;
+import java.util.*;
+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 Date fetchTime;
+
+ @ApiModelProperty(value = "使用时间", required = true)
+ @NotNull(message = "使用时间不能为空")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date useTime;
+
+ @ApiModelProperty(value = "可使用的开始时间", required = true)
+ @NotNull(message = "可使用的开始时间不能为空")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date startTime;
+
+ @ApiModelProperty(value = "有效期结束时间", required = true)
+ @NotNull(message = "有效期结束时间不能为空")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date endTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateReqVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponCreateReqVO.java
old mode 100755
new mode 100644
similarity index 50%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateReqVO.java
rename to yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponCreateReqVO.java
index e01c272a4..2cd3cb419
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponCreateReqVO.java
@@ -1,14 +1,14 @@
-package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
+package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
-@ApiModel("管理后台 - 商品sku创建 Request VO")
+@ApiModel("管理后台 - 优惠券创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class ProductSkuCreateReqVO extends ProductSkuBaseVO {
+public class CouponCreateReqVO extends CouponBaseVO {
}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponExcelVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponExcelVO.java
new file mode 100644
index 000000000..f7d1d1d6f
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponExcelVO.java
@@ -0,0 +1,90 @@
+package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
+
+import lombok.*;
+import java.util.*;
+import java.math.BigDecimal;
+import io.swagger.annotations.*;
+
+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 Date fetchTime;
+
+ @ExcelProperty("使用时间")
+ private Date useTime;
+
+ @ExcelProperty("可使用的开始时间")
+ private Date startTime;
+
+ @ExcelProperty("有效期结束时间")
+ private Date endTime;
+
+ @ExcelProperty("创建时间")
+ private Date createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponExportReqVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponExportReqVO.java
new file mode 100644
index 000000000..a195a61de
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponExportReqVO.java
@@ -0,0 +1,91 @@
+package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
+
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.util.*;
+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(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 Date[] fetchTime;
+
+ @ApiModelProperty(value = "使用时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] useTime;
+
+ @ApiModelProperty(value = "可使用的开始时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] startTime;
+
+ @ApiModelProperty(value = "有效期结束时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] endTime;
+
+ @ApiModelProperty(value = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponPageReqVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponPageReqVO.java
new file mode 100644
index 000000000..9573200a5
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponPageReqVO.java
@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
+
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.util.*;
+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 Date[] fetchTime;
+
+ @ApiModelProperty(value = "使用时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] useTime;
+
+ @ApiModelProperty(value = "可使用的开始时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] startTime;
+
+ @ApiModelProperty(value = "有效期结束时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] endTime;
+
+ @ApiModelProperty(value = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityRespVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponRespVO.java
similarity index 52%
rename from yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityRespVO.java
rename to yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponRespVO.java
index de7ca3af2..9055a36a0 100644
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityRespVO.java
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponRespVO.java
@@ -1,16 +1,16 @@
-package cn.iocoder.yudao.module.market.controller.admin.activity.vo;
+package cn.iocoder.yudao.module.coupon.controller.admin.coupon.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
-@ApiModel("管理后台 - 促销活动 Response VO")
+@ApiModel("管理后台 - 优惠券 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class ActivityRespVO extends ActivityBaseVO {
+public class CouponRespVO extends CouponBaseVO {
- @ApiModelProperty(value = "活动编号", required = true)
+ @ApiModelProperty(value = "用户ID", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponUpdateReqVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponUpdateReqVO.java
new file mode 100644
index 000000000..0c1a741ca
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponUpdateReqVO.java
@@ -0,0 +1,18 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/CouponTempleteController.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/CouponTempleteController.java
new file mode 100644
index 000000000..a81f53c09
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/CouponTempleteController.java
@@ -0,0 +1,81 @@
+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 create(@Valid @RequestBody CouponTempleteCreateReqVO createReqVO) {
+ return success(couponTempleteServiceService.create(createReqVO));
+ }
+
+// @PutMapping("/update")
+// @ApiOperation("更新优惠券模板")
+// @PreAuthorize("@ss.hasPermission('CouponTemplete::update')")
+// public CommonResult 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 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 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> getList(@RequestParam("ids") Collection ids) {
+// List list = couponTempleteServiceService.getList(ids);
+// return success(CouponTempleteConvert.INSTANCE.convertList(list));
+// }
+//
+ @GetMapping("/page")
+ @ApiOperation("获得优惠券模板分页")
+ @PreAuthorize("@ss.hasPermission('CouponTemplete::query')")
+ public CommonResult> getPage(@Valid CouponTempletePageReqVO pageVO) {
+ PageResult pageResult = couponTempleteServiceService.getPage(pageVO);
+ return success(CouponTempleteConvert.INSTANCE.convertPage(pageResult));
+ }
+
+
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteBaseVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteBaseVO.java
new file mode 100644
index 000000000..942abe896
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteBaseVO.java
@@ -0,0 +1,172 @@
+package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
+
+import lombok.*;
+import java.util.*;
+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 Date startUseTime;
+
+ @ApiModelProperty(value = "使用结束日期 过期类型1时必填")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date 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 Date 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;
+
+
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteCreateReqVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteCreateReqVO.java
new file mode 100644
index 000000000..8e1d9a51a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteCreateReqVO.java
@@ -0,0 +1,12 @@
+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 {
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteExcelVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteExcelVO.java
new file mode 100644
index 000000000..1101f9b61
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteExcelVO.java
@@ -0,0 +1,119 @@
+package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
+
+import lombok.*;
+import java.util.*;
+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 Date startUseTime;
+
+ @ExcelProperty("使用结束日期 过期类型1时必填")
+ private Date 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 Date endTime;
+
+ @ExcelProperty("创建时间")
+ private Date createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteExportReqVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteExportReqVO.java
new file mode 100644
index 000000000..0420e3d9e
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteExportReqVO.java
@@ -0,0 +1,119 @@
+package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
+
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.util.*;
+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 Date[] startUseTime;
+
+ @ApiModelProperty(value = "使用结束日期 过期类型1时必填")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] 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 Date[] endTime;
+
+ @ApiModelProperty(value = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempletePageReqVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempletePageReqVO.java
new file mode 100644
index 000000000..3ff5710c7
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempletePageReqVO.java
@@ -0,0 +1,122 @@
+package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
+
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.util.*;
+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 Date[] startUseTime;
+
+ @ApiModelProperty(value = "使用结束日期 过期类型1时必填")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] 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 Date[] endTime;
+
+ @ApiModelProperty(value = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteRespVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteRespVO.java
new file mode 100644
index 000000000..b65f7c259
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteRespVO.java
@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
+
+import lombok.*;
+import java.util.*;
+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 Date createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteUpdateReqVO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteUpdateReqVO.java
new file mode 100644
index 000000000..1ee8b539d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteUpdateReqVO.java
@@ -0,0 +1,17 @@
+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;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/convert/CouponTemplete/CouponTempleteConvert.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/convert/CouponTemplete/CouponTempleteConvert.java
new file mode 100644
index 000000000..a7f37919d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/convert/CouponTemplete/CouponTempleteConvert.java
@@ -0,0 +1,38 @@
+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 convertList(List list);
+
+ PageResult convertPage(PageResult page);
+
+ List convertList02(List list);
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/convert/coupon/CouponConvert.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/convert/coupon/CouponConvert.java
new file mode 100644
index 000000000..e4dab938b
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/convert/coupon/CouponConvert.java
@@ -0,0 +1,34 @@
+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 convertList(List list);
+
+ PageResult convertPage(PageResult page);
+
+ List convertList02(List list);
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/dataobject/CouponTemplete/CouponTempleteDO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/dataobject/CouponTemplete/CouponTempleteDO.java
new file mode 100644
index 000000000..e33771808
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/dataobject/CouponTemplete/CouponTempleteDO.java
@@ -0,0 +1,158 @@
+package cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete;
+
+import lombok.*;
+import java.util.*;
+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") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 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 Date startUseTime;
+ /**
+ * 使用结束日期 过期类型1时必填
+ */
+ private Date 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 Date endTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/dataobject/coupon/CouponDO.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/dataobject/coupon/CouponDO.java
new file mode 100644
index 000000000..70e3aae20
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/dataobject/coupon/CouponDO.java
@@ -0,0 +1,118 @@
+package cn.iocoder.yudao.module.coupon.dal.dataobject.coupon;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import lombok.*;
+import java.util.*;
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.*;
+
+/**
+ * 优惠券 DO
+ *
+ * @author wxr
+ */
+@TableName("coupon")
+@KeySequence("coupon_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 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 Date fetchTime;
+ /**
+ * 使用时间
+ */
+ private Date useTime;
+ /**
+ * 可使用的开始时间
+ */
+ private Date startTime;
+ /**
+ * 有效期结束时间
+ */
+ private Date endTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/mysql/CouponTemplete/CouponTempleteMapper.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/mysql/CouponTemplete/CouponTempleteMapper.java
new file mode 100644
index 000000000..3243ce17a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/mysql/CouponTemplete/CouponTempleteMapper.java
@@ -0,0 +1,98 @@
+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 {
+
+ default PageResult selectPage(CouponTempletePageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .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 selectList(CouponTempleteExportReqVO reqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .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));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/mysql/coupon/CouponMapper.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/mysql/coupon/CouponMapper.java
new file mode 100644
index 000000000..8c9014694
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/mysql/coupon/CouponMapper.java
@@ -0,0 +1,76 @@
+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 {
+
+ default PageResult selectPage(CouponPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .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 selectList(CouponExportReqVO reqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .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));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/package-info.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/package-info.java
new file mode 100644
index 000000000..6743fd141
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * coupon模块,主要负责麦一些优惠券的额增删
+ *
+ * 1. Controller URL:以 /coumon/ 开头,避免和其它 Module 冲突
+ */
+package cn.iocoder.yudao.module.coupon;
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/CouponTemplete/CouponTempleteService.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/CouponTemplete/CouponTempleteService.java
new file mode 100644
index 000000000..0527d11b7
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/CouponTemplete/CouponTempleteService.java
@@ -0,0 +1,70 @@
+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 getList(Collection ids);
+
+ /**
+ * 获得优惠券模板分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 优惠券模板分页
+ */
+ PageResult getPage(CouponTempletePageReqVO pageReqVO);
+
+ /**
+ * 获得优惠券模板列表, 用于 Excel 导出
+ *
+ * @param exportReqVO 查询条件
+ * @return 优惠券模板列表
+ */
+ List getList(CouponTempleteExportReqVO exportReqVO);
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/CouponTemplete/CouponTempleteServiceImpl.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/CouponTemplete/CouponTempleteServiceImpl.java
new file mode 100644
index 000000000..6f07c4b2a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/CouponTemplete/CouponTempleteServiceImpl.java
@@ -0,0 +1,134 @@
+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 getList(Collection ids) {
+ return couponTempleteMapper.selectBatchIds(ids);
+ }
+
+ @Override
+ public PageResult getPage(CouponTempletePageReqVO pageReqVO) {
+ return couponTempleteMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public List getList(CouponTempleteExportReqVO exportReqVO) {
+ return couponTempleteMapper.selectList(exportReqVO);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/coupon/CouponService.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/coupon/CouponService.java
new file mode 100644
index 000000000..6a9d31520
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/coupon/CouponService.java
@@ -0,0 +1,70 @@
+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 getList(Collection ids);
+
+ /**
+ * 获得优惠券分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 优惠券分页
+ */
+ PageResult getPage(CouponPageReqVO pageReqVO);
+
+ /**
+ * 获得优惠券列表, 用于 Excel 导出
+ *
+ * @param exportReqVO 查询条件
+ * @return 优惠券列表
+ */
+ List getList(CouponExportReqVO exportReqVO);
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/coupon/CouponServiceImpl.java
new file mode 100644
index 000000000..0a1737a31
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/coupon/CouponServiceImpl.java
@@ -0,0 +1,107 @@
+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 io.micrometer.core.instrument.Counter;
+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 getList(Collection ids) {
+ return couponMapper.selectBatchIds(ids);
+ }
+
+ @Override
+ public PageResult getPage(CouponPageReqVO pageReqVO) {
+ return couponMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public List getList(CouponExportReqVO exportReqVO) {
+ return couponMapper.selectList(exportReqVO);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/resources/mapper/CouponTemplete/CouponTempleteMapper.xml b/yudao-module-mall/yudao-module-coupon-biz/src/main/resources/mapper/CouponTemplete/CouponTempleteMapper.xml
new file mode 100644
index 000000000..b7db75a77
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/resources/mapper/CouponTemplete/CouponTempleteMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/yudao-module-mall/yudao-module-coupon-biz/src/main/resources/mapper/coupon/CouponMapper.xml b/yudao-module-mall/yudao-module-coupon-biz/src/main/resources/mapper/coupon/CouponMapper.xml
new file mode 100644
index 000000000..a5e70cf5d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-coupon-biz/src/main/resources/mapper/coupon/CouponMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/yudao-module-mall/yudao-module-market-api/pom.xml b/yudao-module-mall/yudao-module-market-api/pom.xml
index fef3428fc..9517c343f 100644
--- a/yudao-module-mall/yudao-module-market-api/pom.xml
+++ b/yudao-module-mall/yudao-module-market-api/pom.xml
@@ -21,6 +21,13 @@
cn.iocoder.boot
yudao-common
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ true
+
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/PriceApi.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/PriceApi.java
new file mode 100644
index 000000000..532a66dc2
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/PriceApi.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.market.api.price;
+
+import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateReqDTO;
+import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateRespDTO;
+
+/**
+ * 价格 API 接口
+ *
+ * @author 芋道源码
+ */
+public interface PriceApi {
+
+ /**
+ * 计算商品的价格
+ *
+ * @param calculateReqDTO 价格请求
+ * @return 价格相应
+ */
+ PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO);
+
+}
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/dto/PriceCalculateReqDTO.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/dto/PriceCalculateReqDTO.java
new file mode 100644
index 000000000..4cc019651
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/dto/PriceCalculateReqDTO.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.market.api.price.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * 价格计算 Request DTO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class PriceCalculateReqDTO {
+
+ /**
+ * 用户编号
+ *
+ * 对应 MemberUserDO 的 id 编号
+ */
+ private Long userId;
+
+ /**
+ * 优惠劵编号
+ */
+ private Long couponId;
+
+ /**
+ * 商品 SKU 数组
+ */
+ @NotNull(message = "商品数组不能为空")
+ private List- items;
+
+ /**
+ * 商品 SKU
+ */
+ @Data
+ public static class Item {
+
+ /**
+ * SKU 编号
+ */
+ @NotNull(message = "商品 SKU 编号不能为空")
+ private Long skuId;
+
+ /**
+ * SKU 数量
+ */
+ @NotNull(message = "商品 SKU 数量不能为空")
+ @Min(value = 0L, message = "商品 SKU 数量必须大于等于 0") // 可传递 0 数量,用于购物车未选中的情况
+ private Integer count;
+
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/dto/PriceCalculateRespDTO.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/dto/PriceCalculateRespDTO.java
new file mode 100644
index 000000000..dc4f10a10
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/dto/PriceCalculateRespDTO.java
@@ -0,0 +1,202 @@
+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
- items;
+
+ /**
+ * 营销活动数组
+ *
+ * 只对应 {@link #items} 商品匹配的活动
+ */
+ private List 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
- 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;
+
+ }
+
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/activity/MarketActivityStatusEnum.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/activity/MarketActivityStatusEnum.java
deleted file mode 100644
index a02b0269c..000000000
--- a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/activity/MarketActivityStatusEnum.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package cn.iocoder.yudao.module.market.enums.activity;
-
-import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
-
-import java.util.Arrays;
-
-/**
- * 促销活动状态枚举
- */
-public enum MarketActivityStatusEnum implements IntArrayValuable {
-
- WAIT(10, "未开始"),
- RUN(20, "进行中"),
- END(30, "已结束"),
- /**
- * 1. WAIT、RUN、END 可以转换成 INVALID 状态。
- * 2. INVALID 只可以转换成 DELETED 状态。
- */
- INVALID(40, "已撤销"),
- DELETED(50, "已删除"),
- ;
-
- public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MarketActivityStatusEnum::getValue).toArray();
-
- /**
- * 状态值
- */
- private final Integer value;
- /**
- * 状态名
- */
- private final String name;
-
- MarketActivityStatusEnum(Integer value, String name) {
- this.value = value;
- this.name = name;
- }
-
- public Integer getValue() {
- return value;
- }
-
- public String getName() {
- return name;
- }
-
- @Override
- public int[] array() {
- return ARRAYS;
- }
-}
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/activity/MarketActivityTypeEnum.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/activity/MarketActivityTypeEnum.java
deleted file mode 100644
index 0413dba66..000000000
--- a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/activity/MarketActivityTypeEnum.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package cn.iocoder.yudao.module.market.enums.activity;
-
-import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
-
-import java.util.Arrays;
-
-/**
- * 促销活动类型枚举
- */
-public enum MarketActivityTypeEnum implements IntArrayValuable {
-
- TIME_LIMITED_DISCOUNT(1, "限时折扣"),
- FULL_PRIVILEGE(2, "满减送"),
- ;
-
- public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MarketActivityTypeEnum::getValue).toArray();
-
- /**
- * 类型值
- */
- private final Integer value;
- /**
- * 类型名
- */
- private final String name;
-
- MarketActivityTypeEnum(Integer value, String name) {
- this.value = value;
- this.name = name;
- }
-
- public Integer getValue() {
- return value;
- }
-
- public String getName() {
- return name;
- }
-
- @Override
- public int[] array() {
- return ARRAYS;
- }
-}
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionActivityStatusEnum.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionActivityStatusEnum.java
new file mode 100644
index 000000000..9577841aa
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionActivityStatusEnum.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.market.enums.common;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 促销活动的状态枚举
+ *
+ * @author 芋道源码
+ */
+@AllArgsConstructor
+@Getter
+public enum PromotionActivityStatusEnum implements IntArrayValuable {
+
+ WAIT(10, "未开始"),
+ RUN(20, "进行中"),
+ END(30, "已结束"),
+ CLOSE(40, "已关闭");
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionActivityStatusEnum::getStatus).toArray();
+
+ /**
+ * 状态值
+ */
+ private final Integer status;
+ /**
+ * 状态名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionConditionTypeEnum.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionConditionTypeEnum.java
new file mode 100644
index 000000000..4df0e6957
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionConditionTypeEnum.java
@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.market.enums.common;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 营销的条件类型枚举
+ *
+ * @author 芋道源码
+ */
+@AllArgsConstructor
+@Getter
+public enum PromotionConditionTypeEnum implements IntArrayValuable {
+
+ PRICE(10, "满 N 元"),
+ COUNT(20, "满 N 件");
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionConditionTypeEnum::getType).toArray();
+
+ /**
+ * 类型值
+ */
+ private final Integer type;
+ /**
+ * 类型名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionLevelEnum.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionLevelEnum.java
new file mode 100644
index 000000000..25e3f33c2
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionLevelEnum.java
@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.market.enums.common;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 营销的级别枚举
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum PromotionLevelEnum implements IntArrayValuable {
+
+ ORDER(1, "订单级"),
+ SKU(2, "商品级"),
+ ;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionLevelEnum::getLevel).toArray();
+
+ /**
+ * 级别值
+ */
+ private final Integer level;
+ /**
+ * 类型名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionProductScopeEnum.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionProductScopeEnum.java
new file mode 100644
index 000000000..e1792ee67
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionProductScopeEnum.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.market.enums.common;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 营销的商品范围枚举
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum PromotionProductScopeEnum implements IntArrayValuable {
+
+ ALL(1, "全部商品参与"),
+ SPU(2, "指定商品参与"),
+ ;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionProductScopeEnum::getScope).toArray();
+
+ /**
+ * 范围值
+ */
+ private final Integer scope;
+ /**
+ * 范围名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionTypeEnum.java b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionTypeEnum.java
new file mode 100644
index 000000000..f3f5cc882
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/enums/common/PromotionTypeEnum.java
@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.market.enums.common;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 营销类型枚举
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum PromotionTypeEnum implements IntArrayValuable {
+
+ DISCOUNT(1, "限时折扣"),
+ REWARD(2, "满减送"),
+ ;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionTypeEnum::getType).toArray();
+
+ /**
+ * 类型值
+ */
+ private final Integer type;
+ /**
+ * 类型名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/MarketTestController.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/MarketTestController.java
deleted file mode 100644
index 49b83b6c9..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/MarketTestController.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package cn.iocoder.yudao.module.market.controller.admin;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-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.RestController;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
-@Api(tags = "管理后台 - 营销")
-@RestController
-@RequestMapping("/market/test")
-@Validated
-public class MarketTestController {
-
- @GetMapping("/get")
- @ApiOperation("获取 market 信息")
- public CommonResult get() {
- return success("true");
- }
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/ActivityController.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/ActivityController.java
deleted file mode 100644
index dac4211a6..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/ActivityController.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package cn.iocoder.yudao.module.market.controller.admin.activity;
-
-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.market.controller.admin.activity.vo.*;
-import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
-import cn.iocoder.yudao.module.market.convert.activity.ActivityConvert;
-import cn.iocoder.yudao.module.market.service.activity.ActivityService;
-
-@Api(tags = "管理后台 - 促销活动")
-@RestController
-@RequestMapping("/market/activity")
-@Validated
-public class ActivityController {
-
- @Resource
- private ActivityService activityService;
-
- @PostMapping("/create")
- @ApiOperation("创建促销活动")
- @PreAuthorize("@ss.hasPermission('market:activity:create')")
- public CommonResult createActivity(@Valid @RequestBody ActivityCreateReqVO createReqVO) {
- return success(activityService.createActivity(createReqVO));
- }
-
- @PutMapping("/update")
- @ApiOperation("更新促销活动")
- @PreAuthorize("@ss.hasPermission('market:activity:update')")
- public CommonResult updateActivity(@Valid @RequestBody ActivityUpdateReqVO updateReqVO) {
- activityService.updateActivity(updateReqVO);
- return success(true);
- }
-
- @DeleteMapping("/delete")
- @ApiOperation("删除促销活动")
- @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
- @PreAuthorize("@ss.hasPermission('market:activity:delete')")
- public CommonResult deleteActivity(@RequestParam("id") Long id) {
- activityService.deleteActivity(id);
- return success(true);
- }
-
- @GetMapping("/get")
- @ApiOperation("获得促销活动")
- @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
- @PreAuthorize("@ss.hasPermission('market:activity:query')")
- public CommonResult getActivity(@RequestParam("id") Long id) {
- ActivityDO activity = activityService.getActivity(id);
- return success(ActivityConvert.INSTANCE.convert(activity));
- }
-
- @GetMapping("/list")
- @ApiOperation("获得促销活动列表")
- @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
- @PreAuthorize("@ss.hasPermission('market:activity:query')")
- public CommonResult
> getActivityList(@RequestParam("ids") Collection ids) {
- List list = activityService.getActivityList(ids);
- return success(ActivityConvert.INSTANCE.convertList(list));
- }
-
- @GetMapping("/page")
- @ApiOperation("获得促销活动分页")
- @PreAuthorize("@ss.hasPermission('market:activity:query')")
- public CommonResult> getActivityPage(@Valid ActivityPageReqVO pageVO) {
- PageResult pageResult = activityService.getActivityPage(pageVO);
- return success(ActivityConvert.INSTANCE.convertPage(pageResult));
- }
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityBaseVO.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityBaseVO.java
deleted file mode 100644
index 3ae5cd679..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityBaseVO.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package cn.iocoder.yudao.module.market.controller.admin.activity.vo;
-
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.market.enums.activity.MarketActivityStatusEnum;
-import cn.iocoder.yudao.module.market.enums.activity.MarketActivityTypeEnum;
-import lombok.*;
-import java.util.*;
-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 ActivityBaseVO {
-
- @ApiModelProperty(value = "活动标题", required = true)
- @NotNull(message = "活动标题不能为空")
- private String title;
-
- @ApiModelProperty(value = "活动类型", required = true)
- @NotNull(message = "活动类型不能为空")
- @InEnum(MarketActivityTypeEnum.class)
- private Integer activityType;
-
- @ApiModelProperty(value = "活动状态", required = true)
- @NotNull(message = "活动状态不能为空")
- @InEnum(MarketActivityStatusEnum.class)
- private Integer status;
-
- @ApiModelProperty(value = "开始时间", required = true)
- @NotNull(message = "开始时间不能为空")
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- private Date startTime;
-
- @ApiModelProperty(value = "结束时间", required = true)
- @NotNull(message = "结束时间不能为空")
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- private Date endTime;
-
- @ApiModelProperty(value = "失效时间")
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- private Date invalidTime;
-
- @ApiModelProperty(value = "删除时间")
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- private Date deleteTime;
-
- @ApiModelProperty(value = "限制折扣字符串,使用 JSON 序列化成字符串存储")
- private String timeLimitedDiscount;
-
- @ApiModelProperty(value = "限制折扣字符串,使用 JSON 序列化成字符串存储")
- private String fullPrivilege;
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityCreateReqVO.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityCreateReqVO.java
deleted file mode 100644
index 0ca112709..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityCreateReqVO.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package cn.iocoder.yudao.module.market.controller.admin.activity.vo;
-
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
-
-/**
- * @author xia
- */
-@ApiModel("管理后台 - 促销活动创建 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ActivityCreateReqVO extends ActivityBaseVO {
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityPageReqVO.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityPageReqVO.java
deleted file mode 100644
index 9543d8fee..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityPageReqVO.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package cn.iocoder.yudao.module.market.controller.admin.activity.vo;
-
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.market.enums.activity.MarketActivityStatusEnum;
-import cn.iocoder.yudao.module.market.enums.activity.MarketActivityTypeEnum;
-import lombok.*;
-import java.util.*;
-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 ActivityPageReqVO extends PageParam {
-
- @ApiModelProperty(value = "活动标题")
- private String title;
-
- @ApiModelProperty(value = "活动类型")
- @InEnum(MarketActivityTypeEnum.class)
- private Integer activityType;
-
- @ApiModelProperty(value = "活动状态")
- @InEnum(MarketActivityStatusEnum.class)
- private Integer status;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "开始时间")
- private Date[] startTime;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "结束时间")
- private Date[] endTime;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "失效时间")
- private Date[] invalidTime;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "删除时间")
- private Date[] deleteTime;
-
- @ApiModelProperty(value = "限制折扣字符串,使用 JSON 序列化成字符串存储")
- private String timeLimitedDiscount;
-
- @ApiModelProperty(value = "限制折扣字符串,使用 JSON 序列化成字符串存储")
- private String fullPrivilege;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "创建时间")
- private Date[] createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityUpdateReqVO.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityUpdateReqVO.java
deleted file mode 100644
index 1db24f259..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/activity/vo/ActivityUpdateReqVO.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package cn.iocoder.yudao.module.market.controller.admin.activity.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 ActivityUpdateReqVO extends ActivityBaseVO {
-
- @ApiModelProperty(value = "活动编号", required = true)
- @NotNull(message = "活动编号不能为空")
- private Long id;
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/discount/package-info.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/discount/package-info.java
new file mode 100644
index 000000000..a3f145f26
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/controller/admin/discount/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * TODO 占位
+ */
+package cn.iocoder.yudao.module.market.controller.admin.discount;
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/convert/activity/ActivityConvert.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/convert/activity/ActivityConvert.java
deleted file mode 100644
index 64ba73975..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/convert/activity/ActivityConvert.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package cn.iocoder.yudao.module.market.convert.activity;
-
-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.market.controller.admin.activity.vo.*;
-import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
-
-/**
- * 促销活动 Convert
- *
- * @author 芋道源码
- */
-@Mapper
-public interface ActivityConvert {
-
- ActivityConvert INSTANCE = Mappers.getMapper(ActivityConvert.class);
-
- ActivityDO convert(ActivityCreateReqVO bean);
-
- ActivityDO convert(ActivityUpdateReqVO bean);
-
- ActivityRespVO convert(ActivityDO bean);
-
- List convertList(List list);
-
- PageResult convertPage(PageResult page);
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/convert/discount/package-info.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/convert/discount/package-info.java
new file mode 100644
index 000000000..787492406
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/convert/discount/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * TODO 占位
+ */
+package cn.iocoder.yudao.module.market.convert.discount;
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/activity/ActivityDO.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/activity/ActivityDO.java
deleted file mode 100644
index 13dcbf67c..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/activity/ActivityDO.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package cn.iocoder.yudao.module.market.dal.dataobject.activity;
-
-import lombok.*;
-import java.util.*;
-import com.baomidou.mybatisplus.annotation.*;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-
-/**
- * 促销活动 DO
- *
- * @author 芋道源码
- */
-@TableName("market_activity")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class ActivityDO extends BaseDO {
-
- /**
- * 活动编号
- */
- @TableId
- private Long id;
- /**
- * 活动标题
- */
- private String title;
- /**
- * 活动类型MarketActivityTypeEnum
- */
- private Integer activityType;
- /**
- * 活动状态MarketActivityStatusEnum
- */
- private Integer status;
- /**
- * 开始时间
- */
- private Date startTime;
- /**
- * 结束时间
- */
- private Date endTime;
- /**
- * 失效时间
- */
- private Date invalidTime;
- /**
- * 删除时间
- */
- private Date deleteTime;
- /**
- * 限制折扣字符串,使用 JSON 序列化成字符串存储
- */
- private String timeLimitedDiscount;
- /**
- * 限制折扣字符串,使用 JSON 序列化成字符串存储
- */
- private String fullPrivilege;
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/discount/DiscountActivityDO.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/discount/DiscountActivityDO.java
new file mode 100644
index 000000000..8780546f6
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/discount/DiscountActivityDO.java
@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.market.dal.dataobject.discount;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.market.enums.common.PromotionActivityStatusEnum;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 限时折扣活动 DO
+ *
+ * 一个活动下,可以有 {@link DiscountProductDO} 商品;
+ * 一个商品,在指定时间段内,只能属于一个活动;
+ *
+ * @author 芋道源码
+ */
+@TableName(value = "promotion_discount_activity", autoResultMap = true)
+@KeySequence("promotion_discount_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class DiscountActivityDO extends BaseDO {
+
+ /**
+ * 活动编号,主键自增
+ */
+ @TableId
+ private Long id;
+ /**
+ * 活动标题
+ */
+ private String name;
+ /**
+ * 状态
+ *
+ * 枚举 {@link PromotionActivityStatusEnum}
+ */
+ private Integer status;
+ /**
+ * 开始时间
+ */
+ private Date startTime;
+ /**
+ * 结束时间
+ */
+ private Date endTime;
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/discount/DiscountProductDO.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/discount/DiscountProductDO.java
new file mode 100644
index 000000000..cd73a19a5
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/discount/DiscountProductDO.java
@@ -0,0 +1,65 @@
+package cn.iocoder.yudao.module.market.dal.dataobject.discount;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 限时折扣商品 DO
+ *
+ * @author 芋道源码
+ */
+@TableName(value = "promotion_discount_product", autoResultMap = true)
+@KeySequence("promotion_discount_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class DiscountProductDO extends BaseDO {
+
+ /**
+ * 编号,主键自增
+ */
+ @TableId
+ private Long id;
+ /**
+ * 限时折扣活动的编号
+ *
+ * 关联 {@link DiscountActivityDO#getId()}
+ */
+ private Long activityId;
+ /**
+ * 商品 SPU 编号
+ *
+ * 关联 ProductSpuDO 的 id 编号
+ */
+ private Long spuId;
+ /**
+ * 商品 SKU 编号
+ *
+ * 关联 ProductSkuDO 的 id 编号
+ */
+ private Long skuId;
+ /**
+ * 开始时间
+ */
+ private Date startTime;
+ /**
+ * 结束时间
+ */
+ private Date endTime;
+ /**
+ * 销售价格,单位:分
+ *
+ * 冗余 ProductSkuDO 的 price 字段
+ */
+ private Integer originalPrice;
+ /**
+ * 优惠价格,单位:分
+ */
+ private Integer promotionPrice;
+
+}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/reward/RewardActivityDO.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/reward/RewardActivityDO.java
new file mode 100644
index 000000000..85cd8c955
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/reward/RewardActivityDO.java
@@ -0,0 +1,116 @@
+package cn.iocoder.yudao.module.market.dal.dataobject.reward;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.market.enums.common.PromotionActivityStatusEnum;
+import cn.iocoder.yudao.module.market.enums.common.PromotionConditionTypeEnum;
+import cn.iocoder.yudao.module.market.enums.common.PromotionProductScopeEnum;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 满减送活动 DO
+ *
+ * @author 芋道源码
+ */
+@TableName(value = "promotion_reward_activity", autoResultMap = true)
+@KeySequence("promotion_reward_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class RewardActivityDO extends BaseDO {
+
+ /**
+ * 活动编号,主键自增
+ */
+ @TableId
+ private Long id;
+ /**
+ * 活动标题
+ */
+ private String name;
+ /**
+ * 状态
+ *
+ * 枚举 {@link PromotionActivityStatusEnum}
+ */
+ private Integer status;
+ /**
+ * 开始时间
+ */
+ private Date startTime;
+ /**
+ * 结束时间
+ */
+ private Date endTime;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 条件类型
+ *
+ * 枚举 {@link PromotionConditionTypeEnum}
+ */
+ private Integer conditionType;
+ /**
+ * 商品范围
+ *
+ * 枚举 {@link PromotionProductScopeEnum}
+ */
+ private Integer productScope;
+ /**
+ * 商品 SPU 编号的数组
+ */
+ @TableField(typeHandler = JacksonTypeHandler.class)
+ private List spuIds;
+ /**
+ * 优惠规则的数组
+ */
+ @TableField(typeHandler = JacksonTypeHandler.class)
+ private List rules;
+
+ /**
+ * 优惠规则
+ */
+ @Data
+ public static class Rule {
+
+ /**
+ * 优惠门槛
+ *
+ * 1. 满 N 元,单位:分
+ * 2. 满 N 件
+ */
+ private Integer limit;
+ /**
+ * 优惠价格,单位:分
+ */
+ private Integer promotionPrice;
+ /**
+ * 是否包邮
+ */
+ private Boolean freeDelivery;
+ /**
+ * 赠送的积分
+ */
+ private Integer integral;
+ /**
+ * 赠送的优惠劵编号的数组
+ */
+ private List couponIds;
+ /**
+ * 赠送的优惠卷数量的数组
+ */
+ private List couponCounts;
+
+ }
+
+
+}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/mysql/activity/ActivityMapper.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/mysql/activity/ActivityMapper.java
deleted file mode 100644
index feb3fb122..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/mysql/activity/ActivityMapper.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package cn.iocoder.yudao.module.market.dal.mysql.activity;
-
-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.market.dal.dataobject.activity.ActivityDO;
-import org.apache.ibatis.annotations.Mapper;
-import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
-
-/**
- * 促销活动 Mapper
- *
- * @author 芋道源码
- */
-@Mapper
-public interface ActivityMapper extends BaseMapperX {
-
- default PageResult selectPage(ActivityPageReqVO reqVO) {
- return selectPage(reqVO, new LambdaQueryWrapperX()
- .eqIfPresent(ActivityDO::getTitle, reqVO.getTitle())
- .eqIfPresent(ActivityDO::getActivityType, reqVO.getActivityType())
- .eqIfPresent(ActivityDO::getStatus, reqVO.getStatus())
- .betweenIfPresent(ActivityDO::getStartTime, reqVO.getStartTime())
- .betweenIfPresent(ActivityDO::getEndTime, reqVO.getEndTime())
- .betweenIfPresent(ActivityDO::getInvalidTime, reqVO.getInvalidTime())
- .betweenIfPresent(ActivityDO::getDeleteTime, reqVO.getDeleteTime())
- .eqIfPresent(ActivityDO::getTimeLimitedDiscount, reqVO.getTimeLimitedDiscount())
- .eqIfPresent(ActivityDO::getFullPrivilege, reqVO.getFullPrivilege())
- .betweenIfPresent(ActivityDO::getCreateTime, reqVO.getCreateTime())
- .orderByDesc(ActivityDO::getId));
- }
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/mysql/discount/package-info.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/mysql/discount/package-info.java
new file mode 100644
index 000000000..f8de42cd9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/mysql/discount/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * TODO 占位
+ */
+package cn.iocoder.yudao.module.market.dal.mysql.discount;
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/package-info.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/package-info.java
index 2efde4ec7..92b9c698d 100644
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/package-info.java
+++ b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/package-info.java
@@ -1,8 +1,8 @@
/**
- * market 模块,我们放营销业务。
+ * promotion 模块,我们放营销业务。
* 例如说:营销活动、banner、优惠券等等
*
- * 1. Controller URL:以 /market/ 开头,避免和其它 Module 冲突
- * 2. DataObject 表名:以 market_ 开头,方便在数据库中区分
+ * 1. Controller URL:以 /promotion/ 开头,避免和其它 Module 冲突
+ * 2. DataObject 表名:以 promotion_ 开头,方便在数据库中区分
*/
package cn.iocoder.yudao.module.market;
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/activity/ActivityService.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/activity/ActivityService.java
deleted file mode 100644
index 1d5e27857..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/activity/ActivityService.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package cn.iocoder.yudao.module.market.service.activity;
-
-import java.util.*;
-import javax.validation.*;
-import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
-import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-/**
- * 促销活动 Service 接口
- *
- * @author 芋道源码
- */
-public interface ActivityService {
-
- /**
- * 创建促销活动
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createActivity(@Valid ActivityCreateReqVO createReqVO);
-
- /**
- * 更新促销活动
- *
- * @param updateReqVO 更新信息
- */
- void updateActivity(@Valid ActivityUpdateReqVO updateReqVO);
-
- /**
- * 删除促销活动
- *
- * @param id 编号
- */
- void deleteActivity(Long id);
-
- /**
- * 获得促销活动
- *
- * @param id 编号
- * @return 促销活动
- */
- ActivityDO getActivity(Long id);
-
- /**
- * 获得促销活动列表
- *
- * @param ids 编号
- * @return 促销活动列表
- */
- List getActivityList(Collection ids);
-
- /**
- * 获得促销活动分页
- *
- * @param pageReqVO 分页查询
- * @return 促销活动分页
- */
- PageResult getActivityPage(ActivityPageReqVO pageReqVO);
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/activity/ActivityServiceImpl.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/activity/ActivityServiceImpl.java
deleted file mode 100644
index 57bb9af53..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/activity/ActivityServiceImpl.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package cn.iocoder.yudao.module.market.service.activity;
-
-import org.springframework.stereotype.Service;
-import javax.annotation.Resource;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.*;
-import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
-import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import cn.iocoder.yudao.module.market.convert.activity.ActivityConvert;
-import cn.iocoder.yudao.module.market.dal.mysql.activity.ActivityMapper;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.market.enums.ErrorCodeConstants.*;
-
-/**
- * 促销活动 Service 实现类
- *
- * @author 芋道源码
- */
-@Service
-@Validated
-public class ActivityServiceImpl implements ActivityService {
-
- @Resource
- private ActivityMapper activityMapper;
-
- @Override
- public Long createActivity(ActivityCreateReqVO createReqVO) {
- // 插入
- ActivityDO activity = ActivityConvert.INSTANCE.convert(createReqVO);
- activityMapper.insert(activity);
- // 返回
- return activity.getId();
- }
-
- @Override
- public void updateActivity(ActivityUpdateReqVO updateReqVO) {
- // 校验存在
- this.validateActivityExists(updateReqVO.getId());
- // 更新
- ActivityDO updateObj = ActivityConvert.INSTANCE.convert(updateReqVO);
- activityMapper.updateById(updateObj);
- }
-
- @Override
- public void deleteActivity(Long id) {
- // 校验存在
- this.validateActivityExists(id);
- // 删除
- activityMapper.deleteById(id);
- }
-
- private void validateActivityExists(Long id) {
- if (activityMapper.selectById(id) == null) {
- throw exception(ACTIVITY_NOT_EXISTS);
- }
- }
-
- @Override
- public ActivityDO getActivity(Long id) {
- return activityMapper.selectById(id);
- }
-
- @Override
- public List getActivityList(Collection ids) {
- return activityMapper.selectBatchIds(ids);
- }
-
- @Override
- public PageResult getActivityPage(ActivityPageReqVO pageReqVO) {
- return activityMapper.selectPage(pageReqVO);
- }
-
-}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/discount/package-info.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/discount/package-info.java
new file mode 100644
index 000000000..f52febd44
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/discount/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * TODO 占位
+ */
+package cn.iocoder.yudao.module.market.service.discount;
diff --git a/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/price/PriceApiImpl.java b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/price/PriceApiImpl.java
new file mode 100644
index 000000000..6b8663d1e
--- /dev/null
+++ b/yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/price/PriceApiImpl.java
@@ -0,0 +1,24 @@
+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();
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-market-biz/src/test/java/cn/iocoder/yudao/module/market/service/activity/ActivityServiceImplTest.java b/yudao-module-mall/yudao-module-market-biz/src/test/java/cn/iocoder/yudao/module/market/service/activity/ActivityServiceImplTest.java
deleted file mode 100644
index b292251a4..000000000
--- a/yudao-module-mall/yudao-module-market-biz/src/test/java/cn/iocoder/yudao/module/market/service/activity/ActivityServiceImplTest.java
+++ /dev/null
@@ -1,197 +0,0 @@
-package cn.iocoder.yudao.module.market.service.activity;
-
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import javax.annotation.Resource;
-
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-
-import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
-import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
-import cn.iocoder.yudao.module.market.dal.mysql.activity.ActivityMapper;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import org.springframework.context.annotation.Import;
-
-import static cn.iocoder.yudao.module.market.enums.ErrorCodeConstants.*;
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
-* {@link ActivityServiceImpl} 的单元测试类
-*
-* @author 芋道源码
-*/
-@Import(ActivityServiceImpl.class)
-public class ActivityServiceImplTest extends BaseDbUnitTest {
-
- @Resource
- private ActivityServiceImpl activityService;
-
- @Resource
- private ActivityMapper activityMapper;
-
- @Test
- public void testCreateActivity_success() {
- // 准备参数
- ActivityCreateReqVO reqVO = randomPojo(ActivityCreateReqVO.class);
-
- // 调用
- Long activityId = activityService.createActivity(reqVO);
- // 断言
- assertNotNull(activityId);
- // 校验记录的属性是否正确
- ActivityDO activity = activityMapper.selectById(activityId);
- assertPojoEquals(reqVO, activity);
- }
-
- @Test
- public void testUpdateActivity_success() {
- // mock 数据
- ActivityDO dbActivity = randomPojo(ActivityDO.class);
- activityMapper.insert(dbActivity);// @Sql: 先插入出一条存在的数据
- // 准备参数
- ActivityUpdateReqVO reqVO = randomPojo(ActivityUpdateReqVO.class, o -> {
- o.setId(dbActivity.getId()); // 设置更新的 ID
- });
-
- // 调用
- activityService.updateActivity(reqVO);
- // 校验是否更新正确
- ActivityDO activity = activityMapper.selectById(reqVO.getId()); // 获取最新的
- assertPojoEquals(reqVO, activity);
- }
-
- @Test
- public void testUpdateActivity_notExists() {
- // 准备参数
- ActivityUpdateReqVO reqVO = randomPojo(ActivityUpdateReqVO.class);
-
- // 调用, 并断言异常
- assertServiceException(() -> activityService.updateActivity(reqVO), ACTIVITY_NOT_EXISTS);
- }
-
- @Test
- public void testDeleteActivity_success() {
- // mock 数据
- ActivityDO dbActivity = randomPojo(ActivityDO.class);
- activityMapper.insert(dbActivity);// @Sql: 先插入出一条存在的数据
- // 准备参数
- Long id = dbActivity.getId();
-
- // 调用
- activityService.deleteActivity(id);
- // 校验数据不存在了
- assertNull(activityMapper.selectById(id));
- }
-
- @Test
- public void testDeleteActivity_notExists() {
- // 准备参数
- Long id = randomLongId();
-
- // 调用, 并断言异常
- assertServiceException(() -> activityService.deleteActivity(id), ACTIVITY_NOT_EXISTS);
- }
-
- @Test
- @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
- public void testGetActivityPage() {
- // mock 数据
- ActivityDO dbActivity = randomPojo(ActivityDO.class, o -> { // 等会查询到
- o.setTitle(null);
- o.setActivityType(null);
- o.setStatus(null);
- o.setStartTime(null);
- o.setEndTime(null);
- o.setInvalidTime(null);
- o.setDeleteTime(null);
- o.setTimeLimitedDiscount(null);
- o.setFullPrivilege(null);
- o.setCreateTime(null);
- });
- activityMapper.insert(dbActivity);
- // 测试 title 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setTitle(null)));
- // 测试 activityType 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setActivityType(null)));
- // 测试 status 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setStatus(null)));
- // 测试 startTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setStartTime(null)));
- // 测试 endTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setEndTime(null)));
- // 测试 invalidTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setInvalidTime(null)));
- // 测试 deleteTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setDeleteTime(null)));
- // 测试 timeLimitedDiscount 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setTimeLimitedDiscount(null)));
- // 测试 fullPrivilege 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setFullPrivilege(null)));
- // 测试 createTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setCreateTime(null)));
- // 准备参数
- ActivityPageReqVO reqVO = new ActivityPageReqVO();
- reqVO.setTitle(null);
- reqVO.setActivityType(null);
- reqVO.setStatus(null);
- reqVO.setStartTime(null);
- reqVO.setEndTime(null);
- reqVO.setInvalidTime(null);
- reqVO.setDeleteTime(null);
- reqVO.setTimeLimitedDiscount(null);
- reqVO.setFullPrivilege(null);
- reqVO.setCreateTime(null);
-
- // 调用
- PageResult pageResult = activityService.getActivityPage(reqVO);
- // 断言
- assertEquals(1, pageResult.getTotal());
- assertEquals(1, pageResult.getList().size());
- assertPojoEquals(dbActivity, pageResult.getList().get(0));
- }
-
- @Test
- @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
- public void testGetActivityList() {
- // mock 数据
- ActivityDO dbActivity = randomPojo(ActivityDO.class, o -> { // 等会查询到
- o.setTitle(null);
- o.setActivityType(null);
- o.setStatus(null);
- o.setStartTime(null);
- o.setEndTime(null);
- o.setInvalidTime(null);
- o.setDeleteTime(null);
- o.setTimeLimitedDiscount(null);
- o.setFullPrivilege(null);
- o.setCreateTime(null);
- });
- activityMapper.insert(dbActivity);
- // 测试 title 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setTitle(null)));
- // 测试 activityType 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setActivityType(null)));
- // 测试 status 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setStatus(null)));
- // 测试 startTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setStartTime(null)));
- // 测试 endTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setEndTime(null)));
- // 测试 invalidTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setInvalidTime(null)));
- // 测试 deleteTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setDeleteTime(null)));
- // 测试 timeLimitedDiscount 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setTimeLimitedDiscount(null)));
- // 测试 fullPrivilege 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setFullPrivilege(null)));
- // 测试 createTime 不匹配
- activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setCreateTime(null)));
- }
-
-}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
new file mode 100644
index 000000000..b3915407f
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
@@ -0,0 +1,30 @@
+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.SkuInfoRespDTO;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author LeeYan9
+ * @since 2022-08-26
+ */
+public interface ProductSkuApi {
+
+
+ /**
+ * 根据skuId列表 查询sku信息
+ *
+ * @param skuIds sku ID列表
+ * @return sku信息列表
+ */
+ List getSkusByIds(Collection skuIds);
+
+ /**
+ * 批量扣减sku库存
+ *
+ * @param batchReqDTO sku库存信息列表
+ */
+ void decrementStockBatch(SkuDecrementStockBatchReqDTO batchReqDTO);
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/SkuDecrementStockBatchReqDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/SkuDecrementStockBatchReqDTO.java
new file mode 100644
index 000000000..c0cee91ba
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/SkuDecrementStockBatchReqDTO.java
@@ -0,0 +1,45 @@
+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- items;
+
+ @Data
+ public static class Item {
+
+ /**
+ * 商品 SPU 编号,自增
+ */
+ private Long productId;
+
+ /**
+ * 商品 SKU 编号,自增
+ */
+ private Long skuId;
+
+ /**
+ * 数量
+ */
+ private Integer count;
+
+ }
+
+ public static SkuDecrementStockBatchReqDTO of(List
- items) {
+ return new SkuDecrementStockBatchReqDTO(items);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/SkuInfoRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/SkuInfoRespDTO.java
new file mode 100644
index 000000000..f9d349e48
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/SkuInfoRespDTO.java
@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.product.api.sku.dto;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author LeeYan9
+ * @since 2022-08-26
+ */
+@Data
+public class SkuInfoRespDTO {
+
+ /**
+ * 商品 SKU 编号,自增
+ */
+ private Long id;
+ /**
+ * 商品 SKU 名字
+ */
+ private String name;
+ /**
+ * SPU 编号
+ */
+ private Long spuId;
+
+ /**
+ * 规格值数组,JSON 格式
+ */
+ private List properties;
+ /**
+ * 销售价格,单位:分
+ */
+ private Integer price;
+ /**
+ * 市场价,单位:分
+ */
+ private Integer marketPrice;
+ /**
+ * 成本价,单位:分
+ */
+ private Integer costPrice;
+ /**
+ * SKU 的条形码
+ */
+ private String barCode;
+ /**
+ * 图片地址
+ */
+ private String picUrl;
+ /**
+ * SKU 状态
+ *
+ * 枚举 {@link CommonStatusEnum}
+ */
+ private Integer status;
+ /**
+ * 库存
+ */
+ private Integer stock;
+ /**
+ * 预警预存
+ */
+ private Integer warnStock;
+ /**
+ * 商品重量,单位:kg 千克
+ */
+ private Double weight;
+ /**
+ * 商品体积,单位:m^3 平米
+ */
+ private Double volume;
+
+ /**
+ * 商品属性
+ */
+ @Data
+ public static class Property {
+
+ /**
+ * 属性编号
+ */
+ private Long propertyId;
+ /**
+ * 属性值编号
+ */
+ private Long valueId;
+
+ }
+
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java
new file mode 100644
index 000000000..5dc2bf4cf
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java
@@ -0,0 +1,23 @@
+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.SpuInfoRespDTO;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author LeeYan9
+ * @since 2022-08-26
+ */
+public interface ProductSpuApi {
+
+
+ /**
+ * 根据spuId列表 查询spu信息
+ *
+ * @param spuIds spu ID列表
+ * @return spu信息列表
+ */
+ List getSpusByIds(Collection spuIds);
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/SpuInfoRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/SpuInfoRespDTO.java
new file mode 100644
index 000000000..6d0206b7d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/SpuInfoRespDTO.java
@@ -0,0 +1,124 @@
+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.enums.spu.ProductSpuSpecTypeEnum;
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author LeeYan9
+ * @since 2022-08-26
+ */
+@Data
+public class SpuInfoRespDTO {
+
+ /**
+ * 商品 SPU 编号,自增
+ */
+ private Long id;
+
+ // ========== 基本信息 =========
+
+ /**
+ * 商品名称
+ */
+ private String name;
+ /**
+ * 商品编码
+ */
+ private String code;
+ /**
+ * 商品卖点
+ */
+ private String sellPoint;
+ /**
+ * 商品详情
+ */
+ private String description;
+ /**
+ * 商品分类编号
+ */
+ private Long categoryId;
+ /**
+ * 商品品牌编号
+ */
+ private Long brandId;
+ /**
+ * 商品图片的数组
+ *
+ * 1. 第一张图片将作为商品主图,支持同时上传多张图;
+ * 2. 建议使用尺寸 800x800 像素以上、大小不超过 1M 的正方形图片;
+ * 3. 至少 1 张,最多上传 10 张
+ */
+ private List picUrls;
+ /**
+ * 商品视频
+ */
+ private String videoUrl;
+
+ /**
+ * 排序字段
+ */
+ private Integer sort;
+ /**
+ * 商品状态
+ *
+ * 枚举 {@link ProductSpuStatusEnum}
+ */
+ private Integer status;
+
+ // ========== SKU 相关字段 =========
+
+ /**
+ * 规格类型
+ *
+ * 枚举 {@link ProductSpuSpecTypeEnum}
+ */
+ private Integer specType;
+ /**
+ * 最小价格,单位使用:分
+ *
+ * 基于其对应的 {@link SkuInfoRespDTO#getPrice()} 最小值
+ */
+ private Integer minPrice;
+ /**
+ * 最大价格,单位使用:分
+ *
+ * 基于其对应的 {@link SkuInfoRespDTO#getPrice()} 最大值
+ */
+ private Integer maxPrice;
+ /**
+ * 市场价,单位使用:分
+ *
+ * 基于其对应的 {@link SkuInfoRespDTO#getMarketPrice()} 最大值
+ */
+ private Integer marketPrice;
+ /**
+ * 总库存
+ *
+ * 基于其对应的 {@link SkuInfoRespDTO#getStock()} 求和
+ */
+ private Integer totalStock;
+ /**
+ * 是否展示库存
+ */
+ private Boolean showStock;
+
+ // ========== 统计相关字段 =========
+
+ /**
+ * 商品销量
+ */
+ private Integer salesCount;
+ /**
+ * 虚拟销量
+ */
+ private Integer virtualSalesCount;
+ /**
+ * 商品点击量
+ */
+ private Integer clickCount;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
index e328d2512..801e2dd51 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -3,30 +3,38 @@ package cn.iocoder.yudao.module.product.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
- * product 错误码枚举类
- *
+ * Product 错误码枚举类
+ *
* product 系统,使用 1-008-000-000 段
*/
public interface ErrorCodeConstants {
- // ========== 商品分类相关 1008001000============
+ // ========== 商品分类相关 1008001000 ============
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
- ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001002, "存在子分类,无法删除");
+ ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
+ ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
+ ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
+ ErrorCode CATEGORY_LEVEL_ERROR = new ErrorCode(1008001005, "商品分类不正确,原因:必须使用第三级的商品分类下");
- // ========== 品牌相关编号 1008002000 ==========
+ // ========== 商品品牌相关编号 1008002000 ==========
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
+ ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在");
+ ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
- // ========== 规格名称 1008003000 ==========
+ // ========== 商品规格名称 1008003000 ==========
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在");
// ========== 规格值 1008004000 ==========
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在");
- // ========== 商品spu 1008005000 ==========
- ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品spu不存在");
+ // ========== 商品 SPU 1008005000 ==========
+ ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
+
+ // ========== 商品 SKU 1008006000 ==========
+ ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
+ ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
+ ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其规格数必须一致");
+ ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
- // ========== 商品sku 1008006000 ==========
- ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品sku不存在");
- ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品sku的属性组合存在重复");
}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java
new file mode 100644
index 000000000..276839daf
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.product.enums.comment;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 商品评论的审批状态枚举
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum ProductCommentAuditStatusEnum implements IntArrayValuable {
+
+ NONE(1, "待审核"),
+ APPROVE(2, "审批通过"),
+ REJECT(2, "审批不通过"),;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductCommentAuditStatusEnum::getStatus).toArray();
+
+ /**
+ * 审批状态
+ */
+ private final Integer status;
+ /**
+ * 状态名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/delivery/DeliveryTypeEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/delivery/DeliveryTypeEnum.java
new file mode 100644
index 000000000..da322ff24
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/delivery/DeliveryTypeEnum.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.product.enums.delivery;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 配送方式枚举
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum DeliveryTypeEnum implements IntArrayValuable {
+
+ // TODO 芋艿:英文单词,需要再想下;
+ EXPRESS(1, "快递发货"),
+ USER(2, "用户自提"),;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DeliveryTypeEnum::getMode).toArray();
+
+ /**
+ * 配送方式
+ */
+ private final Integer mode;
+ /**
+ * 状态名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/group/ProductGroupStyleEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/group/ProductGroupStyleEnum.java
new file mode 100644
index 000000000..c5e55e8e4
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/group/ProductGroupStyleEnum.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.product.enums.group;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 商品分组的样式枚举
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum ProductGroupStyleEnum implements IntArrayValuable {
+
+ ONE(1, "每列一个"),
+ TWO(2, "每列两个"),
+ THREE(2, "每列三个"),;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductGroupStyleEnum::getStyle).toArray();
+
+ /**
+ * 列表样式
+ */
+ private final Integer style;
+ /**
+ * 状态名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
new file mode 100644
index 000000000..30ece744d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.product.enums.spu;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 商品 SPU 规格类型
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum ProductSpuSpecTypeEnum implements IntArrayValuable {
+
+ RECYCLE(1, "统一规格"),
+ DISABLE(2, "多规格");
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuSpecTypeEnum::getType).toArray();
+
+ /**
+ * 规格
+ */
+ private final Integer type;
+ /**
+ * 规格名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
new file mode 100644
index 000000000..1757f1e49
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.product.enums.spu;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 商品 SPU 状态
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum ProductSpuStatusEnum implements IntArrayValuable {
+
+ RECYCLE(-1, "回收站"),
+ DISABLE(0, "下架"),
+ ENABLE(1, "上架"),;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuStatusEnum::getStyle).toArray();
+
+ /**
+ * 状态
+ */
+ private final Integer style;
+ /**
+ * 状态名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/pom.xml b/yudao-module-mall/yudao-module-product-biz/pom.xml
index a06f8937c..bb9a36f94 100644
--- a/yudao-module-mall/yudao-module-product-biz/pom.xml
+++ b/yudao-module-mall/yudao-module-product-biz/pom.xml
@@ -2,13 +2,12 @@
- 4.0.0
cn.iocoder.boot
yudao-module-mall
${revision}
-
+ 4.0.0
yudao-module-product-biz
jar
@@ -18,7 +17,6 @@
例如:品牌、商品分类、spu、sku等功能。
-
cn.iocoder.boot
@@ -31,10 +29,6 @@
cn.iocoder.boot
yudao-spring-boot-starter-biz-operatelog
-
- cn.iocoder.boot
- yudao-spring-boot-starter-biz-weixin
-
cn.iocoder.boot
yudao-spring-boot-starter-biz-tenant
@@ -64,4 +58,4 @@
-
\ No newline at end of file
+
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java
new file mode 100644
index 000000000..162453c3c
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java
@@ -0,0 +1 @@
+package cn.iocoder.yudao.module.product.api;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
new file mode 100644
index 000000000..22636826b
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
@@ -0,0 +1,26 @@
+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.SkuInfoRespDTO;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * todo 注释
+ */
+@Service
+public class ProductSkuApiImpl implements ProductSkuApi {
+
+ @Override
+ public List getSkusByIds(Collection skuIds) {
+ return null;
+ }
+
+ @Override
+ public void decrementStockBatch(SkuDecrementStockBatchReqDTO batchReqDTO) {
+
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
new file mode 100644
index 000000000..8f651f395
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.product.api.spu;
+
+import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * todo 注释
+ */
+@Service
+public class ProductSpuApiImpl implements ProductSpuApi {
+
+ @Override
+ public List getSpusByIds(Collection spuIds) {
+ return null;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/BrandController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java
similarity index 53%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/BrandController.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java
index 0702d206c..2227afeaf 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/BrandController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java
@@ -2,12 +2,10 @@ package cn.iocoder.yudao.module.product.controller.admin.brand;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*;
-import cn.iocoder.yudao.module.product.convert.brand.BrandConvert;
-import cn.iocoder.yudao.module.product.dal.dataobject.brand.BrandDO;
-import cn.iocoder.yudao.module.product.service.brand.BrandService;
+import cn.iocoder.yudao.module.product.convert.brand.ProductBrandConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO;
+import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
@@ -16,34 +14,32 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
-import java.io.IOException;
+import java.util.Comparator;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
-@Api(tags = "管理后台 - 品牌")
+@Api(tags = "管理后台 - 商品品牌")
@RestController
@RequestMapping("/product/brand")
@Validated
-public class BrandController {
+public class ProductBrandController {
@Resource
- private BrandService brandService;
+ private ProductBrandService brandService;
@PostMapping("/create")
@ApiOperation("创建品牌")
@PreAuthorize("@ss.hasPermission('product:brand:create')")
- public CommonResult createBrand(@Valid @RequestBody BrandCreateReqVO createReqVO) {
+ public CommonResult createBrand(@Valid @RequestBody ProductBrandCreateReqVO createReqVO) {
return success(brandService.createBrand(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新品牌")
@PreAuthorize("@ss.hasPermission('product:brand:update')")
- public CommonResult updateBrand(@Valid @RequestBody BrandUpdateReqVO updateReqVO) {
+ public CommonResult updateBrand(@Valid @RequestBody ProductBrandUpdateReqVO updateReqVO) {
brandService.updateBrand(updateReqVO);
return success(true);
}
@@ -61,29 +57,26 @@ public class BrandController {
@ApiOperation("获得品牌")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:brand:query')")
- public CommonResult getBrand(@RequestParam("id") Long id) {
- BrandDO brand = brandService.getBrand(id);
- return success(BrandConvert.INSTANCE.convert(brand));
+ public CommonResult getBrand(@RequestParam("id") Long id) {
+ ProductBrandDO brand = brandService.getBrand(id);
+ return success(ProductBrandConvert.INSTANCE.convert(brand));
}
@GetMapping("/page")
@ApiOperation("获得品牌分页")
@PreAuthorize("@ss.hasPermission('product:brand:query')")
- public CommonResult> getBrandPage(@Valid BrandPageReqVO pageVO) {
- PageResult pageResult = brandService.getBrandPage(pageVO);
- return success(BrandConvert.INSTANCE.convertPage(pageResult));
+ public CommonResult> getBrandPage(@Valid ProductBrandPageReqVO pageVO) {
+ PageResult pageResult = brandService.getBrandPage(pageVO);
+ return success(ProductBrandConvert.INSTANCE.convertPage(pageResult));
}
- @GetMapping("/export-excel")
- @ApiOperation("导出品牌 Excel")
- @PreAuthorize("@ss.hasPermission('product:brand:export')")
- @OperateLog(type = EXPORT)
- public void exportBrandExcel(@Valid BrandExportReqVO exportReqVO,
- HttpServletResponse response) throws IOException {
- List list = brandService.getBrandList(exportReqVO);
- // 导出 Excel
- List datas = BrandConvert.INSTANCE.convertList02(list);
- ExcelUtils.write(response, "品牌.xls", "数据", BrandExcelVO.class, datas);
+ @GetMapping("/list")
+ @ApiOperation("获得品牌列表")
+ @PreAuthorize("@ss.hasPermission('product:brand:query')")
+ public CommonResult> getBrandList(@Valid ProductBrandListReqVO listVO) {
+ List list = brandService.getBrandList(listVO);
+ list.sort(Comparator.comparing(ProductBrandDO::getSort));
+ return success(ProductBrandConvert.INSTANCE.convertList(list));
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandExcelVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandExcelVO.java
deleted file mode 100644
index 261b69ea5..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandExcelVO.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
-
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
-import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
-
-
-/**
- * 品牌 Excel VO
- *
- * @author 芋道源码
- */
-@Data
-public class BrandExcelVO {
-
- @ExcelProperty("品牌编号")
- private Long id;
-
- @ExcelProperty("分类编号")
- private Long categoryId;
-
- @ExcelProperty("品牌名称")
- private String name;
-
- @ExcelProperty("品牌图片")
- private String bannerUrl;
-
- @ExcelProperty("品牌排序")
- private Integer sort;
-
- @ExcelProperty("品牌描述")
- private String description;
-
- @ExcelProperty(value = "状态", converter = DictConvert.class)
- @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
- private Integer status;
-
- @ExcelProperty("创建时间")
- private Date createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandExportReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandExportReqVO.java
deleted file mode 100644
index 1385613a6..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandExportReqVO.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
-
-import lombok.*;
-import java.util.*;
-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(value = "管理后台 - 品牌 Excel 导出 Request VO", description = "参数和 BrandPageReqVO 是一致的")
-@Data
-public class BrandExportReqVO {
-
- @ApiModelProperty(value = "分类编号", example = "1")
- private Long categoryId;
-
- @ApiModelProperty(value = "品牌名称", example = "芋道")
- private String name;
-
- @ApiModelProperty(value = "状态", example = "0")
- private Integer status;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "创建时间")
- private Date[] createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandPageReqVO.java
deleted file mode 100644
index c706e51ca..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandPageReqVO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
-
-import lombok.*;
-import java.util.*;
-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 BrandPageReqVO extends PageParam {
-
- @ApiModelProperty(value = "分类编号", example = "1")
- private Long categoryId;
-
- @ApiModelProperty(value = "品牌名称", example = "芋道")
- private String name;
-
- @ApiModelProperty(value = "状态", example = "0")
- private Integer status;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "创建时间")
- private Date[] createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java
similarity index 62%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandBaseVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java
index 57c5a390c..fa5ecd2d1 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java
@@ -1,20 +1,16 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
/**
-* 品牌 Base VO,提供给添加、修改、详细的子 VO 使用
+* 商品品牌 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
-public class BrandBaseVO {
-
- @ApiModelProperty(value = "分类编号", required = true, example = "1")
- @NotNull(message = "分类编号不能为空")
- private Long categoryId;
+public class ProductBrandBaseVO {
@ApiModelProperty(value = "品牌名称", required = true, example = "芋道")
@NotNull(message = "品牌名称不能为空")
@@ -22,9 +18,10 @@ public class BrandBaseVO {
@ApiModelProperty(value = "品牌图片", required = true)
@NotNull(message = "品牌图片不能为空")
- private String bannerUrl;
+ private String picUrl;
- @ApiModelProperty(value = "品牌排序", example = "1")
+ @ApiModelProperty(value = "品牌排序", required = true, example = "1")
+ @NotNull(message = "品牌排序不能为空")
private Integer sort;
@ApiModelProperty(value = "品牌描述", example = "描述")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java
similarity index 54%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandCreateReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java
index 3a6f844fb..74024929f 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java
@@ -1,14 +1,12 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import lombok.*;
-import java.util.*;
import io.swagger.annotations.*;
-import javax.validation.constraints.*;
-@ApiModel("管理后台 - 品牌创建 Request VO")
+@ApiModel("管理后台 - 商品品牌创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class BrandCreateReqVO extends BrandBaseVO {
+public class ProductBrandCreateReqVO extends ProductBrandBaseVO {
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java
new file mode 100644
index 000000000..5367e2dfe
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java
@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@ApiModel(value = "管理后台 - 商品品牌分页 Request VO")
+@Data
+public class ProductBrandListReqVO {
+
+ @ApiModelProperty(value = "品牌名称", example = "芋道")
+ private String name;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java
similarity index 67%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryPageReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java
index 1cf83bbbe..3b3d829de 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.product.controller.admin.category.vo;
+package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
@@ -12,16 +12,16 @@ import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-@ApiModel("管理后台 - 商品分类分页 Request VO")
+@ApiModel("管理后台 - 商品品牌分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class CategoryPageReqVO extends PageParam {
+public class ProductBrandPageReqVO extends PageParam {
- @ApiModelProperty(value = "分类名称", example = "办公文具")
+ @ApiModelProperty(value = "品牌名称", example = "芋道")
private String name;
- @ApiModelProperty(value = "开启状态", example = "0")
+ @ApiModelProperty(value = "状态", example = "0", notes = "参考 CommonStatusEnum 枚举")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java
similarity index 60%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandRespVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java
index 5e010b4d0..f577a6c26 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java
@@ -1,14 +1,18 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.Date;
@ApiModel("管理后台 - 品牌 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class BrandRespVO extends BrandBaseVO {
+public class ProductBrandRespVO extends ProductBrandBaseVO {
@ApiModelProperty(value = "品牌编号", required = true, example = "1")
private Long id;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java
similarity index 75%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandUpdateReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java
index 287157f0e..54d610207 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/BrandUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java
@@ -1,15 +1,14 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import lombok.*;
-import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
-@ApiModel("管理后台 - 品牌更新 Request VO")
+@ApiModel("管理后台 - 商品品牌更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class BrandUpdateReqVO extends BrandBaseVO {
+public class ProductBrandUpdateReqVO extends ProductBrandBaseVO {
@ApiModelProperty(value = "品牌编号", required = true, example = "1")
@NotNull(message = "品牌编号不能为空")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/CategoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/CategoryController.java
deleted file mode 100644
index 12408ac28..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/CategoryController.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.category;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
-import cn.iocoder.yudao.module.product.convert.category.CategoryConvert;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
-import cn.iocoder.yudao.module.product.service.category.CategoryService;
-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.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-import java.io.IOException;
-import java.util.Comparator;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
-
-@Api(tags = "管理后台 - 商品分类")
-@RestController
-@RequestMapping("/product/category")
-@Validated
-public class CategoryController {
-
- @Resource
- private CategoryService categoryService;
-
- @PostMapping("/create")
- @ApiOperation("创建商品分类")
- @PreAuthorize("@ss.hasPermission('product:category:create')")
- public CommonResult createCategory(@Valid @RequestBody CategoryCreateReqVO createReqVO) {
- return success(categoryService.createCategory(createReqVO));
- }
-
- @PutMapping("/update")
- @ApiOperation("更新商品分类")
- @PreAuthorize("@ss.hasPermission('product:category:update')")
- public CommonResult updateCategory(@Valid @RequestBody CategoryUpdateReqVO updateReqVO) {
- categoryService.updateCategory(updateReqVO);
- return success(true);
- }
-
- @DeleteMapping("/delete")
- @ApiOperation("删除商品分类")
- @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
- @PreAuthorize("@ss.hasPermission('product:category:delete')")
- public CommonResult deleteCategory(@RequestParam("id") Long id) {
- categoryService.deleteCategory(id);
- return success(true);
- }
-
- @GetMapping("/get")
- @ApiOperation("获得商品分类")
- @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
- @PreAuthorize("@ss.hasPermission('product:category:query')")
- public CommonResult getCategory(@RequestParam("id") Long id) {
- CategoryDO category = categoryService.getCategory(id);
- return success(CategoryConvert.INSTANCE.convert(category));
- }
-
- // TODO @JeromeSoar:这应该是个 app 的接口,提供商品分类的树结构。这个调整下,后端只返回列表,前端构建 tree。注意,不需要返回创建时间、是否开启等无关字段。
- // TODO @YunaiV: 这个是在管理端展示了一个类似菜单的分类树列表, treeListReqVO 只是查询参数的封装命名,返给前端的是列表数据。PS: 这里 /page 接口没有使用到。
- @GetMapping("/listByQuery")
- @ApiOperation("获得商品分类列表")
- @PreAuthorize("@ss.hasPermission('product:category:query')")
- public CommonResult> listByQuery(@Valid CategoryTreeListReqVO treeListReqVO) {
- List list = categoryService.getCategoryTreeList(treeListReqVO);
- list.sort(Comparator.comparing(CategoryDO::getSort));
- return success(CategoryConvert.INSTANCE.convertList(list));
- }
-
- @GetMapping("/export-excel")
- @ApiOperation("导出商品分类 Excel")
- @PreAuthorize("@ss.hasPermission('product:category:export')")
- @OperateLog(type = EXPORT)
- public void exportCategoryExcel(@Valid CategoryExportReqVO exportReqVO,
- HttpServletResponse response) throws IOException {
- List list = categoryService.getCategoryList(exportReqVO);
- // 导出 Excel
- List datas = CategoryConvert.INSTANCE.convertList02(list);
- ExcelUtils.write(response, "商品分类.xls", "数据", CategoryExcelVO.class, datas);
- }
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java
new file mode 100644
index 000000000..4144e6a57
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java
@@ -0,0 +1,76 @@
+package cn.iocoder.yudao.module.product.controller.admin.category;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryRespVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO;
+import cn.iocoder.yudao.module.product.convert.category.ProductCategoryConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
+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 java.util.Comparator;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "管理后台 - 商品分类")
+@RestController
+@RequestMapping("/product/category")
+@Validated
+public class ProductCategoryController {
+
+ @Resource
+ private ProductCategoryService categoryService;
+
+ @PostMapping("/create")
+ @ApiOperation("创建商品分类")
+ @PreAuthorize("@ss.hasPermission('product:category:create')")
+ public CommonResult createCategory(@Valid @RequestBody ProductCategoryCreateReqVO createReqVO) {
+ return success(categoryService.createCategory(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @ApiOperation("更新商品分类")
+ @PreAuthorize("@ss.hasPermission('product:category:update')")
+ public CommonResult updateCategory(@Valid @RequestBody ProductCategoryUpdateReqVO updateReqVO) {
+ categoryService.updateCategory(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @ApiOperation("删除商品分类")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
+ @PreAuthorize("@ss.hasPermission('product:category:delete')")
+ public CommonResult deleteCategory(@RequestParam("id") Long id) {
+ categoryService.deleteCategory(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @ApiOperation("获得商品分类")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+ @PreAuthorize("@ss.hasPermission('product:category:query')")
+ public CommonResult getCategory(@RequestParam("id") Long id) {
+ ProductCategoryDO category = categoryService.getCategory(id);
+ return success(ProductCategoryConvert.INSTANCE.convert(category));
+ }
+
+ @GetMapping("/list")
+ @ApiOperation("获得商品分类列表")
+ @PreAuthorize("@ss.hasPermission('product:category:query')")
+ public CommonResult> getCategoryList(@Valid ProductCategoryListReqVO treeListReqVO) {
+ List list = categoryService.getEnableCategoryList(treeListReqVO);
+ list.sort(Comparator.comparing(ProductCategoryDO::getSort));
+ return success(ProductCategoryConvert.INSTANCE.convertList(list));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExcelVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExcelVO.java
deleted file mode 100644
index f8e36ee8c..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExcelVO.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.category.vo;
-
-import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
-import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
-import com.alibaba.excel.annotation.ExcelProperty;
-import lombok.Data;
-
-import java.util.Date;
-
-
-/**
- * 商品分类 Excel VO
- *
- * @author 芋道源码
- */
-@Data
-public class CategoryExcelVO {
-
- @ExcelProperty("分类编号")
- private Long id;
-
- @ExcelProperty("父分类编号")
- private Long parentId;
-
- @ExcelProperty("分类名称")
- private String name;
-
- @ExcelProperty("分类图标")
- private String icon;
-
- @ExcelProperty("分类图片")
- private String bannerUrl;
-
- @ExcelProperty("分类排序")
- private Integer sort;
-
- @ExcelProperty("分类描述")
- private String description;
-
- @ExcelProperty(value = "开启状态", converter = DictConvert.class)
- @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
- private Integer status;
-
- @ExcelProperty("创建时间")
- private Date createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExportReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExportReqVO.java
deleted file mode 100644
index c119fb2dc..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExportReqVO.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.category.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.util.Date;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@ApiModel(value = "管理后台 - 商品分类 Excel 导出 Request VO", description = "参数和 CategoryPageReqVO 是一致的")
-@Data
-public class CategoryExportReqVO {
-
- @ApiModelProperty(value = "分类名称", example = "办公文具")
- private String name;
-
- @ApiModelProperty(value = "开启状态", example = "0")
- private Integer status;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "创建时间")
- private Date[] createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryTreeListReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryTreeListReqVO.java
deleted file mode 100644
index 214349ee5..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryTreeListReqVO.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.category.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.util.Date;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Data
-@ApiModel(value = "管理后台 - 商品分类列表查询 Request VO", description = "参数和 CategoryPageReqVO 是一致的")
-public class CategoryTreeListReqVO extends CategoryExportReqVO {
-
- @ApiModelProperty(value = "分类名称", example = "办公文具")
- private String name;
-
- @ApiModelProperty(value = "开启状态", example = "0")
- private Integer status;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "创建时间")
- private Date[] createTime;
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryBaseVO.java
similarity index 87%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryBaseVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryBaseVO.java
index 598e093eb..9b9c77a08 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryBaseVO.java
@@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull;
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
-public class CategoryBaseVO {
+public class ProductCategoryBaseVO {
@ApiModelProperty(value = "父分类编号", required = true, example = "1")
@NotNull(message = "父分类编号不能为空")
@@ -21,13 +21,9 @@ public class CategoryBaseVO {
@NotBlank(message = "分类名称不能为空")
private String name;
- @ApiModelProperty(value = "分类图标")
- @NotBlank(message = "分类图标不能为空")
- private String icon;
-
@ApiModelProperty(value = "分类图片", required = true)
@NotBlank(message = "分类图片不能为空")
- private String bannerUrl;
+ private String picUrl;
@ApiModelProperty(value = "分类排序", required = true, example = "1")
private Integer sort;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryCreateReqVO.java
similarity index 68%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryCreateReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryCreateReqVO.java
index ce583f08b..d35e1ad3c 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryCreateReqVO.java
@@ -1,14 +1,12 @@
package cn.iocoder.yudao.module.product.controller.admin.category.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 CategoryCreateReqVO extends CategoryBaseVO {
+public class ProductCategoryCreateReqVO extends ProductCategoryBaseVO {
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java
new file mode 100644
index 000000000..a487c16a4
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java
@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.product.controller.admin.category.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@ApiModel(value = "管理后台 - 商品分类列表查询 Request VO")
+@Data
+public class ProductCategoryListReqVO {
+
+ @ApiModelProperty(value = "分类名称", example = "办公文具")
+ private String name;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java
similarity index 87%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryRespVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java
index e7d0b2238..9c3d1b458 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java
@@ -8,7 +8,7 @@ import io.swagger.annotations.*;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class CategoryRespVO extends CategoryBaseVO {
+public class ProductCategoryRespVO extends ProductCategoryBaseVO {
@ApiModelProperty(value = "分类编号", required = true, example = "2")
private Long id;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryUpdateReqVO.java
similarity index 85%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryUpdateReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryUpdateReqVO.java
index 13ee83c1e..b0c8fe57d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryUpdateReqVO.java
@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
import lombok.*;
-import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@@ -9,7 +8,7 @@ import javax.validation.constraints.*;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class CategoryUpdateReqVO extends CategoryBaseVO {
+public class ProductCategoryUpdateReqVO extends ProductCategoryBaseVO {
@ApiModelProperty(value = "分类编号", required = true, example = "2")
@NotNull(message = "分类编号不能为空")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
index f1d31acab..7401ec744 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
@@ -1,29 +1,23 @@
package cn.iocoder.yudao.module.product.controller.admin.property;
-import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
-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 javax.servlet.http.*;
-import java.util.*;
-import java.io.IOException;
-
-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.framework.excel.core.util.ExcelUtils;
-
-import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
-
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.*;
-import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
+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.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 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
@@ -62,36 +56,15 @@ public class ProductPropertyController {
@ApiOperation("获得规格名称")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:query')")
- public CommonResult getProperty(@RequestParam("id") Long id) {
+ public CommonResult getProperty(@RequestParam("id") Long id) {
return success(productPropertyService.getPropertyResp(id));
}
- @GetMapping("/list")
- @ApiOperation("获得规格名称列表")
- @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
- @PreAuthorize("@ss.hasPermission('product:property:query')")
- public CommonResult> getPropertyList(@RequestParam("ids") Collection ids) {
- List list = productPropertyService.getPropertyList(ids);
- return success(ProductPropertyConvert.INSTANCE.convertList(list));
- }
-
@GetMapping("/page")
@ApiOperation("获得规格名称分页")
@PreAuthorize("@ss.hasPermission('product:property:query')")
- public CommonResult> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
+ public CommonResult> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
return success(productPropertyService.getPropertyListPage(pageVO));
}
- @GetMapping("/export-excel")
- @ApiOperation("导出规格名称 Excel")
- @PreAuthorize("@ss.hasPermission('product:property:export')")
- @OperateLog(type = EXPORT)
- public void exportPropertyExcel(@Valid ProductPropertyExportReqVO exportReqVO,
- HttpServletResponse response) throws IOException {
- List list = productPropertyService.getPropertyList(exportReqVO);
- // 导出 Excel
- List datas = ProductPropertyConvert.INSTANCE.convertList02(list);
- ExcelUtils.write(response, "规格名称.xls", "数据", ProductPropertyExcelVO.class, datas);
- }
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyBaseVO.java
deleted file mode 100644
index 4d38763f9..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyBaseVO.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.property.vo;
-
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
-
-/**
-* 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用
-* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
-*/
-@Data
-public class ProductPropertyBaseVO {
-
- @ApiModelProperty(value = "规格名称")
- private String name;
-
- @ApiModelProperty(value = "状态: 0 开启 ,1 禁用")
- private Integer status;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyExcelVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyExcelVO.java
deleted file mode 100644
index c935c1001..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyExcelVO.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.property.vo;
-
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-
-/**
- * 规格名称 Excel VO
- *
- * @author 芋道源码
- */
-@Data
-public class ProductPropertyExcelVO {
-
- @ExcelProperty("主键")
- private Long id;
-
- @ExcelProperty("规格名称")
- private String name;
-
- @ExcelProperty("状态: 0 开启 ,1 禁用")
- private Integer status;
-
- @ExcelProperty("创建时间")
- private Date createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyExportReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyExportReqVO.java
deleted file mode 100644
index 119c76e03..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyExportReqVO.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.property.vo;
-
-import lombok.*;
-import java.util.*;
-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(value = "管理后台 - 规格名称 Excel 导出 Request VO", description = "参数和 PropertyPageReqVO 是一致的")
-@Data
-public class ProductPropertyExportReqVO {
-
- @ApiModelProperty(value = "规格名称")
- private String name;
-
- @ApiModelProperty(value = "状态: 0 开启 ,1 禁用")
- private Integer status;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "创建时间")
- private Date[] createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyRespVO.java
deleted file mode 100644
index 978f26308..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyRespVO.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.property.vo;
-
-import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO;
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-
-@ApiModel("管理后台 - 规格名称 Response VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ProductPropertyRespVO extends ProductPropertyBaseVO {
-
- @ApiModelProperty(value = "主键", required = true)
- private Long id;
-
- @ApiModelProperty(value = "创建时间")
- private Date createTime;
-
- @ApiModelProperty(value = "属性值")
- private List propertyValueList;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java
new file mode 100644
index 000000000..9bdc70bd7
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.product.controller.admin.property.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.List;
+
+/**
+ * @Description: ProductPropertyViewRespVO
+ * @Author: franky
+ * @CreateDate: 2022/7/5 21:29
+ * @Version: 1.0.0
+ */
+@ApiModel("管理后台 - 规格名称详情展示 Request VO")
+@Data
+@ToString(callSuper = true)
+public class ProductPropertyViewRespVO {
+
+ @ApiModelProperty(value = "规格名称id", example = "1")
+ public Long propertyId;
+
+ @ApiModelProperty(value = "规格名称", example = "内存")
+ public String name;
+
+ @ApiModelProperty(value = "规格属性值集合", example = "[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]")
+ public List propertyValues;
+
+ @Data
+ @ApiModel(value = "规格属性值元组")
+ public static class Tuple2 {
+ private final long id;
+ private final String name;
+
+ public Tuple2(Long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ }
+
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
new file mode 100644
index 000000000..7684d4ea7
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
+
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.Date;
+import java.util.List;
+
+@ApiModel("管理后台 - 规格 + 规格值 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class ProductPropertyAndValueRespVO extends ProductPropertyBaseVO {
+
+ @ApiModelProperty(value = "规格的编号", required = true, example = "1024")
+ private Long id;
+
+ @ApiModelProperty(value = "创建时间", required = true)
+ private Date createTime;
+
+ /**
+ * 规格值的集合
+ */
+ private List values;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
new file mode 100644
index 000000000..c900a727b
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+
+/**
+* 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用
+* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+*/
+@Data
+public class ProductPropertyBaseVO {
+
+ @ApiModelProperty(value = "规格名称", required = true, example = "颜色")
+ @NotEmpty(message = "规格名称不能为空")
+ private String name;
+
+ @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
+ @NotEmpty(message = "状态不能为空")
+ private Integer status;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
similarity index 71%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyCreateReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
index 54d72da8a..c0e6b9da2 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
@@ -1,6 +1,6 @@
-package cn.iocoder.yudao.module.product.controller.admin.property.vo;
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
-import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
import lombok.*;
import io.swagger.annotations.*;
@@ -13,6 +13,7 @@ import java.util.List;
@ToString(callSuper = true)
public class ProductPropertyCreateReqVO extends ProductPropertyBaseVO {
+ // TODO @Luowenfeng:规格值的 CRUD 可以单独;前端 + 后端,改成类似字典类型、字典数据的这种交互;在加一个 ProductPropertyValueController
@ApiModelProperty(value = "属性值")
@NotNull(message = "属性值不能为空")
List propertyValueList;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
similarity index 64%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyPageReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
index 360a0a5e1..1902fb205 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
@@ -1,11 +1,15 @@
-package cn.iocoder.yudao.module.product.controller.admin.property.vo;
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
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 java.util.Date;
+
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 规格名称分页 Request VO")
@@ -14,10 +18,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@ToString(callSuper = true)
public class ProductPropertyPageReqVO extends PageParam {
- @ApiModelProperty(value = "规格名称")
+ @ApiModelProperty(value = "规格名称", example = "颜色")
private String name;
- @ApiModelProperty(value = "状态: 0 开启 ,1 禁用")
+ @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
similarity index 83%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyUpdateReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
index ed190e8b0..f4b9d695a 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
@@ -1,6 +1,6 @@
-package cn.iocoder.yudao.module.product.controller.admin.property.vo;
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
-import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
import lombok.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@@ -12,7 +12,7 @@ import java.util.List;
@ToString(callSuper = true)
public class ProductPropertyUpdateReqVO extends ProductPropertyBaseVO {
- @ApiModelProperty(value = "主键", required = true)
+ @ApiModelProperty(value = "主键", required = true, example = "1")
@NotNull(message = "主键不能为空")
private Long id;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
new file mode 100644
index 000000000..1e0708009
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+/**
+* 规格值 Base VO,提供给添加、修改、详细的子 VO 使用
+* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+*/
+@Data
+public class ProductPropertyValueBaseVO {
+
+ @ApiModelProperty(value = "规格编号", required = true, example = "1024")
+ @NotNull(message = "规格编号不能为空")
+ private Long propertyId;
+
+ @ApiModelProperty(value = "规格值名字", required = true, example = "红色")
+ @NotEmpty(message = "规格值名字不能为空")
+ private String name;
+
+ @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
+ @NotEmpty(message = "状态不能为空")
+ private Integer status;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
similarity index 96%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueCreateReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
index 23ea0690c..f7237f9cd 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo;
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
import lombok.*;
import io.swagger.annotations.*;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
similarity index 57%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueRespVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
index 25fa25f02..17eedaae9 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
@@ -1,8 +1,12 @@
-package cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo;
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.Date;
@ApiModel("管理后台 - 规格值 Response VO")
@Data
@@ -10,7 +14,7 @@ import io.swagger.annotations.*;
@ToString(callSuper = true)
public class ProductPropertyValueRespVO extends ProductPropertyValueBaseVO {
- @ApiModelProperty(value = "主键", required = true)
+ @ApiModelProperty(value = "主键", required = true, example = "10")
private Long id;
@ApiModelProperty(value = "创建时间")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
similarity index 83%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueUpdateReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
index 894d6f6eb..4a1bc5778 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo;
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
import lombok.*;
import io.swagger.annotations.*;
@@ -10,7 +10,7 @@ import javax.validation.constraints.*;
@ToString(callSuper = true)
public class ProductPropertyValueUpdateReqVO extends ProductPropertyValueBaseVO {
- @ApiModelProperty(value = "主键", required = true)
+ @ApiModelProperty(value = "主键", required = true, example = "1024")
@NotNull(message = "主键不能为空")
private Integer id;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueBaseVO.java
deleted file mode 100644
index ed600a9ac..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/propertyvalue/vo/ProductPropertyValueBaseVO.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo;
-
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
-
-/**
-* 规格值 Base VO,提供给添加、修改、详细的子 VO 使用
-* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
-*/
-@Data
-public class ProductPropertyValueBaseVO {
-
- @ApiModelProperty(value = "规格键id")
- private Long propertyId;
-
- @ApiModelProperty(value = "规格值名字")
- private String name;
-
- @ApiModelProperty(value = "状态: 1 开启 ,2 禁用")
- private Integer status;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java
index 132d68d94..2081e7da8 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java
@@ -1,29 +1,9 @@
package cn.iocoder.yudao.module.product.controller.admin.sku;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*;
-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 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.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
@Api(tags = "管理后台 - 商品 sku")
@RestController
@@ -31,69 +11,4 @@ import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.E
@Validated
public class ProductSkuController {
- @Resource
- private ProductSkuService ProductSkuService;
-
- @PostMapping("/create")
- @ApiOperation("创建商品sku")
- @PreAuthorize("@ss.hasPermission('product:sku:create')")
- public CommonResult createSku(@Valid @RequestBody ProductSkuCreateReqVO createReqVO) {
- return success(ProductSkuService.createSku(createReqVO));
- }
-
- @PutMapping("/update")
- @ApiOperation("更新商品sku")
- @PreAuthorize("@ss.hasPermission('product:sku:update')")
- public CommonResult updateSku(@Valid @RequestBody ProductSkuUpdateReqVO updateReqVO) {
- ProductSkuService.updateSku(updateReqVO);
- return success(true);
- }
-
- @DeleteMapping("/delete")
- @ApiOperation("删除商品sku")
- @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
- @PreAuthorize("@ss.hasPermission('product:sku:delete')")
- public CommonResult deleteSku(@RequestParam("id") Long id) {
- ProductSkuService.deleteSku(id);
- return success(true);
- }
-
- @GetMapping("/get")
- @ApiOperation("获得商品sku")
- @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
- @PreAuthorize("@ss.hasPermission('product:sku:query')")
- public CommonResult getSku(@RequestParam("id") Long id) {
- ProductSkuDO sku = ProductSkuService.getSku(id);
- return success(ProductSkuConvert.INSTANCE.convert(sku));
- }
-
- @GetMapping("/list")
- @ApiOperation("获得商品sku列表")
- @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
- @PreAuthorize("@ss.hasPermission('product:sku:query')")
- public CommonResult> getSkuList(@RequestParam("ids") Collection ids) {
- List list = ProductSkuService.getSkuList(ids);
- return success(ProductSkuConvert.INSTANCE.convertList(list));
- }
-
- @GetMapping("/page")
- @ApiOperation("获得商品sku分页")
- @PreAuthorize("@ss.hasPermission('product:sku:query')")
- public CommonResult> getSkuPage(@Valid ProductSkuPageReqVO pageVO) {
- PageResult pageResult = ProductSkuService.getSkuPage(pageVO);
- return success(ProductSkuConvert.INSTANCE.convertPage(pageResult));
- }
-
- @GetMapping("/export-excel")
- @ApiOperation("导出商品sku Excel")
- @PreAuthorize("@ss.hasPermission('product:sku:export')")
- @OperateLog(type = EXPORT)
- public void exportSkuExcel(@Valid ProductSkuExportReqVO exportReqVO,
- HttpServletResponse response) throws IOException {
- List list = ProductSkuService.getSkuList(exportReqVO);
- // 导出 Excel
- List datas = ProductSkuConvert.INSTANCE.convertList02(list);
- ExcelUtils.write(response, "商品sku.xls", "数据", ProductSkuExcelVO.class, datas);
- }
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
index cefab9a47..43f67ee53 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
@@ -1,58 +1,72 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
/**
-* 商品sku Base VO,提供给添加、修改、详细的子 VO 使用
+* 商品 SKU Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ProductSkuBaseVO {
- // TODO @franky:example 要写哈;
+ @ApiModelProperty(value = "商品 SKU 名字", required = true, example = "芋道")
+ @NotEmpty(message = "商品 SKU 名字不能为空")
+ private String name;
- @ApiModelProperty(value = "spu编号")
- private Long spuId;
-
- // TODO @franky:类似这种字段,有额外说明的。可以写成; @ApiModelProperty(value = "规格值数组", required = true, notes = "json格式, [{propertyId: , valueId: }, {propertyId: , valueId: }]")
-
- @ApiModelProperty(value = "规格值数组-json格式, [{propertyId: , valueId: }, {propertyId: , valueId: }]", required = true)
- @NotNull(message = "规格值数组-json格式, [{propertyId: , valueId: }, {propertyId: , valueId: }]不能为空")
- private List properties;
-
- @ApiModelProperty(value = "销售价格,单位:分", required = true)
+ @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分")
@NotNull(message = "销售价格,单位:分不能为空")
private Integer price;
- @ApiModelProperty(value = "原价, 单位: 分", required = true)
- @NotNull(message = "原价, 单位: 分不能为空")
- private Integer originalPrice;
+ @ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分")
+ private Integer marketPrice;
- @ApiModelProperty(value = "成本价,单位: 分", required = true)
- @NotNull(message = "成本价,单位: 分不能为空")
+ @ApiModelProperty(value = "成本价", example = "1024", notes = "单位:分")
private Integer costPrice;
- @ApiModelProperty(value = "条形码", required = true)
- @NotNull(message = "条形码不能为空")
+ @ApiModelProperty(value = "条形码", example = "haha")
private String barCode;
- @ApiModelProperty(value = "图片地址", required = true)
+ @ApiModelProperty(value = "图片地址")
@NotNull(message = "图片地址不能为空")
private String picUrl;
- @ApiModelProperty(value = "状态: 0-正常 1-禁用")
+ @ApiModelProperty(value = "SKU 状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
+ @NotNull(message = "SKU 状态不能为空")
+ @InEnum(CommonStatusEnum.class)
private Integer status;
- // TODO @franky 要有 swagger 注解
+ @ApiModelProperty(value = "库存", required = true, example = "1")
+ @NotNull(message = "库存不能为空")
+ private Integer stock;
+
+ @ApiModelProperty(value = "预警预存", example = "1")
+ private Integer warnStock;
+
+ @ApiModelProperty(value = "商品重量", example = "1", notes = "单位:kg 千克")
+ private Double weight;
+
+ @ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
+ private Double volume;
+
+ @ApiModel("规格值")
@Data
public static class Property {
- @NotNull(message = "规格属性名id不能为空")
+
+ @ApiModelProperty(value = "属性编号", required = true, example = "1")
+ @NotNull(message = "属性编号不能为空")
private Long propertyId;
- @NotNull(message = "规格属性值id不能为空")
+
+ @ApiModelProperty(value = "属性值编号", required = true, example = "1024")
+ @NotNull(message = "属性值编号不能为空")
private Long valueId;
+
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
new file mode 100755
index 000000000..84d71d9b7
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.List;
+
+@ApiModel("管理后台 - 商品 SKU 创建/更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
+
+ // TODO @Luowenfeng:可以不用哈,如果基于规格匹配
+ @ApiModelProperty(value = "商品 id 更新时须有", example = "1")
+ private Long id;
+
+ /**
+ * 规格值数组
+ */
+ private List properties;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuExcelVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuExcelVO.java
deleted file mode 100755
index 7caf1313d..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuExcelVO.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-import lombok.Data;
-
-import java.util.Date;
-import java.util.List;
-
-/**
- * 商品sku Excel VO
- *
- * @author 芋道源码
- */
-@Data
-public class ProductSkuExcelVO {
-
- @ExcelProperty("主键")
- private Long id;
-
- @ExcelProperty("spu编号")
- private Long spuId;
-
- // TODO @franky:这个单元格,可能会有点展示的问题
- @ExcelProperty("规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]")
- private List properties;
-
- @ExcelProperty("销售价格,单位:分")
- private Integer price;
-
- @ExcelProperty("原价, 单位: 分")
- private Integer originalPrice;
-
- @ExcelProperty("成本价,单位: 分")
- private Integer costPrice;
-
- @ExcelProperty("条形码")
- private String barCode;
-
- @ExcelProperty("图片地址")
- private String picUrl;
-
- @ExcelProperty("状态: 0-正常 1-禁用")
- private Integer status;
-
- @ExcelProperty("创建时间")
- private Date createTime;
-
- @Data
- public static class Property {
- private Integer propertyId;
- private Integer valueId;
- }
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuExportReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuExportReqVO.java
deleted file mode 100755
index 0bf34a67d..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuExportReqVO.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
-
-import lombok.*;
-import java.util.*;
-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(value = "管理后台 - 商品sku Excel 导出 Request VO", description = "参数和 SkuPageReqVO 是一致的")
-@Data
-public class ProductSkuExportReqVO {
-
- @ApiModelProperty(value = "spu编号")
- private Long spuId;
-
- @ApiModelProperty(value = "规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]")
- private String properties;
-
- @ApiModelProperty(value = "销售价格,单位:分")
- private Integer price;
-
- @ApiModelProperty(value = "原价, 单位: 分")
- private Integer originalPrice;
-
- @ApiModelProperty(value = "成本价,单位: 分")
- private Integer costPrice;
-
- @ApiModelProperty(value = "条形码")
- private String barCode;
-
- @ApiModelProperty(value = "图片地址")
- private String picUrl;
-
- @ApiModelProperty(value = "状态: 0-正常 1-禁用")
- private Integer status;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "创建时间")
- private Date[] createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuPageReqVO.java
deleted file mode 100755
index b5a494902..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuPageReqVO.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
-
-import lombok.*;
-import java.util.*;
-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("管理后台 - 商品sku分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ProductSkuPageReqVO extends PageParam {
-
- @ApiModelProperty(value = "spu编号")
- private Long spuId;
-
- @ApiModelProperty(value = "规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]")
- private String properties;
-
- @ApiModelProperty(value = "销售价格,单位:分")
- private Integer price;
-
- @ApiModelProperty(value = "原价, 单位: 分")
- private Integer originalPrice;
-
- @ApiModelProperty(value = "成本价,单位: 分")
- private Integer costPrice;
-
- @ApiModelProperty(value = "条形码")
- private String barCode;
-
- @ApiModelProperty(value = "图片地址")
- private String picUrl;
-
- @ApiModelProperty(value = "状态: 0-正常 1-禁用")
- private Integer status;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "创建时间")
- private Date[] createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
index 3b12ba21c..46e76cc63 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
@@ -1,8 +1,13 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.Date;
+import java.util.List;
@ApiModel("管理后台 - 商品sku Response VO")
@Data
@@ -10,10 +15,15 @@ import io.swagger.annotations.*;
@ToString(callSuper = true)
public class ProductSkuRespVO extends ProductSkuBaseVO {
- @ApiModelProperty(value = "主键", required = true)
+ @ApiModelProperty(value = "主键", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "创建时间")
private Date createTime;
+ /**
+ * 规格值数组
+ */
+ private List properties;
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuUpdateReqVO.java
deleted file mode 100755
index 984976eee..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuUpdateReqVO.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
-
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
-
-@ApiModel("管理后台 - 商品sku更新 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ProductSkuUpdateReqVO extends ProductSkuBaseVO {
-
- @ApiModelProperty(value = "主键", required = true)
- @NotNull(message = "主键不能为空")
- private Long id;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
index 82c6b5df5..ddae45dc2 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
@@ -2,9 +2,10 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
+import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
+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.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
@@ -16,16 +17,13 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
-import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
-@Api(tags = "管理后台 - 商品spu")
+@Api(tags = "管理后台 - 商品 SPU")
@RestController
@RequestMapping("/product/spu")
@Validated
@@ -35,23 +33,22 @@ public class ProductSpuController {
private ProductSpuService spuService;
@PostMapping("/create")
- @ApiOperation("创建商品spu")
+ @ApiOperation("创建商品 SPU")
@PreAuthorize("@ss.hasPermission('product:spu:create')")
- public CommonResult createSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
+ public CommonResult createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
return success(spuService.createSpu(createReqVO));
}
- // TODO @franky:SpuUpdateReqVO 缺少前缀
@PutMapping("/update")
- @ApiOperation("更新商品spu")
+ @ApiOperation("更新商品 SPU")
@PreAuthorize("@ss.hasPermission('product:spu:update')")
- public CommonResult updateSpu(@Valid @RequestBody SpuUpdateReqVO updateReqVO) {
+ public CommonResult updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) {
spuService.updateSpu(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
- @ApiOperation("删除商品spu")
+ @ApiOperation("删除商品 SPU")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:delete')")
public CommonResult deleteSpu(@RequestParam("id") Long id) {
@@ -60,39 +57,29 @@ public class ProductSpuController {
}
@GetMapping("/get")
- @ApiOperation("获得商品spu")
+ @ApiOperation("获得商品 SPU")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
- public CommonResult getSpu(@RequestParam("id") Long id) {
+ public CommonResult getSpu(@RequestParam("id") Long id) {
return success(spuService.getSpu(id));
}
+ // TODO @luowenfeng:新增 get-detail,返回 SpuDetailRespVO
+
@GetMapping("/list")
- @ApiOperation("获得商品spu列表")
+ @ApiOperation("获得商品 SPU 列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
- public CommonResult> getSpuList(@RequestParam("ids") Collection ids) {
+ public CommonResult> getSpuList(@RequestParam("ids") Collection ids) {
List list = spuService.getSpuList(ids);
return success(ProductSpuConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
- @ApiOperation("获得商品spu分页")
+ @ApiOperation("获得商品 SPU 分页")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
- public CommonResult> getSpuPage(@Valid SpuPageReqVO pageVO) {
+ public CommonResult> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
return success(spuService.getSpuPage(pageVO));
}
- @GetMapping("/export-excel")
- @ApiOperation("导出商品spu Excel")
- @PreAuthorize("@ss.hasPermission('product:spu:export')")
- @OperateLog(type = EXPORT)
- public void exportSpuExcel(@Valid SpuExportReqVO exportReqVO,
- HttpServletResponse response) throws IOException {
- List list = spuService.getSpuList(exportReqVO);
- // 导出 Excel
- List datas = ProductSpuConvert.INSTANCE.convertList02(list);
- ExcelUtils.write(response, "商品spu.xls", "数据", SpuExcelVO.class, datas);
- }
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
index 65a5f2a0e..ec58bab76 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
@@ -1,50 +1,84 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
/**
-* 商品spu Base VO,提供给添加、修改、详细的子 VO 使用
+* 商品 SPU Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ProductSpuBaseVO {
- @ApiModelProperty(value = "商品名称")
+ @ApiModelProperty(value = "商品名称", required = true, example = "芋道")
+ @NotEmpty(message = "商品名称不能为空")
private String name;
- @ApiModelProperty(value = "卖点", required = true)
- @NotNull(message = "卖点不能为空")
+ @ApiModelProperty(value = "商品编码", example = "yudaoyuanma")
+ private String code;
+
+ @ApiModelProperty(value = "商品卖点", example = "好吃!")
private String sellPoint;
- @ApiModelProperty(value = "描述", required = true)
- @NotNull(message = "描述不能为空")
+ @ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述")
+ @NotNull(message = "商品详情不能为空")
private String description;
- @ApiModelProperty(value = "分类id", required = true)
- @NotNull(message = "分类id不能为空")
+ @ApiModelProperty(value = "商品分类编号", required = true, example = "1")
+ @NotNull(message = "商品分类编号不能为空")
private Long categoryId;
- @ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张", required = true)
- @NotNull(message = "商品主图地址,* 数组,以逗号分隔,最多上传15张不能为空")
+ @ApiModelProperty(value = "商品品牌编号", example = "1")
+ private Long brandId;
+
+ @ApiModelProperty(value = "商品图片的数组", required = true)
+ @NotNull(message = "商品图片的数组不能为空")
private List picUrls;
- @ApiModelProperty(value = "排序字段", required = true)
- @NotNull(message = "排序字段不能为空")
+ @ApiModelProperty(value = "商品视频", required = true)
+ private String videoUrl;
+
+ @ApiModelProperty(value = "排序字段", required = true, example = "1")
private Integer sort;
- @ApiModelProperty(value = "点赞初始人数")
- private Integer likeCount;
+ @ApiModelProperty(value = "商品状态", required = true, example = "1", notes = "参见 ProductSpuStatusEnum 枚举类")
+ @NotNull(message = "商品状态不能为空")
+ @InEnum(ProductSpuStatusEnum.class)
+ private Integer status;
- @ApiModelProperty(value = "价格 单位使用:分")
- private Integer price;
+ // ========== SKU 相关字段 =========
- @ApiModelProperty(value = "库存数量")
- private Integer quantity;
+ @ApiModelProperty(value = "规格类型", required = true, example = "1", notes = "参见 ProductSpuSpecTypeEnum 枚举类")
+ @NotNull(message = "规格类型不能为空")
+ @InEnum(ProductSpuSpecTypeEnum.class)
+ private Integer specType;
- @ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
- private Boolean status;
+ @ApiModelProperty(value = "是否展示库存", required = true, example = "true")
+ @NotNull(message = "是否展示库存不能为空")
+ private Boolean showStock;
+ @ApiModelProperty(value = "库存", required = true, example = "true")
+ private Integer totalStock;
+
+ @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
+ private Integer minPrice;
+
+ @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
+ private Integer maxPrice;
+
+ // ========== 统计相关字段 =========
+
+ @ApiModelProperty(value = "虚拟销量", required = true, example = "1024")
+ @NotNull(message = "虚拟销量不能为空")
+ private Integer virtualSalesCount;
+
+ @ApiModelProperty(value = "点击量", example = "1024")
+ private Integer clickCount;
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
index 6281e20d5..87b0dd0b6 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
@@ -1,8 +1,7 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
-import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -10,14 +9,16 @@ import lombok.ToString;
import javax.validation.Valid;
import java.util.List;
-@ApiModel("管理后台 - 商品spu创建 Request VO")
+@ApiModel("管理后台 - 商品 SPU 创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuCreateReqVO extends ProductSpuBaseVO {
- @ApiModelProperty(value = "sku组合")
+ /**
+ * SKU 数组
+ */
@Valid
- List skus;
+ private List skus;
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
new file mode 100644
index 000000000..dafb0a680
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
+
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.Date;
+import java.util.List;
+
+@ApiModel(value = "管理后台 - 商品 SPU 详细 Response VO", description = "包括关联的 SKU 等信息")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
+
+ @ApiModelProperty(value = "主键", required = true, example = "1")
+ private Long id;
+
+ @ApiModelProperty(value = "创建时间")
+ private Date createTime;
+
+ /**
+ * SKU 数组
+ */
+ private List skus;
+
+ @ApiModel(value = "管理后台 - 商品 SKU 详细 Response VO")
+ @Data
+ @EqualsAndHashCode(callSuper = true)
+ @ToString(callSuper = true)
+ public static class Sku extends ProductSkuBaseVO {
+
+ /**
+ * 规格的数组
+ */
+ private List properties;
+
+ }
+
+ @ApiModel(value = "管理后台 - 商品规格的详细 Response VO")
+ @Data
+ @EqualsAndHashCode(callSuper = true)
+ @ToString(callSuper = true)
+ public static class Property extends ProductSkuBaseVO.Property {
+
+ @ApiModelProperty(value = "规格的名字", required = true, example = "颜色")
+ private String propertyName;
+
+ @ApiModelProperty(value = "规格值的名字", required = true, example = "蓝色")
+ private String valueName;
+
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
similarity index 91%
rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuPageReqVO.java
rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
index 12eff36c7..36a37541b 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
@@ -8,11 +8,11 @@ import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-@ApiModel("管理后台 - 商品spu分页 Request VO")
+@ApiModel("管理后台 - 商品 SPU 分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class SpuPageReqVO extends PageParam {
+public class ProductSpuPageReqVO extends PageParam {
@ApiModelProperty(value = "商品名称")
private String name;
@@ -42,7 +42,7 @@ public class SpuPageReqVO extends PageParam {
private Integer quantity;
@ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
- private Boolean status;
+ private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "创建时间")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
new file mode 100755
index 000000000..9db319fdc
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
@@ -0,0 +1,41 @@
+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.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.Date;
+import java.util.List;
+
+// TODO @Luowenfeng:这个类只返回 SPU 相关的信息,删除 skus、categoryIds、productPropertyViews;明细使用 SpuDetailRespVO 替代
+@ApiModel("管理后台 - 商品 SPU Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class ProductSpuRespVO extends ProductSpuBaseVO {
+
+ @ApiModelProperty(value = "主键", required = true, example = "1")
+ private Long id;
+
+ @ApiModelProperty(value = "创建时间")
+ private Date 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 skus;
+
+ @ApiModelProperty(value = "分类id数组,一直递归到一级父节点", example = "[1,2,4]")
+ private List 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 productPropertyViews;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
new file mode 100755
index 000000000..378a98dc6
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
+
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@ApiModel("管理后台 - 商品 SPU 更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class ProductSpuUpdateReqVO extends ProductSpuBaseVO {
+
+ @ApiModelProperty(value = "商品编号", required = true, example = "1")
+ @NotNull(message = "商品编号不能为空")
+ private Long id;
+
+ /**
+ * SKU 数组
+ */
+ @Valid
+ private List skus;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuExcelVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuExcelVO.java
deleted file mode 100755
index 9e90acd3d..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuExcelVO.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
-
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-
-/**
- * 商品spu Excel VO
- *
- * @author 芋道源码
- */
-@Data
-public class SpuExcelVO {
-
- @ExcelProperty("主键")
- private Integer id;
-
- @ExcelProperty("商品名称")
- private String name;
-
- @ExcelProperty("卖点")
- private String sellPoint;
-
- @ExcelProperty("描述")
- private String description;
-
- @ExcelProperty("分类id")
- private Long categoryId;
-
- @ExcelProperty("商品主图地址,* 数组,以逗号分隔,最多上传15张")
- private List picUrls;
-
- @ExcelProperty("排序字段")
- private Integer sort;
-
- @ExcelProperty("点赞初始人数")
- private Integer likeCount;
-
- @ExcelProperty("价格 单位使用:分")
- private Integer price;
-
- @ExcelProperty("库存数量")
- private Integer quantity;
-
- @ExcelProperty("上下架状态: 0 上架(开启) 1 下架(禁用)")
- private Boolean status;
-
- @ExcelProperty("创建时间")
- private Date createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuExportReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuExportReqVO.java
deleted file mode 100755
index 29a3086a2..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuExportReqVO.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
-
-import lombok.*;
-import java.util.*;
-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(value = "管理后台 - 商品spu Excel 导出 Request VO", description = "参数和 SpuPageReqVO 是一致的")
-@Data
-public class SpuExportReqVO {
-
- @ApiModelProperty(value = "商品名称")
- private String name;
-
- @ApiModelProperty(value = "卖点")
- private String sellPoint;
-
- @ApiModelProperty(value = "描述")
- private String description;
-
- @ApiModelProperty(value = "分类id")
- private Long categoryId;
-
- @ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张")
- private List picUrls;
-
- @ApiModelProperty(value = "排序字段")
- private Integer sort;
-
- @ApiModelProperty(value = "点赞初始人数")
- private Integer likeCount;
-
- @ApiModelProperty(value = "价格 单位使用:分")
- private Integer price;
-
- @ApiModelProperty(value = "库存数量")
- private Integer quantity;
-
- @ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
- private Boolean status;
-
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @ApiModelProperty(value = "创建时间")
- private Date[] createTime;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java
deleted file mode 100755
index 90387f90a..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
-
-import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-
-@ApiModel("管理后台 - 商品spu Response VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SpuRespVO extends ProductSpuBaseVO {
-
- // TODO @franky:注解要完整
-
- @ApiModelProperty(value = "主键", required = true)
- private Long id;
-
- @ApiModelProperty(value = "创建时间")
- private Date createTime;
-
- /**
- * SKU 数组
- */
- List skus;
-
- @ApiModelProperty(value = "分类id数组,一直递归到一级父节点", example = "[1,2,4]")
- LinkedList categoryIds;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuUpdateReqVO.java
deleted file mode 100755
index 9e4092235..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuUpdateReqVO.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
-
-import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO;
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-
-import javax.validation.Valid;
-import javax.validation.constraints.*;
-
-@ApiModel("管理后台 - 商品spu更新 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SpuUpdateReqVO extends ProductSpuBaseVO {
-
- @ApiModelProperty(value = "主键", required = true)
- @NotNull(message = "主键不能为空")
- private Long id;
-
- @ApiModelProperty(value = "sku组合")
- @Valid
- List skus;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java
new file mode 100644
index 000000000..fec882c48
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.product.controller.app.category;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryRespVO;
+import cn.iocoder.yudao.module.product.convert.category.ProductCategoryConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+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.RestController;
+
+import javax.annotation.Resource;
+import java.util.Comparator;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "用户 APP - 商品分类")
+@RestController
+@RequestMapping("/product/category")
+@Validated
+public class AppCategoryController {
+
+ @Resource
+ private ProductCategoryService categoryService;
+
+ @GetMapping("/list")
+ @ApiOperation("获得商品分类列表")
+ public CommonResult> getProductCategoryList() {
+ List list = categoryService.getEnableCategoryList();
+ list.sort(Comparator.comparing(ProductCategoryDO::getSort));
+ return success(ProductCategoryConvert.INSTANCE.convertList03(list));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java
new file mode 100644
index 000000000..e46a50cd3
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java
@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.product.controller.app.category.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Data
+@ApiModel(value = "用户 APP - 商品分类 Response VO")
+public class AppCategoryRespVO {
+
+ @ApiModelProperty(value = "分类编号", required = true, example = "2")
+ private Long id;
+
+ @ApiModelProperty(value = "父分类编号", required = true, example = "1")
+ @NotNull(message = "父分类编号不能为空")
+ private Long parentId;
+
+ @ApiModelProperty(value = "分类名称", required = true, example = "办公文具")
+ @NotBlank(message = "分类名称不能为空")
+ private String name;
+
+ @ApiModelProperty(value = "分类图片", required = true)
+ @NotBlank(message = "分类图片不能为空")
+ private String picUrl;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
new file mode 100644
index 000000000..7e0f912b4
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.product.controller.app.spu;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+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.AppSpuRespVO;
+import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+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.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "用户 APP - 商品spu")
+@RestController
+@RequestMapping("/product/spu")
+@Validated
+public class AppProductSpuController {
+
+ @Resource
+ private ProductSpuService spuService;
+
+ @GetMapping("/page")
+ @ApiOperation("获得商品spu分页")
+ public CommonResult> getSpuPage(@Valid AppSpuPageReqVO pageVO) {
+ return success(spuService.getSpuPage(pageVO));
+ }
+
+ @GetMapping("/")
+ @ApiOperation("获取商品 - 通过商品id")
+ public CommonResult getSpu(@RequestParam("spuId") Long spuId) {
+ AppSpuRespVO appSpuRespVO = BeanUtil.toBean(spuService.getSpu(spuId), AppSpuRespVO.class);
+ return success(appSpuRespVO);
+ }
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
new file mode 100644
index 000000000..38ed4975e
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.product.controller.app.spu.vo;
+
+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;
+
+@ApiModel("App - 商品spu分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class AppSpuPageReqVO extends PageParam {
+
+ @ApiModelProperty(value = "分类id")
+ private Long categoryId;
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
new file mode 100644
index 000000000..c0a0f0eb8
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
@@ -0,0 +1,52 @@
+package cn.iocoder.yudao.module.product.controller.app.spu.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@ApiModel("App - 商品spu分页 Request VO")
+@Data
+public class AppSpuPageRespVO {
+
+ @ApiModelProperty(value = "主键", required = true, example = "1")
+ private Long id;
+
+ @ApiModelProperty(value = "商品名称")
+ private String name;
+
+ @ApiModelProperty(value = "卖点", required = true)
+ @NotNull(message = "卖点不能为空")
+ private String sellPoint;
+
+ @ApiModelProperty(value = "描述", required = true)
+ @NotNull(message = "描述不能为空")
+ private String description;
+
+ @ApiModelProperty(value = "分类id", required = true)
+ @NotNull(message = "分类id不能为空")
+ private Long categoryId;
+
+ @ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张", required = true)
+ @NotNull(message = "商品主图地址,* 数组,以逗号分隔,最多上传15张不能为空")
+ private List picUrls;
+
+ @ApiModelProperty(value = "排序字段", required = true)
+ @NotNull(message = "排序字段不能为空")
+ 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;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java
new file mode 100644
index 000000000..b45987370
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.product.controller.app.spu.vo;
+
+import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ *
+ *
+ *
+ *
+ * @author LuoWenFeng
+ */
+@ApiModel("App - 商品spu Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class AppSpuRespVO extends ProductSpuRespVO {
+
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/BrandConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/BrandConvert.java
deleted file mode 100644
index 316515603..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/BrandConvert.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package cn.iocoder.yudao.module.product.convert.brand;
-
-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.product.controller.admin.brand.vo.*;
-import cn.iocoder.yudao.module.product.dal.dataobject.brand.BrandDO;
-
-/**
- * 品牌 Convert
- *
- * @author 芋道源码
- */
-@Mapper
-public interface BrandConvert {
-
- BrandConvert INSTANCE = Mappers.getMapper(BrandConvert.class);
-
- BrandDO convert(BrandCreateReqVO bean);
-
- BrandDO convert(BrandUpdateReqVO bean);
-
- BrandRespVO convert(BrandDO bean);
-
- List convertList(List list);
-
- PageResult convertPage(PageResult page);
-
- List convertList02(List list);
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java
new file mode 100644
index 000000000..a318e9128
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.product.convert.brand;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandRespVO;
+import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 品牌 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface ProductBrandConvert {
+
+ ProductBrandConvert INSTANCE = Mappers.getMapper(ProductBrandConvert.class);
+
+ ProductBrandDO convert(ProductBrandCreateReqVO bean);
+
+ ProductBrandDO convert(ProductBrandUpdateReqVO bean);
+
+ ProductBrandRespVO convert(ProductBrandDO bean);
+
+ List convertList(List list);
+
+ PageResult convertPage(PageResult page);
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/CategoryConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/CategoryConvert.java
deleted file mode 100644
index 2b2cfe99c..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/CategoryConvert.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package cn.iocoder.yudao.module.product.convert.category;
-
-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.product.controller.admin.category.vo.*;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
-
-/**
- * 商品分类 Convert
- *
- * @author 芋道源码
- */
-@Mapper
-public interface CategoryConvert {
-
- CategoryConvert INSTANCE = Mappers.getMapper(CategoryConvert.class);
-
- CategoryDO convert(CategoryCreateReqVO bean);
-
- CategoryDO convert(CategoryUpdateReqVO bean);
-
- CategoryRespVO convert(CategoryDO bean);
-
- List convertList(List list);
-
- PageResult convertPage(PageResult page);
-
- List convertList02(List list);
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/ProductCategoryConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/ProductCategoryConvert.java
new file mode 100644
index 000000000..ae01ca9d5
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/ProductCategoryConvert.java
@@ -0,0 +1,32 @@
+package cn.iocoder.yudao.module.product.convert.category;
+
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryRespVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO;
+import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryRespVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 商品分类 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface ProductCategoryConvert {
+
+ ProductCategoryConvert INSTANCE = Mappers.getMapper(ProductCategoryConvert.class);
+
+ ProductCategoryDO convert(ProductCategoryCreateReqVO bean);
+
+ ProductCategoryDO convert(ProductCategoryUpdateReqVO bean);
+
+ ProductCategoryRespVO convert(ProductCategoryDO bean);
+
+ List convertList(List list);
+
+ List convertList03(List list);
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
index c44cdc841..52b82a2ea 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
@@ -1,13 +1,14 @@
package cn.iocoder.yudao.module.product.convert.property;
-import java.util.*;
-
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.ProductPropertyCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.*;
+
+import java.util.List;
/**
* 规格名称 Convert
@@ -23,12 +24,10 @@ public interface ProductPropertyConvert {
ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
- ProductPropertyRespVO convert(ProductPropertyDO bean);
+ ProductPropertyAndValueRespVO convert(ProductPropertyDO bean);
- List convertList(List list);
+ List