fix:完善商品管理, 完善 mall.sql, 完善 product 测试相关sql, 完善 ProductSpuServiceImplTest 测试

This commit is contained in:
puhui999 2023-05-23 11:01:40 +08:00
parent 96e2bf020f
commit cac5545762
42 changed files with 1318 additions and 653 deletions

View File

@ -22,23 +22,23 @@ SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
DROP TABLE IF EXISTS `market_activity`;
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
`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 = '促销活动';
-- ----------------------------
@ -52,20 +52,20 @@ COMMIT;
-- ----------------------------
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
`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管理';
-- ----------------------------
@ -79,22 +79,22 @@ COMMIT;
-- ----------------------------
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
`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 = '用户收件地址';
-- ----------------------------
@ -109,19 +109,19 @@ COMMIT;
-- ----------------------------
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
`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 = '商品品牌';
-- ----------------------------
@ -136,20 +136,20 @@ COMMIT;
-- ----------------------------
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
`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 = '商品分类';
-- ----------------------------
@ -164,18 +164,18 @@ COMMIT;
-- ----------------------------
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 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) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`remark` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_name` (`name`(32)) USING BTREE COMMENT '规格名称索引'
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci 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) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`remark` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_name` (`name`(32)) USING BTREE COMMENT '规格名称索引'
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='规格名称';
-- ----------------------------
@ -189,18 +189,18 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `product_property_value`;
CREATE TABLE `product_property_value` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`property_id` bigint DEFAULT NULL COMMENT '规格键id',
`name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '规格值名字',
`status` tinyint DEFAULT NULL COMMENT '状态 1 开启 2 禁用',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`remark` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`property_id` bigint DEFAULT NULL COMMENT '规格键id',
`name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '规格值名字',
`status` tinyint DEFAULT NULL COMMENT '状态 1 开启 2 禁用',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`remark` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='规格值';
-- ----------------------------
@ -214,26 +214,26 @@ COMMIT;
-- ----------------------------
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(512) 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 '成本价单位 ',
`bar_code` varchar(64) DEFAULT NULL COMMENT 'SKU 的条形码',
`pic_url` varchar(256) NOT NULL COMMENT '图片地址',
`stock` int DEFAULT NULL COMMENT '库存',
`weight` double DEFAULT NULL COMMENT '商品重量单位kg 千克',
`volume` double DEFAULT NULL COMMENT '商品体积单位m^3 平米',
`sub_commission_first_price` int DEFAULT NULL COMMENT '一级分销的佣金单位',
`sub_commission_second_price` int DEFAULT NULL COMMENT '二级分销的佣金单位',
`sales_count` int DEFAULT NULL 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` double(64,0) DEFAULT NULL COMMENT '更新人',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`spu_id` bigint NOT NULL COMMENT 'spu编号',
`properties` varchar(512) 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 '成本价单位 ',
`bar_code` varchar(64) DEFAULT NULL COMMENT 'SKU 的条形码',
`pic_url` varchar(256) NOT NULL COMMENT '图片地址',
`stock` int DEFAULT NULL COMMENT '库存',
`weight` double DEFAULT NULL COMMENT '商品重量单位kg 千克',
`volume` double DEFAULT NULL COMMENT '商品体积单位m^3 平米',
`sub_commission_first_price` int DEFAULT NULL COMMENT '一级分销的佣金单位',
`sub_commission_second_price` int DEFAULT NULL COMMENT '二级分销的佣金单位',
`sales_count` int DEFAULT NULL 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` double(64,0) DEFAULT NULL 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='商品sku';
@ -248,45 +248,45 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `product_spu`;
CREATE TABLE `product_spu` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '商品 SPU 编号自增',
`name` varchar(128) NOT NULL COMMENT '商品名称',
`keyword` varchar(256) DEFAULT NULL COMMENT '关键字',
`introduction` varchar(256) COMMENT '商品简介',
`description` text COMMENT '商品详情',
`bar_code` varchar(64) DEFAULT NULL COMMENT '条形码',
`category_id` bigint NOT NULL COMMENT '商品分类编号',
`brand_id` int DEFAULT NULL COMMENT '商品品牌编号',
`pic_url` varchar(256) NOT NULL COMMENT '商品封面图',
`slider_pic_urls` varchar(2000) DEFAULT '' COMMENT '商品轮播图地址\n 数组以逗号分隔\n 最多上传15张',
`video_url` varchar(256) DEFAULT NULL COMMENT '商品视频',
`unit` tinyint NOT NULL COMMENT '单位',
`sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',
`status` tinyint NOT NULL COMMENT '商品状态: 0 上架开启 1 下架禁用-1 回收',
`spec_type` bit(1) DEFAULT NULL COMMENT '规格类型0 单规格 1 多规格',
`price` int NOT NULL DEFAULT '-1' COMMENT '商品价格单位使用',
`market_price` int DEFAULT NULL COMMENT '市场价单位使用',
`cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价单位 ',
`stock` int NOT NULL DEFAULT '0' COMMENT '库存',
`delivery_template_id` bigint NOT NULL COMMENT '物流配置模板编号',
`recommend_hot` bit(1) DEFAULT NULL COMMENT '是否热卖推荐: 0 默认 1 热卖',
`recommend_benefit` bit(1) DEFAULT NULL COMMENT '是否优惠推荐: 0 默认 1 优选',
`recommend_best` bit(1) DEFAULT NULL COMMENT '是否精品推荐: 0 默认 1 精品',
`recommend_new` bit(1) DEFAULT NULL COMMENT '是否新品推荐: 0 默认 1 新品',
`recommend_good` bit(1) DEFAULT NULL COMMENT '是否优品推荐',
`give_integral` int NOT NULL COMMENT '赠送积分',
`give_coupon_template_ids` varchar(512) DEFAULT '' COMMENT '赠送的优惠劵编号的数组',
`sub_commission_type` bit(1) DEFAULT NULL COMMENT '分销类型',
`activity_orders` varchar(16) NOT NULL DEFAULT '' COMMENT '活动显示排序0=默认, 1=秒杀2=砍价3=拼团',
`sales_count` int DEFAULT '0' COMMENT '商品销量',
`virtual_sales_count` int DEFAULT '0' COMMENT '虚拟销量',
`browse_count` int 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 '是否删除',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '商品 SPU 编号自增',
`name` varchar(128) NOT NULL COMMENT '商品名称',
`keyword` varchar(256) DEFAULT NULL COMMENT '关键字',
`introduction` varchar(256) COMMENT '商品简介',
`description` text COMMENT '商品详情',
`bar_code` varchar(64) DEFAULT NULL COMMENT '条形码',
`category_id` bigint NOT NULL COMMENT '商品分类编号',
`brand_id` int DEFAULT NULL COMMENT '商品品牌编号',
`pic_url` varchar(256) NOT NULL COMMENT '商品封面图',
`slider_pic_urls` varchar(2000) DEFAULT '' COMMENT '商品轮播图地址\n 数组以逗号分隔\n 最多上传15张',
`video_url` varchar(256) DEFAULT NULL COMMENT '商品视频',
`unit` tinyint NOT NULL COMMENT '单位',
`sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',
`status` tinyint NOT NULL COMMENT '商品状态: 0 上架开启 1 下架禁用-1 回收',
`spec_type` bit(1) DEFAULT NULL COMMENT '规格类型0 单规格 1 多规格',
`price` int NOT NULL DEFAULT '-1' COMMENT '商品价格单位使用',
`market_price` int DEFAULT NULL COMMENT '市场价单位使用',
`cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价单位 ',
`stock` int NOT NULL DEFAULT '0' COMMENT '库存',
`delivery_template_id` bigint NOT NULL COMMENT '物流配置模板编号',
`recommend_hot` bit(1) DEFAULT NULL COMMENT '是否热卖推荐: 0 默认 1 热卖',
`recommend_benefit` bit(1) DEFAULT NULL COMMENT '是否优惠推荐: 0 默认 1 优选',
`recommend_best` bit(1) DEFAULT NULL COMMENT '是否精品推荐: 0 默认 1 精品',
`recommend_new` bit(1) DEFAULT NULL COMMENT '是否新品推荐: 0 默认 1 新品',
`recommend_good` bit(1) DEFAULT NULL COMMENT '是否优品推荐',
`give_integral` int NOT NULL COMMENT '赠送积分',
`give_coupon_template_ids` varchar(512) DEFAULT '' COMMENT '赠送的优惠劵编号的数组',
`sub_commission_type` bit(1) DEFAULT NULL COMMENT '分销类型',
`activity_orders` varchar(16) NOT NULL DEFAULT '' COMMENT '活动显示排序0=默认, 1=秒杀2=砍价3=拼团',
`sales_count` int DEFAULT '0' COMMENT '商品销量',
`virtual_sales_count` int DEFAULT '0' COMMENT '虚拟销量',
`browse_count` int 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 '是否删除',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB COMMENT='商品spu';
-- ----------------------------
@ -294,17 +294,17 @@ CREATE TABLE `product_spu` (
-- ----------------------------
DROP TABLE IF EXISTS `product_favorite`;
CREATE TABLE `product_favorite` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号自增',
`spu_id` bigint NOT NULL COMMENT '商品 SPU 编号',
`user_id` bigint NOT NULL COMMENT '用户id',
`type` int(10) NOT NULL DEFAULT 1 COMMENT '类型1:收藏 2:点赞',
`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
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号自增',
`spu_id` bigint NOT NULL COMMENT '商品 SPU 编号',
`user_id` bigint NOT NULL COMMENT '用户id',
`type` int(10) NOT NULL DEFAULT 1 COMMENT '类型1:收藏 2:点赞',
`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 COMMENT='喜欢的商品表';
@ -316,6 +316,7 @@ COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
BEGIN;
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');
@ -334,6 +335,7 @@ INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `
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 (2018, '商品导出', 'product:spu:export', 3, 5, 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');
@ -345,37 +347,16 @@ INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `
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');
BEGIN;
INSERT INTO `system_dict_data`(`sort`,`label`,`value`,`dict_type`,`status`,`color_type`,`css_class`,`remark`,`creator`,`create_time`,`updater`,`update_time`,`deleted`) VALUES
(1,'打',2,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'盒',3,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'袋',4,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'箱',5,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'套',6,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'包',7,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'双',8,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'卷',9,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'张',10,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'克',11,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'千克',12,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'毫克',13,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'微克',14,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'吨',15,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'升',16,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1,'毫升',17,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
(1, '平方米', 18, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '平方千米', 19, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '平方英里', 20, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '平方码', 21, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '平方英尺', 22, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '立方米', 23, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '立方厘米', 24, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '立方英寸', 25, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '米', 26, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '千米', 27, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '厘米', 28, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '毫米', 29, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '英寸', 30, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '英尺', 31, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1, '码', 32, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
(1,'个',1,'product_unit',0,'','','',1, NOW(),1, NOW(),0);
BEGIN;
INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '个', 1, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), b'0');
INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '件', 2, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), b'0');
INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '盒', 3, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), b'0');
INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '袋', 4, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), b'0');
INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '箱', 5, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), b'0');
INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '套', 6, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), b'0');
INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '包', 7, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), b'0');
INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '双', 8, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), b'0');
INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '卷', 9, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), b'0');
COMMIT;

View File

@ -0,0 +1,10 @@
package cn.iocoder.yudao.module.product.enums;
/**
* product 字典类型的枚举类
* @author HUIHUI
*/
public interface DictTypeConstants {
String PRODUCT_UNIT = "product_unit"; // 商品单位
String PRODUCT_SPU_STATUS = "product_spu_status"; // 商品 SPU 状态
}

View File

@ -18,7 +18,7 @@ public interface ErrorCodeConstants {
// ========== 商品品牌相关编号 1008002000 ==========
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在");
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌已禁用");
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
// ========== 商品属性项 1008003000 ==========
@ -32,8 +32,9 @@ public interface ErrorCodeConstants {
// ========== 商品 SPU 1008005000 ==========
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类");
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第二级的商品分类及以");
ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");
ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1008005003, "商品 SPU 不处于回收站状态");
// ========== 商品 SKU 1008006000 ==========
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.product.enums;
/**
* Product 常量 TODO 把使用到的常量收拢到一块定义替换魔法值
*
* @author HUIHUI
*/
public interface ProductConstants {
/**
* 父分类编号 - 根分类
*/
Long PARENT_ID_NULL = 0L;
/**
* 限定分类层级
*/
int CATEGORY_LEVEL = 2;
/**
* SPU 分页 tab 个数
*/
int SPU_TAB_COUNTS = 5;
/**
* 警戒库存 TODO 警戒库存暂时为 10后期需要使用常量或者数据库配置替换
*/
int ALERT_STOCK = 10;
/**
* 默认商品销量 TODO 默认商品销量为零
*/
Integer SALES_COUNT = 0;
/**
* 默认善品浏览量 TODO 默认浏览量为零
*/
Integer BROWSE_COUNT = 0;
}

View File

@ -1,24 +1,27 @@
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;
// TODO @puhui999中英文之间要有空格 商品 spu Tab 标签枚举这个类可以改成 ProductSpuPageTabEnum 会更好一点哈分页 Tab 的意思
/**
* 商品spu标签枚举类型
* 商品 spu Tabs 标签枚举类型
*
* @author HUIHUI
*/
@Getter
@AllArgsConstructor
public enum ProductSpuTabTypeEnum {
public enum ProductSpuPageTabEnum implements IntArrayValuable {
FOR_SALE(0,"出售中商品"),
IN_WAREHOUSE(1,"仓库中商品"),
SOLD_OUT(2,"已售空商品"),
ALERT_STOCK(3,"警戒库存"),
RECYCLE_BIN(4,"商品回收站");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuPageTabEnum::getType).toArray();
/**
* 状态
*/
@ -28,4 +31,8 @@ public enum ProductSpuTabTypeEnum {
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.product.controller.admin.brand;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*;
@ -61,7 +62,14 @@ public class ProductBrandController {
ProductBrandDO brand = brandService.getBrand(id);
return success(ProductBrandConvert.INSTANCE.convert(brand));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获取品牌精简信息列表", description = "主要用于前端的下拉选项")
public CommonResult<List<ProductBrandSimpleRespVO>> getSimpleUserList() {
// 获取品牌列表只要开启状态的
List<ProductBrandDO> list = brandService.getBrandListByStatus(CommonStatusEnum.ENABLE.getStatus());
// 排序后返回给前端
return success(ProductBrandConvert.INSTANCE.convertList1(list));
}
@GetMapping("/page")
@Operation(summary = "获得品牌分页")
@PreAuthorize("@ss.hasPermission('product:brand:query')")

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 品牌精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductBrandSimpleRespVO {
@Schema(description = "品牌编号", required = true, example = "1024")
private Long id;
@Schema(description = "品牌名称", required = true, example = "芋道")
private String name;
}

View File

@ -1,7 +1,11 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@ -41,20 +45,51 @@ public class ProductSkuBaseVO {
@Schema(description = "预警预存", example = "1")
private Integer warnStock;
@Schema(description = "商品重量", example = "1") // 单位kg 千克
@Schema(description = "商品重量,单位kg 千克", example = "1")
private Double weight;
@Schema(description = "商品体积", example = "1024") // 单位m^3 平米
@Schema(description = "商品体积,单位m^3 平米", example = "1024")
private Double volume;
// TODO @pitui999注释可以去掉VO 使用 @Schema 作为注释
/**
* 一级分销的佣金单位
*/
@Schema(description = "一级分销的佣金", example = "1024")
@Schema(description = "一级分销的佣金,单位:分", example = "1024")
private Integer subCommissionFirstPrice;
/**
* 二级分销的佣金单位
*/
@Schema(description = "二级分销的佣金", example = "1024")
@Schema(description = "二级分销的佣金,单位:分", example = "1024")
private Integer subCommissionSecondPrice;
/**
* 商品属性
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Property {
/**
* 属性编号
* 关联 {@link ProductPropertyDO#getId()}
*/
private Long propertyId;
/**
* 属性名字
* 冗余 {@link ProductPropertyDO#getName()}
*
* 注意每次属性名字发生变化时需要更新该冗余
*/
private String propertyName;
/**
* 属性值编号
* 关联 {@link ProductPropertyValueDO#getId()}
*/
private Long valueId;
/**
* 属性值名字
* 冗余 {@link ProductPropertyValueDO#getName()}
*
* 注意每次属性值名字发生变化时需要更新该冗余
*/
private String valueName;
}
}

View File

@ -12,22 +12,6 @@ import java.util.List;
@ToString(callSuper = true)
public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
@Schema(description = "商品属性")
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Property {
@Schema(description = "属性编号", required = true, example = "1")
@NotNull(message = "属性编号不能为空")
private Long propertyId;
@Schema(description = "属性值编号", required = true, example = "1024")
@NotNull(message = "属性值编号不能为空")
private Long valueId;
}
/**
* 属性数组
*/

View File

@ -15,27 +15,6 @@ public class ProductSkuRespVO extends ProductSkuBaseVO {
@Schema(description = "主键", required = true, example = "1024")
private Long id;
@Schema(description = "商品属性")
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Property {
@Schema(description = "属性编号", required = true, example = "1")
@NotNull(message = "属性编号不能为空")
private Long propertyId;
// TODO @puhui999:propertyName 是不是也返回下
@Schema(description = "属性值编号", required = true, example = "1024")
@NotNull(message = "属性值编号不能为空")
private Long valueId;
@Schema(description = "属性值", example = "1024")
private String valueName;
}
/**
* 属性数组
*/

View File

@ -2,6 +2,9 @@ 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.common.util.collection.MapUtils;
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.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
@ -16,12 +19,24 @@ 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.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
/**
* 商品 SPU 相关接口
*
* @author HUIHUI
*/
@Tag(name = "管理后台 - 商品 SPU")
@RestController
@RequestMapping("/product/spu")
@ -30,10 +45,6 @@ public class ProductSpuController {
@Resource
private ProductSpuService productSpuService;
@Resource
private ProductSkuService productSkuService;
@Resource
private ProductPropertyValueService productPropertyValueService;
@PostMapping("/create")
@Operation(summary = "创建商品 SPU")
@ -50,7 +61,7 @@ public class ProductSpuController {
return success(true);
}
@PutMapping("/updateStatus")
@PutMapping("/update-status")
@Operation(summary = "更新商品 SPU Status")
@PreAuthorize("@ss.hasPermission('product:spu:update')")
public CommonResult<Boolean> updateStatus(@Valid @RequestBody ProductSpuUpdateStatusReqVO updateReqVO) {
@ -86,16 +97,27 @@ public class ProductSpuController {
@GetMapping("/page")
@Operation(summary = "获得商品 SPU 分页")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<PageResult<ProductSpuPageRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
public CommonResult<PageResult<ProductSpuRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
}
// TODO @tuihui999get-count另外url 使用 - 拆分
@GetMapping("/tabsCount")
@Operation(summary = "获得商品 SPU tabsCount")
// TODO @tuihui999get-count另外url 使用 - 拆分 fix
@GetMapping("/get-count")
@Operation(summary = "获得商品 SPU 分页 tab count")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<Map<Integer, Long>> getTabsCount() {
return success(productSpuService.getTabsCount());
}
@GetMapping("/export")
@Operation(summary = "导出用户")
@PreAuthorize("@ss.hasPermission('product:spu:export')")
@OperateLog(type = EXPORT)
public void exportUserList(@Validated ProductSpuExportReqVO reqVO,
HttpServletResponse response) throws IOException {
List<ProductSpuDO> spuList = productSpuService.getSpuList(reqVO);
// 导出 Excel
List<ProductSpuExcelVO> datas = ProductSpuConvert.INSTANCE.convertList03(spuList);
ExcelUtils.write(response, "商品spu.xls", "数据", ProductSpuExcelVO.class, datas);
}
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -10,7 +11,9 @@ import java.util.List;
/**
* 商品 SPU Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
*
* @author HUIHUI
*/
@Data
public class ProductSpuBaseVO {
@ -30,11 +33,12 @@ public class ProductSpuBaseVO {
@NotEmpty(message = "商品详情不能为空")
private String description;
@Schema(description = "商品分类编号", required = true, example = "芋道")
@NotNull(message = "商品分类编号不能为空")
@Schema(description = "商品分类编号", required = true, example = "1")
@NotNull(message = "商品分类不能为空")
private Long categoryId;
@Schema(description = "商品品牌编号", required = true, example = "芋道")
@Schema(description = "商品品牌编号", required = true, example = "1")
@NotNull(message = "商品品牌不能为空")
private Long brandId;
@Schema(description = "商品封面图", required = true, example = "芋道")
@ -96,16 +100,16 @@ public class ProductSpuBaseVO {
@Schema(description = "赠送的优惠劵编号的数组") // TODO 这块前端还未实现
private List<Long> giveCouponTemplateIds;
@Schema(description = "分销类型")
@Schema(description = "分销类型", example = "true")
@NotNull(message = "商品分销类型不能为空")
private Boolean subCommissionType;
@Schema(description = "活动展示顺序") // TODO 这块前端还未实现
@Schema(description = "活动展示顺序", example = "[1、3、2、4、5]") // TODO 这块前端还未实现
private List<Integer> activityOrders;
// ========== 统计相关字段 =========
@Schema(description = "虚拟销量", required = true, example = "芋道")
@Schema(description = "虚拟销量", example = "芋道")
private Integer virtualSalesCount;
}

View File

@ -9,15 +9,20 @@ import lombok.ToString;
import javax.validation.Valid;
import java.util.List;
/**
* 商品 SPU 创建 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SPU 创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuCreateReqVO extends ProductSpuBaseVO {
/**
* SKU 数组
*/
// ========== SKU 相关字段 =========
@Schema(description = "SKU 数组")
@Valid
private List<ProductSkuCreateOrUpdateReqVO> skus;

View File

@ -6,20 +6,36 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 商品 SPU 详细 Response VO") // 包括关联的 SKU 等信息
/**
* 商品 SPU 详细 Response VO
* 包括关联的 SKU 等信息
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SPU 详细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
@Schema(description = "商品编号", example = "1")
@Schema(description = "spuId")
private Long id;
@Schema(description = "商品销量")
private Integer salesCount;
@Schema(description = "浏览量")
private Integer browseCount;
@Schema(description = "商品状态")
private Integer status;
// ========== SKU 相关字段 =========
@Schema(description = "SKU 数组", example = "1")
@Schema(description = "SKU 数组")
private List<ProductSkuRespVO> skus;
}

View File

@ -0,0 +1,119 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.product.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 商品 Spu Excel 导出 VO TODO 暂定
*
* @author HUIHUI
*/
@Data
public class ProductSpuExcelVO {
@ExcelProperty("商品编号")
private Long id;
@ExcelProperty("商品名称")
private String name;
@ExcelProperty("关键字")
private String keyword;
@ExcelProperty("商品简介")
private String introduction;
@ExcelProperty("商品详情")
private String description;
@ExcelProperty("条形码")
private String barCode;
@ExcelProperty("商品分类编号")
private Long categoryId;
@ExcelProperty("商品品牌编号")
private Long brandId;
@ExcelProperty("商品封面图")
private String picUrl;
@ExcelProperty("商品轮播图地址")
private String sliderPicUrls;
@ExcelProperty("商品视频")
private String videoUrl;
@ExcelProperty(value = "商品单位", converter = DictConvert.class)
@DictFormat(DictTypeConstants.PRODUCT_UNIT)
private Integer unit;
@ExcelProperty("排序字段")
private Integer sort;
@ExcelProperty(value = "商品状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.PRODUCT_SPU_STATUS)
private Integer status;
@ExcelProperty("规格类型")
private Boolean specType;
@ExcelProperty("商品价格")
private Integer price;
@ExcelProperty("市场价")
private Integer marketPrice;
@ExcelProperty("成本价")
private Integer costPrice;
@ExcelProperty("库存")
private Integer stock;
@ExcelProperty("物流配置模板编号")
private Long deliveryTemplateId;
@ExcelProperty("是否热卖推荐")
private Boolean recommendHot;
@ExcelProperty("是否优惠推荐")
private Boolean recommendBenefit;
@ExcelProperty("是否精品推荐")
private Boolean recommendBest;
@ExcelProperty("是否新品推荐")
private Boolean recommendNew;
@ExcelProperty("是否优品推荐")
private Boolean recommendGood;
@ExcelProperty("赠送积分")
private Integer giveIntegral;
@ExcelProperty("赠送的优惠劵编号的数组")
private String giveCouponTemplateIds;
@ExcelProperty("分销类型")
private Boolean subCommissionType;
@ExcelProperty("活动显示排序")
private String activityOrders;
@ExcelProperty("商品销量")
private Integer salesCount;
@ExcelProperty("虚拟销量")
private Integer virtualSalesCount;
@ExcelProperty("商品点击量")
private Integer browseCount;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductSpuExportReqVO {
@Schema(description = "商品名称", example = "yutou")
private String name;
@Schema(description = "前端请求的tab类型", example = "1")
@InEnum(ProductSpuPageTabEnum.class)
private Integer tabType;
@Schema(description = "商品分类编号")
private Long categoryId;
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -1,16 +1,24 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 商品 SPU 分页 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SPU 分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ -20,10 +28,13 @@ public class ProductSpuPageReqVO extends PageParam {
@Schema(description = "商品名称", example = "yutou")
private String name;
// TODO @puhui999加下 @InEnum 校验
@Schema(description = "前端请求的tab类型", example = "1")
@InEnum(ProductSpuPageTabEnum.class)
private Integer tabType;
@Schema(description = "商品分类编号")
private Long categoryId;
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;

View File

@ -1,32 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
// TODO @puhui999可以直接继承 ProductSpuRespVO 一般情况下多返回一些字段问题不大的另外是不是使用 ProductSpuRespVO 替代
@Schema(description = "管理后台 - 商品 SPU 分页 response VO")
@Data
public class ProductSpuPageRespVO {
@Schema(description = "spuId", example = "1")
private Long id;
@Schema(description = "商品封面图", example = "1")
private String picUrl;
@Schema(description = "商品名称", example = "1")
private String name;
@Schema(description = "商品价格", example = "1")
private Integer price;
@Schema(description = "商品销量", example = "1")
private Integer salesCount;
@Schema(description = "商品排序", example = "1")
private Integer stock;
@Schema(description = "商品封面图", example = "1")
private Integer sort;
@Schema(description = "商品创建时间", example = "1")
private LocalDateTime createTime;
@Schema(description = "商品状态", example = "1")
private Integer status;
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -7,16 +8,39 @@ import lombok.ToString;
import java.time.LocalDateTime;
/**
* 商品 SPU Response VO
* TODO 移除ProductSpuPageRespVO相关应用跟换为ProductSpuRespVO已继承ProductSpuBaseVO 补全表格展示所需属性
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SPU Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuRespVO extends ProductSpuBaseVO {
@Schema(description = "主键", required = true, example = "1")
@Schema(description = "spuId")
private Long id;
@Schema(description = "创建时间")
@Schema(description = "商品价格")
private Integer price;
@Schema(description = "商品销量")
private Integer salesCount;
@Schema(description = "市场价,单位使用:分")
private Integer marketPrice;
@Schema(description = "成本价,单位使用:分")
private Integer costPrice;
@Schema(description = "商品库存")
private Integer stock;
@Schema(description = "商品创建时间")
private LocalDateTime createTime;
@Schema(description = "商品状态")
private Integer status;
}

View File

@ -1,26 +1,48 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 商品 SPU 精简 Response VO
* TODO 商品 SPU 精简 VO 暂时没有使用到用到的时候再按需添加\修改属性
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SPU 精简 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuSimpleRespVO extends ProductSpuBaseVO {
public class ProductSpuSimpleRespVO {
@Schema(description = "主键", required = true, example = "1")
@Schema(description = "主键")
private Long id;
@Schema(description = "商品名称", required = true, example = "芋道")
@Schema(description = "商品名称")
private String name;
@Schema(description = " 最小价格,单位使用:分", required = true, example = "1024")
private Integer minPrice;
@Schema(description = "商品价格,单位使用:分")
private Integer price;
@Schema(description = "最大价格,单位使用:分", required = true, example = "1024")
private Integer maxPrice;
@Schema(description = "商品市场价,单位使用:分")
private Integer marketPrice;
@Schema(description = "商品成本价,单位使用:分")
private Integer costPrice;
@Schema(description = "商品库存")
private Integer stock;
// ========== 统计相关字段 =========
@Schema(description = "商品销量")
private Integer salesCount;
@Schema(description = "商品虚拟销量")
private Integer virtualSalesCount;
@Schema(description = "商品浏览量")
private Integer browseCount;
}

View File

@ -1,6 +1,9 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -8,8 +11,14 @@ import lombok.ToString;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
/**
* 商品 SPU 更新 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SPU 更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ -20,9 +29,19 @@ public class ProductSpuUpdateReqVO extends ProductSpuBaseVO {
@NotNull(message = "商品编号不能为空")
private Long id;
/**
* SKU 数组
*/
@Schema(description = "商品销量")
private Integer salesCount;
@Schema(description = "浏览量")
private Integer browseCount;
@Schema(description = "商品状态")
@InEnum(ProductSpuStatusEnum.class)
private Integer status;
// ========== SKU 相关字段 =========
@Schema(description = "SKU 数组")
@Valid
private List<ProductSkuCreateOrUpdateReqVO> skus;

View File

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -10,6 +12,11 @@ import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 商品 SPU Status 更新 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO")
@Data
public class ProductSpuUpdateStatusReqVO{
@ -20,7 +27,7 @@ public class ProductSpuUpdateStatusReqVO{
@Schema(description = "商品状态", required = true, example = "1")
@NotNull(message = "商品状态不能为空")
@InEnum(ProductSpuStatusEnum.class)
private Integer status;
}

View File

@ -3,6 +3,7 @@ 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.ProductBrandSimpleRespVO;
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;
@ -25,7 +26,7 @@ public interface ProductBrandConvert {
ProductBrandDO convert(ProductBrandUpdateReqVO bean);
ProductBrandRespVO convert(ProductBrandDO bean);
List<ProductBrandSimpleRespVO> convertList1(List<ProductBrandDO> list);
List<ProductBrandRespVO> convertList(List<ProductBrandDO> list);
PageResult<ProductBrandRespVO> convertPage(PageResult<ProductBrandDO> page);

View File

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.product.convert.spu;
import java.time.LocalDateTime;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
@ -10,6 +12,7 @@ import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProdu
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
@ -19,6 +22,9 @@ import org.mapstruct.factory.Mappers;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@ -34,46 +40,63 @@ public interface ProductSpuConvert {
ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class);
ProductSpuDO convert(ProductSpuCreateReqVO bean);
// TODO 还是使用convert重命名改动太多
ProductSpuDO convert(ProductSpuUpdateReqVO bean);
List<ProductSpuDO> convertList(List<ProductSpuDO> list);
PageResult<ProductSpuPageRespVO> convertPage(PageResult<ProductSpuDO> page);
PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page);
ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean);
List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list);
List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
// TODO @puhui999是不是可以删除啦
default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List<ProductSkuDO> skus,
List<ProductPropertyValueDetailRespBO> propertyValues) {
ProductSpuDetailRespVO spuVO = convert03(spu);
spuVO.setSkus(convertList04(skus));
// 处理商品属性
Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
for (int i = 0; i < skus.size(); i++) {
List<ProductSkuDO.Property> properties = skus.get(i).getProperties();
if (CollUtil.isEmpty(properties)) {
continue;
}
ProductSkuRespVO sku = spuVO.getSkus().get(i);
sku.setProperties(new ArrayList<>(properties.size()));
// 遍历每个 properties设置到 AppSpuDetailRespVO.Sku
properties.forEach(property -> {
ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
if (propertyValue == null) {
return;
}
//sku.getProperties().add(convert04(propertyValue)); TODO 需要重写
});
}
return spuVO;
default List<ProductSpuExcelVO> convertList03(List<ProductSpuDO> list){
ArrayList<ProductSpuExcelVO> spuExcelVOs = new ArrayList<>();
list.forEach((spu)->{
ProductSpuExcelVO spuExcelVO = new ProductSpuExcelVO();
spuExcelVO.setId(spu.getId());
spuExcelVO.setName(spu.getName());
spuExcelVO.setKeyword(spu.getKeyword());
spuExcelVO.setIntroduction(spu.getIntroduction());
spuExcelVO.setDescription(spu.getDescription());
spuExcelVO.setBarCode(spu.getBarCode());
spuExcelVO.setCategoryId(spu.getCategoryId());
spuExcelVO.setBrandId(spu.getBrandId());
spuExcelVO.setPicUrl(spu.getPicUrl());
spuExcelVO.setSliderPicUrls(StrUtil.toString(spu.getSliderPicUrls()));
spuExcelVO.setVideoUrl(spu.getVideoUrl());
spuExcelVO.setUnit(spu.getUnit());
spuExcelVO.setSort(spu.getSort());
spuExcelVO.setStatus(spu.getStatus());
spuExcelVO.setSpecType(spu.getSpecType());
spuExcelVO.setPrice(spu.getPrice()/100);
spuExcelVO.setMarketPrice(spu.getMarketPrice()/100);
spuExcelVO.setCostPrice(spu.getCostPrice()/100);
spuExcelVO.setStock(spu.getStock());
spuExcelVO.setDeliveryTemplateId(spu.getDeliveryTemplateId());
spuExcelVO.setRecommendHot(spu.getRecommendHot());
spuExcelVO.setRecommendBenefit(spu.getRecommendBenefit());
spuExcelVO.setRecommendBest(spu.getRecommendBest());
spuExcelVO.setRecommendNew(spu.getRecommendNew());
spuExcelVO.setRecommendGood(spu.getRecommendGood());
spuExcelVO.setGiveIntegral(spu.getGiveIntegral());
spuExcelVO.setGiveCouponTemplateIds(StrUtil.toString(spu.getGiveCouponTemplateIds())); // TODO 暂定
spuExcelVO.setSubCommissionType(spu.getSubCommissionType());
spuExcelVO.setActivityOrders(StrUtil.toString(spu.getActivityOrders())); // TODO 暂定
spuExcelVO.setSalesCount(spu.getSalesCount());
spuExcelVO.setVirtualSalesCount(spu.getVirtualSalesCount());
spuExcelVO.setBrowseCount(spu.getBrowseCount());
spuExcelVO.setCreateTime(spu.getCreateTime());
spuExcelVOs.add(spuExcelVO);
});
return spuExcelVOs;
}
ProductSpuDetailRespVO convert03(ProductSpuDO spu);
List<ProductSkuRespVO> convertList04(List<ProductSkuDO> skus);
ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue);
// ========== 用户 App 相关 ==========
@ -84,6 +107,7 @@ public interface ProductSpuConvert {
// 然后进行转换
return convertPageForGetSpuPage0(page);
}
PageResult<AppProductSpuPageItemRespVO> convertPageForGetSpuPage0(PageResult<ProductSpuDO> page);
default AppProductSpuDetailRespVO convertForGetSpuDetail(ProductSpuDO spu, List<ProductSkuDO> skus,
@ -111,8 +135,32 @@ public interface ProductSpuConvert {
}
return spuVO;
}
AppProductSpuDetailRespVO convertForGetSpuDetail(ProductSpuDO spu);
List<AppProductSpuDetailRespVO.Sku> convertListForGetSpuDetail(List<ProductSkuDO> skus);
AppProductPropertyValueDetailRespVO convertForGetSpuDetail(ProductPropertyValueDetailRespBO propertyValue);
default ProductSpuDetailRespVO convertForSpuDetailRespVO(ProductSpuDO spu, List<ProductSkuDO> skus, Function<Set<Long>, List<ProductPropertyValueDetailRespBO>> func) {
ProductSpuDetailRespVO productSpuDetailRespVO = convert03(spu);
if (CollUtil.isNotEmpty(skus)) {
List<ProductSkuRespVO> skuVOs = ProductSkuConvert.INSTANCE.convertList(skus);
// fix:统一模型即使是单规格也查询下如若Properties为空报错则为单属性不做处理
try {
// 获取所有的属性值 id
Set<Long> valueIds = skus.stream().flatMap(p -> p.getProperties().stream())
.map(ProductSkuDO.Property::getValueId)
.collect(Collectors.toSet());
List<ProductPropertyValueDetailRespBO> valueDetailList = func.apply(valueIds);
Map<Long, String> stringMap = valueDetailList.stream().collect(Collectors.toMap(ProductPropertyValueDetailRespBO::getValueId, ProductPropertyValueDetailRespBO::getValueName));
// 设置属性值名称
skuVOs.stream().flatMap(p -> p.getProperties().stream()).forEach(item -> item.setValueName(stringMap.get(item.getValueId())));
} catch (Exception ignored) {
}
productSpuDetailRespVO.setSkus(skuVOs);
}
return productSpuDetailRespVO;
}
}

View File

@ -19,12 +19,6 @@ import lombok.*;
@NoArgsConstructor
@AllArgsConstructor
public class ProductCategoryDO extends BaseDO {
/**
* 父分类编号 - 根分类
*/
public static final Long PARENT_ID_NULL = 0L;
/**
* 分类编号
*/

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.product.dal.dataobject.property;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
@ -19,7 +20,7 @@ import lombok.*;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProductPropertyDO extends TenantBaseDO { // TODO @puhui999这里是不是用 BaseDO 就可以了
public class ProductPropertyDO extends BaseDO {
/**
* 主键

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.product.dal.dataobject.property;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
@ -20,7 +21,7 @@ import lombok.*;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProductPropertyValueDO extends TenantBaseDO { // TODO @puhui999这里是不是用 BaseDO 就可以了
public class ProductPropertyValueDO extends BaseDO {
/**
* 主键

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.product.dal.dataobject.sku;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
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;
@ -27,7 +27,7 @@ import java.util.List;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProductSkuDO extends TenantBaseDO { // TODO @puhui999这里是不是用 BaseDO 就可以了
public class ProductSkuDO extends BaseDO {
/**
* 商品 SKU 编号自增
@ -105,33 +105,29 @@ public class ProductSkuDO extends TenantBaseDO { // TODO @puhui999这里是
/**
* 属性编号
*
* 关联 {@link ProductPropertyDO#getId()}
*/
private Long propertyId;
///**
// * 属性名字
// *
// * 冗余 {@link ProductPropertyDO#getName()}
// *
// * 注意每次属性名字发生变化时需要更新该冗余
// */ TODO @puhui999与已有代码逻辑存在冲突芋艿冲突点是啥呀
//private String propertyName;
/**
* 属性名字
* 冗余 {@link ProductPropertyDO#getName()}
*
* 注意每次属性名字发生变化时需要更新该冗余
*/
private String propertyName;
/**
* 属性值编号
*
* 关联 {@link ProductPropertyValueDO#getId()}
*/
private Long valueId;
///**
// * 属性值名字
// *
// * 冗余 {@link ProductPropertyValueDO#getName()}
// *
// * 注意每次属性值名字发生变化时需要更新该冗余
// */ TODO @puhui999与已有代码逻辑存在冲突芋艿冲突点是啥呀
//private String valueName;
/**
* 属性值名字
* 冗余 {@link ProductPropertyValueDO#getName()}
*
* 注意每次属性值名字发生变化时需要更新该冗余
*/
private String valueName;
}

View File

@ -29,7 +29,7 @@ import java.util.List;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProductSpuDO extends TenantBaseDO {
public class ProductSpuDO extends BaseDO {
/**
* 商品 SPU 编号自增

View File

@ -31,4 +31,7 @@ public interface ProductBrandMapper extends BaseMapperX<ProductBrandDO> {
return selectOne(ProductBrandDO::getName, name);
}
default List<ProductBrandDO> selectListByStatus(Integer status){
return selectList(ProductBrandDO::getStatus,status);
}
}

View File

@ -1,40 +1,56 @@
package cn.iocoder.yudao.module.product.dal.mysql.spu;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
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.spu.vo.ProductSpuExportReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.enums.ProductConstants;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuTabTypeEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import org.apache.ibatis.annotations.Mapper;
import org.apache.poi.ss.formula.functions.T;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@Mapper
public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
/**
* 获取 商品 SPU 分页列表数据
*
* @param reqVO 分页请求参数
* @return 商品 SPU 分页列表数据
*/
default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO) {
// TODO @puhui999多个 tab if else 去补条件可阅读性会好点哈
return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>()
// 商品名称
Integer tabType = reqVO.getTabType();
LambdaQueryWrapperX<ProductSpuDO> queryWrapper = new LambdaQueryWrapperX<ProductSpuDO>()
.likeIfPresent(ProductSpuDO::getName, reqVO.getName())
.eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId())
.betweenIfPresent(ProductSpuDO::getCreateTime, reqVO.getCreateTime())
// 出售中商品
.eq(ProductSpuTabTypeEnum.FOR_SALE.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.ENABLE.getStatus())
// 仓储中商品
.eq(ProductSpuTabTypeEnum.IN_WAREHOUSE.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.DISABLE.getStatus())
// 已售空商品
.eq(ProductSpuTabTypeEnum.SOLD_OUT.getType().equals(reqVO.getTabType()),ProductSpuDO::getStock,0)
// TODO @phuui999警戒库存暂时为 10后期需要使用常量或者数据库配置替换
.le(ProductSpuTabTypeEnum.ALERT_STOCK.getType().equals(reqVO.getTabType()),ProductSpuDO::getStock,10)
// 回收站
.eq(ProductSpuTabTypeEnum.RECYCLE_BIN.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.RECYCLE.getStatus())
.orderByDesc(ProductSpuDO::getSort));
.orderByDesc(ProductSpuDO::getSort);
validateTabType(tabType, queryWrapper);
return selectPage(reqVO, queryWrapper);
}
/**
* 获取库存小于value且状态不等于status的的个数
*/
default Long selectCountByStockAndStatus() {
LambdaQueryWrapperX<ProductSpuDO> queryWrapper = new LambdaQueryWrapperX<>();
queryWrapper.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK)
// 如果库存触发警戒库存且状态为回收站的话则不计入触发警戒库存的个数
.and(q -> q.ne(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
return selectCount(queryWrapper);
}
/**
@ -42,10 +58,12 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
*/
default PageResult<ProductSpuDO> selectPage(AppProductSpuPageReqVO pageReqVO, Set<Long> categoryIds) {
LambdaQueryWrapperX<ProductSpuDO> query = new LambdaQueryWrapperX<ProductSpuDO>()
.likeIfPresent(ProductSpuDO::getName, pageReqVO.getKeyword()) // 关键字匹配目前只匹配商品名
.inIfPresent(ProductSpuDO::getCategoryId, categoryIds); // 分类
query.eq(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()) // 上架状态
.gt(ProductSpuDO::getStock, 0); // 有库存
// 关键字匹配目前只匹配商品名
.likeIfPresent(ProductSpuDO::getName, pageReqVO.getKeyword())
// 分类
.inIfPresent(ProductSpuDO::getCategoryId, categoryIds);
// 上架状态 且有库存
query.eq(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()).gt(ProductSpuDO::getStock, 0);
// 推荐类型的过滤条件
if (ObjUtil.equal(pageReqVO.getRecommendType(), AppProductSpuPageReqVO.RECOMMEND_TYPE_HOT)) {
query.eq(ProductSpuDO::getRecommendHot, true);
@ -66,14 +84,60 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
/**
* 更新商品 SPU 库存
*
* @param id 商品 SPU 编号
* @param id 商品 SPU 编号
* @param incrCount 增加的库存数量
*/
default void updateStock(Long id, Integer incrCount) {
LambdaUpdateWrapper<ProductSpuDO> updateWrapper = new LambdaUpdateWrapper<ProductSpuDO>()
.setSql(" total_stock = total_stock +" + incrCount) // 负数所以使用 +
// 负数所以使用 +
.setSql(" stock = stock +" + incrCount)
.eq(ProductSpuDO::getId, id);
update(null, updateWrapper);
}
/**
* 获得 Spu 列表
*
* @param reqVO 查询条件
* @return Spu 列表
*/
default List<ProductSpuDO> selectList(ProductSpuExportReqVO reqVO){
Integer tabType = reqVO.getTabType();
LambdaQueryWrapperX<ProductSpuDO> queryWrapper = new LambdaQueryWrapperX<>();
queryWrapper.eqIfPresent(ProductSpuDO::getName,reqVO.getName());
queryWrapper.eqIfPresent(ProductSpuDO::getCategoryId,reqVO.getCategoryId());
queryWrapper.betweenIfPresent(ProductSpuDO::getCreateTime,reqVO.getCreateTime());
validateTabType(tabType, queryWrapper);
return selectList(queryWrapper);
}
/**
* 验证选项卡类型构建条件
*
* @param tabType 标签类型
* @param queryWrapper 查询条件
*/
static void validateTabType(Integer tabType, LambdaQueryWrapperX<ProductSpuDO> queryWrapper) {
if (ObjectUtil.equals(ProductSpuPageTabEnum.FOR_SALE.getType(), tabType)) {
// 出售中商品
queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus());
}
if (ObjectUtil.equals(ProductSpuPageTabEnum.IN_WAREHOUSE.getType(), tabType)) {
// 仓储中商品
queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus());
}
if (ObjectUtil.equals(ProductSpuPageTabEnum.SOLD_OUT.getType(), tabType)) {
// 已售空商品
queryWrapper.eqIfPresent(ProductSpuDO::getStock, 0);
}
if (ObjectUtil.equals(ProductSpuPageTabEnum.ALERT_STOCK.getType(), tabType)) {
queryWrapper.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK)
// 如果库存触发警戒库存且状态为回收站的话则不在警戒库存列表展示
.and(q -> q.ne(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
}
if (ObjectUtil.equals(ProductSpuPageTabEnum.RECYCLE_BIN.getType(), tabType)) {
// 回收站
queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus());
}
}
}

View File

@ -76,4 +76,11 @@ public interface ProductBrandService {
*/
PageResult<ProductBrandDO> getBrandPage(ProductBrandPageReqVO pageReqVO);
/**
* 获取指定状态的品牌列表
*
* @param status 状态
* @return 返回品牌列表
*/
List<ProductBrandDO> getBrandListByStatus(Integer status);
}

View File

@ -114,4 +114,9 @@ public class ProductBrandServiceImpl implements ProductBrandService {
return brandMapper.selectPage(pageReqVO);
}
@Override
public List<ProductBrandDO> getBrandListByStatus(Integer status) {
return brandMapper.selectListByStatus(status);
}
}

View File

@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg
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 cn.iocoder.yudao.module.product.enums.ProductConstants;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -68,7 +69,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
private void validateParentProductCategory(Long id) {
// 如果是根分类无需验证
if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) {
if (Objects.equals(id, ProductConstants.PARENT_ID_NULL)) {
return;
}
// 父分类不存在
@ -77,7 +78,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
throw exception(CATEGORY_PARENT_NOT_EXISTS);
}
// 父分类不能是二级分类
if (!Objects.equals(category.getParentId(), ProductCategoryDO.PARENT_ID_NULL)) {
if (!Objects.equals(category.getParentId(), ProductConstants.PARENT_ID_NULL)) {
throw exception(CATEGORY_PARENT_NOT_FIRST_LEVEL);
}
}
@ -107,15 +108,16 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
@Override
public Integer getCategoryLevel(Long id) {
if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) {
if (Objects.equals(id, ProductConstants.PARENT_ID_NULL)) {
return 0;
}
int level = 1;
for (int i = 0; i < 100; i++) {
// fix: 循环次数不确定改为while循环
while (true){
ProductCategoryDO category = productCategoryMapper.selectById(id);
// 如果没有父节点break 结束
if (category == null
|| Objects.equals(category.getParentId(), ProductCategoryDO.PARENT_ID_NULL)) {
|| Objects.equals(category.getParentId(), ProductConstants.PARENT_ID_NULL)) {
break;
}
// 继续递归父节点

View File

@ -176,7 +176,6 @@ public class ProductSkuServiceImpl implements ProductSkuService {
Long existsSkuId = existsSkuMap.remove(propertiesKey);
if (existsSkuId != null) {
sku.setId(existsSkuId);
// TODO 那spuId岂不是为null了
updateSkus.add(sku);
return;
}

View File

@ -74,6 +74,14 @@ public interface ProductSpuService {
*/
List<ProductSpuDO> getSpuList();
/**
* 获得所有商品 SPU 列表
*
* @param reqVO 导出条件
* @return 商品 SPU 列表
*/
List<ProductSpuDO> getSpuList(ProductSpuExportReqVO reqVO);
/**
* 获得商品 SPU 分页提供给挂你兰后台使用
*

View File

@ -10,11 +10,13 @@ import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
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.ProductCategoryDO;
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.enums.ProductConstants;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuTabTypeEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
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.ProductPropertyValueService;
@ -31,8 +33,7 @@ import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
/**
* 商品 SPU Service 实现类
@ -59,11 +60,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Override
@Transactional(rollbackFor = Exception.class)
public Long createSpu(ProductSpuCreateReqVO createReqVO) {
// 校验分类 TODO puhui999暂不清楚为什么只能选择第三层的结点芋艿改成二级分类因为商品只能放在叶子节点级别
//validateCategory(createReqVO.getCategoryId());
// 校验品牌 TODO puhui999暂不校验前端没有做品牌选择芋艿可以加下哈
//brandService.validateProductBrand(createReqVO.getBrandId());
// 校验分类 TODO puhui999暂不清楚为什么只能选择第三层的结点芋艿改成二级分类因为商品只能放在叶子节点级别fix
validateCategory(createReqVO.getCategoryId());
brandService.validateProductBrand(createReqVO.getBrandId());
List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus();
// 校验 SKU
productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType());
@ -84,10 +83,10 @@ public class ProductSpuServiceImpl implements ProductSpuService {
public void updateSpu(ProductSpuUpdateReqVO updateReqVO) {
// 校验 SPU 是否存在
validateSpuExists(updateReqVO.getId());
// 校验分类 TODO 暂不清楚为什么只能选择第三层的结点
//validateCategory(updateReqVO.getCategoryId());
// 校验品牌 TODO 暂不校验前端没有做品牌选择
//brandService.validateProductBrand(updateReqVO.getBrandId());
// 校验分类
validateCategory(updateReqVO.getCategoryId());
// 校验品牌
brandService.validateProductBrand(updateReqVO.getBrandId());
// 校验SKU
List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = updateReqVO.getSkus();
productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType());
@ -103,7 +102,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
* 基于 SKU 的信息初始化 SPU 的信息
* 主要是计数相关的字段例如说市场价最大最小价库存等等
*
* @param spu 商品 SPU
* @param spu 商品 SPU
* @param skus 商品 SKU 数组
*/
private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuCreateOrUpdateReqVO> skus) {
@ -119,13 +118,17 @@ public class ProductSpuServiceImpl implements ProductSpuService {
spu.setCostPrice(vo.getCostPrice());
// sku单价最低的商品的条形码
spu.setBarCode(vo.getBarCode());
// 默认状态为上架
spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
// TODO 默认商品销量和浏览量为零
spu.setSalesCount(0);
spu.setBrowseCount(0);
// skus库存总数
spu.setStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
// 若是 spu 已有状态则不处理
if (spu.getStatus() == null) {
// 默认状态为上架
spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
// 默认商品销量
spu.setSalesCount(ProductConstants.SALES_COUNT);
// 默认商品浏览量
spu.setBrowseCount(ProductConstants.BROWSE_COUNT);
}
}
/**
@ -136,7 +139,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
private void validateCategory(Long id) {
categoryService.validateCategory(id);
// 校验层级
if (categoryService.getCategoryLevel(id) != 3) {
if (categoryService.getCategoryLevel(id) != ProductConstants.CATEGORY_LEVEL) {
throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR);
}
}
@ -146,6 +149,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
public void deleteSpu(Long id) {
// 校验存在
validateSpuExists(id);
// 校验商品状态不是回收站不能删除
validateSpuStatus(id);
// 删除 SPU
productSpuMapper.deleteById(id);
// 删除关联的 SKU
@ -158,6 +163,19 @@ public class ProductSpuServiceImpl implements ProductSpuService {
}
}
/**
* 验证 SPU 状态是否为回收站
*
* @param id id
*/
private void validateSpuStatus(Long id) {
ProductSpuDO spuDO = productSpuMapper.selectById(id);
// 判断 SPU 状态是否为回收站
if (ObjectUtil.notEqual(spuDO.getStatus(), ProductSpuStatusEnum.RECYCLE.getStatus())) {
throw exception(SPU_NOT_RECYCLE);
}
}
@Override
public ProductSpuDO getSpu(Long id) {
return productSpuMapper.selectById(id);
@ -173,6 +191,11 @@ public class ProductSpuServiceImpl implements ProductSpuService {
return productSpuMapper.selectList();
}
@Override
public List<ProductSpuDO> getSpuList(ProductSpuExportReqVO reqVO) {
return productSpuMapper.selectList(reqVO);
}
@Override
public PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO) {
return productSpuMapper.selectPage(pageReqVO);
@ -190,7 +213,6 @@ public class ProductSpuServiceImpl implements ProductSpuService {
stockIncrCounts.forEach((id, incCount) -> productSpuMapper.updateStock(id, incCount));
}
// TODO @puhui999Service 尽量不做一些跟 VO 相关的拼接逻辑目的是让 Service 更加简洁一点哈
@Override
public ProductSpuDetailRespVO getSpuDetail(Long id) {
// 获得商品 SPU
@ -198,28 +220,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
if (spu == null) {
throw exception(SPU_NOT_EXISTS);
}
ProductSpuDetailRespVO productSpuDetailRespVO = ProductSpuConvert.INSTANCE.convert03(spu);
// 查询商品 SKU
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
if (CollUtil.isNotEmpty(skus)){
// TODO @puhui999skuVOs 更简洁一点然后大小写要注释哈RespVOs因为 VO 是缩写s 是复数
List<ProductSkuRespVO> skuRespVoS = ProductSkuConvert.INSTANCE.convertList(skus);
// 非多规格不需要处理
// TODO @puhui999统一模型即使是单规格也查询下问题不大的
if (ObjectUtil.equal(productSpuDetailRespVO.getSpecType(), true)) {
// 获取所有的属性值 id
Set<Long> valueIds = skus.stream().flatMap(p -> p.getProperties().stream())
.map(ProductSkuDO.Property::getValueId)
.collect(Collectors.toSet());
List<ProductPropertyValueDetailRespBO> valueDetailList = productPropertyValueService.getPropertyValueDetailList(valueIds);
// TODO @puhui999拼接的逻辑最好查询好后丢到 convert 里面统一处理这样 Service or Controller 也可以更简洁原则上Controller 去组合Service 写逻辑Convert 转换
Map<Long, String> stringMap = valueDetailList.stream().collect(Collectors.toMap(ProductPropertyValueDetailRespBO::getValueId, ProductPropertyValueDetailRespBO::getValueName));
// 设置属性值名称
skuRespVoS.stream().flatMap(p -> p.getProperties().stream()).forEach(item ->item.setValueName(stringMap.get(item.getValueId())));
}
productSpuDetailRespVO.setSkus(skuRespVoS);
}
return productSpuDetailRespVO;
return ProductSpuConvert.INSTANCE.convertForSpuDetailRespVO(spu, skus, productPropertyValueService::getPropertyValueDetailList);
}
@Override
@ -235,21 +238,21 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Override
public Map<Integer, Long> getTabsCount() {
// TODO @puhui999map =counts尽量避免出现 map 这种命名无命名含义哈
Map<Integer, Long> map = new HashMap<>();
// TODO @puhui999map =尽量避免出现 map 这种命名无命名含义哈 fix
Map<Integer, Long> counts = new HashMap<>(ProductConstants.SPU_TAB_COUNTS);
// 查询销售中的商品数量
map.put(ProductSpuTabTypeEnum.FOR_SALE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
counts.put(ProductSpuPageTabEnum.FOR_SALE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
// 查询仓库中的商品数量
map.put(ProductSpuTabTypeEnum.IN_WAREHOUSE.getType(),productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus()));
counts.put(ProductSpuPageTabEnum.IN_WAREHOUSE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus()));
// 查询售空的商品数量
map.put(ProductSpuTabTypeEnum.SOLD_OUT.getType(),productSpuMapper.selectCount(ProductSpuDO::getStock, 0));
// 查询触发警戒库存的商品数量 TODO 警戒库存暂时为 10后期需要使用常量或者数据库配置替换
// TODO @puhui999要有空格, productSpuMapper
// TODO @puhui999Service 不要有 Mapper 的逻辑想想咋抽象一下哈
map.put(ProductSpuTabTypeEnum.ALERT_STOCK.getType(),productSpuMapper.selectCount(new LambdaQueryWrapperX<ProductSpuDO>().le(ProductSpuDO::getStock, 10)));
counts.put(ProductSpuPageTabEnum.SOLD_OUT.getType(), productSpuMapper.selectCount(ProductSpuDO::getStock, 0));
// 查询触发警戒库存的商品数量
// TODO @puhui999要有空格, productSpuMapper fix
// TODO @puhui999Service 不要有 Mapper 的逻辑想想咋抽象一下哈 fix调整为在 productSpuMapper 中书写逻辑
counts.put(ProductSpuPageTabEnum.ALERT_STOCK.getType(), productSpuMapper.selectCountByStockAndStatus());
// 查询回收站中的商品数量
map.put(ProductSpuTabTypeEnum.RECYCLE_BIN.getType(),productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
return map;
counts.put(ProductSpuPageTabEnum.RECYCLE_BIN.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
return counts;
}
}

View File

@ -18,8 +18,9 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
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.dal.dataobject.category.ProductCategoryDO.PARENT_ID_NULL;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS;
import static cn.iocoder.yudao.module.product.enums.ProductConstants.PARENT_ID_NULL;
import static org.junit.jupiter.api.Assertions.*;
/**

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.product.service.sku;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
@ -49,23 +50,26 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
@MockBean
private ProductPropertyValueService productPropertyValueService;
public Long generateId() {
return RandomUtil.randomLong(100000, 999999);
}
public int generaInt(){return RandomUtil.randomInt(1,9999999);}
@Test
public void testUpdateSkuList() {
// mock 数据
ProductSkuDO sku01 = randomPojo(ProductSkuDO.class, o -> { // 测试更新
o.setSpuId(1L);
//o.setProperties(singletonList(new ProductSkuDO.Property(
// 10L, "颜色", 20L, "红色"))); TODO 新增字段已注释
o.setProperties(singletonList(new ProductSkuDO.Property(
10L, 20L)));
10L, "颜色", 20L, "红色")));
});
productSkuMapper.insert(sku01);
ProductSkuDO sku02 = randomPojo(ProductSkuDO.class, o -> { // 测试删除
o.setSpuId(1L);
//o.setProperties(singletonList(new ProductSkuDO.Property(
// 10L, "颜色", 30L, "蓝色"))); TODO 新增字段已注释
o.setProperties(singletonList(new ProductSkuDO.Property(
10L, 30L)));
10L, "颜色", 30L, "蓝色")));
});
productSkuMapper.insert(sku02);
// 准备参数
@ -73,10 +77,12 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
String spuName = "测试商品";
List<ProductSkuCreateOrUpdateReqVO> skus = Arrays.asList(
randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试更新
o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(10L, 20L)));
o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(
10L, "颜色", 20L, "红色")));
}),
randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试新增
o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(10L, 40L)));
o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(
10L, "颜色", 20L, "红色")));
})
);

View File

@ -6,15 +6,16 @@ import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
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.ProductSpuCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
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.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import cn.iocoder.yudao.module.product.service.brand.ProductBrandServiceImpl;
import cn.iocoder.yudao.module.product.service.category.ProductCategoryServiceImpl;
@ -22,6 +23,7 @@ import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl;
import com.google.common.collect.Lists;
import org.apache.poi.ss.formula.functions.T;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -30,14 +32,19 @@ import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
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.RandomUtils.randomPojo;
import static org.assertj.core.util.Lists.newArrayList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
// TODO @芋艿review 下单元测试
@ -47,7 +54,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
* @author 芋道源码
*/
@Import(ProductSpuServiceImpl.class)
@Disabled // TODO 芋艿临时去掉
public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Resource
@ -75,10 +81,35 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
return RandomUtil.randomLong(100000, 999999);
}
public int generaInt(){return RandomUtil.randomInt(1,9999999);}
@Test
public void testCreateSpu_success() {
// 准备参数
ProductSpuCreateReqVO createReqVO = randomPojo(ProductSpuCreateReqVO.class);
ProductSkuCreateOrUpdateReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuCreateOrUpdateReqVO.class,o->{
// 限制范围为正整数
o.setCostPrice(generaInt());
o.setPrice(generaInt());
o.setMarketPrice(generaInt());
o.setStock(generaInt());
o.setWarnStock(10);
o.setSubCommissionFirstPrice(generaInt());
o.setSubCommissionSecondPrice(generaInt());
// 限制分数为两位数
o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
});
ProductSpuCreateReqVO createReqVO = randomPojo(ProductSpuCreateReqVO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setSkus(newArrayList(skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO));
});
when(categoryService.getCategoryLevel(eq(createReqVO.getCategoryId()))).thenReturn(2);
Long spu = productSpuService.createSpu(createReqVO);
ProductSpuDO productSpuDO = productSpuMapper.selectById(spu);
assertPojoEquals(createReqVO, productSpuDO);
@ -87,12 +118,55 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test
public void testUpdateSpu_success() {
// 准备参数
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(generaInt()); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
});
productSpuMapper.insert(createReqVO);
// 准备参数
ProductSkuCreateOrUpdateReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuCreateOrUpdateReqVO.class,o->{
// 限制范围为正整数
o.setCostPrice(generaInt());
o.setPrice(generaInt());
o.setMarketPrice(generaInt());
o.setStock(generaInt());
o.setWarnStock(10);
o.setSubCommissionFirstPrice(generaInt());
o.setSubCommissionSecondPrice(generaInt());
// 限制分数为两位数
o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
});
// 准备参数
ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> {
o.setId(createReqVO.getId()); // 设置更新的 ID
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
o.setStatus(0);
o.setSkus(newArrayList(skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO));
});
when(categoryService.getCategoryLevel(eq(reqVO.getCategoryId()))).thenReturn(2);
// 调用
productSpuService.updateSpu(reqVO);
// 校验是否更新正确
@ -110,7 +184,24 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test
void deleteSpu() {
// 准备参数
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(generaInt()); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
o.setStatus(-1); // 加入回收站才可删除
});
productSpuMapper.insert(createReqVO);
// 调用
@ -122,7 +213,23 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test
void getSpu() {
// 准备参数
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(generaInt()); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
});
productSpuMapper.insert(createReqVO);
ProductSpuDO spu = productSpuService.getSpu(createReqVO.getId());
@ -132,19 +239,86 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test
void getSpuList() {
// 准备参数
ArrayList<ProductSpuDO> createReqVO = Lists.newArrayList(randomPojo(ProductSpuDO.class), randomPojo(ProductSpuDO.class));
productSpuMapper.insertBatch(createReqVO);
ArrayList<ProductSpuDO> createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(generaInt()); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
}), randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(generaInt()); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
}));
productSpuMapper.insertBatch(createReqVOs);
// 调用
List<ProductSpuDO> spuList = productSpuService.getSpuList(createReqVO.stream().map(ProductSpuDO::getId).collect(Collectors.toList()));
Assertions.assertIterableEquals(createReqVO, spuList);
List<ProductSpuDO> spuList = productSpuService.getSpuList(createReqVOs.stream().map(ProductSpuDO::getId).collect(Collectors.toList()));
Assertions.assertIterableEquals(createReqVOs, spuList);
}
@Test
void getSpuPage_alarmStock_empty() {
// 准备参数
ArrayList<ProductSpuDO> createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(11); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
}), randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(11); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
}));
productSpuMapper.insertBatch(createReqVOs);
// 调用
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
//productSpuPageReqVO.setAlarmStock(true);
productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.ALERT_STOCK.getType());
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
@ -155,76 +329,67 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test
void getSpuPage_alarmStock() {
// mock 数据
Long brandId = generateId();
Long categoryId = generateId();
String code = generateNo();
// 准备参数
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class, o->{
o.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
//o.setTotalStock(500);
//o.setMinPrice(1); // TODO ProductSpuDO中已没有相关属性
//o.setMaxPrice(50);
o.setMarketPrice(25);
o.setBrandId(brandId);
o.setCategoryId(categoryId);
//o.setClickCount(100);
//o.setCode(code); // TODO ProductSpuDO中已没有相关属性
o.setDescription("测试商品");
o.setSliderPicUrls(new ArrayList<>());
o.setName("测试");
o.setSalesCount(100);
//o.setSellPoint("超级加倍");
//o.setShowStock(true); // TODO ProductSpuDO中已没有相关属性
o.setVideoUrl("");
});
productSpuMapper.insert(createReqVO);
//Set<Long> alarmStockSpuIds = SetUtils.asSet(createReqVO.getId()); TODO 查询接口已改变没有使用到这个变量
List<ProductSkuDO> productSpuDOS = Arrays.asList(randomPojo(ProductSkuDO.class, o -> {
o.setSpuId(createReqVO.getId());
}), randomPojo(ProductSkuDO.class, o -> {
o.setSpuId(createReqVO.getId());
ArrayList<ProductSpuDO> createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(5); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
}), randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(9); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
}));
Mockito.when(productSkuService.getSkuListByAlarmStock()).thenReturn(productSpuDOS);
productSpuMapper.insertBatch(createReqVOs);
// 调用
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
//productSpuPageReqVO.setAlarmStock(true);
productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.ALERT_STOCK.getType());
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
PageResult<ProductSpuPageRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO));
Assertions.assertIterableEquals(result.getList(), spuPage.getList());
assertEquals(spuPage.getTotal(), result.getTotal());
assertEquals(createReqVOs.size(), spuPage.getTotal());
}
@Test
void getSpuPage() {
// mock 数据
Long brandId = generateId();
Long categoryId = generateId();
void testGetSpuPage() {
// 准备参数
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class, o->{
o.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
//o.setTotalStock(1);
//o.setMinPrice(1); // TODO ProductSpuDO中已没有相关属性
//o.setMaxPrice(1);
o.setMarketPrice(1);
o.setBrandId(brandId);
o.setSpecType(false);
o.setCategoryId(categoryId);
//o.setClickCount(1); // TODO ProductSpuDO中已没有相关属性
//o.setCode(generateNo());
o.setDescription("测试商品");
o.setSliderPicUrls(new ArrayList<>());
o.setName("测试");
o.setSalesCount(1);
//o.setSellPoint("卖点");
//o.setShowStock(true); // TODO ProductSpuDO中已没有相关属性
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(generaInt()); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
});
// 准备参数
@ -241,45 +406,21 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
// 调用
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
// TODO 已暂时没有相关属性等用到时再添加
//productSpuPageReqVO.setAlarmStock(false);
//productSpuPageReqVO.setBrandId(brandId);
//productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
//productSpuPageReqVO.setCategoryId(categoryId);
// 查询条件 按需打开
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.ALERT_STOCK.getType());
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.RECYCLE_BIN.getType());
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.FOR_SALE.getType());
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.IN_WAREHOUSE.getType());
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.SOLD_OUT.getType());
//productSpuPageReqVO.setName(createReqVO.getName());
//productSpuPageReqVO.setCategoryId(createReqVO.getCategoryId());
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
PageResult<ProductSpuPageRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO));
assertEquals(result, spuPage);
PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO));
assertEquals(result.getTotal(), spuPage.getTotal());
}
@Test
void testGetSpuPage() {
// 准备参数
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class, o -> {
o.setCategoryId(2L);
});
productSpuMapper.insert(createReqVO);
// 调用
AppProductSpuPageReqVO appSpuPageReqVO = new AppProductSpuPageReqVO();
appSpuPageReqVO.setCategoryId(2L);
// PageResult<AppSpuPageItemRespVO> spuPage = productSpuService.getSpuPage(appSpuPageReqVO);
//
// PageResult<ProductSpuDO> result = productSpuMapper.selectPage(
// ProductSpuConvert.INSTANCE.convert(appSpuPageReqVO));
//
// List<AppSpuPageItemRespVO> collect = result.getList()
// .stream()
// .map(ProductSpuConvert.INSTANCE::convertAppResp)
// .collect(Collectors.toList());
//
// Assertions.assertIterableEquals(collect, spuPage.getList());
// assertEquals(spuPage.getTotal(), result.getTotal());
}
/**
* 生成笛卡尔积
*
@ -316,14 +457,48 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
// 准备参数
Map<Long, Integer> stockIncrCounts = MapUtil.builder(1L, 10).put(2L, -20).build();
// mock 方法数据 // TODO ProductSpuDO中已没有相关属性
//productSpuMapper.insert(randomPojo(ProductSpuDO.class, o -> o.setId(1L).setTotalStock(20)));
//productSpuMapper.insert(randomPojo(ProductSpuDO.class, o -> o.setId(2L).setTotalStock(30)));
productSpuMapper.insert(randomPojo(ProductSpuDO.class, o ->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(generaInt()); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
o.setId(1L).setStock(20);
}));
productSpuMapper.insert(randomPojo(ProductSpuDO.class, o -> {
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setDeliveryTemplateId(generateId());
o.setUnit(RandomUtil.randomInt(1,20)); // 限制商品单位范围
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setActivityOrders(newArrayList(1,3,2,4,5)); // 活动排序
o.setPrice(generaInt()); // 限制范围为正整数
o.setMarketPrice(generaInt()); // 限制范围为正整数
o.setCostPrice(generaInt()); // 限制范围为正整数
o.setStock(generaInt()); // 限制范围为正整数
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
o.setId(2L).setStock(30);
}));
// 调用
productSpuService.updateSpuStock(stockIncrCounts);
// 断言 // TODO ProductSpuDO中已没有相关属性
//assertEquals(productSpuService.getSpu(1L).getTotalStock(), 30);
//assertEquals(productSpuService.getSpu(2L).getTotalStock(), 10);
assertEquals(productSpuService.getSpu(1L).getStock(), 30);
assertEquals(productSpuService.getSpu(2L).getStock(), 10);
}
}

View File

@ -1,5 +1,7 @@
DELETE FROM "product_sku";
DELETE FROM "product_spu";
DELETE FROM "product_brand";
DELETE FROM "product_category";
DELETE FROM "product_brand";
DELETE FROM "product_property";
DELETE FROM "product_property_value";
DELETE FROM "product_comment";

View File

@ -1,88 +1,131 @@
CREATE TABLE IF NOT EXISTS `product_sku` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
`spu_id` bigint NOT NULL COMMENT 'spu编号',
`spu_name` varchar DEFAULT NULL COMMENT '商品 SPU 名字',
`properties` varchar DEFAULT NULL COMMENT '规格值数组-json格式 [{propertId: , valueId: }, {propertId: , valueId: }]',
`price` int NOT NULL DEFAULT '-1' COMMENT '销售价格单位',
`market_price` int DEFAULT NULL COMMENT '市场价',
`properties` varchar(512) DEFAULT NULL COMMENT '属性数组JSON 格式',
`price` int NOT NULL DEFAULT '-1' COMMENT '商品价格单位',
`market_price` int DEFAULT NULL COMMENT '市场价单位',
`cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价单位 ',
`pic_url` varchar NOT NULL COMMENT '图片地址',
`bar_code` varchar(64) DEFAULT NULL COMMENT 'SKU 的条形码',
`pic_url` varchar(256) 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 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 DEFAULT NULL COMMENT '创建人',
`updater` varchar DEFAULT NULL COMMENT '更新人',
`deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`)
`weight` double DEFAULT NULL COMMENT '商品重量单位kg 千克',
`volume` double DEFAULT NULL COMMENT '商品体积单位m^3 平米',
`sub_commission_first_price` int DEFAULT NULL COMMENT '一级分销的佣金单位',
`sub_commission_second_price` int DEFAULT NULL COMMENT '二级分销的佣金单位',
`sales_count` int DEFAULT NULL COMMENT '商品销量',
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY("id")
) COMMENT '商品sku';
CREATE TABLE IF NOT EXISTS `product_spu` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
`brand_id` bigint DEFAULT NULL COMMENT '商品品牌编号',
`category_id` bigint NOT NULL COMMENT '分类id',
`spec_type` int NOT NULL COMMENT '规格类型0 单规格 1 多规格',
`code` varchar(128) DEFAULT NULL COMMENT '商品编码',
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '商品 SPU 编号自增',
`name` varchar(128) NOT NULL COMMENT '商品名称',
`sell_point` varchar(128) DEFAULT NULL COMMENT '卖点',
`description` text COMMENT '描述',
`pic_urls` varchar(1024) DEFAULT '' COMMENT '商品轮播图地址数组以逗号分隔最多上传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 '是否展示库存',
`keyword` varchar(256) NOT NULL COMMENT '关键字',
`introduction` varchar(256) NOT NULL COMMENT '商品简介',
`description` text NOT NULL COMMENT '商品详情',
`bar_code` varchar(64) NOT NULL COMMENT '条形码',
`category_id` bigint NOT NULL COMMENT '商品分类编号',
`brand_id` int DEFAULT NULL COMMENT '商品品牌编号',
`pic_url` varchar(256) NOT NULL COMMENT '商品封面图',
`slider_pic_urls` varchar(2000) DEFAULT '' COMMENT '商品轮播图地址\n 数组以逗号分隔\n 最多上传15张',
`video_url` varchar(256) DEFAULT NULL COMMENT '商品视频',
`unit` tinyint NOT NULL COMMENT '单位',
`sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',
`status` tinyint NOT NULL COMMENT '商品状态: 0 上架开启 1 下架禁用-1 回收',
`spec_type` bit(1) NOT NULL COMMENT '规格类型0 单规格 1 多规格',
`price` int NOT NULL DEFAULT '-1' COMMENT '商品价格单位使用',
`market_price` int NOT NULL COMMENT '市场价单位使用',
`cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价单位 ',
`stock` int NOT NULL DEFAULT '0' COMMENT '库存',
`delivery_template_id` bigint NOT NULL COMMENT '物流配置模板编号',
`recommend_hot` bit(1) NOT NULL COMMENT '是否热卖推荐: 0 默认 1 热卖',
`recommend_benefit` bit(1) NOT NULL COMMENT '是否优惠推荐: 0 默认 1 优选',
`recommend_best` bit(1) NOT NULL COMMENT '是否精品推荐: 0 默认 1 精品',
`recommend_new` bit(1) NOT NULL COMMENT '是否新品推荐: 0 默认 1 新品',
`recommend_good` bit(1) NOT NULL COMMENT '是否优品推荐',
`give_integral` int NOT NULL COMMENT '赠送积分',
`give_coupon_template_ids` varchar(512) DEFAULT '' COMMENT '赠送的优惠劵编号的数组',
`sub_commission_type` bit(1) NOT NULL COMMENT '分销类型',
`activity_orders` varchar(16) NOT NULL DEFAULT '' COMMENT '活动显示排序0=默认, 1=秒杀2=砍价3=拼团',
`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 DEFAULT NULL COMMENT '创建人',
`updater` varchar DEFAULT NULL COMMENT '更新人',
`deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`)
`browse_count` int DEFAULT '0' COMMENT '商品点击量',
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY("id")
) COMMENT '商品spu';
CREATE TABLE IF NOT EXISTS `product_category` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号',
`parent_id` bigint DEFAULT NULL COMMENT '父分类编号',
`name` varchar(128) NOT NULL COMMENT '分类名称',
`pic_url` varchar DEFAULT NULL COMMENT '分类图片',
`big_pic_url` varchar DEFAULT NULL COMMENT 'PC端分类图',
`sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',
`status` bit(1) DEFAULT NULL COMMENT '状态',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`creator` varchar DEFAULT NULL COMMENT '创建人',
`updater` varchar DEFAULT NULL COMMENT '更新人',
`deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`)
`parent_id` bigint NOT NULL COMMENT '父分类编号',
`name` varchar(255) NOT NULL COMMENT '分类名称',
`pic_url` varchar(255) NOT NULL COMMENT '移动端分类图',
`big_pic_url` varchar(255) DEFAULT NULL COMMENT 'PC 端分类图',
`sort` int DEFAULT '0' COMMENT '分类排序',
`status` tinyint NOT NULL COMMENT '开启状态',
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY("id")
) COMMENT '商品分类';
CREATE TABLE IF NOT EXISTS `product_brand` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '品牌编号',
`name` varchar(128) NOT NULL COMMENT '品牌名称',
`pic_url` varchar DEFAULT NULL COMMENT '品牌图片',
`sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',
`description` varchar(256) NOT NULL DEFAULT '0' COMMENT '品牌描述',
`status` bit(1) DEFAULT NULL COMMENT '状态',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`creator` varchar DEFAULT NULL COMMENT '创建人',
`updater` varchar DEFAULT NULL COMMENT '更新人',
`deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`)
`name` varchar(255) NOT NULL COMMENT '品牌名称',
`pic_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 '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY("id")
) COMMENT '商品品牌';
CREATE TABLE IF NOT EXISTS `product_property` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(64) DEFAULT NULL COMMENT '规格名称',
`status` tinyint DEFAULT NULL COMMENT '状态 0 开启 1 禁用',
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY("id")
) COMMENT '规格名称';
CREATE TABLE IF NOT EXISTS `product_property_value` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`property_id` bigint DEFAULT NULL COMMENT '规格键id',
`name` varchar(128) DEFAULT NULL COMMENT '规格值名字',
`status` tinyint DEFAULT NULL COMMENT '状态 1 开启 2 禁用',
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY("id")
) COMMENT '规格值';
CREATE TABLE IF NOT EXISTS `product_comment` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '评价编号',
`user_id` bigint NOT NULL COMMENT ' 评价ID 用户编号',
@ -108,10 +151,11 @@ CREATE TABLE IF NOT EXISTS `product_comment` (
`additional_content` varchar(2000) COMMENT '追加评价内容',
`additional_pic_urls` varchar(1024) COMMENT '追评评价图片地址数组以逗号分隔最多上传9张',
`additional_time` datetime COMMENT '追加评价时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`creator` varchar DEFAULT NULL COMMENT '创建人',
`updater` varchar DEFAULT NULL COMMENT '更新人',
`deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY (`id`)
) COMMENT '商品评价';