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 convertList(List list); - PageResult convertPage(PageResult page); - - List convertList02(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/propertyvalue/ProductPropertyValueConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java index 447b9a5ea..331ad623f 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java @@ -4,10 +4,12 @@ import java.util.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; -import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.*; /** * 规格值 Convert diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java index 232ce3178..0ee468d36 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java @@ -1,17 +1,13 @@ package cn.iocoder.yudao.module.product.convert.sku; -import java.util.*; - -import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.mapstruct.Named; import org.mapstruct.factory.Mappers; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import org.springframework.util.StringUtils; + +import java.util.List; /** * 商品sku Convert @@ -23,38 +19,13 @@ public interface ProductSkuConvert { ProductSkuConvert INSTANCE = Mappers.getMapper(ProductSkuConvert.class); - @Mapping(source = "properties", target = "properties", qualifiedByName = "translateStringFromList") - ProductSkuDO convert(ProductSkuCreateReqVO bean); + ProductSkuDO convert(ProductSkuCreateOrUpdateReqVO bean); - @Mapping(source = "properties", target = "properties", qualifiedByName = "translateStringFromList") - ProductSkuDO convert(ProductSkuUpdateReqVO bean); - - @Mapping(source = "properties", target = "properties", qualifiedByName = "tokenizeToBeanArray") + @Mapping(source = "properties", target = "properties") ProductSkuRespVO convert(ProductSkuDO bean); - @Mapping(source = "properties", target = "properties", qualifiedByName = "tokenizeToExcelBeanArray") - ProductSkuExcelVO convertToExcelVO(ProductSkuDO bean); - List convertList(List list); - List convertSkuDOList(List list); + List convertSkuDOList(List list); - PageResult convertPage(PageResult page); - - List convertList02(List list); - - @Named("tokenizeToBeanArray") - default List translatePropertyArrayFromString(String properties) { - return JSONUtil.toList(properties, ProductSkuBaseVO.Property.class); - } - - @Named("tokenizeToExcelBeanArray") - default List translateExcelPropertyArrayFromString(String properties) { - return JSONUtil.toList(properties, ProductSkuExcelVO.Property.class); - } - - @Named("translateStringFromList") - default String translatePropertyStringFromList(List properties) { - return JSONUtil.toJsonStr(properties); - } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java index 92efaf0e8..2fb6639ab 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java @@ -1,16 +1,14 @@ package cn.iocoder.yudao.module.product.convert.spu; -import java.util.*; - import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.Named; -import org.mapstruct.factory.Mappers; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import org.springframework.util.StringUtils; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; /** * 商品spu Convert @@ -22,31 +20,18 @@ public interface ProductSpuConvert { ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class); - @Mapping(source = "picUrls", target = "picUrls", qualifiedByName = "translatePicUrlsFromStringList") ProductSpuDO convert(ProductSpuCreateReqVO bean); - @Mapping(source = "picUrls", target = "picUrls", qualifiedByName = "translatePicUrlsFromStringList") - ProductSpuDO convert(SpuUpdateReqVO bean); + ProductSpuDO convert(ProductSpuUpdateReqVO bean); - @Mapping(source = "picUrls", target = "picUrls", qualifiedByName = "tokenizeToStringArray") - SpuRespVO convert(ProductSpuDO bean); + ProductSpuRespVO convert(ProductSpuDO bean); - @Mapping(source = "picUrls", target = "picUrls", qualifiedByName = "tokenizeToStringArray") - SpuExcelVO convertToExcelVO(ProductSpuDO bean); + List convertList(List list); - List convertList(List list); + PageResult convertPage(PageResult page); - PageResult convertPage(PageResult page); + ProductSpuPageReqVO convert(AppSpuPageReqVO bean); - List convertList02(List list); + AppSpuPageRespVO convertAppResp(ProductSpuDO list); - @Named("tokenizeToStringArray") - default List translatePicUrlsArrayFromString(String picUrls) { - return Arrays.asList(StringUtils.tokenizeToStringArray(picUrls, ",")); - } - - @Named("translatePicUrlsFromStringList") - default String translatePicUrlsFromList(List picUrls) { - return StringUtils.collectionToCommaDelimitedString(picUrls); - } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/BrandDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java similarity index 83% rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/BrandDO.java rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java index 2cbcee877..9775f36a5 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/BrandDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java @@ -6,9 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -// TODO @JeromeSoar:Product 前缀 /** - * 品牌 DO + * 商品品牌 DO * * @author 芋道源码 */ @@ -19,17 +18,13 @@ import lombok.*; @Builder @NoArgsConstructor @AllArgsConstructor -public class BrandDO extends BaseDO { +public class ProductBrandDO extends BaseDO { /** * 品牌编号 */ @TableId private Long id; - /** - * 分类编号 - */ - private Long categoryId; /** * 品牌名称 */ @@ -37,7 +32,7 @@ public class BrandDO extends BaseDO { /** * 品牌图片 */ - private String bannerUrl; + private String picUrl; /** * 品牌排序 */ @@ -53,4 +48,6 @@ public class BrandDO extends BaseDO { */ private Integer status; + // TODO 芋艿:firstLetter 首字母 + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/CategoryDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java similarity index 66% rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/CategoryDO.java rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java index c6eb655ab..6671e9b44 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/CategoryDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java @@ -6,10 +6,13 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -// TODO @JeromeSoar:Product 前缀 /** * 商品分类 DO * + * 商品分类一共两类: + * 1)一级分类:{@link #parentId} 等于 0 + * 2)二级 + 三级分类:{@link #parentId} 不等于 0 + * * @author 芋道源码 */ @TableName("product_category") @@ -19,7 +22,12 @@ import lombok.*; @Builder @NoArgsConstructor @AllArgsConstructor -public class CategoryDO extends BaseDO { +public class ProductCategoryDO extends BaseDO { + + /** + * 父分类编号 - 根分类 + */ + public static final Long PARENT_ID_NULL = 0L; /** * 分类编号 @@ -35,15 +43,12 @@ public class CategoryDO extends BaseDO { */ private String name; /** - * 分类图标 - */ - private String icon; - /** - * 分类 Banner 图片 + * 分类图片 * - * 第一层的商品分类,会有该字段,用于用户 App 展示 + * 一级分类:推荐 200 x 100 分辨率 + * 二级 + 三级分类:推荐 100 x 100 分辨率 */ - private String bannerUrl; + private String picUrl; /** * 分类排序 */ @@ -59,4 +64,6 @@ public class CategoryDO extends BaseDO { */ private Integer status; + // TODO 芋艿:is_recommend 是否首页推荐:1-是;0-否 + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java new file mode 100644 index 000000000..30db12819 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java @@ -0,0 +1,129 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.comment; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.enums.comment.ProductCommentAuditStatusEnum; +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.*; + +import java.util.Date; +import java.util.List; + +/** + * 商品评论 DO + * + * @author 芋道源码 + */ +@TableName("product_comment") +@KeySequence("product_comment_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductCommentDO extends BaseDO { + + /** + * 评论编号,主键自增 + */ + @TableId + private Long id; + /** + * 商品 SPU 编号 + * + * 关联 {@link ProductSpuDO#getId()} + */ + private Long spuId; + /** + * 交易订单编号 + * + * 关联 TradeOrderDO 的 id 编号 + */ + private Long orderId; + /** + * 交易订单项编号 + * + * 关联 TradeOrderItemDO 的 id 编号 + */ + private Long orderItemId; + /** + * 审核状态 + * + * 枚举 {@link ProductCommentAuditStatusEnum} + */ + private Integer auditStatus; + + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + /** + * 用户 IP + */ + private String userIp; + /** + * 是否匿名 + */ + private Boolean anonymous; + /** + * 评论内容 + */ + private String content; + /** + * 评论图片地址数组 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List picUrls; + /** + * 描述相符星级 + * + * 1-5 星 + */ + private Integer descriptionScore; + /** + * 商品评论星级 + * + * 1-5 星 + */ + private Integer productScore; + /** + * 服务评论星级 + * + * 1-5 星 + */ + private Integer serviceScore; + /** + * 物流评论星级 + * + * 1-5 星 + */ + private Integer expressComment; + + /** + * 商家是否回复 + */ + private Boolean replied; + /** + * 商家回复内容 + */ + private String replyContent; + /** + * 商家回复时间 + */ + private Date replyTime; + + /** + * 有用的计数 + * + * 其他用户看到评论时,可点击「有用」按钮 + */ + private Integer usefulCount; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/delivery/DeliveryTemplateDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/delivery/DeliveryTemplateDO.java new file mode 100644 index 000000000..70445dc01 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/delivery/DeliveryTemplateDO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.delivery; + +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.*; + +/** + * 配送模板 SPU DO + * + * @author 芋道源码 + */ +@TableName("delivery_template") +@KeySequence("delivery_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeliveryTemplateDO extends BaseDO { + + /** + * 编号,自增 + */ + @TableId + private Long id; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java new file mode 100644 index 000000000..54d4b31ac --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.favorite; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商品收藏 DO + * + * @author 芋道源码 + */ +@TableName("product_favorite") +@KeySequence("product_favorite_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductFavoriteDO extends BaseDO { + + /** + * 编号,主键自增 + */ + @TableId + private Long id; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + /** + * 商品 SPU 编号 + * + * 关联 {@link ProductSpuDO#getId()} + */ + private Long spuId; + + // TODO 芋艿:type 1 收藏;2 点赞 + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/group/ProductGroupBindDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/group/ProductGroupBindDO.java new file mode 100644 index 000000000..2e3b63e59 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/group/ProductGroupBindDO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.group; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商品分组的绑定 DO + * + * @author 芋道源码 + */ +@TableName("product_group_bind") +@KeySequence("product_group_bind_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductGroupBindDO extends BaseDO { + + /** + * 编号,自增 + */ + @TableId + private Long id; + /** + * 商品分组编号 + * + * 关联 {@link ProductGroupDO#getId()} + */ + private Long groupId; + /** + * 商品 SPU 编号 + * + * 关联 {@link ProductSpuDO#getId()} + */ + private Long spuId; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/group/ProductGroupDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/group/ProductGroupDO.java new file mode 100644 index 000000000..605e8c38a --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/group/ProductGroupDO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.group; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.enums.group.ProductGroupStyleEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商品分组 DO + * + * @author 芋道源码 + */ +@TableName("product_group") +@KeySequence("product_group_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductGroupDO extends BaseDO { + + /** + * 商品分组编号,自增 + */ + @TableId + private Long id; + /** + * 分组名称 + */ + private String name; + /** + * 状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + /** + * 商品数量 + */ + private Integer count; + /** + * 排序 + */ + private Integer sort; + /** + * 风格,用于 APP 首页展示商品的样式 + * + * 枚举 {@link ProductGroupStyleEnum} + */ + private Integer style; + /** + * 是否默认 + * + * true - 系统默认,不允许删除 + * false - 自定义,允许删除 + */ + private Boolean defaulted; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java index 5255c36ed..608b248fe 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java @@ -32,10 +32,12 @@ public class ProductPropertyDO extends BaseDO { */ private String name; /** - * 状态: 0 开启 ,1 禁用 + * 状态 * - * {@link CommonStatusEnum} + * 枚举 {@link CommonStatusEnum} */ private Integer status; + // TODO 芋艿:rule;规格属性 (发布商品时,和 SKU 关联);规格参数(搜索商品时,与 Category 关联搜索) + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java index 0203939cc..007b95a4f 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.product.dal.dataobject.property; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; @@ -28,9 +29,9 @@ public class ProductPropertyValueDO extends BaseDO { @TableId private Long id; /** - * 规格键 id + * 规格键编号 * - * TODO @franky:加个 关联 {@link ProductPropertyDO#getId()} ,这样就能更好的知道 + * 关联 {@link ProductPropertyDO#getId()} */ private Long propertyId; /** @@ -38,7 +39,9 @@ public class ProductPropertyValueDO extends BaseDO { */ private String name; /** - * 状态: 1 开启 ,2 禁用 + * 状态 + * + * 枚举 {@link CommonStatusEnum} */ private Integer status; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/search/ProductHotSearchDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/search/ProductHotSearchDO.java new file mode 100644 index 000000000..3d5cf9101 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/search/ProductHotSearchDO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.search; + +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.*; + +/** + * 商品热搜关键字 DO + * + * @author 芋道源码 + */ +@TableName("product_hot_search") +@KeySequence("product_hot_search_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductHotSearchDO extends BaseDO { + + /** + * 编号,主键自增 + */ + @TableId + private Long id; + /** + * 关键字 + */ + private String name; + /** + * 内容 + */ + private String content; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/shop/ShopDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/shop/ShopDO.java new file mode 100644 index 000000000..1c702da91 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/shop/ShopDO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.shop; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +// TODO 芋艿:待设计 +/** + * 店铺 DO + * + * @author 芋道源码 + */ +@TableName("shop") +@KeySequence("shop_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ShopDO extends BaseDO { + + private Long id; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java index 1ffaaeef2..fc7bbe9ec 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java @@ -1,17 +1,26 @@ package cn.iocoder.yudao.module.product.dal.dataobject.sku; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 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.AbstractJsonTypeHandler; import lombok.*; +import java.util.List; + /** - * 商品sku DO + * 商品 SKU DO * * @author 芋道源码 */ -@TableName("product_sku") +@TableName(value = "product_sku",autoResultMap = true) @KeySequence("product_sku_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @@ -22,33 +31,39 @@ import lombok.*; public class ProductSkuDO extends BaseDO { /** - * 主键 + * 商品 SKU 编号,自增 */ @TableId private Long id; /** - * spu编号 + * 商品 SKU 名字 + */ + private String name; + /** + * SPU 编号 + *

+ * 关联 {@link ProductSpuDO#getId()} */ private Long spuId; /** - * 规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }] + * 规格值数组,JSON 格式 */ - // TODO franky:可以定义一个内部的 Property 类,然后 List - private String properties; + @TableField(typeHandler = PropertyTypeHandler.class) + private List properties; /** * 销售价格,单位:分 */ private Integer price; /** - * 原价,单位:分 + * 市场价,单位:分 */ - private Integer originalPrice; + private Integer marketPrice; /** - * 成本价,单位: 分 + * 成本价,单位:分 */ private Integer costPrice; /** - * 条形码 + * SKU 的条形码 */ private String barCode; /** @@ -56,9 +71,77 @@ public class ProductSkuDO extends BaseDO { */ private String picUrl; /** - * 状态: 0-正常 1-禁用 + * 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 { + + /** + * 属性编号 + *

+ * 关联 {@link ProductPropertyDO#getId()} + */ + private Long propertyId; + /** + * 属性值编号 + *

+ * 关联 {@link ProductPropertyValueDO#getId()} + */ + private Long valueId; + + } + + // TODO @芋艿:可以找一些新的思路 + public static class PropertyTypeHandler extends AbstractJsonTypeHandler { + + @Override + protected Object parse(String json) { + return JsonUtils.parseArray(json, Property.class); + } + + @Override + protected String toJson(Object obj) { + return JsonUtils.toJsonString(obj); + } + + } + + // TODO ========== 待定字段:yv ========= + // TODO brokerage:一级返佣 + // TODO brokerage_two:二级返佣 + // TODO pink_price:拼团价 + // TODO pink_stock:拼团库存 + // TODO seckill_price:秒杀价 + // TODO seckill_stock:秒杀库存 + // TODO integral:需要积分 + + // TODO ========== 待定字段:cf ========= + // TODO type 活动显示排序 0=默认 1=秒 2=砍价 3=拼团 + // TODO quota 活动限购数量 + // TODO quota_show 活动限购数量显示 } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java index 2da638077..a22b68a2c 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java @@ -1,17 +1,26 @@ package cn.iocoder.yudao.module.product.dal.dataobject.spu; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; 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.*; +import java.util.List; + /** - * 商品spu DO + * 商品 SPU DO * * @author 芋道源码 */ -@TableName("product_spu") +@TableName(value = "product_spu", autoResultMap = true) @KeySequence("product_spu_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @@ -22,50 +31,182 @@ import lombok.*; public class ProductSpuDO extends BaseDO { /** - * 主键 + * 商品 SPU 编号,自增 */ @TableId private Long id; + + // ========== 基本信息 ========= + /** * 商品名称 */ private String name; /** - * 卖点 + * 商品编码 + */ + private String code; + /** + * 商品卖点 */ private String sellPoint; /** - * 描述 + * 商品详情 */ private String description; /** - * 分类id + * 商品分类编号 + * + * 关联 {@link ProductCategoryDO#getId()} */ private Long categoryId; /** - * 商品主图地址,* 数组,以逗号分隔,最多上传15张 + * 商品品牌编号 + * + * 关联 {@link ProductBrandDO#getId()} */ - // TODO franky:List。可以参考别的模块,怎么处理这种类型的哈 - private String picUrls; + private Long brandId; + /** + * 商品图片的数组 + * + * 1. 第一张图片将作为商品主图,支持同时上传多张图; + * 2. 建议使用尺寸 800x800 像素以上、大小不超过 1M 的正方形图片; + * 3. 至少 1 张,最多上传 10 张 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List picUrls; + /** + * 商品视频 + */ + private String videoUrl; + /** * 排序字段 */ private Integer sort; /** - * 点赞初始人数 + * 商品状态 + * + * 枚举 {@link ProductSpuStatusEnum} */ - private Integer likeCount; + private Integer status; + + // ========== SKU 相关字段 ========= + /** - * 价格 单位使用:分 + * 规格类型 + * + * 枚举 {@link ProductSpuSpecTypeEnum} */ - private Integer price; + private Integer specType; /** - * 库存数量 + * 最小价格,单位使用:分 + * + * 基于其对应的 {@link ProductSkuDO#getPrice()} 最小值 */ - private Integer quantity; + private Integer minPrice; /** - * 上下架状态: 0 上架(开启) 1 下架(禁用) + * 最大价格,单位使用:分 + * + * 基于其对应的 {@link ProductSkuDO#getPrice()} 最大值 */ - private Boolean status; + private Integer maxPrice; + /** + * 市场价,单位使用:分 + * + * 基于其对应的 {@link ProductSkuDO#getMarketPrice()} 最大值 + */ + private Integer marketPrice; + /** + * 总库存 + * + * 基于其对应的 {@link ProductSkuDO#getStock()} 求和 + */ + private Integer totalStock; + /** + * 是否展示库存 + */ + private Boolean showStock; + + // ========== 统计相关字段 ========= + + /** + * 商品销量 + */ + private Integer salesCount; + /** + * 虚拟销量 + */ + private Integer virtualSalesCount; + /** + * 商品点击量 + */ + private Integer clickCount; + + // ========== 物流相关字段 ========= + + // TODO 芋艿:稍后完善物流的字段 +// /** +// * 配送方式 +// * +// * 枚举 {@link DeliveryModeEnum} +// */ +// private Integer deliveryMode; +// /** +// * 配置模板编号 +// * +// * 关联 {@link DeliveryTemplateDO#getId()} +// */ +// private Long deliveryTemplateId; + + // TODO ========== 待定字段:yv ========= + // TODO vip_price 会员价格 + // TODO postage 邮费 + // TODO is_postage 是否包邮 + // TODO unit_name 单位 + // TODO is_new 商户是否代理 + // TODO give_integral 获得积分 + // TODO is_integral 是开启积分兑换 + // TODO integral 所需积分 + // TODO is_seckill 秒杀状态 + // TODO is_bargain 砍价状态 + // TODO code_path 产品二维码地址 + // TODO is_sub 是否分佣 + + // TODO ↓↓ 芋艿 ↓↓ 看起来走分组更合适? + // TODO is_hot 是否热卖 + // TODO is_benefit 是否优惠 + // TODO is_best 是否精品 + // TODO is_new 是否新品 + // TODO is_good 是否优品推荐 + + // TODO ========== 待定字段:cf ========= + // TODO source_link 淘宝京东1688类型 + // TODO activity 活动显示排序 0=默认 1=秒 2=砍价 3=拼团 + + // TODO ========== 待定字段:lf ========= + + // TODO free_shipping_type:运费类型:1-包邮;2-统一运费;3-运费模板 + // TODO free_shipping:统一运费金额 + // TODO free_shipping_template_id:运费模板 + // TODO is_commission:分销佣金:1-开启;0-不开启;first_ratio second_ratio three_ratio + // TODO is_share_bouns:区域股东分红:1-开启;0-不开启;region_ratio;shareholder_ratio + + // TODO is_new:新品推荐:1-是;0-否 + // TODO is_best:好物优选:1-是;0-否 + // TODO is_like:猜你喜欢:1-是;0-否 + + // TODO is_team:是否开启拼团[0=否, 1=是] + // TODO is_integral:积分抵扣:1-开启;0-不开启 + // TODO is_member:会员价:1-开启;0-不开启 + // TODO give_integral_type:赠送积分类型:0-不赠送;1-赠送固定积分;2-按比例赠送积分 + // TODO give_integral:赠送积分; + + // TODO poster:商品自定义海报 + + // TODO ========== 待定字段:laoji ========= + // TODO productType 1 - 普通商品 2 - 预售商品;可能和 type 合并不错 + // TODO productUnit 商品单位 + // TODO extJson 扩展信息;例如说,预售商品的信息 } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/BrandMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/BrandMapper.java deleted file mode 100644 index cf7c5f69a..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/BrandMapper.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.brand; - -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.product.dal.dataobject.brand.BrandDO; -import org.apache.ibatis.annotations.Mapper; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; - -/** - * 品牌 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface BrandMapper extends BaseMapperX { - - default PageResult selectPage(BrandPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(BrandDO::getCategoryId, reqVO.getCategoryId()) - .likeIfPresent(BrandDO::getName, reqVO.getName()) - .eqIfPresent(BrandDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(BrandDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(BrandDO::getId)); - } - - default List selectList(BrandExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(BrandDO::getCategoryId, reqVO.getCategoryId()) - .likeIfPresent(BrandDO::getName, reqVO.getName()) - .eqIfPresent(BrandDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(BrandDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(BrandDO::getId)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java new file mode 100644 index 000000000..a62df7dc8 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.product.dal.mysql.brand; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface ProductBrandMapper extends BaseMapperX { + + default PageResult selectPage(ProductBrandPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ProductBrandDO::getName, reqVO.getName()) + .eqIfPresent(ProductBrandDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(ProductBrandDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ProductBrandDO::getId)); + } + + + default List selectList(ProductBrandListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(ProductBrandDO::getName, reqVO.getName())); + } + + default ProductBrandDO selectByName(String name) { + return selectOne(ProductBrandDO::getName, name); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/CategoryMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/CategoryMapper.java deleted file mode 100644 index e0f798e18..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/CategoryMapper.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.category; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryExportReqVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * 商品分类 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface CategoryMapper extends BaseMapperX { - - default PageResult selectPage(CategoryPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(CategoryDO::getName, reqVO.getName()) - .eqIfPresent(CategoryDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(CategoryDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(CategoryDO::getId)); - } - - default List selectList(CategoryExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(CategoryDO::getName, reqVO.getName()) - .eqIfPresent(CategoryDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(CategoryDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(CategoryDO::getId)); - } - - default Long selectCountByParentId(Long parentId) { - return selectCount(CategoryDO::getParentId, parentId); - } -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java new file mode 100644 index 000000000..8130d5a46 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.product.dal.mysql.category; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 商品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ProductCategoryMapper extends BaseMapperX { + + default List selectList(ProductCategoryListReqVO listReqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(ProductCategoryDO::getName, listReqVO.getName()) + .orderByDesc(ProductCategoryDO::getId)); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(ProductCategoryDO::getParentId, parentId); + } + + default List selectListByStatus(Integer status) { + return selectList(ProductCategoryDO::getStatus, status); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java index 28f4ea51c..bd088466f 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java @@ -1,13 +1,11 @@ package cn.iocoder.yudao.module.product.dal.mysql.property; -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.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; import org.apache.ibatis.annotations.Mapper; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.*; /** * 规格名称 Mapper @@ -25,12 +23,4 @@ public interface ProductPropertyMapper extends BaseMapperX { .orderByDesc(ProductPropertyDO::getId)); } - default List selectList(ProductPropertyExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(ProductPropertyDO::getName, reqVO.getName()) - .eqIfPresent(ProductPropertyDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ProductPropertyDO::getId)); - } - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/propertyvalue/ProductPropertyValueMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java similarity index 95% rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/propertyvalue/ProductPropertyValueMapper.java rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java index 5c11a9f42..6c5fc7570 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/propertyvalue/ProductPropertyValueMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.product.dal.mysql.propertyvalue; +package cn.iocoder.yudao.module.product.dal.mysql.property; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java index 2f2ced33c..cc45e5764 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java @@ -1,55 +1,27 @@ package cn.iocoder.yudao.module.product.dal.mysql.sku; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuExportReqVO; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuPageReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** - * 商品sku Mapper + * 商品 SKU Mapper * * @author 芋道源码 */ @Mapper public interface ProductSkuMapper extends BaseMapperX { - default PageResult selectPage(ProductSkuPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(ProductSkuDO::getSpuId, reqVO.getSpuId()) - .eqIfPresent(ProductSkuDO::getProperties, reqVO.getProperties()) - .eqIfPresent(ProductSkuDO::getPrice, reqVO.getPrice()) - .eqIfPresent(ProductSkuDO::getOriginalPrice, reqVO.getOriginalPrice()) - .eqIfPresent(ProductSkuDO::getCostPrice, reqVO.getCostPrice()) - .eqIfPresent(ProductSkuDO::getBarCode, reqVO.getBarCode()) - .eqIfPresent(ProductSkuDO::getPicUrl, reqVO.getPicUrl()) - .eqIfPresent(ProductSkuDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(ProductSkuDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ProductSkuDO::getId)); - } - - default List selectList(ProductSkuExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(ProductSkuDO::getSpuId, reqVO.getSpuId()) - .eqIfPresent(ProductSkuDO::getProperties, reqVO.getProperties()) - .eqIfPresent(ProductSkuDO::getPrice, reqVO.getPrice()) - .eqIfPresent(ProductSkuDO::getOriginalPrice, reqVO.getOriginalPrice()) - .eqIfPresent(ProductSkuDO::getCostPrice, reqVO.getCostPrice()) - .eqIfPresent(ProductSkuDO::getBarCode, reqVO.getBarCode()) - .eqIfPresent(ProductSkuDO::getPicUrl, reqVO.getPicUrl()) - .eqIfPresent(ProductSkuDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(ProductSkuDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ProductSkuDO::getId)); - } - // TODO @franky:方法名 selectList; 可以直接调用 selectList - default List selectBySpuIds(List spuIds) { - return selectList(new LambdaQueryWrapperX() - .inIfPresent(ProductSkuDO::getSpuId, spuIds)); + default List selectListBySpuIds(List spuIds) { + return selectList(ProductSkuDO::getSpuId, spuIds); + } + + default List selectListBySpuId(Long spuId) { + return selectList(ProductSkuDO::getSpuId, spuId); } default void deleteBySpuId(Long spuId) { @@ -58,4 +30,5 @@ public interface ProductSkuMapper extends BaseMapperX { .eqIfPresent(ProductSkuDO::getSpuId, spuId); delete(lambdaQueryWrapperX); } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java index 72fb68b29..1755695cb 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java @@ -1,13 +1,11 @@ package cn.iocoder.yudao.module.product.dal.mysql.spu; -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.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import org.apache.ibatis.annotations.Mapper; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; /** * 商品spu Mapper @@ -17,36 +15,15 @@ import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; @Mapper public interface ProductSpuMapper extends BaseMapperX { - default PageResult selectPage(SpuPageReqVO reqVO) { + default PageResult selectPage(ProductSpuPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(ProductSpuDO::getName, reqVO.getName()) .eqIfPresent(ProductSpuDO::getSellPoint, reqVO.getSellPoint()) - .eqIfPresent(ProductSpuDO::getDescription, reqVO.getDescription()) .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId()) .eqIfPresent(ProductSpuDO::getPicUrls, reqVO.getPicUrls()) - .eqIfPresent(ProductSpuDO::getSort, reqVO.getSort()) - .eqIfPresent(ProductSpuDO::getLikeCount, reqVO.getLikeCount()) - .eqIfPresent(ProductSpuDO::getPrice, reqVO.getPrice()) - .eqIfPresent(ProductSpuDO::getQuantity, reqVO.getQuantity()) .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus()) .betweenIfPresent(ProductSpuDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ProductSpuDO::getId)); - } - - default List selectList(SpuExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(ProductSpuDO::getName, reqVO.getName()) - .eqIfPresent(ProductSpuDO::getSellPoint, reqVO.getSellPoint()) - .eqIfPresent(ProductSpuDO::getDescription, reqVO.getDescription()) - .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId()) - .eqIfPresent(ProductSpuDO::getPicUrls, reqVO.getPicUrls()) - .eqIfPresent(ProductSpuDO::getSort, reqVO.getSort()) - .eqIfPresent(ProductSpuDO::getLikeCount, reqVO.getLikeCount()) - .eqIfPresent(ProductSpuDO::getPrice, reqVO.getPrice()) - .eqIfPresent(ProductSpuDO::getQuantity, reqVO.getQuantity()) - .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(ProductSpuDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ProductSpuDO::getId)); + .orderByDesc(ProductSpuDO::getSort)); } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java index 4e80cc2bc..117f35931 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java @@ -1,7 +1,8 @@ /** - * TODO + * trade 模块,主要实现交易相关功能 + * 例如:订单、退款、购物车等功能。 * - * @author JeromeSoar - * @since 2022-04-24 + * 1. Controller URL:以 /trade/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 trade_ 开头,方便在数据库中区分 */ -package cn.iocoder.yudao.module.product; \ No newline at end of file +package cn.iocoder.yudao.module.product; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/BrandServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/BrandServiceImpl.java deleted file mode 100644 index dedda3ae2..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/BrandServiceImpl.java +++ /dev/null @@ -1,82 +0,0 @@ -package cn.iocoder.yudao.module.product.service.brand; - -import org.springframework.stereotype.Service; -import javax.annotation.Resource; -import org.springframework.validation.annotation.Validated; - -import java.util.*; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.BrandDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import cn.iocoder.yudao.module.product.convert.brand.BrandConvert; -import cn.iocoder.yudao.module.product.dal.mysql.brand.BrandMapper; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; - -/** - * 品牌 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class BrandServiceImpl implements BrandService { - - @Resource - private BrandMapper brandMapper; - - @Override - public Long createBrand(BrandCreateReqVO createReqVO) { - // 插入 - BrandDO brand = BrandConvert.INSTANCE.convert(createReqVO); - brandMapper.insert(brand); - // 返回 - return brand.getId(); - } - - @Override - public void updateBrand(BrandUpdateReqVO updateReqVO) { - // 校验存在 - this.validateBrandExists(updateReqVO.getId()); - // 更新 - BrandDO updateObj = BrandConvert.INSTANCE.convert(updateReqVO); - brandMapper.updateById(updateObj); - } - - @Override - public void deleteBrand(Long id) { - // 校验存在 - this.validateBrandExists(id); - // 删除 - brandMapper.deleteById(id); - } - - private void validateBrandExists(Long id) { - if (brandMapper.selectById(id) == null) { - throw exception(BRAND_NOT_EXISTS); - } - } - - @Override - public BrandDO getBrand(Long id) { - return brandMapper.selectById(id); - } - - @Override - public List getBrandList(Collection ids) { - return brandMapper.selectBatchIds(ids); - } - - @Override - public PageResult getBrandPage(BrandPageReqVO pageReqVO) { - return brandMapper.selectPage(pageReqVO); - } - - @Override - public List getBrandList(BrandExportReqVO exportReqVO) { - return brandMapper.selectList(exportReqVO); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/BrandService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java similarity index 51% rename from yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/BrandService.java rename to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java index 2cb356fed..a90ec8a87 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/BrandService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java @@ -1,17 +1,19 @@ package cn.iocoder.yudao.module.product.service.brand; -import java.util.*; -import javax.validation.*; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.BrandDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; /** - * 品牌 Service 接口 + * 商品品牌 Service 接口 * * @author 芋道源码 */ -public interface BrandService { +public interface ProductBrandService { /** * 创建品牌 @@ -19,14 +21,14 @@ public interface BrandService { * @param createReqVO 创建信息 * @return 编号 */ - Long createBrand(@Valid BrandCreateReqVO createReqVO); + Long createBrand(@Valid ProductBrandCreateReqVO createReqVO); /** * 更新品牌 * * @param updateReqVO 更新信息 */ - void updateBrand(@Valid BrandUpdateReqVO updateReqVO); + void updateBrand(@Valid ProductBrandUpdateReqVO updateReqVO); /** * 删除品牌 @@ -41,7 +43,7 @@ public interface BrandService { * @param id 编号 * @return 品牌 */ - BrandDO getBrand(Long id); + ProductBrandDO getBrand(Long id); /** * 获得品牌列表 @@ -49,7 +51,22 @@ public interface BrandService { * @param ids 编号 * @return 品牌列表 */ - List getBrandList(Collection ids); + List getBrandList(Collection ids); + + /** + * 获得品牌列表 + * + * @param listReqVO 请求参数 + * @return 品牌列表 + */ + List getBrandList(ProductBrandListReqVO listReqVO); + + /** + * 验证选择的商品分类是否合法 + * + * @param id 分类编号 + */ + void validateProductBrand(Long id); /** * 获得品牌分页 @@ -57,14 +74,6 @@ public interface BrandService { * @param pageReqVO 分页查询 * @return 品牌分页 */ - PageResult getBrandPage(BrandPageReqVO pageReqVO); - - /** - * 获得品牌列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 品牌列表 - */ - List getBrandList(BrandExportReqVO exportReqVO); + PageResult getBrandPage(ProductBrandPageReqVO pageReqVO); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java new file mode 100644 index 000000000..c7a3e5198 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.module.product.service.brand; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +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.ProductBrandListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO; +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.dal.mysql.brand.ProductBrandMapper; +import com.google.common.annotations.VisibleForTesting; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; + +/** + * 品牌 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ProductBrandServiceImpl implements ProductBrandService { + + @Resource + private ProductBrandMapper brandMapper; + + @Override + public Long createBrand(ProductBrandCreateReqVO createReqVO) { + // 校验 + validateBrandNameUnique(null, createReqVO.getName()); + + // 插入 + ProductBrandDO brand = ProductBrandConvert.INSTANCE.convert(createReqVO); + brandMapper.insert(brand); + // 返回 + return brand.getId(); + } + + @Override + public void updateBrand(ProductBrandUpdateReqVO updateReqVO) { + // 校验存在 + validateBrandExists(updateReqVO.getId()); + validateBrandNameUnique(updateReqVO.getId(), updateReqVO.getName()); + // 更新 + ProductBrandDO updateObj = ProductBrandConvert.INSTANCE.convert(updateReqVO); + brandMapper.updateById(updateObj); + } + + @Override + public void deleteBrand(Long id) { + // 校验存在 + validateBrandExists(id); + // 删除 + brandMapper.deleteById(id); + } + + private void validateBrandExists(Long id) { + if (brandMapper.selectById(id) == null) { + throw exception(BRAND_NOT_EXISTS); + } + } + + @VisibleForTesting + public void validateBrandNameUnique(Long id, String name) { + ProductBrandDO brand = brandMapper.selectByName(name); + if (brand == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的字典类型 + if (id == null) { + throw exception(BRAND_NAME_EXISTS); + } + if (!brand.getId().equals(id)) { + throw exception(BRAND_NAME_EXISTS); + } + } + + @Override + public ProductBrandDO getBrand(Long id) { + return brandMapper.selectById(id); + } + + @Override + public List getBrandList(Collection ids) { + return brandMapper.selectBatchIds(ids); + } + + @Override + public List getBrandList(ProductBrandListReqVO listReqVO) { + return brandMapper.selectList(listReqVO); + } + + @Override + public void validateProductBrand(Long id) { + ProductBrandDO brand = brandMapper.selectById(id); + if (brand == null) { + throw exception(BRAND_NOT_EXISTS); + } + if (brand.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { + throw exception(BRAND_DISABLED); + } + } + + @Override + public PageResult getBrandPage(ProductBrandPageReqVO pageReqVO) { + return brandMapper.selectPage(pageReqVO); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java deleted file mode 100644 index 4df2f19f9..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java +++ /dev/null @@ -1,86 +0,0 @@ -package cn.iocoder.yudao.module.product.service.category; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; - -import javax.validation.Valid; -import java.util.Collection; -import java.util.List; - -// TODO @JeromeSoar:需要 Product 前缀 -/** - * 商品分类 Service 接口 - * - * @author 芋道源码 - */ -public interface CategoryService { - - /** - * 创建商品分类 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createCategory(@Valid CategoryCreateReqVO createReqVO); - - /** - * 更新商品分类 - * - * @param updateReqVO 更新信息 - */ - void updateCategory(@Valid CategoryUpdateReqVO updateReqVO); - - /** - * 删除商品分类 - * - * @param id 编号 - */ - void deleteCategory(Long id); - - /** - * 获得商品分类 - * - * @param id 编号 - * @return 商品分类 - */ - CategoryDO getCategory(Long id); - - /** - * 获得商品分类列表 - * - * @param ids 编号 - * @return 商品分类列表 - */ - List getCategoryList(Collection ids); - - /** - * 获得商品分类分页 - * - * @param pageReqVO 分页查询 - * @return 商品分类分页 - */ - PageResult getCategoryPage(CategoryPageReqVO pageReqVO); - - /** - * 获得商品分类列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 商品分类列表 - */ - List getCategoryList(CategoryExportReqVO exportReqVO); - - /** - * 获得商品分类列表 - * - * @param treeListReqVO 查询条件 - * @return 商品分类列表 - */ - List getCategoryTreeList(CategoryTreeListReqVO treeListReqVO); - - /** - * 验证选择的分类的合法性 - * @param categoryId 分类id - */ - void validatedCategoryById(Long categoryId); -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java deleted file mode 100644 index 3fa441b66..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java +++ /dev/null @@ -1,109 +0,0 @@ -package cn.iocoder.yudao.module.product.service.category; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -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.dal.mysql.category.CategoryMapper; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; - -/** - * 商品分类 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class CategoryServiceImpl implements CategoryService { - - @Resource - private CategoryMapper categoryMapper; - - @Override - public Long createCategory(CategoryCreateReqVO createReqVO) { - // 校验父分类存在 - this.validateCategoryExists(createReqVO.getParentId(), CATEGORY_PARENT_NOT_EXISTS); - // 插入 - CategoryDO category = CategoryConvert.INSTANCE.convert(createReqVO); - categoryMapper.insert(category); - // 返回 - return category.getId(); - } - - @Override - public void updateCategory(CategoryUpdateReqVO updateReqVO) { - // 校验父分类存在 - this.validateCategoryExists(updateReqVO.getParentId(), CATEGORY_PARENT_NOT_EXISTS); - // 校验分类是否存在 - this.validateCategoryExists(updateReqVO.getId(), CATEGORY_NOT_EXISTS); - // 更新 - CategoryDO updateObj = CategoryConvert.INSTANCE.convert(updateReqVO); - categoryMapper.updateById(updateObj); - } - - @Override - public void deleteCategory(Long id) { - // TODO 芋艿 补充只有不存在商品才可以删除 - // 校验分类是否存在 - CategoryDO categoryDO = this.validateCategoryExists(id, CATEGORY_NOT_EXISTS); - // 校验是否还有子分类 - if (categoryMapper.selectCountByParentId(categoryDO.getParentId()) > 0) { - throw ServiceExceptionUtil.exception(CATEGORY_EXISTS_CHILDREN); - } - // 删除 - categoryMapper.deleteById(id); - } - - private CategoryDO validateCategoryExists(Long id, ErrorCode errorCode) { - // TODO franky:0 要枚举哈 - if (id == 0) { - return new CategoryDO().setId(id); - } - CategoryDO categoryDO = categoryMapper.selectById(id); - if (categoryDO == null) { - throw exception(errorCode); - } - return categoryDO; - } - - @Override - public void validatedCategoryById(Long categoryId) { - this.validateCategoryExists(categoryId, CATEGORY_NOT_EXISTS); - } - - @Override - public CategoryDO getCategory(Long id) { - return categoryMapper.selectById(id); - } - - @Override - public List getCategoryList(Collection ids) { - return categoryMapper.selectBatchIds(ids); - } - - @Override - public PageResult getCategoryPage(CategoryPageReqVO pageReqVO) { - return categoryMapper.selectPage(pageReqVO); - } - - @Override - public List getCategoryList(CategoryExportReqVO exportReqVO) { - return categoryMapper.selectList(exportReqVO); - } - - @Override - public List getCategoryTreeList(CategoryTreeListReqVO treeListReqVO) { - return categoryMapper.selectList(treeListReqVO); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java new file mode 100644 index 000000000..118e8118b --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.product.service.category; + +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 商品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface ProductCategoryService { + + /** + * 创建商品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCategory(@Valid ProductCategoryCreateReqVO createReqVO); + + /** + * 更新商品分类 + * + * @param updateReqVO 更新信息 + */ + void updateCategory(@Valid ProductCategoryUpdateReqVO updateReqVO); + + /** + * 删除商品分类 + * + * @param id 编号 + */ + void deleteCategory(Long id); + + /** + * 获得商品分类 + * + * @param id 编号 + * @return 商品分类 + */ + ProductCategoryDO getCategory(Long id); + + /** + * 获得商品分类列表 + * + * @param ids 编号 + * @return 商品分类列表 + */ + List getEnableCategoryList(Collection ids); + + /** + * 获得商品分类列表 + * + * @param listReqVO 查询条件 + * @return 商品分类列表 + */ + List getEnableCategoryList(ProductCategoryListReqVO listReqVO); + + /** + * 验证选择的商品分类的级别是否合法 + * 例如说,商品发布的时候,必须在第 3 级别 + * + * @param id 分类编号 + */ + void validateCategoryLevel(Long id); + + /** + * 获得开启状态的商品分类列表 + * + * @return 商品分类列表 + */ + List getEnableCategoryList(); + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java new file mode 100644 index 000000000..ebfe599d6 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.product.service.category; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +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.dal.mysql.category.ProductCategoryMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; + +/** + * 商品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ProductCategoryServiceImpl implements ProductCategoryService { + + @Resource + private ProductCategoryMapper productCategoryMapper; + + @Override + public Long createCategory(ProductCategoryCreateReqVO createReqVO) { + // 校验父分类存在 + validateParentProductCategory(createReqVO.getParentId()); + + // 插入 + ProductCategoryDO category = ProductCategoryConvert.INSTANCE.convert(createReqVO); + productCategoryMapper.insert(category); + // 返回 + return category.getId(); + } + + @Override + public void updateCategory(ProductCategoryUpdateReqVO updateReqVO) { + // 校验分类是否存在 + validateProductCategoryExists(updateReqVO.getId()); + // 校验父分类存在 + validateParentProductCategory(updateReqVO.getParentId()); + + // 更新 + ProductCategoryDO updateObj = ProductCategoryConvert.INSTANCE.convert(updateReqVO); + productCategoryMapper.updateById(updateObj); + } + + @Override + public void deleteCategory(Long id) { + // 校验分类是否存在 + validateProductCategoryExists(id); + // 校验是否还有子分类 + if (productCategoryMapper.selectCountByParentId(id) > 0) { + throw exception(CATEGORY_EXISTS_CHILDREN); + } + // TODO 芋艿 补充只有不存在商品才可以删除 + // 删除 + productCategoryMapper.deleteById(id); + } + + private void validateParentProductCategory(Long id) { + // 如果是根分类,无需验证 + if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) { + return; + } + // 父分类不存在 + ProductCategoryDO category = productCategoryMapper.selectById(id); + if (category == null) { + throw exception(CATEGORY_PARENT_NOT_EXISTS); + } + // 父分类不能是二级分类 + if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) { + throw exception(CATEGORY_PARENT_NOT_FIRST_LEVEL); + } + } + + private void validateProductCategoryExists(Long id) { + ProductCategoryDO category = productCategoryMapper.selectById(id); + if (category == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + } + + @Override + public void validateCategoryLevel(Long id) { + Integer level = getProductCategoryLevel(id, 1); + if (level < 3){ + throw exception(CATEGORY_LEVEL_ERROR); + } + } + + // TODO @Luowenfeng:建议使用 for 循环,避免递归 + /** + * 获得商品分类的级别 + * + * @param id 商品分类的编号 + * @return 级别 + */ + private Integer getProductCategoryLevel(Long id, int level){ + ProductCategoryDO category = productCategoryMapper.selectById(id); + if (category == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + // TODO Luowenfeng:去掉是否开启,它不影响级别哈 + if (ObjectUtil.notEqual(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { + throw exception(CATEGORY_DISABLED); + } + // TODO Luowenfeng:不使用 0 直接比较哈,使用枚举 + if (category.getParentId() == 0) { + return level; + } + return getProductCategoryLevel(category.getParentId(), ++level); + } + + @Override + public ProductCategoryDO getCategory(Long id) { + return productCategoryMapper.selectById(id); + } + + @Override + public List getEnableCategoryList(Collection ids) { + return productCategoryMapper.selectBatchIds(ids); + } + + @Override + public List getEnableCategoryList(ProductCategoryListReqVO listReqVO) { + return productCategoryMapper.selectList(listReqVO); + } + + @Override + public List getEnableCategoryList() { + return productCategoryMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java index a663a49ce..a87e15d70 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java @@ -1,10 +1,13 @@ package cn.iocoder.yudao.module.product.service.property; -import java.util.*; -import javax.validation.*; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; /** * 规格名称 Service 接口 @@ -59,27 +62,21 @@ public interface ProductPropertyService { */ PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO); - /** - * 获得规格名称列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 规格名称列表 - */ - List getPropertyList(ProductPropertyExportReqVO exportReqVO); - /** * 获取属性及属性值列表 分页 * @param pageReqVO * @return */ - PageResult getPropertyListPage(ProductPropertyPageReqVO pageReqVO); + PageResult getPropertyListPage(ProductPropertyPageReqVO pageReqVO); - ProductPropertyRespVO getPropertyResp(Long id); + ProductPropertyAndValueRespVO getPropertyResp(Long id); /** - * 根据数据名id集合查询属性名以及属性值的集合 - * @param propertyIds 属性名id集合 - * @return + * 根据规格属性编号的集合,获得对应的规格 + 规格值的集合 + * + * @param ids 规格编号的集合 + * @return 对应的规格 + 规格值的集合 */ - List selectByIds(List propertyIds); + List getPropertyAndValueList(Collection ids); + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java index 9cb1a0da3..d48c8b1ff 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java @@ -1,15 +1,16 @@ package cn.iocoder.yudao.module.product.service.property; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.*; -import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert; import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper; -import cn.iocoder.yudao.module.product.dal.mysql.propertyvalue.ProductPropertyValueMapper; +import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -49,7 +50,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { //插入属性值 List propertyValueList = createReqVO.getPropertyValueList(); List productPropertyValueDOList = ProductPropertyValueConvert.INSTANCE.convertList03(propertyValueList); - productPropertyValueDOList.stream().forEach(x-> x.setPropertyId(property.getId())); + productPropertyValueDOList.forEach(x-> x.setPropertyId(property.getId())); productPropertyValueMapper.insertBatch(productPropertyValueDOList); // 返回 return property.getId(); @@ -67,7 +68,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { productPropertyValueMapper.deletePropertyValueByPropertyId(updateReqVO.getId()); List propertyValueList = updateReqVO.getPropertyValueList(); List productPropertyValueDOList = ProductPropertyValueConvert.INSTANCE.convertList03(propertyValueList); - productPropertyValueDOList.stream().forEach(x-> x.setPropertyId(updateReqVO.getId())); + productPropertyValueDOList.forEach(x-> x.setPropertyId(updateReqVO.getId())); productPropertyValueMapper.insertBatch(productPropertyValueDOList); } @@ -103,16 +104,11 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { } @Override - public List getPropertyList(ProductPropertyExportReqVO exportReqVO) { - return productPropertyMapper.selectList(exportReqVO); - } - - @Override - public PageResult getPropertyListPage(ProductPropertyPageReqVO pageReqVO) { + public PageResult getPropertyListPage(ProductPropertyPageReqVO pageReqVO) { //获取属性列表 PageResult pageResult = productPropertyMapper.selectPage(pageReqVO); - PageResult propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult); - List propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyRespVO::getId).collect(Collectors.toList()); + PageResult propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult); + List propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyAndValueRespVO::getId).collect(Collectors.toList()); //获取属性值列表 List productPropertyValueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(propertyIds); @@ -121,7 +117,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { propertyRespVOPageResult.getList().forEach(x->{ Long propertyId = x.getId(); List valueDOList = propertyValueRespVOList.stream().filter(v -> v.getPropertyId().equals(propertyId)).collect(Collectors.toList()); - x.setPropertyValueList(valueDOList); + x.setValues(valueDOList); }); return propertyRespVOPageResult; } @@ -131,25 +127,25 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { } @Override - public ProductPropertyRespVO getPropertyResp(Long id) { + public ProductPropertyAndValueRespVO getPropertyResp(Long id) { //查询规格 ProductPropertyDO property = getProperty(id); - ProductPropertyRespVO propertyRespVO = ProductPropertyConvert.INSTANCE.convert(property); + ProductPropertyAndValueRespVO propertyRespVO = ProductPropertyConvert.INSTANCE.convert(property); //查询属性值 List valueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(Arrays.asList(id)); List propertyValueRespVOS = ProductPropertyValueConvert.INSTANCE.convertList(valueDOList); //组装 - propertyRespVO.setPropertyValueList(propertyValueRespVOS); + propertyRespVO.setValues(propertyValueRespVOS); return propertyRespVO; } @Override - public List selectByIds(List propertyIds) { - List productPropertyRespVO = ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(propertyIds)); + public List getPropertyAndValueList(Collection ids) { + List productPropertyRespVO = ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(ids)); //查询属性值 - List valueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(propertyIds); + List valueDOList = productPropertyValueMapper.selectBatchIds(ids); Map> propertyValuesMap = valueDOList.stream().collect(Collectors.groupingBy(ProductPropertyValueDO::getPropertyId)); - productPropertyRespVO.forEach(p -> p.setPropertyValueList(ProductPropertyValueConvert.INSTANCE.convertList(propertyValuesMap.get(p.getId())))); + productPropertyRespVO.forEach(p -> p.setValues(ProductPropertyValueConvert.INSTANCE.convertList(propertyValuesMap.get(p.getId())))); return productPropertyRespVO; } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java index 0396506ef..5316f4764 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java @@ -1,10 +1,6 @@ package cn.iocoder.yudao.module.product.service.sku; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuExportReqVO; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuUpdateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import javax.validation.Valid; @@ -12,27 +8,12 @@ import java.util.Collection; import java.util.List; /** - * 商品sku Service 接口 + * 商品 SKU Service 接口 * * @author 芋道源码 */ public interface ProductSkuService { - /** - * 创建商品sku - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createSku(@Valid ProductSkuCreateReqVO createReqVO); - - /** - * 更新商品sku - * - * @param updateReqVO 更新信息 - */ - void updateSku(@Valid ProductSkuUpdateReqVO updateReqVO); - /** * 删除商品sku * @@ -56,35 +37,28 @@ public interface ProductSkuService { */ List getSkuList(Collection ids); - /** - * 获得商品sku分页 - * - * @param pageReqVO 分页查询 - * @return 商品sku分页 - */ - PageResult getSkuPage(ProductSkuPageReqVO pageReqVO); - - /** - * 获得商品sku列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 商品sku列表 - */ - List getSkuList(ProductSkuExportReqVO exportReqVO); - /** * 对 sku 的组合的属性等进行合法性校验 * * @param list sku组合的集合 */ - void validateSkus(List list); + void validateSkus(List list, Integer specType); /** - * 批量保存 sku + * 批量创建 SKU * - * @param list sku对象集合 + * @param spuId 商品 SPU 编号 + * @param list SKU 对象集合 */ - void createSkus(List list); + void createSkus(Long spuId, List list); + + /** + * 根据 SPU 编号,批量更新它的 SKU 信息 + * + * @param spuId SPU 编码 + * @param skus SKU 的集合 + */ + void updateProductSkus(Long spuId, List skus); /** * 获得商品 sku 集合 @@ -109,11 +83,4 @@ public interface ProductSkuService { */ void deleteSkuBySpuId(Long spuId); - /** - * 根据 spuId 更新 spu 下的 sku 信息 - * - * @param spuId spu 编码 - * @param skus sku 的集合 - */ - void updateSkus(Long spuId, List skus); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java index 91a60929b..bf8dab778 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java @@ -1,14 +1,17 @@ package cn.iocoder.yudao.module.product.service.sku; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyRespVO; -import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,11 +22,10 @@ import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_NOT_EXISTS; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; /** - * 商品sku Service 实现类 + * 商品 SKU Service 实现类 * * @author 芋道源码 */ @@ -37,24 +39,6 @@ public class ProductSkuServiceImpl implements ProductSkuService { @Resource private ProductPropertyService productPropertyService; - @Override - public Long createSku(ProductSkuCreateReqVO createReqVO) { - // 插入 - ProductSkuDO sku = ProductSkuConvert.INSTANCE.convert(createReqVO); - productSkuMapper.insert(sku); - // 返回 - return sku.getId(); - } - - @Override - public void updateSku(ProductSkuUpdateReqVO updateReqVO) { - // 校验存在 - this.validateSkuExists(updateReqVO.getId()); - // 更新 - ProductSkuDO updateObj = ProductSkuConvert.INSTANCE.convert(updateReqVO); - productSkuMapper.updateById(updateObj); - } - @Override public void deleteSku(Long id) { // 校验存在 @@ -80,61 +64,65 @@ public class ProductSkuServiceImpl implements ProductSkuService { } @Override - public PageResult getSkuPage(ProductSkuPageReqVO pageReqVO) { - return productSkuMapper.selectPage(pageReqVO); - } - - @Override - public List getSkuList(ProductSkuExportReqVO exportReqVO) { - return productSkuMapper.selectList(exportReqVO); - } - - // TODO @franky:这个方法,貌似实现的还是有点问题哈。例如说,throw 异常,后面还执行逻辑~ - // TODO @艿艿 咳咳,throw 那里我是偷懒省略了{},哈哈,我加上,然后我调试下,在优化下 - @Override - public void validateSkus(List list) { - List skuPropertyList = list.stream().flatMap(p -> p.getProperties().stream()).collect(Collectors.toList()); - // 校验规格属性以及规格值是否存在 - List propertyIds = skuPropertyList.stream().map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toList()); - List propertyAndValueList = productPropertyService.selectByIds(propertyIds); - if (propertyAndValueList.isEmpty()) { - throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS); + public void validateSkus(List skus, Integer specType) { + // 非多规格,不需要校验 + if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) { + return; } - Map propertyMap = propertyAndValueList.stream().collect(Collectors.toMap(ProductPropertyRespVO::getId, p -> p)); - skuPropertyList.forEach(p -> { - ProductPropertyRespVO productPropertyRespVO = propertyMap.get(p.getPropertyId()); - // 如果对应的属性名不存在或属性名下的属性值集合为空,给出提示 - if (null == productPropertyRespVO || productPropertyRespVO.getPropertyValueList().isEmpty()) - throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS); - // 判断改属性名对应的属性值是否存在,不存在,给出提示 - if (!productPropertyRespVO.getPropertyValueList().stream().map(ProductPropertyValueRespVO::getId).collect(Collectors.toSet()).contains(p.getValueId())) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS); + + // 1、校验规格属性存在 + // TODO @Luowenfeng:stream 的写法;不用改哈,就是说下可以酱紫写; + Set propertyIds = skus.stream().filter(p -> p.getProperties() != null).flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 + .map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toSet()); // 将每个 Property 转换成对应的 propertyId,最后形成集合 + List propertyAndValueList = productPropertyService.getPropertyAndValueList(propertyIds); + if (propertyAndValueList.size() == propertyIds.size()) { + throw exception(PROPERTY_NOT_EXISTS); + } + + // 2. 校验,一个 SKU 下,没有重复的规格。校验方式是,遍历每个 SKU ,看看是否有重复的规格 propertyId + Map propertyValueMap = propertyAndValueList.stream().filter(p -> p.getValues() != null).flatMap(p -> p.getValues().stream()) + .collect(Collectors.toMap(ProductPropertyValueRespVO::getId, value -> value)); // KEY:规格属性值的编号 + skus.forEach(sku -> { + Set skuPropertyIds = CollectionUtils.convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId()); + if (skuPropertyIds.size() != sku.getProperties().size()) { + throw exception(SKU_PROPERTIES_DUPLICATED); } }); - // 校验是否有重复的sku组合 - List> skuProperties = list.stream().map(ProductSkuBaseVO::getProperties).collect(Collectors.toList()); - Set skuPropertiesConvertSet = new HashSet<>(); - skuProperties.forEach(p -> { - // 组合属性值id为 1~2~3.... 形式的字符串,通过set的特性判断是否有重复的组合 - if (!skuPropertiesConvertSet.add(p.stream().map(pr -> String.valueOf(pr.getValueId())).sorted().collect(Collectors.joining("~")))) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.SKU_PROPERTIES_DUPLICATED); + + // 3. 再校验,每个 Sku 的规格值的数量,是一致的。 + int attrValueIdsSize = skus.get(0).getProperties().size(); + for (int i = 1; i < skus.size(); i++) { + if (attrValueIdsSize != skus.get(i).getProperties().size()) { + throw exception(ErrorCodeConstants.SPU_ATTR_NUMBERS_MUST_BE_EQUALS); } - }); + } + + // 4. 最后校验,每个 Sku 之间不是重复的 + Set> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的. + for (ProductSkuCreateOrUpdateReqVO sku : skus) { + // TODO @Luowenfeng:可以使用 CollectionUtils.convertSet(),简化下面的 stream 操作 + if (!skuAttrValues.add(sku.getProperties().stream().map(ProductSkuBaseVO.Property::getValueId).collect(Collectors.toSet()))) { // 添加失败,说明重复 + throw exception(ErrorCodeConstants.SPU_SKU_NOT_DUPLICATE); + } + } } @Override - public void createSkus(List skuDOList) { + public void createSkus(Long spuId, List skuCreateReqList) { + // 批量插入 SKU + List skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList); + skuDOList.forEach(v -> v.setSpuId(spuId)); productSkuMapper.insertBatch(skuDOList); } @Override public List getSkusBySpuId(Long spuId) { - return productSkuMapper.selectBySpuIds(Collections.singletonList(spuId)); + return productSkuMapper.selectListBySpuIds(Collections.singletonList(spuId)); } @Override public List getSkusBySpuIds(List spuIds) { - return productSkuMapper.selectBySpuIds(spuIds); + return productSkuMapper.selectListBySpuIds(spuIds); } @Override @@ -144,22 +132,21 @@ public class ProductSkuServiceImpl implements ProductSkuService { @Override @Transactional - public void updateSkus(Long spuId, List skus) { - List allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus); - // 查询 spu 下已经存在的 sku 的集合 - List existsSkus = productSkuMapper.selectBySpuIds(Collections.singletonList(spuId)); - // TODO @franky:使用 CollUtils 即可 - Map existsSkuMap = existsSkus.stream().collect(Collectors.toMap(ProductSkuDO::getId, p -> p)); + public void updateProductSkus(Long spuId, List skus) { + // 查询 SPU 下已经存在的 SKU 的集合 + List existsSkus = productSkuMapper.selectListBySpuId(spuId); + Map existsSkuMap = CollectionUtils.convertMap(existsSkus, ProductSkuDO::getId); - // 拆分三个集合, 新插入的, 需要更新的,需要删除的 + // 拆分三个集合,新插入的、需要更新的、需要删除的 List insertSkus = new ArrayList<>(); - List updateSkus = new ArrayList<>(); + List updateSkus = new ArrayList<>(); // TODO Luowenfeng:使用 Long 即可 List deleteSkus = new ArrayList<>(); - // TODO @芋艿:是不是基于规格匹配会比较好。 + // TODO @Luowenfeng:是不是基于规格匹配会比较好。可以参考下 onemall 的 ProductSpuServiceImpl 的 updateProductSpu 逻辑 + List allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus); allUpdateSkus.forEach(p -> { - if (null != p.getId()) { - if (existsSkuMap.get(p.getId()) != null) { + if (p.getId() != null) { + if (existsSkuMap.containsKey(p.getId())) { updateSkus.add(p); return; } @@ -170,14 +157,12 @@ public class ProductSkuServiceImpl implements ProductSkuService { insertSkus.add(p); }); - if (insertSkus.size() > 0) { + if (CollectionUtil.isNotEmpty(insertSkus)) { productSkuMapper.insertBatch(insertSkus); } - if (updateSkus.size() > 0) { updateSkus.forEach(p -> productSkuMapper.updateById(p)); } - if (deleteSkus.size() > 0) { productSkuMapper.deleteBatchIds(deleteSkus.stream().map(ProductSkuDO::getId).collect(Collectors.toList())); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java index e4fc47d56..e5affa8d2 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java @@ -1,20 +1,27 @@ package cn.iocoder.yudao.module.product.service.spu; -import java.util.*; -import javax.validation.*; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.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.controller.app.spu.vo.AppSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; /** - * 商品spu Service 接口 + * 商品 SPU Service 接口 * * @author 芋道源码 */ public interface ProductSpuService { /** - * 创建商品spu + * 创建商品 SPU * * @param createReqVO 创建信息 * @return 编号 @@ -22,11 +29,11 @@ public interface ProductSpuService { Long createSpu(@Valid ProductSpuCreateReqVO createReqVO); /** - * 更新商品spu + * 更新商品 SPU * * @param updateReqVO 更新信息 */ - void updateSpu(@Valid SpuUpdateReqVO updateReqVO); + void updateSpu(@Valid ProductSpuUpdateReqVO updateReqVO); /** * 删除商品spu @@ -41,7 +48,7 @@ public interface ProductSpuService { * @param id 编号 * @return 商品spu */ - SpuRespVO getSpu(Long id); + ProductSpuRespVO getSpu(Long id); /** * 获得商品spu列表 @@ -57,14 +64,15 @@ public interface ProductSpuService { * @param pageReqVO 分页查询 * @return 商品spu分页 */ - PageResult getSpuPage(SpuPageReqVO pageReqVO); + PageResult getSpuPage(ProductSpuPageReqVO pageReqVO); /** - * 获得商品spu列表, 用于 Excel 导出 + * 获得商品spu分页 * - * @param exportReqVO 查询条件 - * @return 商品spu列表 + * @param pageReqVO 分页查询 + * @return 商品spu分页 */ - List getSpuList(SpuExportReqVO exportReqVO); + PageResult getSpuPage(AppSpuPageReqVO pageReqVO); + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java index 4420b0af8..847301ba8 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java @@ -1,16 +1,27 @@ package cn.iocoder.yudao.module.product.service.spu; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; -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.ProductSpuPageReqVO; +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.app.spu.vo.AppSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; -import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; -import cn.iocoder.yudao.module.product.service.category.CategoryService; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; +import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; +import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,7 +35,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; /** - * 商品spu Service 实现类 + * 商品 SPU Service 实现类 * * @author 芋道源码 */ @@ -36,55 +47,70 @@ public class ProductSpuServiceImpl implements ProductSpuService { private ProductSpuMapper ProductSpuMapper; @Resource - private CategoryService categoryService; + private ProductCategoryService categoryService; @Resource private ProductSkuService productSkuService; + @Resource + private ProductPropertyService productPropertyService; + + @Resource + private ProductBrandService brandService; + @Override @Transactional public Long createSpu(ProductSpuCreateReqVO createReqVO) { // 校验分类 - categoryService.validatedCategoryById(createReqVO.getCategoryId()); + categoryService.validateCategoryLevel(createReqVO.getCategoryId()); + // 校验品牌 + brandService.validateProductBrand(createReqVO.getBrandId()); // 校验SKU - List skuCreateReqList = createReqVO.getSkus(); - productSkuService.validateSkus(skuCreateReqList); - // 插入SPU + List skuCreateReqList = createReqVO.getSkus(); + productSkuService.validateSkus(skuCreateReqList, createReqVO.getSpecType()); + // 插入 SPU ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); + spu.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); + spu.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); + spu.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); + spu.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); ProductSpuMapper.insert(spu); - // sku关联SPU属性 - skuCreateReqList.forEach(p -> { - p.setSpuId(spu.getId()); - }); - List skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList); - // 批量插入sku - productSkuService.createSkus(skuDOList); + // 插入 SKU + productSkuService.createSkus(spu.getId(), skuCreateReqList); // 返回 return spu.getId(); } @Override @Transactional - public void updateSpu(SpuUpdateReqVO updateReqVO) { - // 校验 spu 是否存在 - this.validateSpuExists(updateReqVO.getId()); + public void updateSpu(ProductSpuUpdateReqVO updateReqVO) { + // 校验 SPU 是否存在 + validateSpuExists(updateReqVO.getId()); // 校验分类 - categoryService.validatedCategoryById(updateReqVO.getCategoryId()); + categoryService.validateCategoryLevel(updateReqVO.getCategoryId()); + // 校验品牌 + brandService.validateProductBrand(updateReqVO.getBrandId()); // 校验SKU - List skuCreateReqList = updateReqVO.getSkus(); - productSkuService.validateSkus(skuCreateReqList); - // 更新 + List skuCreateReqList = updateReqVO.getSkus(); + // 多规格才需校验 + productSkuService.validateSkus(skuCreateReqList, updateReqVO.getSpecType()); + + // 更新 SPU ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO); + updateObj.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); + updateObj.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); + updateObj.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); + updateObj.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); ProductSpuMapper.updateById(updateObj); - // 更新 sku - productSkuService.updateSkus(updateObj.getId(), updateReqVO.getSkus()); + // 批量更新 SKU + productSkuService.updateProductSkus(updateObj.getId(), updateReqVO.getSkus()); } @Override @Transactional public void deleteSpu(Long id) { // 校验存在 - this.validateSpuExists(id); + validateSpuExists(id); // 删除 SPU ProductSpuMapper.deleteById(id); // 删除关联的 SKU @@ -98,12 +124,38 @@ public class ProductSpuServiceImpl implements ProductSpuService { } @Override - public SpuRespVO getSpu(Long id) { + // TODO @芋艿:需要再 review 下 + public ProductSpuRespVO getSpu(Long id) { ProductSpuDO spu = ProductSpuMapper.selectById(id); - SpuRespVO spuVO = ProductSpuConvert.INSTANCE.convert(spu); + ProductSpuRespVO spuVO = ProductSpuConvert.INSTANCE.convert(spu); if (null != spuVO) { List skuReqs = ProductSkuConvert.INSTANCE.convertList(productSkuService.getSkusBySpuId(id)); spuVO.setSkus(skuReqs); + List properties = new ArrayList<>(); + // 组合 sku 规格属性 + if(spu.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) { + for (ProductSkuRespVO productSkuRespVO : skuReqs) { + properties.addAll(productSkuRespVO.getProperties()); + } + Map> propertyMaps = properties.stream().collect(Collectors.groupingBy(ProductSkuBaseVO.Property::getPropertyId)); + List propertyAndValueList = productPropertyService.getPropertyAndValueList(new ArrayList<>(propertyMaps.keySet())); + // 装载组装过后的属性 + List productPropertyViews = new ArrayList<>(); + propertyAndValueList.forEach(p -> { + ProductPropertyViewRespVO productPropertyViewRespVO = new ProductPropertyViewRespVO(); + productPropertyViewRespVO.setPropertyId(p.getId()); + productPropertyViewRespVO.setName(p.getName()); + List propertyValues = new ArrayList<>(); + Map propertyValueMaps = p.getValues().stream().collect(Collectors.toMap(ProductPropertyValueRespVO::getId, pv -> pv)); + propertyMaps.get(p.getId()).forEach(pv -> { + ProductPropertyViewRespVO.Tuple2 tuple2 = new ProductPropertyViewRespVO.Tuple2(pv.getValueId(), propertyValueMaps.get(pv.getValueId()).getName()); + propertyValues.add(tuple2); + }); + productPropertyViewRespVO.setPropertyValues(propertyValues.stream().distinct().collect(Collectors.toList())); + productPropertyViews.add(productPropertyViewRespVO); + }); + spuVO.setProductPropertyViews(productPropertyViews); + } // 组合分类 if (null != spuVO.getCategoryId()) { LinkedList categoryArray = new LinkedList<>(); @@ -127,21 +179,30 @@ public class ProductSpuServiceImpl implements ProductSpuService { } @Override - public PageResult getSpuPage(SpuPageReqVO pageReqVO) { - PageResult spuVOs = ProductSpuConvert.INSTANCE.convertPage(ProductSpuMapper.selectPage(pageReqVO)); + public PageResult getSpuPage(ProductSpuPageReqVO pageReqVO) { + PageResult spuVOs = ProductSpuConvert.INSTANCE.convertPage(ProductSpuMapper.selectPage(pageReqVO)); // 查询 sku 的信息 - List spuIds = spuVOs.getList().stream().map(SpuRespVO::getId).collect(Collectors.toList()); + List spuIds = spuVOs.getList().stream().map(ProductSpuRespVO::getId).collect(Collectors.toList()); List skus = ProductSkuConvert.INSTANCE.convertList(productSkuService.getSkusBySpuIds(spuIds)); // TODO @franky:使用 CollUtil 里的方法替代哈 - Map> skuMap = skus.stream().collect(Collectors.groupingBy(ProductSkuRespVO::getSpuId)); - // 将 spu 和 sku 进行组装 - spuVOs.getList().forEach(p -> p.setSkus(skuMap.get(p.getId()))); + // TODO 芋艿:临时注释 +// Map> skuMap = skus.stream().collect(Collectors.groupingBy(ProductSkuRespVO::getSpuId)); +// // 将 spu 和 sku 进行组装 +// spuVOs.getList().forEach(p -> p.setSkus(skuMap.get(p.getId()))); return spuVOs; } @Override - public List getSpuList(SpuExportReqVO exportReqVO) { - return ProductSpuMapper.selectList(exportReqVO); + public PageResult getSpuPage(AppSpuPageReqVO pageReqVO) { + PageResult productSpuDOPageResult = ProductSpuMapper.selectPage(ProductSpuConvert.INSTANCE.convert(pageReqVO)); + PageResult pageResult = new PageResult<>(); + List collect = productSpuDOPageResult.getList() + .stream() + .map(ProductSpuConvert.INSTANCE::convertAppResp) + .collect(Collectors.toList()); + pageResult.setList(collect); + pageResult.setTotal(productSpuDOPageResult.getTotal()); + return pageResult; } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/BrandServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/BrandServiceImplTest.java deleted file mode 100644 index fc819e6b6..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/BrandServiceImplTest.java +++ /dev/null @@ -1,173 +0,0 @@ -package cn.iocoder.yudao.module.product.service.brand; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; - -import javax.annotation.Resource; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.BrandDO; -import cn.iocoder.yudao.module.product.dal.mysql.brand.BrandMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import javax.annotation.Resource; -import org.springframework.context.annotation.Import; -import java.util.*; - -import static cn.hutool.core.util.RandomUtil.*; -import static cn.iocoder.yudao.module.product.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 cn.iocoder.yudao.framework.common.util.date.DateUtils.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -/** -* {@link BrandServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(BrandServiceImpl.class) -public class BrandServiceImplTest extends BaseDbUnitTest { - - @Resource - private BrandServiceImpl brandService; - - @Resource - private BrandMapper brandMapper; - - @Test - public void testCreateBrand_success() { - // 准备参数 - BrandCreateReqVO reqVO = randomPojo(BrandCreateReqVO.class); - - // 调用 - Long brandId = brandService.createBrand(reqVO); - // 断言 - assertNotNull(brandId); - // 校验记录的属性是否正确 - BrandDO brand = brandMapper.selectById(brandId); - assertPojoEquals(reqVO, brand); - } - - @Test - public void testUpdateBrand_success() { - // mock 数据 - BrandDO dbBrand = randomPojo(BrandDO.class); - brandMapper.insert(dbBrand);// @Sql: 先插入出一条存在的数据 - // 准备参数 - BrandUpdateReqVO reqVO = randomPojo(BrandUpdateReqVO.class, o -> { - o.setId(dbBrand.getId()); // 设置更新的 ID - }); - - // 调用 - brandService.updateBrand(reqVO); - // 校验是否更新正确 - BrandDO brand = brandMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, brand); - } - - @Test - public void testUpdateBrand_notExists() { - // 准备参数 - BrandUpdateReqVO reqVO = randomPojo(BrandUpdateReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> brandService.updateBrand(reqVO), BRAND_NOT_EXISTS); - } - - @Test - public void testDeleteBrand_success() { - // mock 数据 - BrandDO dbBrand = randomPojo(BrandDO.class); - brandMapper.insert(dbBrand);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbBrand.getId(); - - // 调用 - brandService.deleteBrand(id); - // 校验数据不存在了 - assertNull(brandMapper.selectById(id)); - } - - @Test - public void testDeleteBrand_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> brandService.deleteBrand(id), BRAND_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetBrandPage() { - // mock 数据 - BrandDO dbBrand = randomPojo(BrandDO.class, o -> { // 等会查询到 - o.setCategoryId(null); - o.setName(null); - o.setStatus(null); - o.setCreateTime(null); - }); - brandMapper.insert(dbBrand); - // 测试 categoryId 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setCategoryId(null))); - // 测试 name 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setName(null))); - // 测试 status 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setStatus(null))); - // 测试 createTime 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setCreateTime(null))); - // 准备参数 - BrandPageReqVO reqVO = new BrandPageReqVO(); - reqVO.setCategoryId(null); - reqVO.setName(null); - reqVO.setStatus(null); - reqVO.setCreateTime((new Date[]{})); - - // 调用 - PageResult pageResult = brandService.getBrandPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbBrand, pageResult.getList().get(0)); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetBrandList() { - // mock 数据 - BrandDO dbBrand = randomPojo(BrandDO.class, o -> { // 等会查询到 - o.setCategoryId(null); - o.setName(null); - o.setStatus(null); - o.setCreateTime(null); - }); - brandMapper.insert(dbBrand); - // 测试 categoryId 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setCategoryId(null))); - // 测试 name 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setName(null))); - // 测试 status 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setStatus(null))); - // 测试 createTime 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setCreateTime(null))); - // 准备参数 - BrandExportReqVO reqVO = new BrandExportReqVO(); - reqVO.setCategoryId(null); - reqVO.setName(null); - reqVO.setStatus(null); - reqVO.setCreateTime((new Date[]{})); - - // 调用 - List list = brandService.getBrandList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbBrand, list.get(0)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java new file mode 100644 index 000000000..93817d44c --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java @@ -0,0 +1,132 @@ +package cn.iocoder.yudao.module.product.service.brand; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; +import cn.iocoder.yudao.module.product.dal.mysql.brand.ProductBrandMapper; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.Date; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.BRAND_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** +* {@link ProductBrandServiceImpl} 的单元测试类 +* +* @author 芋道源码 +*/ +@Import(ProductBrandServiceImpl.class) +public class ProductBrandServiceImplTest extends BaseDbUnitTest { + + @Resource + private ProductBrandServiceImpl brandService; + + @Resource + private ProductBrandMapper brandMapper; + + @Test + public void testCreateBrand_success() { + // 准备参数 + ProductBrandCreateReqVO reqVO = randomPojo(ProductBrandCreateReqVO.class); + + // 调用 + Long brandId = brandService.createBrand(reqVO); + // 断言 + assertNotNull(brandId); + // 校验记录的属性是否正确 + ProductBrandDO brand = brandMapper.selectById(brandId); + assertPojoEquals(reqVO, brand); + } + + @Test + public void testUpdateBrand_success() { + // mock 数据 + ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class); + brandMapper.insert(dbBrand);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ProductBrandUpdateReqVO reqVO = randomPojo(ProductBrandUpdateReqVO.class, o -> { + o.setId(dbBrand.getId()); // 设置更新的 ID + }); + + // 调用 + brandService.updateBrand(reqVO); + // 校验是否更新正确 + ProductBrandDO brand = brandMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, brand); + } + + @Test + public void testUpdateBrand_notExists() { + // 准备参数 + ProductBrandUpdateReqVO reqVO = randomPojo(ProductBrandUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> brandService.updateBrand(reqVO), BRAND_NOT_EXISTS); + } + + @Test + public void testDeleteBrand_success() { + // mock 数据 + ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class); + brandMapper.insert(dbBrand);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbBrand.getId(); + + // 调用 + brandService.deleteBrand(id); + // 校验数据不存在了 + assertNull(brandMapper.selectById(id)); + } + + @Test + public void testDeleteBrand_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> brandService.deleteBrand(id), BRAND_NOT_EXISTS); + } + + @Test + public void testGetBrandPage() { + // mock 数据 + ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class, o -> { // 等会查询到 + o.setName("芋道源码"); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setCreateTime(buildTime(2022, 2, 1)); + }); + brandMapper.insert(dbBrand); + // 测试 name 不匹配 + brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setName("源码"))); + // 测试 status 不匹配 + brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 createTime 不匹配 + brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setCreateTime(buildTime(2022, 3, 1)))); + // 准备参数 + ProductBrandPageReqVO reqVO = new ProductBrandPageReqVO(); + reqVO.setName("芋道"); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setCreateTime((new Date[]{buildTime(2022, 1, 1), buildTime(2022, 2, 25)})); + + // 调用 + PageResult pageResult = brandService.getBrandPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbBrand, pageResult.getList().get(0)); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImplTest.java deleted file mode 100644 index 34384201b..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImplTest.java +++ /dev/null @@ -1,192 +0,0 @@ -package cn.iocoder.yudao.module.product.service.category; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryExportReqVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryUpdateReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; -import cn.iocoder.yudao.module.product.dal.mysql.category.CategoryMapper; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -/** - * {@link CategoryServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Import(CategoryServiceImpl.class) -public class CategoryServiceImplTest extends BaseDbUnitTest { - - @Resource - private CategoryServiceImpl categoryService; - - @Resource - private CategoryMapper categoryMapper; - - @Test - public void testCreateCategory_success() { - // 准备参数 - CategoryCreateReqVO reqVO = randomPojo(CategoryCreateReqVO.class); - - // 调用 - Long categoryId = categoryService.createCategory(reqVO); - // 断言 - assertNotNull(categoryId); - // 校验记录的属性是否正确 - CategoryDO category = categoryMapper.selectById(categoryId); - assertPojoEquals(reqVO, category); - } - - @Test - public void testUpdateCategory_success() { - // mock 数据 - CategoryDO dbCategory = randomPojo(CategoryDO.class); - categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 - // 准备参数 - CategoryUpdateReqVO reqVO = randomPojo(CategoryUpdateReqVO.class, o -> { - o.setId(dbCategory.getId()); // 设置更新的 ID - }); - - // 调用 - categoryService.updateCategory(reqVO); - // 校验是否更新正确 - CategoryDO category = categoryMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, category); - } - - @Test - public void testUpdateCategory_notExists() { - // 准备参数 - CategoryUpdateReqVO reqVO = randomPojo(CategoryUpdateReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> categoryService.updateCategory(reqVO), CATEGORY_NOT_EXISTS); - } - - @Test - public void testDeleteCategory_success() { - // mock 数据 - CategoryDO dbCategory = randomPojo(CategoryDO.class); - categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbCategory.getId(); - - // 调用 - categoryService.deleteCategory(id); - // 校验数据不存在了 - assertNull(categoryMapper.selectById(id)); - } - - @Test - public void testDeleteCategory_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> categoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetCategoryPage() { - // mock 数据 - CategoryDO dbCategory = randomPojo(CategoryDO.class, o -> { // 等会查询到 - o.setParentId(null); - o.setName(null); - o.setIcon(null); - o.setBannerUrl(null); - o.setSort(null); - o.setDescription(null); - o.setStatus(null); - o.setCreateTime(null); - }); - categoryMapper.insert(dbCategory); - // 测试 pid 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setParentId(null))); - // 测试 name 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null))); - // 测试 icon 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setIcon(null))); - // 测试 bannerUrl 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setBannerUrl(null))); - // 测试 sort 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setSort(null))); - // 测试 description 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setDescription(null))); - // 测试 status 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(null))); - // 测试 createTime 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(null))); - // 准备参数 - CategoryPageReqVO reqVO = new CategoryPageReqVO(); - reqVO.setName(null); - reqVO.setStatus(null); - reqVO.setCreateTime(null); - - // 调用 - PageResult pageResult = categoryService.getCategoryPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbCategory, pageResult.getList().get(0)); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetCategoryList() { - // mock 数据 - CategoryDO dbCategory = randomPojo(CategoryDO.class, o -> { // 等会查询到 - o.setParentId(null); - o.setName(null); - o.setIcon(null); - o.setBannerUrl(null); - o.setSort(null); - o.setDescription(null); - o.setStatus(null); - o.setCreateTime(null); - }); - categoryMapper.insert(dbCategory); - // 测试 pid 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setParentId(null))); - // 测试 name 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null))); - // 测试 icon 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setIcon(null))); - // 测试 bannerUrl 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setBannerUrl(null))); - // 测试 sort 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setSort(null))); - // 测试 description 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setDescription(null))); - // 测试 status 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(null))); - // 测试 createTime 不匹配 - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(null))); - // 准备参数 - CategoryExportReqVO reqVO = new CategoryExportReqVO(); - reqVO.setName(null); - reqVO.setStatus(null); - reqVO.setCreateTime(null); - - // 调用 - List list = categoryService.getCategoryList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbCategory, list.get(0)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java new file mode 100644 index 000000000..a56c1aa1a --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.product.service.category; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import cn.iocoder.yudao.module.product.dal.mysql.category.ProductCategoryMapper; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link ProductCategoryServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(ProductCategoryServiceImpl.class) +public class ProductCategoryServiceImplTest extends BaseDbUnitTest { + + @Resource + private ProductCategoryServiceImpl productCategoryService; + + @Resource + private ProductCategoryMapper productCategoryMapper; + + @Test + public void testCreateCategory_success() { + // 准备参数 + ProductCategoryCreateReqVO reqVO = randomPojo(ProductCategoryCreateReqVO.class); + // mock 父类 + ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> o.setId(reqVO.getParentId())); + productCategoryMapper.insert(parentProductCategory); + + // 调用 + Long categoryId = productCategoryService.createCategory(reqVO); + // 断言 + assertNotNull(categoryId); + // 校验记录的属性是否正确 + ProductCategoryDO category = productCategoryMapper.selectById(categoryId); + assertPojoEquals(reqVO, category); + } + + @Test + public void testUpdateCategory_success() { + // mock 数据 + ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class); + productCategoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ProductCategoryUpdateReqVO reqVO = randomPojo(ProductCategoryUpdateReqVO.class, o -> { + o.setId(dbCategory.getId()); // 设置更新的 ID + }); + // mock 父类 + ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> o.setId(reqVO.getParentId())); + productCategoryMapper.insert(parentProductCategory); + + // 调用 + productCategoryService.updateCategory(reqVO); + // 校验是否更新正确 + ProductCategoryDO category = productCategoryMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, category); + } + + @Test + public void testUpdateCategory_notExists() { + // 准备参数 + ProductCategoryUpdateReqVO reqVO = randomPojo(ProductCategoryUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> productCategoryService.updateCategory(reqVO), CATEGORY_NOT_EXISTS); + } + + @Test + public void testDeleteCategory_success() { + // mock 数据 + ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class); + productCategoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbCategory.getId(); + + // 调用 + productCategoryService.deleteCategory(id); + // 校验数据不存在了 + assertNull(productCategoryMapper.selectById(id)); + } + + @Test + public void testDeleteCategory_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> productCategoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); + } + + @Test + public void testGetCategoryList() { + // mock 数据 + ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class, o -> { // 等会查询到 + o.setName("奥特曼"); + }); + productCategoryMapper.insert(dbCategory); + // 测试 name 不匹配 + productCategoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName("奥特块"))); + // 准备参数 + ProductCategoryListReqVO reqVO = new ProductCategoryListReqVO(); + reqVO.setName("特曼"); + + // 调用 + List list = productCategoryService.getEnableCategoryList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbCategory, list.get(0)); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/SkuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/SkuServiceImplTest.java index 42eb96fd8..10ab8a3d1 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/SkuServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/SkuServiceImplTest.java @@ -1,30 +1,17 @@ package cn.iocoder.yudao.module.product.service.sku; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; - -import javax.annotation.Resource; - import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; import javax.annotation.Resource; -import org.springframework.context.annotation.Import; -import java.util.*; -import static cn.hutool.core.util.RandomUtil.*; -import static cn.iocoder.yudao.module.product.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 cn.iocoder.yudao.framework.common.util.date.DateUtils.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.assertNull; /** * {@link ProductSkuServiceImpl} 的单元测试类 @@ -40,46 +27,6 @@ public class SkuServiceImplTest extends BaseDbUnitTest { @Resource private ProductSkuMapper ProductSkuMapper; - @Test - public void testCreateSku_success() { - // 准备参数 - ProductSkuCreateReqVO reqVO = randomPojo(ProductSkuCreateReqVO.class); - - // 调用 - Long skuId = ProductSkuService.createSku(reqVO); - // 断言 - assertNotNull(skuId); - // 校验记录的属性是否正确 - ProductSkuDO sku = ProductSkuMapper.selectById(skuId); - assertPojoEquals(reqVO, sku); - } - - @Test - public void testUpdateSku_success() { - // mock 数据 - ProductSkuDO dbSku = randomPojo(ProductSkuDO.class); - ProductSkuMapper.insert(dbSku);// @Sql: 先插入出一条存在的数据 - // 准备参数 - ProductSkuUpdateReqVO reqVO = randomPojo(ProductSkuUpdateReqVO.class, o -> { - o.setId(dbSku.getId()); // 设置更新的 ID - }); - - // 调用 - ProductSkuService.updateSku(reqVO); - // 校验是否更新正确 - ProductSkuDO sku = ProductSkuMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, sku); - } - - @Test - public void testUpdateSku_notExists() { - // 准备参数 - ProductSkuUpdateReqVO reqVO = randomPojo(ProductSkuUpdateReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> ProductSkuService.updateSku(reqVO), SKU_NOT_EXISTS); - } - @Test public void testDeleteSku_success() { // mock 数据 @@ -103,111 +50,4 @@ public class SkuServiceImplTest extends BaseDbUnitTest { assertServiceException(() -> ProductSkuService.deleteSku(id), SKU_NOT_EXISTS); } - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetSkuPage() { - // mock 数据 - ProductSkuDO dbSku = randomPojo(ProductSkuDO.class, o -> { // 等会查询到 - o.setSpuId(null); - o.setProperties(null); - o.setPrice(null); - o.setOriginalPrice(null); - o.setCostPrice(null); - o.setBarCode(null); - o.setPicUrl(null); - o.setStatus(null); - o.setCreateTime(null); - }); - ProductSkuMapper.insert(dbSku); - // 测试 spuId 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setSpuId(null))); - // 测试 properties 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setProperties(null))); - // 测试 price 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setPrice(null))); - // 测试 originalPrice 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setOriginalPrice(null))); - // 测试 costPrice 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setCostPrice(null))); - // 测试 barCode 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setBarCode(null))); - // 测试 picUrl 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setPicUrl(null))); - // 测试 status 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setStatus(null))); - // 测试 createTime 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setCreateTime(null))); - // 准备参数 - ProductSkuPageReqVO reqVO = new ProductSkuPageReqVO(); - reqVO.setSpuId(null); - reqVO.setProperties(null); - reqVO.setPrice(null); - reqVO.setOriginalPrice(null); - reqVO.setCostPrice(null); - reqVO.setBarCode(null); - reqVO.setPicUrl(null); - reqVO.setStatus(null); - reqVO.setCreateTime(null); - - // 调用 - PageResult pageResult = ProductSkuService.getSkuPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbSku, pageResult.getList().get(0)); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetSkuList() { - // mock 数据 - ProductSkuDO dbSku = randomPojo(ProductSkuDO.class, o -> { // 等会查询到 - o.setSpuId(null); - o.setProperties(null); - o.setPrice(null); - o.setOriginalPrice(null); - o.setCostPrice(null); - o.setBarCode(null); - o.setPicUrl(null); - o.setStatus(null); - o.setCreateTime(null); - }); - ProductSkuMapper.insert(dbSku); - // 测试 spuId 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setSpuId(null))); - // 测试 properties 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setProperties(null))); - // 测试 price 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setPrice(null))); - // 测试 originalPrice 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setOriginalPrice(null))); - // 测试 costPrice 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setCostPrice(null))); - // 测试 barCode 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setBarCode(null))); - // 测试 picUrl 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setPicUrl(null))); - // 测试 status 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setStatus(null))); - // 测试 createTime 不匹配 - ProductSkuMapper.insert(cloneIgnoreId(dbSku, o -> o.setCreateTime(null))); - // 准备参数 - ProductSkuExportReqVO reqVO = new ProductSkuExportReqVO(); - reqVO.setSpuId(null); - reqVO.setProperties(null); - reqVO.setPrice(null); - reqVO.setOriginalPrice(null); - reqVO.setCostPrice(null); - reqVO.setBarCode(null); - reqVO.setPicUrl(null); - reqVO.setStatus(null); - reqVO.setCreateTime(null); - - // 调用 - List list = ProductSkuService.getSkuList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbSku, list.get(0)); - } - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java index fae41788f..bb0fa9d32 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java @@ -1,30 +1,25 @@ package cn.iocoder.yudao.module.product.service.spu; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; - -import javax.annotation.Resource; - +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - -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.ProductSpuPageReqVO; +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.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; import javax.annotation.Resource; -import org.springframework.context.annotation.Import; -import java.util.*; -import static cn.hutool.core.util.RandomUtil.*; -import static cn.iocoder.yudao.module.product.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 cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; /** * {@link ProductSpuServiceImpl} 的单元测试类 @@ -60,7 +55,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { ProductSpuDO dbSpu = randomPojo(ProductSpuDO.class); ProductSpuMapper.insert(dbSpu);// @Sql: 先插入出一条存在的数据 // 准备参数 - SpuUpdateReqVO reqVO = randomPojo(SpuUpdateReqVO.class, o -> { + ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> { o.setId(dbSpu.getId()); // 设置更新的 ID }); @@ -74,7 +69,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateSpu_notExists() { // 准备参数 - SpuUpdateReqVO reqVO = randomPojo(SpuUpdateReqVO.class); + ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class); // 调用, 并断言异常 assertServiceException(() -> spuService.updateSpu(reqVO), SPU_NOT_EXISTS); @@ -114,9 +109,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { o.setCategoryId(null); o.setPicUrls(null); o.setSort(null); - o.setLikeCount(null); - o.setPrice(null); - o.setQuantity(null); +// o.setLikeCount(null); +// o.setPrice(null); +// o.setQuantity(null); o.setStatus(null); o.setCreateTime(null); }); @@ -134,17 +129,17 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { // 测试 sort 不匹配 ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setSort(null))); // 测试 likeCount 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setLikeCount(null))); +// ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setLikeCount(null))); // 测试 price 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setPrice(null))); +// ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setPrice(null))); // 测试 quantity 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setQuantity(null))); +// ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setQuantity(null))); // 测试 status 不匹配 ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setStatus(null))); // 测试 createTime 不匹配 ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setCreateTime(null))); // 准备参数 - SpuPageReqVO reqVO = new SpuPageReqVO(); + ProductSpuPageReqVO reqVO = new ProductSpuPageReqVO(); reqVO.setName(null); reqVO.setSellPoint(null); reqVO.setDescription(null); @@ -158,72 +153,11 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { reqVO.setCreateTime(null); // 调用 - PageResult pageResult = spuService.getSpuPage(reqVO); + PageResult pageResult = spuService.getSpuPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); assertPojoEquals(dbSpu, pageResult.getList().get(0)); } - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetSpuList() { - // mock 数据 - ProductSpuDO dbSpu = randomPojo(ProductSpuDO.class, o -> { // 等会查询到 - o.setName(null); - o.setSellPoint(null); - o.setDescription(null); - o.setCategoryId(null); - o.setPicUrls(null); - o.setSort(null); - o.setLikeCount(null); - o.setPrice(null); - o.setQuantity(null); - o.setStatus(null); - o.setCreateTime(null); - }); - ProductSpuMapper.insert(dbSpu); - // 测试 name 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setName(null))); - // 测试 sellPoint 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setSellPoint(null))); - // 测试 description 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setDescription(null))); - // 测试 categoryId 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setCategoryId(null))); - // 测试 picUrls 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setPicUrls(null))); - // 测试 sort 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setSort(null))); - // 测试 likeCount 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setLikeCount(null))); - // 测试 price 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setPrice(null))); - // 测试 quantity 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setQuantity(null))); - // 测试 status 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setStatus(null))); - // 测试 createTime 不匹配 - ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setCreateTime(null))); - // 准备参数 - SpuExportReqVO reqVO = new SpuExportReqVO(); - reqVO.setName(null); - reqVO.setSellPoint(null); - reqVO.setDescription(null); - reqVO.setCategoryId(null); - reqVO.setPicUrls(null); - reqVO.setSort(null); - reqVO.setLikeCount(null); - reqVO.setPrice(null); - reqVO.setQuantity(null); - reqVO.setStatus(null); - reqVO.setCreateTime(null); - - // 调用 - List list = spuService.getSpuList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbSpu, list.get(0)); - } - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml b/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml new file mode 100644 index 000000000..3a2079cdc --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml @@ -0,0 +1,50 @@ +spring: + main: + lazy-initialization: true # 开启懒加载,加快速度 + banner-mode: off # 单元测试,禁用 Banner + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + datasource: + name: ruoyi-vue-pro + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写 + driver-class-name: org.h2.Driver + username: sa + password: + druid: + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 + initial-size: 1 # 单元测试,配置为 1,提升启动速度 + sql: + init: + schema-locations: classpath:/sql/create_tables.sql + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 16379 # 端口(单元测试,使用 16379 端口) + database: 0 # 数据库索引 + +mybatis-plus: + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 + type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项(单元测试,禁用 Lock4j) + +# Resilience4j 配置项 + +--- #################### 监控相关配置 #################### + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml b/yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml new file mode 100644 index 000000000..daf756bff --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql index 94f0b7937..37fc0ff21 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql @@ -2,8 +2,7 @@ CREATE TABLE IF NOT EXISTS "product_category" ( "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, "parent_id" bigint(20) NOT NULL, "name" varchar(255) NOT NULL, - "icon" varchar(100), - "banner_url" varchar(255) NOT NULL, + "pic_url" varchar(255) NOT NULL, "sort" int(11) NOT NULL, "description" varchar(1024) NOT NULL, "status" tinyint(4) NOT NULL, @@ -12,15 +11,13 @@ CREATE TABLE IF NOT EXISTS "product_category" ( "updater" varchar(64) DEFAULT '', "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint(20) NOT NULL, PRIMARY KEY ("id") ) COMMENT '商品分类'; CREATE TABLE IF NOT EXISTS "product_brand" ( "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "category_id" bigint(20) NOT NULL, "name" varchar(255) NOT NULL, - "banner_url" varchar(255) NOT NULL, + "pic_url" varchar(255) NOT NULL, "sort" int(11), "description" varchar(1024), "status" tinyint(4) NOT NULL, @@ -29,6 +26,5 @@ CREATE TABLE IF NOT EXISTS "product_brand" ( "updater" varchar(64) DEFAULT '', "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint(20) NOT NULL, PRIMARY KEY ("id") -) COMMENT '品牌'; +) COMMENT '商品品牌'; diff --git a/yudao-module-mall/yudao-module-trade-api/pom.xml b/yudao-module-mall/yudao-module-trade-api/pom.xml new file mode 100644 index 000000000..1299ad11d --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/pom.xml @@ -0,0 +1,26 @@ + + + + cn.iocoder.boot + yudao-module-mall + ${revision} + + 4.0.0 + yudao-module-trade-api + jar + + ${project.artifactId} + + trade 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/enums/ErrorCodeConstants.java new file mode 100644 index 000000000..5bdc0ff82 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/enums/ErrorCodeConstants.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.trade.enums.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * Trade-Order 错误码 Core 枚举类 + *

+ * Trade-Order 系统,使用 1-011-000-000 段 + * + * @author LeeYan9 + * @since 2022-08-26 + */ +public interface ErrorCodeConstants { + + /** + * ========== Order 模块 1-011-000-000 ========== + */ + ErrorCode ORDER_SKU_NOT_FOUND = new ErrorCode(1011000001, "商品不存在"); + ErrorCode ORDER_SPU_NOT_SALE = new ErrorCode(1011000002, "商品不可售卖"); + ErrorCode ORDER_SKU_NOT_SALE = new ErrorCode(1011000003, "商品Sku不可售卖"); + ErrorCode ORDER_SKU_STOCK_NOT_ENOUGH = new ErrorCode(1011000004, "商品库存不足"); + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java new file mode 100644 index 000000000..670651d4e --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.trade.enums.order; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * 交易订单 - 关闭类型 + * + * @author Sin + */ +@RequiredArgsConstructor +@Getter +public enum TradeOrderCancelTypeEnum { + + PAY_TIMEOUT(10, "超时未支付"), + REFUND_CLOSE(20, "退款关闭"), + MEMBER_CANCEL(30, "买家取消"), + PAY_ON_DELIVERY(40, "已通过货到付款交易"),; + + /** + * 关闭类型 + */ + private final Integer type; + /** + * 关闭类型名 + */ + private final String name; + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemRefundStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemRefundStatusEnum.java new file mode 100644 index 000000000..4d81ea9eb --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemRefundStatusEnum.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.trade.enums.order; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * 交易订单项 - 退款状态 + * + * @author Sin + */ +@RequiredArgsConstructor +@Getter +public enum TradeOrderItemRefundStatusEnum { + + NONE(0, "未申请退款"), + APPLY(1, "申请退款"), + WAIT(2, "等待退款"), + SUCCESS(3, "退款成功"); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderRefundStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderRefundStatusEnum.java new file mode 100644 index 000000000..50fd88b12 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderRefundStatusEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.trade.enums.order; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * 交易订单 - 退款状态 + * + * @author Sin + */ +@RequiredArgsConstructor +@Getter +public enum TradeOrderRefundStatusEnum { + + NONE(0, "未退款"), + PART(1, "部分退款"), + ALL(2, "全部退款"); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java new file mode 100644 index 000000000..fe0a85f3d --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.trade.enums.order; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * 交易订单 - 状态 + * + * @author Sin + */ +@RequiredArgsConstructor +@Getter +public enum TradeOrderStatusEnum { + + WAITING_PAYMENT(0, "待付款"), + WAIT_SHIPMENT(1, "待发货"), + ALREADY_SHIPMENT(2, "待收货"), + COMPLETED(3, "已完成"), + CANCEL(4, "已关闭"); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderTypeEnum.java new file mode 100644 index 000000000..c10d0065a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderTypeEnum.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.trade.enums.order; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * 交易订单 - 类型 + * + * @author Sin + */ +@RequiredArgsConstructor +@Getter +public enum TradeOrderTypeEnum { + + NORMAL(0, "普通订单"), + SECKILL(1, "秒杀订单"), + TEAM(2, "拼团订单"), + BARGAIN(3, "砍价订单"); + + /** + * 类型 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/refund/TradeRefundTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/refund/TradeRefundTypeEnum.java new file mode 100644 index 000000000..f74b39bba --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/refund/TradeRefundTypeEnum.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.trade.enums.refund; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * 交易退款 - 申请类型 + * + * @author Sin + */ +@RequiredArgsConstructor +@Getter +public enum TradeRefundTypeEnum { + + REFUND(10, "退款"), + RETURN_AND_REFUND(20, "退货退款"); + + /** + * 状态值 + */ + private final Integer type; + /** + * 状态名 + */ + private final String name; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/pom.xml b/yudao-module-mall/yudao-module-trade-biz/pom.xml new file mode 100644 index 000000000..c9b582d93 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/pom.xml @@ -0,0 +1,78 @@ + + + + cn.iocoder.boot + yudao-module-mall + ${revision} + + 4.0.0 + yudao-module-trade-biz + jar + + ${project.artifactId} + + trade 模块,主要实现交易相关功能 + 例如:订单、退款、购物车等功能。 + + + + + cn.iocoder.boot + yudao-module-trade-api + ${revision} + + + + cn.iocoder.boot + yudao-module-product-api + ${revision} + + + + cn.iocoder.boot + yudao-module-pay-api + ${revision} + + + + cn.iocoder.boot + yudao-module-market-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 + + + + diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/CartController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/CartController.java new file mode 100644 index 000000000..91e51dfd5 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/CartController.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.trade.controller.app.cart; + +import io.swagger.annotations.Api; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = "购物车 API") +@RestController +@RequestMapping("/cart") +@Validated +public class CartController { + +// @Autowired +// private CartManager cartManager; +// +// @PostMapping("add") +// @ApiOperation("添加商品到购物车") +// @ApiImplicitParams({ +// @ApiImplicitParam(name = "skuId", value = "商品 SKU 编号", required = true, example = "1"), +// @ApiImplicitParam(name = "quantity", value = "增加数量", required = true, example = "1024") +// }) +// @RequiresAuthenticate +// public CommonResult addCartItem(@RequestParam("skuId") Integer skuId, +// @RequestParam("quantity") Integer quantity) { +// cartManager.addCartItem(UserSecurityContextHolder.getUserId(), skuId, quantity); +// return success(true); +// } +// +// @GetMapping("sum-quantity") +// @ApiOperation("查询用户在购物车中的商品数量") +// @RequiresAuthenticate +// public CommonResult sumCartItemQuantity() { +// return success(cartManager.sumCartItemQuantity(UserSecurityContextHolder.getUserId())); +// } +// +// @GetMapping("/get-detail") +// @ApiOperation("查询用户的购物车的商品列表") +// @RequiresAuthenticate +// public CommonResult getCartDetail() { +// return success(cartManager.getCartDetail(UserSecurityContextHolder.getUserId())); +// } +// +// @PostMapping("update-quantity") +// @ApiOperation("更新购物车商品数量") +// @ApiImplicitParams({ +// @ApiImplicitParam(name = "skuId", value = "商品 SKU 编号", required = true, example = "1"), +// @ApiImplicitParam(name = "quantity", value = "增加数量", required = true, example = "1024") +// }) +// @RequiresAuthenticate +// public CommonResult updateCartItemQuantity(@RequestParam("skuId") Integer skuId, +// @RequestParam("quantity") Integer quantity) { +// cartManager.updateCartItemQuantity(UserSecurityContextHolder.getUserId(), skuId, quantity); +// return success(true); +// } +// +// @PostMapping("update-selected") +// @ApiOperation("更新购物车商品是否选中") +// @ApiImplicitParams({ +// @ApiImplicitParam(name = "skuIds", value = "商品 SKU 编号数组", required = true, example = "1,3"), +// @ApiImplicitParam(name = "selected", value = "是否选中", required = true, example = "true") +// }) +// @RequiresAuthenticate +// public CommonResult updateCartItemSelected(@RequestParam("skuIds") Set skuIds, +// @RequestParam("selected") Boolean selected) { +// cartManager.updateCartItemSelected(UserSecurityContextHolder.getUserId(), skuIds, selected); +// // 获得目前购物车明细 +// return success(true); +// } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/CartDetailVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/CartDetailVO.java new file mode 100644 index 000000000..403efbebe --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/CartDetailVO.java @@ -0,0 +1,211 @@ +package cn.iocoder.yudao.module.trade.controller.app.cart.vo; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +@ApiModel(value = "用户的购物车明细 Response VO") // TODO 芋艿:swagger 文档完善 +@Data +@Accessors(chain = true) +public class CartDetailVO { + + /** + * 商品分组数组 + */ + private List itemGroups; + /** + * 费用 + */ + private Fee fee; + + /** + * 商品分组 + * + * 多个商品,参加同一个活动,从而形成分组。 + */ + @Data + @Accessors(chain = true) + public static class ItemGroup { + +// /** +// * 优惠活动 +// */ +// private PromotionActivityRespDTO activity; // TODO 芋艿,偷懒 + /** + * 促销减少的金额 + * + * 1. 若未参与促销活动,或不满足促销条件,返回 null + * 2. 该金额,已经分摊到每个 Item 的 discountTotal ,需要注意。 + */ + private Integer activityDiscountTotal; + /** + * 商品数组 + */ + private List items; + + } + + @Data + @Accessors(chain = true) + public static class Sku { + + // SKU 自带信息 + /** + * sku 编号 + */ + private Integer id; + /** + * SPU 信息 + */ + private Spu spu; + /** + * 图片地址 + */ + private String picURL; +// /** +// * 规格值数组 +// */ +// private List attrs; // TODO 后面改下 + /** + * 价格,单位:分 + */ + private Integer price; + /** + * 库存数量 + */ + private Integer quantity; + + // 非 SKU 自带信息 + + /** + * 购买数量 + */ + private Integer buyQuantity; + /** + * 是否选中 + */ + private Boolean selected; +// /** +// * 优惠活动 +// */ +// private PromotionActivityRespDTO activity; // TODO 芋艿,偷懒 + /** + * 原始单价,单位:分。 + */ + private Integer originPrice; + /** + * 购买单价,单位:分 + */ + private Integer buyPrice; + /** + * 最终价格,单位:分。 + */ + private Integer presentPrice; + /** + * 购买总金额,单位:分 + * + * 用途类似 {@link #presentTotal} + */ + private Integer buyTotal; + /** + * 优惠总金额,单位:分。 + */ + private Integer discountTotal; + /** + * 最终总金额,单位:分。 + * + * 注意,presentPrice * quantity 不一定等于 presentTotal 。 + * 因为,存在无法整除的情况。 + * 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。 + * 所以,需要存储一个该字段。 + */ + private Integer presentTotal; + + } + + @Data + @Accessors(chain = true) + public static class Spu { + + /** + * SPU 编号 + */ + private Integer id; + + // ========== 基本信息 ========= + /** + * SPU 名字 + */ + private String name; + /** + * 分类编号 + */ + private Integer cid; + /** + * 商品主图地址 + * + * 数组,以逗号分隔 + * + * 建议尺寸:800*800像素,你可以拖拽图片调整顺序,最多上传15张 + */ + private List picUrls; + + } + + /** + * 费用(合计) + */ + @Data + @Accessors(chain = true) + public static class Fee { + + /** + * 购买总价 + */ + private Integer buyTotal; + /** + * 优惠总价 + * + * 注意,满多少元包邮,不算在优惠中。 + */ + private Integer discountTotal; + /** + * 邮费 + */ + private Integer postageTotal; + /** + * 最终价格 + * + * 计算公式 = 总价 - 优惠总价 + 邮费 + */ + private Integer presentTotal; + + public Fee() { + } + + public Fee(Integer buyTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) { + this.buyTotal = buyTotal; + this.discountTotal = discountTotal; + this.postageTotal = postageTotal; + this.presentTotal = presentTotal; + } + + } + + /** + * 邮费信息 TODO 芋艿,未完成 + */ + @Data + @Accessors(chain = true) + public static class Postage { + + /** + * 需要满足多少钱,可以包邮。单位:分 + */ + private Integer threshold; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.http b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.http new file mode 100644 index 000000000..778e99029 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.http @@ -0,0 +1,31 @@ +### /trade-order/confirm-create-order-info 基于商品,确认创建订单 +GET {{appApi}}/trade/order/get-create-info?items[0].skuId=1&items[0].count=1 +Authorization: Bearer {{user-access-token}} +tenant-id: {{appTenentId}} + +### /trade-order/confirm-create-order-info-from-cart 基于购物车,确认创建订单 +GET {{shop-api-base-url}}/trade-order/confirm-create-order-info-from-cart +Content-Type: application/x-www-form-urlencoded +Authorization: Bearer {{user-access-token}} + +### /trade-order/confirm-create-order-info-from-cart 基于商品,创建订单 +POST {{shop-api-base-url}}/trade-order/create +Content-Type: application/json +Authorization: Bearer {{user-access-token}} + +{ + "userAddressId": 19, + "remark": "我是备注", + "orderItems": [ + { + "skuId": 3, + "quantity": 1 + } + ] +} + +### /trade-order/page 获得订单交易分页 +GET {{shop-api-base-url}}/trade-order/page?status=1&pageNo=1&pageSize=10 +Content-Type: application/x-www-form-urlencoded + +### diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java new file mode 100644 index 000000000..7b7ed4b83 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.trade.controller.app.order; + +import cn.hutool.extra.servlet.ServletUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderGetCreateInfoRespVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.TradeOrderPageReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.TradeOrderRespVO; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; + +@Api(tags = "用户 App - 交易订单") +@RestController +@RequestMapping("/trade/order") +@RequiredArgsConstructor +@Validated +@Slf4j +public class AppTradeOrderController { + + // TODO 在思考下; + + private final TradeOrderService tradeOrderService; + + + @GetMapping("/get-create-info") + @ApiOperation("基于商品,确认创建订单") + @PreAuthenticated + public CommonResult getTradeOrderCreateInfo(AppTradeOrderCreateReqVO createReqVO) { +// return success(tradeOrderService.getOrderConfirmCreateInfo(UserSecurityContextHolder.getUserId(), skuId, quantity, couponCardId)); + return null; + } + + @PostMapping("/create") + @ApiOperation("创建订单") + @PreAuthenticated + public CommonResult createTradeOrder(@RequestBody AppTradeOrderCreateReqVO createReqVO, + HttpServletRequest servletRequest) { +// return success(tradeOrderService.createTradeOrder(UserSecurityContextHolder.getUserId(), +// HttpUtil.getIp(servletRequest), createReqVO)); + // 获取登录用户 + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 获取用户ip地址 + String clientIp = ServletUtil.getClientIP(servletRequest); + // 创建交易订单,预支付记录 + Long result = tradeOrderService.createTradeOrder(loginUserId, clientIp, createReqVO); + + return CommonResult.success(result); + } + + @GetMapping("/get") + @ApiOperation("获得交易订单") + @ApiImplicitParam(name = "tradeOrderId", value = "交易订单编号", required = true) + public CommonResult getTradeOrder(@RequestParam("tradeOrderId") Integer tradeOrderId) { +// return success(tradeOrderService.getTradeOrder(tradeOrderId)); + return null; + } + + @GetMapping("/page") + @ApiOperation("获得订单交易分页") + public CommonResult> pageTradeOrder(TradeOrderPageReqVO pageVO) { +// return success(tradeOrderService.pageTradeOrder(UserSecurityContextHolder.getUserId(), pageVO)); + return null; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java new file mode 100644 index 000000000..54e856a6b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.trade.controller.app.order.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.List; + +@ApiModel(value = "用户 App - 交易订单创建 Request VO") +@Data +public class AppTradeOrderCreateReqVO { + + @ApiModelProperty(name = "收件地址编号", required = true, example = "1") + @NotNull(message = "收件地址不能为空") + private Integer addressId; + + @ApiModelProperty(name = "优惠劵编号", example = "1024") + private Long couponId; + + @ApiModelProperty(name = "备注", example = "1024") + private String remark; + + @ApiModelProperty(name = "是否来自购物车", required = true, example = "true", notes = "true - 来自购物车;false - 立即购买") + @NotNull(message = "是否来自购物车不能为空") + private Boolean fromCart; + + /** + * 订单商品项列表 + */ + @NotNull(message = "必须选择购买的商品") + private List items; + + @ApiModel(value = "订单商品项") + @Data + public static class Item { + + @ApiModelProperty(name = "商品 SKU 编号", required = true, example = "111") + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + + @ApiModelProperty(name = "商品 SKU 购买数量", required = true, example = "1024") + @NotNull(message = "商品 SKU 购买数量不能为空") + @Min(value = 1, message = "商品 SKU 购买数量必须大于 0") + private Integer count; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderGetCreateInfoRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderGetCreateInfoRespVO.java new file mode 100644 index 000000000..d0bf595f6 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderGetCreateInfoRespVO.java @@ -0,0 +1,169 @@ +package cn.iocoder.yudao.module.trade.controller.app.order.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +@ApiModel(value = "用户 App - 订单获得创建信息 Response VO") +@Data +public class AppTradeOrderGetCreateInfoRespVO { + + /** + * 商品分组数组 + */ + private List itemGroups; + /** + * 费用 + */ + private Fee fee; + +// /** +// * 优惠劵列表 TODO 芋艿,后续改改 +// */ +// private List coupons; + + @ApiModel(value = "商品分组", description = "多个商品,参加同一个活动,从而形成分组") + @Data + public static class ItemGroup { + +// /** +// * 优惠活动 +// */ +// private PromotionActivityRespDTO activity; // TODO 芋艿,偷懒 + /** + * 商品 SKU 数组 + */ + private List items; + + } + + @ApiModel("商品 SKU") + @Data + public static class Sku { + + // SKU 自带信息 + @ApiModelProperty(value = "SKU 编号", required = true, example = "1024") + private Integer id; + /** + * SPU 信息 + */ + private Spu spu; + /** + * 图片地址 + */ + private String picURL; +// /** +// * 规格值数组 +// */ +// private List attrs; // TODO 后面改下 + /** + * 价格,单位:分 + */ + private Integer price; + /** + * 库存数量 + */ + private Integer stock; + + // 非 SKU 自带信息 + + /** + * 购买数量 + */ + private Integer buyQuantity; +// /** +// * 优惠活动 +// */ +// private PromotionActivityRespDTO activity; // TODO 芋艿,偷懒 + /** + * 原始单价,单位:分。 + */ + private Integer originPrice; + /** + * 购买单价,单位:分 + */ + private Integer buyPrice; + /** + * 最终价格,单位:分。 + */ + private Integer presentPrice; + /** + * 购买总金额,单位:分 + * + * 用途类似 {@link #presentTotal} + */ + private Integer buyTotal; + /** + * 优惠总金额,单位:分。 + */ + private Integer discountTotal; + /** + * 最终总金额,单位:分。 + * + * 注意,presentPrice * quantity 不一定等于 presentTotal 。 + * 因为,存在无法整除的情况。 + * 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。 + * 所以,需要存储一个该字段。 + */ + private Integer presentTotal; + + } + + @Data + public static class Spu { + + /** + * SPU 编号 + */ + private Integer id; + + // ========== 基本信息 ========= + /** + * SPU 名字 + */ + private String name; + /** + * 分类编号 + */ + private Integer cid; + /** + * 商品主图地址 + * + * 数组,以逗号分隔 + * + * 建议尺寸:800*800像素,你可以拖拽图片调整顺序,最多上传15张 + */ + private List picUrls; + + } + + @ApiModel("费用(合计)") + @Data + @AllArgsConstructor + public static class Fee { + + @ApiModelProperty(value = "购买总价", required = true, example = "1024") + private Integer buyPrice; + /** + * 优惠总价 + * + * 注意,满多少元包邮,不算在优惠中。 + */ + private Integer discountTotal; + /** + * 邮费 + */ + private Integer postageTotal; + /** + * 最终价格 + * + * 计算公式 = 总价 - 优惠总价 + 邮费 + */ + private Integer presentTotal; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderItemRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderItemRespVO.java new file mode 100644 index 000000000..195f7330f --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderItemRespVO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.trade.controller.app.order.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; + +@ApiModel("交易订单项 Response VO") +@Data +public class TradeOrderItemRespVO { + + @ApiModelProperty(value = "id自增长", required = true) + private Integer id; + @ApiModelProperty(value = "订单编号", required = true) + private Integer orderId; + @ApiModelProperty(value = "订单项状态", required = true) + private Integer status; + @ApiModelProperty(value = "商品 SKU 编号", required = true) + private Integer skuId; + @ApiModelProperty(value = "商品 SPU 编号", required = true) + private Integer spuId; + @ApiModelProperty(value = "商品名字", required = true) + private String skuName; + @ApiModelProperty(value = "图片名字", required = true) + private String skuImage; + @ApiModelProperty(value = "商品数量", required = true) + private Integer quantity; + @ApiModelProperty(value = "原始单价,单位:分", required = true) + private Integer originPrice; + @ApiModelProperty(value = "购买单价,单位:分", required = true) + private Integer buyPrice; + @ApiModelProperty(value = "最终价格,单位:分", required = true) + private Integer presentPrice; + @ApiModelProperty(value = "购买总金额,单位:分", required = true) + private Integer buyTotal; + @ApiModelProperty(value = "优惠总金额,单位:分", required = true) + private Integer discountTotal; + @ApiModelProperty(value = "最终总金额,单位:分", required = true) + private Integer presentTotal; + @ApiModelProperty(value = "退款总金额,单位:分", required = true) + private Integer refundTotal; + @ApiModelProperty(value = "物流id") + private Integer logisticsId; + @ApiModelProperty(value = "售后状态", required = true) + private Integer afterSaleStatus; + @ApiModelProperty(value = "售后订单编号") + private Integer afterSaleOrderId; + @ApiModelProperty(value = "创建时间", required = true) + private Date createTime; + + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderPageReqVO.java new file mode 100644 index 000000000..5c8b6c872 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderPageReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.trade.controller.app.order.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; + +@ApiModel("交易订单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class TradeOrderPageReqVO extends PageParam { + + @ApiModelProperty(value = "订单状态", example = "1", notes = "参见 TradeOrderStatusEnum 枚举") + private Integer orderStatus; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderRespVO.java new file mode 100644 index 000000000..4b7ffa77c --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderRespVO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.trade.controller.app.order.vo; + +import lombok.*; +import io.swagger.annotations.*; +import java.util.*; + +@ApiModel("订单交易 Response VO") +@Data +public class TradeOrderRespVO { + + @ApiModelProperty(value = "订单编号", required = true) + private Integer id; + @ApiModelProperty(value = "用户编号", required = true) + private Integer userId; + @ApiModelProperty(value = "订单单号", required = true) + private String orderNo; + @ApiModelProperty(value = "订单状态", required = true) + private Integer orderStatus; + @ApiModelProperty(value = "备注") + private String remark; + @ApiModelProperty(value = "订单结束时间") + private Date endTime; + @ApiModelProperty(value = "订单金额(总金额),单位:分", required = true) + private Integer buyPrice; + @ApiModelProperty(value = "优惠总金额,单位:分", required = true) + private Integer discountPrice; + @ApiModelProperty(value = "物流金额,单位:分", required = true) + private Integer logisticsPrice; + @ApiModelProperty(value = "最终金额,单位:分", required = true) + private Integer presentPrice; + @ApiModelProperty(value = "支付金额,单位:分", required = true) + private Integer payPrice; + @ApiModelProperty(value = "退款金额,单位:分", required = true) + private Integer refundPrice; + @ApiModelProperty(value = "付款时间") + private Date payTime; + @ApiModelProperty(value = "支付订单编号") + private Integer payTransactionId; + @ApiModelProperty(value = "支付渠道") + private Integer payChannel; + @ApiModelProperty(value = "配送类型", required = true) + private Integer deliveryType; + @ApiModelProperty(value = "发货时间") + private Date deliveryTime; + @ApiModelProperty(value = "收货时间") + private Date receiveTime; + @ApiModelProperty(value = "收件人名称", required = true) + private String receiverName; + @ApiModelProperty(value = "手机号", required = true) + private String receiverMobile; + @ApiModelProperty(value = "地区编码", required = true) + private Integer receiverAreaCode; + @ApiModelProperty(value = "收件详细地址", required = true) + private String receiverDetailAddress; + @ApiModelProperty(value = "售后状态", required = true) + private Integer afterSaleStatus; + @ApiModelProperty(value = "优惠劵编号") + private Integer couponCardId; + @ApiModelProperty(value = "创建时间", required = true) + private Date createTime; + + /** + * 订单项数组 + * + * // TODO 芋艿,后续考虑怎么优化下,目前是内嵌了别的 dto + */ + private List orderItems; + + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/refund/TradeRefundController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/refund/TradeRefundController.java new file mode 100644 index 000000000..aa419190e --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/refund/TradeRefundController.java @@ -0,0 +1,4 @@ +package cn.iocoder.yudao.module.trade.controller.app.refund; + +public class TradeRefundController { +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/package-info.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/package-info.java new file mode 100644 index 000000000..aa2f99f35 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.trade.controller; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java new file mode 100644 index 000000000..1b81212b8 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.trade.convert.order; + +import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateRespDTO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +@Mapper +public interface TradeOrderConvert { + + TradeOrderConvert INSTANCE = Mappers.getMapper(TradeOrderConvert.class); + + @Mapping(source = "order.couponId", target = "couponId") + TradeOrderDO convert(AppTradeOrderCreateReqVO createReqVO, PriceCalculateRespDTO.Order order); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderItemConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderItemConvert.java new file mode 100644 index 000000000..23113f9f3 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderItemConvert.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.trade.convert.order; + +import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateRespDTO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +@Mapper +public interface TradeOrderItemConvert { + + TradeOrderItemConvert INSTANCE = Mappers.getMapper(TradeOrderItemConvert.class); + + /** + * + * @param tradeOrder 交易订单 + * @param items sku列表价格 + * @return 订单项 + */ + @Mappings({ + @Mapping(source = "tradeOrder.userId", target = "userId"), + @Mapping(source = "tradeOrder.orderId", target = "orderId") + }) + default List convertList(TradeOrderDO tradeOrder, List items) { + // TODO @Com: Mapstruct 生成会报错 + throw new UnsupportedOperationException("无法实现"); + } +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/pay/PayOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/pay/PayOrderConvert.java new file mode 100644 index 000000000..22dd11fe9 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/pay/PayOrderConvert.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.trade.convert.pay; + +import cn.iocoder.yudao.module.pay.api.order.PayOrderDataCreateReqDTO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import org.mapstruct.factory.Mappers; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +public interface PayOrderConvert { + + PayOrderConvert INSTANCE = Mappers.getMapper(PayOrderConvert.class); + + + PayOrderDataCreateReqDTO convert(TradeOrderDO tradeOrderDO); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/price/PriceConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/price/PriceConvert.java new file mode 100644 index 000000000..3b2d173c3 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/price/PriceConvert.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.trade.convert.price; + +import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateReqDTO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +@Mapper +public interface PriceConvert { + + PriceConvert INSTANCE = Mappers.getMapper(PriceConvert.class); + + @Mappings( + @Mapping(source = "userId" , target = "userId") + ) + PriceCalculateReqDTO convert(AppTradeOrderCreateReqVO createReqVO , Long userId); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/sku/ProductSkuConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/sku/ProductSkuConvert.java new file mode 100644 index 000000000..fffc6fa42 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/sku/ProductSkuConvert.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.trade.convert.sku; + +import cn.iocoder.yudao.module.product.api.sku.dto.SkuDecrementStockBatchReqDTO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +@Mapper +public interface ProductSkuConvert { + + ProductSkuConvert INSTANCE = Mappers.getMapper(ProductSkuConvert.class); + + List convert(List tradeOrderItems); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/CartItemDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/CartItemDO.java new file mode 100644 index 000000000..b92ca8b54 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/CartItemDO.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.cart; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.util.Date; + +/** + * 购物车的商品信息 DO + */ +@TableName("trade_cart_item") +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class CartItemDO extends BaseDO { + + // ========= 基础字段 BEGIN ========= + + /** + * 编号,唯一自增 + */ + private Long id; + /** + * 是否选中 + */ + private Boolean selected; + /** + * 购物时间 + */ + private Date buyTime; // basket_date + + // ========= 基础字段 END ========= + + // ========= 买家信息 BEGIN ========= + + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + + // ========= 买家信息 END ========= + + // ========= 商品信息 BEGIN ========= + + /** + * 商品 SPU 编号 + * + * 关联 ProductSpuDO 的 id 编号 + */ + private Long spuId; + /** + * 商品 SKU 编号 + * + * 关联 ProductSkuDO 的 id 编号 + */ + private Long skuId; + /** + * 商品购买数量 + */ + private Integer stock; + + // ========= 商品信息 END ========= + + // ========= 优惠信息 BEGIN ========= + +// /** +// * 商品营销活动编号 +// */ +// private Long activityId; // discount_id +// /** +// * 商品营销活动类型 +// */ +// private Integer activityType; + // TODO 芋艿:combination_id 拼团 ID + // TODO 芋艿:seckill_id 秒杀产品 ID + // TODO 芋艿:bargain_id 砍价 ID + + // ========= 优惠信息 END ========= + + // TODO 待确定字段:mf + // TODO 芋艿:distribution_card_no 推广员 + // TODO 芋艿:is_pay 未购买、已购买 + // TODO 芋艿:is_new 是否立即购买 + + // TODO 待确定字段: yv + // TODO isPay: 是否购买 + // TODO isNew:是否立即购买 + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java new file mode 100644 index 000000000..77bdf66b0 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java @@ -0,0 +1,304 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.order; + +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.enums.delivery.DeliveryTypeEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.util.Date; + +/** + * 交易订单 DO + * + * @author 芋道源码 + */ +@TableName("trade_order") +@KeySequence("trade_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TradeOrderDO extends BaseDO { + + // ========== 订单基本信息 ========== + /** + * 订单编号,主键自增 + */ + private Long id; + /** + * 订单流水号 + * + * 例如说,1146347329394184195 + */ + private String sn; + /** + * 订单类型 + * + * 枚举 {@link TradeOrderTypeEnum} + */ + private Integer type; // TODO order_promotion_type + /** + * 订单来源终端 + * + * 枚举 {@link TerminalEnum} + */ + private Integer terminal; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + /** + * 用户 IP + */ + private String userIp; + /** + * 用户备注 + */ + private String userRemark; + /** + * 订单状态 + * + * 枚举 {@link TradeOrderStatusEnum} + */ + private Integer status; + // TODO 芋艿:要不要存储 prod_name 购买的商品名门? + /** + * 购买的商品数量 + */ + private Integer productCount; // total_num + /** + * 订单完成时间 + */ + private Date finishTime; + /** + * 订单取消时间 + */ + private Date cancelTime; + /** + * 取消类型 + * + * 枚举 {@link TradeOrderCancelTypeEnum} + */ + private Integer cancelType; + /** + * 商家备注 + */ + private String remark; + + // ========== 价格 + 支付基本信息 ========== + /** + * 是否已支付 + * + * true - 已经支付过 + * false - 没有支付过 + */ + private Boolean payed; + /** + * 付款时间 + */ + private Date payTime; + + // ========== 价格 + 支付基本信息 ========== + // 价格文档 - 淘宝:https://open.taobao.com/docV3.htm?docId=108471&docType=1 + // 价格文档 - 京东到家:https://openo2o.jddj.com/api/getApiDetail/182/4d1494c5e7ac4679bfdaaed950c5bc7f.htm + // 价格文档 - 有赞:https://doc.youzanyun.com/detail/API/0/906 + +// TODO promotion_details(订单优惠信息明细,商品和订单级优惠一般都在里面) + + /** + * 商品原价(总),单位:分 + * + * 基于 {@link TradeOrderItemDO#getTotalOriginalPrice()} 求和 + */ + // niu - goods_money; + private Integer skuOriginalPrice; + /** + * 商品优惠(总),单位:分 + * + * 基于 {@link TradeOrderItemDO#getTotalPromotionPrice()} 求和 + */ + private Integer skuPromotionPrice; + /** + * 订单优惠(总),单位:分 + * + * 例如说:满减折扣;不包括优惠劵、商品优惠 + */ + // niu - promotion_money;taobao - discount_fee(主订单优惠) + private Integer orderPromotionPrice; + /** + * 运费金额,单位:分 + */ + // niu - delivery_money;taobao - post_fee(订单邮费) + private Integer deliveryPrice; + // TODO 芋艿:taobao 的:trade.adjust_fee/order.adjust_fee(调整金额,如:卖家手动修改订单价格,官方数据修复等等) + /** + * 应付金额(总),单位:分 + * + * = {@link #skuOriginalPrice} + * + {@link #deliveryPrice} + * - {@link #skuPromotionPrice} + * - {@link #orderPromotionPrice} + */ + // niu - pay_money;taobao - payment(主订单实付金额) | trade.total_fee(主订单应付金额,参考使用); +// * - {@link #couponPrice} // TODO 芋艿:靠营销表记录 + private Integer payPrice; + /** + * 支付订单编号 + * + * 对接 pay-module-biz 支付服务的支付订单编号,即 PayOrderDO 的 id 编号 + */ + private Long payOrderId; + /** + * 支付成功的支付渠道 + * + * 对应 PayChannelEnum 枚举 + */ + private Integer payChannel; + + // ========== 收件 + 物流基本信息 ========== + /** + * 配送方式 + * 会员用户下单时,选择的配送方式 + * + * 枚举 {@link DeliveryTypeEnum} + */ + private Integer deliveryType; + /** + * 实际的配送方式 + * 管理后台发货时,选择的配送方式 + * + * 0 - 无需物流 + * 枚举 {@link DeliveryTypeEnum} + */ + private Integer actualDeliveryType; // like - shipping_status; + /** + * 配置模板的编号 + * + * 关联 DeliveryTemplateDO 的 id 编号 + */ + private Long deliveryTemplateId; // dvy_id + /** + * 物流公司单号 + */ + private String expressNo; // dvy_flow_id + /** + * 发货状态 + * + * true - 已发货 + * false - 未发货 + */ + private Boolean deliveryStatus; + /** + * 发货时间 + */ + private Date deliveryTime; + /** + * 收货时间 + */ + private Date receiveTime; + /** + * 收件人名称 + */ + private String receiverName; + /** + * 收件人手机 + */ + private String receiverMobile; + /** + * 收件人地区编号 + */ + private Integer receiverAreaId; + /** + * 收件人邮编 + */ + private Integer receiverPostCode; + /** + * 收件人详细地址 + */ + private String receiverDetailAddress; + + // ========== 退款基本信息 ========== + /** + * 退款状态 + * + * 枚举 {@link TradeOrderRefundStatusEnum} + */ + private Integer refundStatus; + /** + * 退款金额,单位:分 + * + * 注意,退款并不会影响 {@link #payPrice} 实际支付金额 + * 也就说,一个订单最终产生多少金额的收入 = payPrice - refundPrice + */ + private Integer refundPrice; + + // ========== 营销基本信息 ========== + /** + * 优惠劵编号 + */ + private Long couponId; +// /** +// * 优惠劵减免金额,单位:分 // TODO 芋艿:靠营销表记录 +// */ +// // niu - coupon_money; +// private Integer couponPrice; +// /** +// * 积分抵扣的金额,单位:分 +// */ +// private Integer integralPrice; +// /** +// * 使用的积分 +// */ +// private Integer useIntegral; + + // TODO ========== 待定字段:yv ========= + // TODO cart_id:购物车 id + // TODO refund_reason_wap_img:退款图片 + // TODO refund_reason_wap_explain:退款用户说明 + // TODO refund_reason_time:退款时间 + // TODO refund_reason_wap:前台退款原因 + // TODO refund_reason:不退款的理由 + + // TODO gain_integral:消费赚取积分 + // TODO back_integral:给用户退了多少积分 + + // TODO combination_id:拼团产品id + // TODO pink_id:拼团id + // TODO seckill_id:秒杀产品ID + // TODO bargain_id:砍价id + + // TODO cost:成本价 + // TODO verify_code:核销码 + // TODO store_id:门店id + + // TODO ========== 待定字段:cf ========= + // TODO before_pay_price:改价前支付金额 + // TODO is_alter_price:是否改价 + // TODO out_trade_no:商户系统内部的订单号 String + + // TODO ========== 待定字段:lf ========= + // TODO settle_id:未结算 + // TODO settle_amount:结算金额 + // TODO team_found_id: 拼团id + // TODO team_id: 拼团活动id + // TODO delivery_id: 发货单ID + // TODO attach_values: 附带的值(赠送时机,赠送积分成长值什么的)Json格式 + + // TODO ========== 待定字段:nf ========= + // TODO delivery_code:整体提货编码 + + // TODO ========== 待定字段:niu ========= + // TODO adjust_money '订单调整金额' + // TODO balance_money ''余额支付金额'' + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java new file mode 100644 index 000000000..14e4de0f4 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java @@ -0,0 +1,214 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.order; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemRefundStatusEnum; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 交易订单项 DO + * + * @author 芋道源码 + */ +@TableName(value = "trade_order_item") +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class TradeOrderItemDO extends BaseDO { + + // ========== 订单项基本信息 ========== + /** + * 编号 + */ + private Long id; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + /** + * 订单编号 + * + * 关联 {@link TradeOrderDO#getId()} + */ + private Long orderId; + + // ========== 商品基本信息 ========== + /** + * 商品 SPU 编号 + * + * 关联 ProductSkuDO 的 spuId 编号 + */ + private Long spuId; + /** + * 商品 SKU 编号 + * + * 关联 ProductSkuDO 的 id 编号 + */ + private Long skuId; + /** + * 规格值数组,JSON 格式 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List properties; + /** + * 商品名称 + */ + private String name; + /** + * 商品图片 + */ + private String picUrl; + /** + * 购买数量 + */ + private Integer count; + /** + * 是否评论 + * + * false - 未评论 + * true - 已评论 + */ + private Boolean commented; + + // ========== 价格 + 支付基本信息 ========== + /** + * 商品原价(单),单位:分 + * + * 对应 ProductSkuDO 的 price 字段 + */ + // like - original_price;niu - costPrice + private Integer originalPrice; + /** + * 商品原价(总),单位:分 + * + * = {@link #originalPrice} * {@link #count} + */ + // like - total_price;niu - 暂无 + private Integer totalOriginalPrice; + /** + * 商品级优惠(总),单位:分 + * + * 例如说“限时折扣”:商品原价的 8 折;商品原价的减 50 元 + */ + // taobao - order.discount_fee(子订单商品优惠) + private Integer totalPromotionPrice; + /** + * 最终购买金额(单),单位:分。 + * + * = {@link #totalPresentPrice} / {@link #count} + */ + private Integer presentPrice; + /** + * 最终购买金额(总),单位:分。 + * + * = {@link #totalOriginalPrice} + * - {@link #totalPromotionPrice} + */ + // like - total_pay_price;niu - goods_money; taobao - order.payment(子订单实付金额,不算主订单分摊金额) | order.total_fee(子订单应付金额,参考使用) + private Integer totalPresentPrice; + // TODO 芋艿:part_mjz_discount(子订单分摊金额);本质上,totalOriginalPrice - totalPayPrice + /** + * 应付金额(总),单位:分 + */ + // taobao - divide_order_fee (分摊后子订单实付金额); + private Integer totalPayPrice; + + // ========== 营销基本信息 ========== +// /** +// * 积分抵扣的金额,单位:分 +// */ +// private Integer integralTotal; // like - integral_price;niu - point_money +// /** +// * 使用的积分 +// */ +// private Integer useIntegral; // niu - use_point + + // ========== 退款基本信息 ========== + /** + * 退款状态 + * + * 枚举 {@link TradeOrderItemRefundStatusEnum} + */ + private Integer refundStatus; // TODO 芋艿:可以考虑去查 + // 如上字段,举个例子: + // 假设购买三个,即 stock = 3 。 + // originPrice = 15 + // 使用限时折扣(单品优惠)8 折,buyPrice = 12 + // 开始算总的价格 + // buyTotal = buyPrice * stock = 12 * 3 = 36 + // discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11 + // presentTotal = buyTotal - discountTotal = 24 - 11 = 13 + // 最终 presentPrice = presentTotal / stock = 13 / 3 = 4.33 + /** + * 退款总金额,单位:分 + */ + private Integer refundTotal; + + /** + * 商品属性 + */ + @Data + public static class Property { + + /** + * 属性编号 + * + * 关联 ProductPropertyDO 的 id 编号 + */ + private Long propertyId; + /** + * 属性值编号 + * + * 关联 ProductPropertyValueDO 的 id 编号 + */ + private Long valueId; + + } + + // TODO 芋艿:basket_date 加入购物车时间; + // TODO 芋艿:distribution_card_no 推广员使用的推销卡号 + + // TODO 待确定:mf + // TODO give_integral:赠送积分 + // TODO is_reply:是否评价,0-未评价,1-已评价 + // TODO is_sub:是否单独分佣,0-否,1-是 + // TODO vip_price:会员价 + // TODO product_type:商品类型:0-普通,1-秒杀,2-砍价,3-拼团,4-视频号 + + // TODO 待确定:lf + // TODO integral_price:积分抵扣的金额 + // TODO member_price:会员价格 + // TODO is_member:是否为会员折扣;0-不是;1-是 + // TODO member_discount:会员折扣(百分比) + + // TODO goods_info 商品信息 + + // TODO integral_price:积分抵扣的金额 + + // TODO 待确定:niu + // TODO is_virtual '是否是虚拟商品' + // TODO goods_class '商品种类(1.实物 2.虚拟3.卡券)' + // TODO adjust_money ''调整金额'' + + // TODO is_fenxiao 是否分销, + // TODO adjust_money 是否分销, + + // TODO delivery_status '配送状态' + // TODO delivery_no ''配送单号'' + // TODO gift_flag '赠品标识' + // TODO gift_flag '赠品标识' + + // TODO refund_status '退款状态' + // TODO refund_type '退款状态' + // TODO 一堆退款字段 + +} + diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/refund/TradeRefundDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/refund/TradeRefundDO.java new file mode 100644 index 000000000..cd246a297 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/refund/TradeRefundDO.java @@ -0,0 +1,148 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.refund; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; +import cn.iocoder.yudao.module.trade.enums.refund.TradeRefundTypeEnum; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.util.Date; +import java.util.List; + +/** + * 交易退款,用于处理 {@link TradeOrderDO} 交易订单的退货换流程 + */ +// TODO 芋艿:需要调整下每个字段的命名;未完全实现; +@TableName(value = "trade_refund") +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TradeRefundDO extends BaseDO { + + /** + * 交易退款编号,主键自增 + */ + @Deprecated + private Long id; + /** + * 退款流水号 + * + * 例如说,1146347329394184195 + */ + private String sn; + /** + * 退款状态 + * + * 枚举 {@link TradeOrderRefundStatusEnum} + */ + private Integer status; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + /** + * 用户手机 + */ + private String userMobile; + /** + * 申请类型 + * + * 枚举 {@link TradeRefundTypeEnum} + */ + private Integer type; + /** + * 用户售后说明 + */ + private String reasonMemo; // buyer_msg + /** + * 用户售后凭证图片的地址数组 + * + * 数组,以逗号分隔 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List reasonPicUrls; // photo_files + + // ========== 商家相关 ========== + + /** + * 商家处理时间 + */ + private Date handleTime; // handel_time + /** + * 商家拒绝理由 + */ + private String rejectReasonMemo; // seller_msg + + // ========== 交易订单相关 ========== + /** + * 交易订单编号 + * + * 外键 {@link TradeOrderDO#getId()} + */ + private Long tradeOrderId; + /** + * 交易订单项编号 + * + * 关联 {@link TradeOrderItemDO#getId()} + * 如果全部退款,则该值设置为 0 即可 + */ + private Long tradeOrderItemId; + /** + * 商品 SKU 编号 + */ + @Deprecated + private Integer skuId; + /** + * 退货商品数量 + */ + private Integer stock; // goods_num + + // ========== 退款相关 ========== + /** + * 退款金额,单位:分。 + */ + private Integer refundPrice; // refund_amount + /** + * 支付退款编号 + * + * 对接 pay-module-biz 支付服务的退款订单编号,即 PayRefundDO 的 id 编号 + */ + private Long payRefundId; + // TODO 芋艿:看看是否有必要冗余,order_number、order_amount、flow_trade_no、out_refund_no、pay_type、return_money_sts、refund_time + + // ========== 退货相关 ========== + /** + * 退货物流公司编号 + * + * 关联 ExpressDO 的 id 编号 + */ + private Long returnExpressId; // express_name + /** + * 退货物流单号 + */ + private String returnExpressNo; // express_no + /** + * 退货时间 + */ + private Date returnDate; // ship_time + + // ========== 收获相关 ========== + + /** + * 收获备注 + */ + private String receiveMemo; // receive_message + /** + * 收货时间 + */ + private Date receiveDate; // receive_time + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java new file mode 100644 index 000000000..3b963540b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.order; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +@Mapper +public interface TradeOrderMapper extends BaseMapperX { +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/orderitem/TradeOrderItemMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/orderitem/TradeOrderItemMapper.java new file mode 100644 index 000000000..987d5a3f5 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/orderitem/TradeOrderItemMapper.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.orderitem; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +@Mapper +public interface TradeOrderItemMapper extends BaseMapperX { +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/package-info.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/package-info.java new file mode 100644 index 000000000..37e0ba7d6 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/package-info.java @@ -0,0 +1,4 @@ +/** + * TODO 占位 + */ +package cn.iocoder.yudao.module.trade.dal.mysql; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/package-info.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/package-info.java new file mode 100644 index 000000000..393abea6a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/package-info.java @@ -0,0 +1,8 @@ +/** + * product 模块,product 模块,主要实现商品相关功能 + * 例如:品牌、商品分类、spu、sku等功能。 + * + * 1. Controller URL:以 /product/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 product_ 开头,方便在数据库中区分 + */ +package cn.iocoder.yudao.module.trade; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java new file mode 100644 index 000000000..f3fc4b5e1 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.trade.service.order; + +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +public interface TradeOrderService { + + /** + * 创建交易订单 + * @param loginUserId 登录用户 + * @param clientIp 用户ip地址 + * @param createReqVO 创建交易订单请求模型 + * @return 交易订单创建结果 + */ + Long createTradeOrder(Long loginUserId, String clientIp, AppTradeOrderCreateReqVO createReqVO); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java new file mode 100644 index 000000000..3554e7d4c --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java @@ -0,0 +1,138 @@ +package cn.iocoder.yudao.module.trade.service.order; + +import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +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 cn.iocoder.yudao.module.pay.api.order.PayOrderApi; +import cn.iocoder.yudao.module.pay.api.order.PayOrderDataCreateReqDTO; +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; +import cn.iocoder.yudao.module.product.api.sku.dto.SkuDecrementStockBatchReqDTO; +import cn.iocoder.yudao.module.product.api.sku.dto.SkuInfoRespDTO; +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; +import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO.Item; +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderItemConvert; +import cn.iocoder.yudao.module.trade.convert.pay.PayOrderConvert; +import cn.iocoder.yudao.module.trade.convert.price.PriceConvert; +import cn.iocoder.yudao.module.trade.convert.sku.ProductSkuConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; +import cn.iocoder.yudao.module.trade.dal.mysql.orderitem.TradeOrderItemMapper; +import cn.iocoder.yudao.module.trade.enums.enums.ErrorCodeConstants; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +@Service +@RequiredArgsConstructor +public class TradeOrderServiceImpl implements TradeOrderService { + + private final TradeOrderMapper tradeOrderMapper; + + private final TradeOrderItemMapper tradeOrderItemMapper; + + private final PriceApi priceApi; + + private final ProductSkuApi productSkuApi; + + private final ProductSpuApi productSpuApi; + + private final PayOrderApi payOrderApi; + + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createTradeOrder(Long loginUserId, String clientIp, AppTradeOrderCreateReqVO createReqVO) { + + List items = createReqVO.getItems(); + // 商品SKU检查 sku可售状态,库存 + List skuInfos = productSkuApi.getSkusByIds(CollectionUtils.convertSet(items, Item::getSkuId)); + Map skuInfoMap = CollectionUtils.convertMap(skuInfos, SkuInfoRespDTO::getId); + checkSaleableAndStockFromSpu(skuInfoMap, items); + + // 商品SPU检查 sku可售状态,库存 + List spuInfos = productSpuApi.getSpusByIds(CollectionUtils.convertSet(skuInfos, SkuInfoRespDTO::getSpuId)); + checkSaleableFromSpu(spuInfos); + + // 价格计算 + PriceCalculateReqDTO priceCalculateReqDTO = PriceConvert.INSTANCE.convert(createReqVO, loginUserId); + PriceCalculateRespDTO priceResp = priceApi.calculatePrice(priceCalculateReqDTO); + + // 订单信息记录 + TradeOrderDO tradeOrderDO = TradeOrderConvert.INSTANCE.convert(createReqVO, priceResp.getOrder()); + tradeOrderMapper.insert(tradeOrderDO); + + // 订单项信息记录 + List tradeOrderItems = TradeOrderItemConvert.INSTANCE.convertList(tradeOrderDO, priceResp.getItems()); + //-填充订单项-SKU信息 + fillItemsInfoFromSku(tradeOrderItems, skuInfoMap); + tradeOrderItemMapper.insertBatch(tradeOrderItems); + + // 库存扣减 + List skuDecrementStockItems = ProductSkuConvert.INSTANCE.convert(tradeOrderItems); + productSkuApi.decrementStockBatch(SkuDecrementStockBatchReqDTO.of(skuDecrementStockItems)); + // 生成预支付 + + PayOrderDataCreateReqDTO payOrderCreateReqDTO = PayOrderConvert.INSTANCE.convert(tradeOrderDO); + return payOrderApi.createPayOrder(payOrderCreateReqDTO); + } + + private void fillItemsInfoFromSku(List tradeOrderItems, + Map spuInfos) { + for (TradeOrderItemDO tradeOrderItem : tradeOrderItems) { + // 填充SKU信息 + SkuInfoRespDTO skuInfoRespDTO = spuInfos.get(tradeOrderItem.getSkuId()); + tradeOrderItem.setSpuId(skuInfoRespDTO.getSpuId()); + tradeOrderItem.setPicUrl(skuInfoRespDTO.getPicUrl()); + tradeOrderItem.setName(skuInfoRespDTO.getName()); + // todo + List property = + BeanUtil.copyToList(skuInfoRespDTO.getProperties(), TradeOrderItemDO.Property.class); + tradeOrderItem.setProperties(property); + } + } + + private void checkSaleableFromSpu(List spuInfos) { + SpuInfoRespDTO spu = CollectionUtils.findFirst(spuInfos, + spuInfoDTO -> !Objects.equals(ProductSpuStatusEnum.ENABLE.getStyle(), spuInfoDTO.getStatus())); + if (Objects.isNull(spu)) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_SPU_NOT_SALE); + } + } + + private void checkSaleableAndStockFromSpu(Map skuInfoMap, + List items) { + // sku 不存在 + if (items.size() != skuInfoMap.size()) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_SKU_NOT_FOUND); + } + for (Item item : items) { + SkuInfoRespDTO skuInfoDTO = skuInfoMap.get(item.getSkuId()); + // sku禁用 + if (!Objects.equals(CommonStatusEnum.ENABLE.getStatus(), skuInfoDTO.getStatus())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_SKU_NOT_SALE); + } + // sku库存不足 + if (item.getCount() > skuInfoDTO.getStock()) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_SKU_STOCK_NOT_ENOUGH); + } + } + + } +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index 2fbb61c8b..1e77db1c8 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -22,6 +22,5 @@ public interface ErrorCodeConstants { // ========== 用户收件地址 1004004000 ========== ErrorCode ADDRESS_NOT_EXISTS = new ErrorCode(1004004000, "用户收件地址不存在"); - ErrorCode ADDRESS_FORBIDDEN = new ErrorCode(1004004001, "没有该操作权限"); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.http b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.http index 7f943448a..6bae7c7eb 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.http +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.http @@ -2,53 +2,53 @@ POST {{appApi}}//member/address/create Content-Type: application/json tenant-id: {{appTenentId}} -Authorization: Bearer 2510e2e4287346eb8e36353a55e27fd6 +Authorization: Bearer {{appToken}} { - "userId": "245", "name": "yunai", "mobile": "15601691300", - "areaCode": "610632", + "areaId": "610632", + "postCode": "200000", "detailAddress": "芋道源码 233 号 666 室", - "type": "1" + "defaulted": true } ### 请求 /update 接口 => 成功 PUT {{appApi}}//member/address/update Content-Type: application/json tenant-id: {{appTenentId}} -Authorization: Bearer 2510e2e4287346eb8e36353a55e27fd6 +Authorization: Bearer {{appToken}} { "id": "1", - "userId": "245", "name": "yunai888", "mobile": "15601691300", - "areaCode": "610632", + "areaId": "610632", + "postCode": "200000", "detailAddress": "芋道源码 233 号 666 室", - "type": "1" + "defaulted": false } ### 请求 /delete 接口 => 成功 DELETE {{appApi}}//member/address/delete?id=2 Content-Type: application/json tenant-id: {{appTenentId}} -Authorization: Bearer fa4848b001de4eae9faf516c0c8520f8 +Authorization: Bearer {{appToken}} ### 请求 /get 接口 => 成功 GET {{appApi}}//member/address/get?id=1 Content-Type: application/json tenant-id: {{appTenentId}} -Authorization: Bearer fa4848b001de4eae9faf516c0c8520f8 +Authorization: Bearer {{appToken}} ### 请求 /get-default 接口 => 成功 GET {{appApi}}//member/address/get-default Content-Type: application/json tenant-id: {{appTenentId}} -Authorization: Bearer fa4848b001de4eae9faf516c0c8520f8 +Authorization: Bearer {{appToken}} ### 请求 /list 接口 => 成功 GET {{appApi}}//member/address/list Content-Type: application/json tenant-id: {{appTenentId}} -Authorization: Bearer fa4848b001de4eae9faf516c0c8520f8 \ No newline at end of file +Authorization: Bearer {{appToken}} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressBaseVO.java index 81231a881..8cfbac7d2 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressBaseVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressBaseVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.member.controller.app.address.vo; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.member.enums.AddressTypeEnum; -import lombok.*; -import io.swagger.annotations.*; -import javax.validation.constraints.*; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; /** * 用户收件地址 Base VO,提供给添加、修改、详细的子 VO 使用 @@ -21,17 +21,20 @@ public class AppAddressBaseVO { @NotNull(message = "手机号不能为空") private String mobile; - @ApiModelProperty(value = "地区编码", required = true) - @NotNull(message = "地区编码不能为空") - private Integer areaCode; + @ApiModelProperty(value = "地区编号", required = true) + @NotNull(message = "地区编号不能为空") + private Long areaId; + + @ApiModelProperty(value = "邮编", required = true) + @NotEmpty(message = "邮编不能为空") + private String postCode; @ApiModelProperty(value = "收件详细地址", required = true) @NotNull(message = "收件详细地址不能为空") private String detailAddress; - @ApiModelProperty(value = "地址类型", required = true) - @NotNull(message = "地址类型不能为空") - @InEnum(AddressTypeEnum.class) - private Integer type; + @ApiModelProperty(value = "是否默认地址", required = true) + @NotNull(message = "是否默认地址不能为空") + private Boolean defaulted; } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java index 546df00c6..467432460 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.member.dal.dataobject.address; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.member.enums.AddressTypeEnum; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; @@ -38,18 +37,22 @@ public class AddressDO extends BaseDO { */ private String mobile; /** - * 地区编码 + * 地区编号 */ - private Integer areaCode; + private Long areaId; + /** + * 邮编 + */ + private String postCode; /** * 收件详细地址 */ private String detailAddress; /** - * 地址类型 + * 是否默认 * - * 枚举 {@link AddressTypeEnum} + * true - 默认收件地址 */ - private Integer type; + private Boolean defaulted; } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java index 40391bfe3..a0bf946fe 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java @@ -69,4 +69,10 @@ public class MemberUserDO extends TenantBaseDO { */ private Date loginDate; + // TODO 芋艿:name 真实名字; + // TODO 芋艿:email 邮箱; + // TODO 芋艿:gender 性别; + // TODO 芋艿:score 积分; + // TODO 芋艿:payPassword 支付密码; + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java index fc02e5879..80f78d41f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java @@ -1,64 +1,22 @@ package cn.iocoder.yudao.module.member.dal.mysql.address; - import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; -import cn.iocoder.yudao.module.member.enums.AddressTypeEnum; import org.apache.ibatis.annotations.Mapper; import java.util.List; -/** - * 用户收件地址 Mapper - * - * @author 芋道源码 - */ @Mapper public interface AddressMapper extends BaseMapperX { - /** - * 获取当前地址 根据id和userId - * @param userId - * @param id - * @return - */ - default AddressDO getAddressByIdAndUserId(Long userId, Long id) { - QueryWrapperX queryWrapperX = new QueryWrapperX<>(); - queryWrapperX.eq("user_id", userId).eq("id", id); - return selectList(queryWrapperX).stream().findFirst().orElse(null); + default AddressDO selectByIdAndUserId(Long id, Long userId) { + return selectOne(AddressDO::getId, id, AddressDO::getUserId, userId); } - /** - * 获取地址列表 - * @param userId - * @param type - * @return - */ - default List selectListByUserIdAndType(Long userId, Integer type) { - QueryWrapperX queryWrapperX = new QueryWrapperX().eq("user_id", userId) - .eqIfPresent("type", type); - return selectList(queryWrapperX); - } - - /** - * 获取默认地址 - * @param userId - * @return - */ - default AddressDO getDefaultUserAddress(Long userId) { - List addressDOList = selectListByUserIdAndType(userId, AddressTypeEnum.DEFAULT.getType()); - return addressDOList.stream().findFirst().orElse(null); - } - - /** - * 获取默认地址 - * @param id - * @param addressTypeEnum - * @return - */ - default int updateTypeById(Long id, AddressTypeEnum addressTypeEnum) { - return updateById(new AddressDO().setId(id).setType(addressTypeEnum.getType())); + default List selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) { + return selectList(new LambdaQueryWrapperX().eq(AddressDO::getUserId, userId) + .eqIfPresent(AddressDO::getDefaulted, defaulted)); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/AddressTypeEnum.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/AddressTypeEnum.java deleted file mode 100644 index 59465e495..000000000 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/AddressTypeEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.member.enums; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * 用户收件地址的类型枚举 - */ -@Getter -@AllArgsConstructor -public enum AddressTypeEnum implements IntArrayValuable { - - DEFAULT(1, "默认收件地址"), - NORMAL(2, "普通收件地址"), // 即非默认收件地址 - - ; - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AddressTypeEnum::getType).toArray(); - - private final Integer type; - private final String desc; - - @Override - public int[] array() { - return ARRAYS; - } -} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/package-info.java deleted file mode 100644 index 9e136937a..000000000 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位 - */ -package cn.iocoder.yudao.module.member.enums; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java index e45b075fe..456a3d8ac 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java @@ -1,10 +1,11 @@ package cn.iocoder.yudao.module.member.service.address; -import java.util.*; -import javax.validation.*; -import cn.iocoder.yudao.module.member.controller.app.address.vo.*; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.validation.Valid; +import java.util.List; /** * 用户收件地址 Service 接口 @@ -55,5 +56,12 @@ public interface AddressService { */ List getAddressList(Long userId); + /** + * 获得用户默认的收件地址 + * + * @param userId 用户编号 + * @return 用户收件地址 + */ AddressDO getDefaultUserAddress(Long userId); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java index a9cd91d59..bbcbbe592 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java @@ -1,23 +1,20 @@ package cn.iocoder.yudao.module.member.service.address; -import cn.iocoder.yudao.module.member.enums.AddressTypeEnum; -import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; +import cn.iocoder.yudao.module.member.convert.address.AddressConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.mysql.address.AddressMapper; import org.springframework.stereotype.Service; - -import javax.annotation.Resource; - import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.util.*; -import cn.iocoder.yudao.module.member.controller.app.address.vo.*; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; - -import cn.iocoder.yudao.module.member.convert.address.AddressConvert; -import cn.iocoder.yudao.module.member.dal.mysql.address.AddressMapper; +import javax.annotation.Resource; +import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ADDRESS_NOT_EXISTS; /** * 用户收件地址 Service 实现类 @@ -35,18 +32,11 @@ public class AddressServiceImpl implements AddressService { @Transactional(rollbackFor = Exception.class) public Long createAddress(Long userId, AppAddressCreateReqVO createReqVO) { // 如果添加的是默认收件地址,则将原默认地址修改为非默认 - if (AddressTypeEnum.DEFAULT.getType().equals(createReqVO.getType())) { - //查询到一个,然后进行 update - List addressDOs = selectListByUserIdAndType(userId, AddressTypeEnum.DEFAULT.getType()); - AddressDO defaultUserAddress = addressMapper.getDefaultUserAddress(userId); - if (!CollectionUtils.isEmpty(addressDOs)) { - addressDOs.forEach(userAddressDO -> addressMapper.updateById(new AddressDO() - .setId(userAddressDO.getId()).setType(AddressTypeEnum.NORMAL.getType()))); - } - Optional.ofNullable(defaultUserAddress) - //更新为非默认 - .ifPresent( u -> addressMapper.updateTypeById(u.getId(), AddressTypeEnum.NORMAL)); + if (Boolean.TRUE.equals(createReqVO.getDefaulted())) { + List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); + addresses.forEach(address -> addressMapper.updateById(new AddressDO().setId(address.getId()).setDefaulted(false))); } + // 插入 AddressDO address = AddressConvert.INSTANCE.convert(createReqVO); address.setUserId(userId); @@ -59,17 +49,15 @@ public class AddressServiceImpl implements AddressService { @Transactional(rollbackFor = Exception.class) public void updateAddress(Long userId, AppAddressUpdateReqVO updateReqVO) { // 校验存在,校验是否能够操作 - check(userId, updateReqVO.getId()); + validAddressExists(userId, updateReqVO.getId()); + // 如果修改的是默认收件地址,则将原默认地址修改为非默认 - if (AddressTypeEnum.DEFAULT.getType().equals(updateReqVO.getType())) { - //获取默认地址 - AddressDO defaultUserAddress = addressMapper.getDefaultUserAddress(userId); - Optional.ofNullable(defaultUserAddress) - //排除当前地址 - .filter(u -> !u.getId().equals(updateReqVO.getId())) - //更新为非默认 - .ifPresent( u -> addressMapper.updateTypeById(u.getId(), AddressTypeEnum.NORMAL)); + if (Boolean.TRUE.equals(updateReqVO.getDefaulted())) { + List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); + addresses.stream().filter(u -> !u.getId().equals(updateReqVO.getId())) // 排除自己 + .forEach(address -> addressMapper.updateById(new AddressDO().setId(address.getId()).setDefaulted(false))); } + // 更新 AddressDO updateObj = AddressConvert.INSTANCE.convert(updateReqVO); addressMapper.updateById(updateObj); @@ -78,56 +66,32 @@ public class AddressServiceImpl implements AddressService { @Override public void deleteAddress(Long userId, Long id) { // 校验存在,校验是否能够操作 - check(userId, id); + validAddressExists(userId, id); // 删除 addressMapper.deleteById(id); } - /** - * 校验用户收件地址是不是属于该用户 - * - * @param userId 用户编号 - * @param userAddressId 用户收件地址 - */ - private void check(Long userId, Long userAddressId) { - AddressDO addressDO = getAddress(userId, userAddressId); - if(null == addressDO){ + private void validAddressExists(Long userId, Long id) { + AddressDO addressDO = getAddress(userId, id); + if (addressDO == null) { throw exception(ADDRESS_NOT_EXISTS); } - if (!addressDO.getUserId().equals(userId)) { - throw exception(ADDRESS_FORBIDDEN); - } } @Override public AddressDO getAddress(Long userId, Long id) { - return addressMapper.getAddressByIdAndUserId(userId, id); + return addressMapper.selectByIdAndUserId(id, userId); } @Override public List getAddressList(Long userId) { - return selectListByUserIdAndType(userId, null); + return addressMapper.selectListByUserIdAndDefaulted(userId, null); } - /** - * 获取默认地址 - * @param userId - * @return - */ @Override public AddressDO getDefaultUserAddress(Long userId) { - return addressMapper.getDefaultUserAddress(userId); + List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); + return CollUtil.getFirst(addresses); } - /** - * 根据类型获取地址列表 - * @param userId - * @param type null则查询全部 - * @return - */ - public List selectListByUserIdAndType(Long userId, Integer type) { - return addressMapper.selectListByUserIdAndType(userId, type); - } - - } diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java index eefa2e13e..6ddf80a0e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java @@ -5,20 +5,18 @@ import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreate import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; import cn.iocoder.yudao.module.member.dal.mysql.address.AddressMapper; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import javax.annotation.Resource; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ADDRESS_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; /** * {@link AddressServiceImpl} 的单元测试类 @@ -40,7 +38,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { AppAddressCreateReqVO reqVO = randomPojo(AppAddressCreateReqVO.class); // 调用 - Long addressId = addressService.createAddress(getLoginUserId(), reqVO); + Long addressId = addressService.createAddress(randomLongId(), reqVO); // 断言 assertNotNull(addressId); // 校验记录的属性是否正确 @@ -59,7 +57,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { }); // 调用 - addressService.updateAddress(getLoginUserId(), reqVO); + addressService.updateAddress(dbAddress.getUserId(), reqVO); // 校验是否更新正确 AddressDO address = addressMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, address); @@ -71,7 +69,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { AppAddressUpdateReqVO reqVO = randomPojo(AppAddressUpdateReqVO.class); // 调用, 并断言异常 - assertServiceException(() -> addressService.updateAddress(getLoginUserId(), reqVO), ADDRESS_NOT_EXISTS); + assertServiceException(() -> addressService.updateAddress(randomLongId(), reqVO), ADDRESS_NOT_EXISTS); } @Test @@ -83,7 +81,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { Long id = dbAddress.getId(); // 调用 - addressService.deleteAddress(getLoginUserId(), id); + addressService.deleteAddress(dbAddress.getUserId(), id); // 校验数据不存在了 assertNull(addressMapper.selectById(id)); } @@ -94,67 +92,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { Long id = randomLongId(); // 调用, 并断言异常 - assertServiceException(() -> addressService.deleteAddress(getLoginUserId(), id), ADDRESS_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void ins() { - // mock 数据 - AddressDO dbAddress = randomPojo(AddressDO.class, o -> { // 等会查询到 - o.setUserId(null); - o.setName(null); - o.setMobile(null); - o.setAreaCode(null); - o.setDetailAddress(null); - o.setType(null); - o.setCreateTime(null); - }); - addressMapper.insert(dbAddress); - // 测试 userId 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setUserId(null))); - // 测试 name 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setName(null))); - // 测试 mobile 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setMobile(null))); - // 测试 areaCode 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setAreaCode(null))); - // 测试 detailAddress 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setDetailAddress(null))); - // 测试 type 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setType(null))); - // 测试 createTime 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setCreateTime(null))); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetAddressList() { - // mock 数据 - AddressDO dbAddress = randomPojo(AddressDO.class, o -> { // 等会查询到 - o.setUserId(null); - o.setName(null); - o.setMobile(null); - o.setAreaCode(null); - o.setDetailAddress(null); - o.setType(null); - o.setCreateTime(null); - }); - addressMapper.insert(dbAddress); - // 测试 userId 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setUserId(null))); - // 测试 name 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setName(null))); - // 测试 mobile 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setMobile(null))); - // 测试 areaCode 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setAreaCode(null))); - // 测试 detailAddress 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setDetailAddress(null))); - // 测试 type 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setType(null))); - // 测试 createTime 不匹配 - addressMapper.insert(cloneIgnoreId(dbAddress, o -> o.setCreateTime(null))); + assertServiceException(() -> addressService.deleteAddress(randomLongId(), id), ADDRESS_NOT_EXISTS); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql index 608a3bddf..b0347b058 100644 --- a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql @@ -35,15 +35,15 @@ CREATE TABLE IF NOT EXISTS "member_address" ( "user_id" bigint(20) NOT NULL, "name" varchar(10) NOT NULL, "mobile" varchar(20) NOT NULL, - "area_code" int(11) NOT NULL, + "area_id" bigint(20) NOT NULL, + "post_code" varchar(16) NOT NULL, "detail_address" varchar(250) NOT NULL, - "type" tinyint(4) NOT NULL, + "defaulted" bit NOT NULL, "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, "creator" varchar(64) DEFAULT '', "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, "deleted" bit NOT NULL DEFAULT FALSE, "updater" varchar(64) DEFAULT '', - "tenant_id" bigint(20) NOT NULL, PRIMARY KEY ("id") - ) COMMENT '用户收件地址'; +) COMMENT '用户收件地址'; diff --git a/yudao-module-pay/yudao-module-pay-api/pom.xml b/yudao-module-pay/yudao-module-pay-api/pom.xml index a7bebc2f1..0903abed5 100644 --- a/yudao-module-pay/yudao-module-pay-api/pom.xml +++ b/yudao-module-pay/yudao-module-pay-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-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java new file mode 100644 index 000000000..204ce7a32 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.pay.api.order; + +import javax.validation.Valid; + +/** + * @author LeeYan9 + * @since 2022-08-26 + */ +public interface PayOrderApi { + + + /** + * 创建支付单 + * + * @param reqDTO 创建请求 + * @return 支付单编号 + */ + Long createPayOrder(@Valid PayOrderDataCreateReqDTO reqDTO); + +} diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderDataCreateReqDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderDataCreateReqDTO.java new file mode 100644 index 000000000..acdfa7a20 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderDataCreateReqDTO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.pay.api.order; + +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * 支付单创建 Request DTO + * @author LeeYan9 + */ +@Data +public class PayOrderDataCreateReqDTO implements Serializable { + + /** + * 应用编号 + */ + @NotNull(message = "应用编号不能为空") + private Long appId; + /** + * 用户 IP + */ + @NotEmpty(message = "用户 IP 不能为空") + private String userIp; + + // ========== 商户相关字段 ========== + + /** + * 商户订单编号 + */ + @NotEmpty(message = "商户订单编号不能为空") + private String merchantOrderId; + /** + * 商品标题 + */ + @NotEmpty(message = "商品标题不能为空") + @Length(max = 32, message = "商品标题不能超过 32") + private String subject; + /** + * 商品描述 + */ + @NotEmpty(message = "商品描述信息不能为空") + @Length(max = 128, message = "商品描述信息长度不能超过128") + private String body; + + // ========== 订单相关字段 ========== + + /** + * 支付金额,单位:分 + */ + @NotNull(message = "支付金额不能为空") + @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零") + private Integer amount; + + /** + * 支付过期时间 + */ + @NotNull(message = "支付过期时间不能为空") + private Date expireTime; + +} \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/PayOrderApiImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/PayOrderApiImpl.java new file mode 100644 index 000000000..ff902be92 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/PayOrderApiImpl.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.pay.api; + +import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; +import cn.iocoder.yudao.module.pay.api.order.PayOrderDataCreateReqDTO; +import org.springframework.stereotype.Service; + +/** + * TODO 注释 + */ +@Service +public class PayOrderApiImpl implements PayOrderApi { + + @Override + public Long createPayOrder(PayOrderDataCreateReqDTO reqDTO) { + return null; + } + +} diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 55c91e2f8..852a9dff0 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -51,6 +51,16 @@ yudao-module-product-biz ${revision} + + cn.iocoder.boot + yudao-module-trade-biz + ${revision} + + + cn.iocoder.boot + yudao-module-coupon-biz + ${revision} + diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index fb31aa345..c26354ead 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -45,7 +45,7 @@ spring: datasource: master: name: ruoyi-vue-pro - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + url: jdbc:mysql://139.9.196.247:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 @@ -56,7 +56,7 @@ spring: # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W slave: # 模拟从库,可根据自己需要修改 name: ruoyi-vue-pro - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + url: jdbc:mysql://139.9.196.247:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 @@ -68,10 +68,10 @@ spring: # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 redis: - host: 127.0.0.1 # 地址 + host: 139.9.196.247 # 地址 port: 6379 # 端口 database: 0 # 数据库索引 -# password: 123456 # 密码,建议生产环境开启 + password: 123456 # 密码,建议生产环境开启 jasypt: encryptor: diff --git a/yudao-ui-admin/.eslintignore b/yudao-ui-admin/.eslintignore index 89be6f659..21cfec76a 100644 --- a/yudao-ui-admin/.eslintignore +++ b/yudao-ui-admin/.eslintignore @@ -7,4 +7,4 @@ public # 忽略当前目录下为js的文件的语法检查 *.js # 忽略当前目录下为vue的文件的语法检查 -*.vue \ No newline at end of file +*.vue diff --git a/yudao-ui-admin/src/api/mall/CouponTemplete/CouponTemplete.js b/yudao-ui-admin/src/api/mall/CouponTemplete/CouponTemplete.js new file mode 100644 index 000000000..639a75a1d --- /dev/null +++ b/yudao-ui-admin/src/api/mall/CouponTemplete/CouponTemplete.js @@ -0,0 +1,54 @@ +import request from '@/utils/request' + +// 创建优惠券模板 +export function create(data) { + return request({ + url: '/coupon/template/create', + method: 'post', + data: data + }) +} + +// 更新优惠券模板 +export function update(data) { + return request({ + url: '/coupon/template/update', + method: 'put', + data: data + }) +} + +// 删除优惠券模板 +export function deleteCouponTemplete (id) { + return request({ + url: '/coupon/template/delete?id=' + id, + method: 'delete' + }) +} + +// 获得优惠券模板 +export function get(id) { + return request({ + url: '/coupon/template/get?id=' + id, + method: 'get' + }) +} + +// 获得优惠券模板分页 +export function getPage(query) { + return request({ + url: '/coupon/template/page', + method: 'get', + params: query + }) +} + +// 导出优惠券模板 Excel +export function exportExcel(query) { + return request({ + url: '/coupon/template/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} diff --git a/yudao-ui-admin/src/api/mall/product/brand.js b/yudao-ui-admin/src/api/mall/product/brand.js index 69cb61c08..2218f42cb 100644 --- a/yudao-ui-admin/src/api/mall/product/brand.js +++ b/yudao-ui-admin/src/api/mall/product/brand.js @@ -34,6 +34,15 @@ export function getBrand(id) { }) } +// 获得品牌list +export function getBrandList() { + return request({ + url: '/product/brand/list', + method: 'get' + }) +} + + // 获得品牌分页 export function getBrandPage(query) { return request({ diff --git a/yudao-ui-admin/src/api/mall/product/category.js b/yudao-ui-admin/src/api/mall/product/category.js index bd825034d..4b8754b5a 100644 --- a/yudao-ui-admin/src/api/mall/product/category.js +++ b/yudao-ui-admin/src/api/mall/product/category.js @@ -1,7 +1,7 @@ import request from '@/utils/request' // 创建商品分类 -export function createCategory(data) { +export function createProductCategory(data) { return request({ url: '/product/category/create', method: 'post', @@ -10,7 +10,7 @@ export function createCategory(data) { } // 更新商品分类 -export function updateCategory(data) { +export function updateProductCategory(data) { return request({ url: '/product/category/update', method: 'put', @@ -19,7 +19,7 @@ export function updateCategory(data) { } // 删除商品分类 -export function deleteCategory(id) { +export function deleteProductCategory(id) { return request({ url: '/product/category/delete?id=' + id, method: 'delete' @@ -27,37 +27,18 @@ export function deleteCategory(id) { } // 获得商品分类 -export function getCategory(id) { +export function getProductCategory(id) { return request({ url: '/product/category/get?id=' + id, method: 'get' }) } -// 获得商品分类 -export function listCategory(query) { +// 获得商品分类列表 +export function getProductCategoryList(query) { return request({ - url: '/product/category/listByQuery', + url: '/product/category/list', method: 'get', params: query }) } - -// 获得商品分类分页 -export function getCategoryPage(query) { - return request({ - url: '/product/category/page', - method: 'get', - params: query - }) -} - -// 导出商品分类 Excel -export function exportCategoryExcel(query) { - return request({ - url: '/product/category/export-excel', - method: 'get', - params: query, - responseType: 'blob' - }) -} diff --git a/yudao-ui-admin/src/api/mall/product/spu.js b/yudao-ui-admin/src/api/mall/product/spu.js index 068e7d838..fc4a545f2 100644 --- a/yudao-ui-admin/src/api/mall/product/spu.js +++ b/yudao-ui-admin/src/api/mall/product/spu.js @@ -42,13 +42,3 @@ export function getSpuPage(query) { params: query }) } - -// 导出商品spu Excel -export function exportSpuExcel(query) { - return request({ - url: '/product/spu/export-excel', - method: 'get', - params: query, - responseType: 'blob' - }) -} diff --git a/yudao-ui-admin/src/components/ImageUpload/index.vue b/yudao-ui-admin/src/components/ImageUpload/index.vue index 3f2bda7cc..08ff0f8fe 100644 --- a/yudao-ui-admin/src/components/ImageUpload/index.vue +++ b/yudao-ui-admin/src/components/ImageUpload/index.vue @@ -85,8 +85,8 @@ export default { value: { handler(val) { if (val) { - // 首先将值转为数组 - const list = Array.isArray(val) ? val : this.value.split(','); + // 首先将值转为数组, 当只穿了一个图片时,会报map方法错误 + const list = Array.isArray(val) ? val : Array.isArray(this.value.split(',')) ? this.value.split(','): Array.of(this.value); // 然后将数组转为对象数组 this.fileList = list.map(item => { if (typeof item === "string") { diff --git a/yudao-ui-admin/src/layout/components/Sidebar/SidebarItem.vue b/yudao-ui-admin/src/layout/components/Sidebar/SidebarItem.vue index c4febee2d..7880cbba6 100644 --- a/yudao-ui-admin/src/layout/components/Sidebar/SidebarItem.vue +++ b/yudao-ui-admin/src/layout/components/Sidebar/SidebarItem.vue @@ -13,8 +13,8 @@ +

+ + + + + + + + + + + + + + + + + + + + + + + 搜索 + 重置 + + + + + + + 新增 + + + 导出 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 请选择字典生成 + + + + + + + + + 请选择字典生成 + + + + + + + + + + + + + + + + + + + + + + + 请选择字典生成 + + + + + + + + + + + + + + 请选择字典生成 + + + + + + + + 请选择字典生成 + + + + + + + + 请选择字典生成 + + + + + + + + + + + + + + 请选择字典生成 + + + + + + + + 请选择字典生成 + + + + + + + + +
+ + + diff --git a/yudao-ui-admin/src/views/mall/product/brand/index.vue b/yudao-ui-admin/src/views/mall/product/brand/index.vue index b0c3c97b8..106080406 100644 --- a/yudao-ui-admin/src/views/mall/product/brand/index.vue +++ b/yudao-ui-admin/src/views/mall/product/brand/index.vue @@ -26,25 +26,18 @@ 新增 - - - - 导出 - + v-hasPermi="['product:brand:create']">新增 - + - + @@ -77,15 +70,11 @@ - - - - - + + @@ -113,20 +102,18 @@ import { createBrand, deleteBrand, - exportBrandExcel, getBrand, getBrandPage, updateBrand } from "@/api/mall/product/brand"; -import {listCategory} from "@/api/mall/product/category"; import ImageUpload from '@/components/ImageUpload'; -import Treeselect from "@riophae/vue-treeselect"; import "@riophae/vue-treeselect/dist/vue-treeselect.css"; +import {CommonStatusEnum} from "@/utils/constants"; export default { - name: "Brand", + name: "ProductBrand", components: { - ImageUpload, Treeselect, + ImageUpload }, data() { return { @@ -153,21 +140,18 @@ export default { status: null, createTime: [] }, - // 商品分类树选项 - categoryOptions: [], // 表单参数 form: {}, // 表单校验 rules: { - categoryId: [{required: true, message: "分类编号不能为空", trigger: "blur"}], name: [{required: true, message: "品牌名称不能为空", trigger: "blur"}], - bannerUrl: [{required: true, message: "品牌图片不能为空", trigger: "blur"}], + picUrl: [{required: true, message: "品牌图片不能为空", trigger: "blur"}], + sort: [{required: true, message: "品牌排序不能为空", trigger: "blur"}], status: [{required: true, message: "状态不能为空", trigger: "change"}], } }; }, created() { - this.getTreeselect(); this.getList(); }, methods: { @@ -181,26 +165,6 @@ export default { this.loading = false; }); }, - /** 转换菜单数据结构 */ - normalizer(node) { - if (node.children && !node.children.length) { - delete node.children; - } - return { - id: node.id, - label: node.name, - children: node.children - }; - }, - /** 查询分类下拉树结构 */ - getTreeselect() { - listCategory().then(response => { - this.categoryOptions = []; - const menu = {id: 0, name: '商品分类', children: []}; - menu.children = this.handleTree(response.data, "id", "pid"); - this.categoryOptions.push(menu); - }); - }, /** 取消按钮 */ cancel() { this.open = false; @@ -210,12 +174,11 @@ export default { reset() { this.form = { id: undefined, - categoryId: undefined, name: undefined, - bannerUrl: undefined, - sort: undefined, + picUrl: undefined, + sort: 0, description: undefined, - status: undefined, + status: CommonStatusEnum.ENABLE, }; this.resetForm("form"); }, @@ -232,14 +195,12 @@ export default { /** 新增按钮操作 */ handleAdd() { this.reset(); - this.getTreeselect(); this.open = true; this.title = "添加品牌"; }, /** 修改按钮操作 */ handleUpdate(row) { this.reset(); - this.getTreeselect(); const id = row.id; getBrand(id).then(response => { this.form = response.data; @@ -280,30 +241,7 @@ export default { this.$modal.msgSuccess("删除成功"); }).catch(() => { }); - }, - /** 导出按钮操作 */ - handleExport() { - // 处理查询参数 - let params = {...this.queryParams}; - params.pageNo = undefined; - params.pageSize = undefined; - // 执行导出 - this.$modal.confirm('是否确认导出所有品牌数据项?').then(() => { - this.exportLoading = true; - return exportBrandExcel(params); - }).then(response => { - this.$download.excel(response, "品牌.xls"); - this.exportLoading = false; - }).catch(() => { - }); } } }; - - diff --git a/yudao-ui-admin/src/views/mall/product/category/index.vue b/yudao-ui-admin/src/views/mall/product/category/index.vue index 41ed4c020..24ae64319 100644 --- a/yudao-ui-admin/src/views/mall/product/category/index.vue +++ b/yudao-ui-admin/src/views/mall/product/category/index.vue @@ -6,12 +6,6 @@ - - - - - 搜索 重置 @@ -28,27 +22,16 @@ 展开/折叠 - - 导出 - - - - + + - - - @@ -78,32 +61,20 @@ - + - - - - - - - - - - - + + +
推荐 200x100 图片分辨率
+
推荐 100x100 图片分辨率
- - - + + +