453 lines
20 KiB
PL/PgSQL
453 lines
20 KiB
PL/PgSQL
-- ===================================================================
|
||
-- 电商商城商品管理数据库设计
|
||
-- 基于PostgreSQL,兼容现有ak_contents资讯系统
|
||
-- ===================================================================
|
||
|
||
-- ===================================================================
|
||
-- 1. 商品核心表
|
||
-- ===================================================================
|
||
|
||
-- 商品基础信息表
|
||
CREATE TABLE IF NOT EXISTS public.mall_products (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
product_code VARCHAR(50) UNIQUE NOT NULL, -- 商品编码
|
||
name VARCHAR(500) NOT NULL, -- 商品名称
|
||
subtitle VARCHAR(1000), -- 副标题/卖点
|
||
description TEXT, -- 商品描述
|
||
|
||
-- 商家信息
|
||
merchant_id UUID NOT NULL REFERENCES public.ak_users(id),
|
||
brand_id UUID REFERENCES public.mall_brands(id),
|
||
|
||
-- 分类信息
|
||
category_id UUID NOT NULL REFERENCES public.mall_categories(id),
|
||
category_path TEXT[], -- 分类路径,便于查询
|
||
|
||
-- 基础属性
|
||
weight DECIMAL(10,3), -- 重量(kg)
|
||
dimensions JSONB, -- 尺寸信息 {长,宽,高}
|
||
|
||
-- 价格信息
|
||
base_price DECIMAL(12,2) NOT NULL, -- 基础价格
|
||
market_price DECIMAL(12,2), -- 市场价
|
||
cost_price DECIMAL(12,2), -- 成本价
|
||
|
||
-- 库存信息
|
||
stock_quantity INTEGER DEFAULT 0, -- 总库存
|
||
available_quantity INTEGER DEFAULT 0, -- 可用库存
|
||
reserved_quantity INTEGER DEFAULT 0, -- 预留库存
|
||
min_order_quantity INTEGER DEFAULT 1, -- 最小起订量
|
||
max_order_quantity INTEGER, -- 最大限购量
|
||
|
||
-- 状态信息
|
||
status VARCHAR(20) DEFAULT 'draft', -- 状态:draft/active/inactive/deleted
|
||
is_featured BOOLEAN DEFAULT false, -- 是否精选
|
||
is_new BOOLEAN DEFAULT false, -- 是否新品
|
||
is_hot BOOLEAN DEFAULT false, -- 是否热卖
|
||
is_on_sale BOOLEAN DEFAULT false, -- 是否促销
|
||
|
||
-- 多媒体
|
||
main_image_url TEXT, -- 主图
|
||
image_urls TEXT[], -- 图片URL数组
|
||
video_urls TEXT[], -- 视频URL数组
|
||
|
||
-- SEO相关
|
||
seo_title VARCHAR(200), -- SEO标题
|
||
seo_description VARCHAR(500), -- SEO描述
|
||
seo_keywords TEXT[], -- SEO关键词
|
||
slug VARCHAR(200) UNIQUE, -- URL友好标识
|
||
|
||
-- 销售统计
|
||
view_count INTEGER DEFAULT 0, -- 浏览次数
|
||
sale_count INTEGER DEFAULT 0, -- 销售数量
|
||
favorite_count INTEGER DEFAULT 0, -- 收藏次数
|
||
rating_average DECIMAL(3,2) DEFAULT 0, -- 平均评分
|
||
rating_count INTEGER DEFAULT 0, -- 评分次数
|
||
|
||
-- 时间信息
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
published_at TIMESTAMP WITH TIME ZONE, -- 上架时间
|
||
sale_start_at TIMESTAMP WITH TIME ZONE, -- 开售时间
|
||
sale_end_at TIMESTAMP WITH TIME ZONE, -- 停售时间
|
||
|
||
-- 额外信息
|
||
tags TEXT[], -- 标签
|
||
attributes JSONB DEFAULT '{}', -- 自定义属性
|
||
notes TEXT, -- 内部备注
|
||
|
||
-- 约束
|
||
CONSTRAINT chk_price_positive CHECK (base_price >= 0),
|
||
CONSTRAINT chk_stock_non_negative CHECK (stock_quantity >= 0),
|
||
CONSTRAINT chk_available_stock CHECK (available_quantity >= 0),
|
||
CONSTRAINT chk_reserved_stock CHECK (reserved_quantity >= 0),
|
||
CONSTRAINT chk_rating_range CHECK (rating_average >= 0 AND rating_average <= 5)
|
||
);
|
||
|
||
-- 商品表索引
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_merchant ON public.mall_products(merchant_id, status);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_category ON public.mall_products(category_id, status);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_status ON public.mall_products(status, published_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_featured ON public.mall_products(is_featured, published_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_price ON public.mall_products(base_price, status);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_sale_count ON public.mall_products(sale_count DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_rating ON public.mall_products(rating_average DESC, rating_count DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_code ON public.mall_products(product_code);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_slug ON public.mall_products(slug);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_tags ON public.mall_products USING GIN(tags);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_products_category_path ON public.mall_products USING GIN(category_path);
|
||
|
||
COMMENT ON TABLE public.mall_products IS '商品基础信息表';
|
||
|
||
-- ===================================================================
|
||
-- 2. 商品SKU表
|
||
-- ===================================================================
|
||
|
||
-- 商品SKU表
|
||
CREATE TABLE IF NOT EXISTS public.mall_product_skus (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
product_id UUID NOT NULL REFERENCES public.mall_products(id) ON DELETE CASCADE,
|
||
sku_code VARCHAR(100) UNIQUE NOT NULL, -- SKU编码
|
||
|
||
-- 规格信息
|
||
specification_values JSONB NOT NULL DEFAULT '{}', -- 规格值 {"颜色":"红色","尺寸":"L"}
|
||
specification_text VARCHAR(500), -- 规格描述文本
|
||
|
||
-- 价格库存
|
||
price DECIMAL(12,2) NOT NULL, -- SKU价格
|
||
cost_price DECIMAL(12,2), -- SKU成本价
|
||
stock_quantity INTEGER DEFAULT 0, -- SKU库存
|
||
available_quantity INTEGER DEFAULT 0, -- SKU可用库存
|
||
reserved_quantity INTEGER DEFAULT 0, -- SKU预留库存
|
||
|
||
-- SKU属性
|
||
weight DECIMAL(10,3), -- SKU重量
|
||
barcode VARCHAR(50), -- 条形码
|
||
image_url TEXT, -- SKU图片
|
||
|
||
-- 状态
|
||
is_active BOOLEAN DEFAULT true, -- 是否启用
|
||
is_default BOOLEAN DEFAULT false, -- 是否默认SKU
|
||
|
||
-- 销售统计
|
||
sale_count INTEGER DEFAULT 0, -- 销售数量
|
||
|
||
-- 时间
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
|
||
-- 约束
|
||
CONSTRAINT chk_sku_price_positive CHECK (price >= 0),
|
||
CONSTRAINT chk_sku_stock_non_negative CHECK (stock_quantity >= 0)
|
||
);
|
||
|
||
-- SKU表索引
|
||
CREATE INDEX IF NOT EXISTS idx_mall_product_skus_product ON public.mall_product_skus(product_id, is_active);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_product_skus_code ON public.mall_product_skus(sku_code);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_product_skus_barcode ON public.mall_product_skus(barcode);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_product_skus_default ON public.mall_product_skus(product_id, is_default);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_product_skus_spec ON public.mall_product_skus USING GIN(specification_values);
|
||
|
||
COMMENT ON TABLE public.mall_product_skus IS '商品SKU表';
|
||
|
||
-- ===================================================================
|
||
-- 3. 商品分类表
|
||
-- ===================================================================
|
||
|
||
-- 商品分类表
|
||
CREATE TABLE IF NOT EXISTS public.mall_categories (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
name VARCHAR(200) NOT NULL, -- 分类名称
|
||
slug VARCHAR(200) UNIQUE, -- URL友好标识
|
||
description TEXT, -- 分类描述
|
||
|
||
-- 层级关系
|
||
parent_id UUID REFERENCES public.mall_categories(id),
|
||
level INTEGER DEFAULT 0, -- 层级:0=顶级
|
||
path TEXT, -- 路径:/1/2/3
|
||
sort_order INTEGER DEFAULT 0, -- 排序
|
||
|
||
-- 显示信息
|
||
icon_url TEXT, -- 分类图标
|
||
banner_url TEXT, -- 分类横幅
|
||
|
||
-- 状态
|
||
is_active BOOLEAN DEFAULT true, -- 是否启用
|
||
is_featured BOOLEAN DEFAULT false, -- 是否精选
|
||
|
||
-- 统计
|
||
product_count INTEGER DEFAULT 0, -- 商品数量
|
||
|
||
-- SEO
|
||
seo_title VARCHAR(200),
|
||
seo_description VARCHAR(500),
|
||
seo_keywords TEXT[],
|
||
|
||
-- 时间
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
|
||
-- 自定义属性
|
||
attributes JSONB DEFAULT '{}'
|
||
);
|
||
|
||
-- 分类表索引
|
||
CREATE INDEX IF NOT EXISTS idx_mall_categories_parent ON public.mall_categories(parent_id, sort_order);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_categories_level ON public.mall_categories(level, sort_order);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_categories_active ON public.mall_categories(is_active, sort_order);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_categories_featured ON public.mall_categories(is_featured, sort_order);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_categories_slug ON public.mall_categories(slug);
|
||
|
||
COMMENT ON TABLE public.mall_categories IS '商品分类表';
|
||
|
||
-- ===================================================================
|
||
-- 4. 商品品牌表
|
||
-- ===================================================================
|
||
|
||
-- 商品品牌表
|
||
CREATE TABLE IF NOT EXISTS public.mall_brands (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
name VARCHAR(200) NOT NULL UNIQUE, -- 品牌名称
|
||
english_name VARCHAR(200), -- 英文名称
|
||
slug VARCHAR(200) UNIQUE, -- URL友好标识
|
||
description TEXT, -- 品牌描述
|
||
|
||
-- 品牌信息
|
||
logo_url TEXT, -- 品牌Logo
|
||
banner_url TEXT, -- 品牌横幅
|
||
website_url TEXT, -- 官网地址
|
||
origin_country VARCHAR(100), -- 品牌原产国
|
||
founded_year INTEGER, -- 创立年份
|
||
|
||
-- 状态
|
||
is_active BOOLEAN DEFAULT true, -- 是否启用
|
||
is_featured BOOLEAN DEFAULT false, -- 是否精选
|
||
|
||
-- 统计
|
||
product_count INTEGER DEFAULT 0, -- 商品数量
|
||
|
||
-- SEO
|
||
seo_title VARCHAR(200),
|
||
seo_description VARCHAR(500),
|
||
seo_keywords TEXT[],
|
||
|
||
-- 时间
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
|
||
-- 排序
|
||
sort_order INTEGER DEFAULT 0
|
||
);
|
||
|
||
-- 品牌表索引
|
||
CREATE INDEX IF NOT EXISTS idx_mall_brands_active ON public.mall_brands(is_active, sort_order);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_brands_featured ON public.mall_brands(is_featured, sort_order);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_brands_slug ON public.mall_brands(slug);
|
||
|
||
COMMENT ON TABLE public.mall_brands IS '商品品牌表';
|
||
|
||
-- ===================================================================
|
||
-- 5. 商品规格相关表
|
||
-- ===================================================================
|
||
|
||
-- 规格名表(如:颜色、尺寸、款式等)
|
||
CREATE TABLE IF NOT EXISTS public.mall_specifications (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
name VARCHAR(100) NOT NULL, -- 规格名称:颜色、尺寸等
|
||
slug VARCHAR(100) UNIQUE, -- URL友好标识
|
||
type VARCHAR(50) DEFAULT 'select', -- 类型:select/input/color/image
|
||
sort_order INTEGER DEFAULT 0, -- 排序
|
||
is_required BOOLEAN DEFAULT false, -- 是否必选
|
||
is_active BOOLEAN DEFAULT true, -- 是否启用
|
||
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||
);
|
||
|
||
-- 规格值表(如:红色、蓝色、L、XL等)
|
||
CREATE TABLE IF NOT EXISTS public.mall_specification_values (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
specification_id UUID NOT NULL REFERENCES public.mall_specifications(id) ON DELETE CASCADE,
|
||
value VARCHAR(200) NOT NULL, -- 规格值:红色、L等
|
||
color_code VARCHAR(20), -- 颜色代码(仅颜色规格)
|
||
image_url TEXT, -- 规格值图片
|
||
sort_order INTEGER DEFAULT 0, -- 排序
|
||
is_active BOOLEAN DEFAULT true, -- 是否启用
|
||
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
|
||
UNIQUE(specification_id, value)
|
||
);
|
||
|
||
-- 商品规格关联表
|
||
CREATE TABLE IF NOT EXISTS public.mall_product_specifications (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
product_id UUID NOT NULL REFERENCES public.mall_products(id) ON DELETE CASCADE,
|
||
specification_id UUID NOT NULL REFERENCES public.mall_specifications(id) ON DELETE CASCADE,
|
||
is_required BOOLEAN DEFAULT false, -- 该商品的该规格是否必选
|
||
sort_order INTEGER DEFAULT 0, -- 在该商品中的排序
|
||
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
|
||
UNIQUE(product_id, specification_id)
|
||
);
|
||
|
||
-- 索引
|
||
CREATE INDEX IF NOT EXISTS idx_mall_specifications_active ON public.mall_specifications(is_active, sort_order);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_specification_values_spec ON public.mall_specification_values(specification_id, is_active, sort_order);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_product_specifications_product ON public.mall_product_specifications(product_id, sort_order);
|
||
|
||
-- ===================================================================
|
||
-- 6. 商品详情相关表
|
||
-- ===================================================================
|
||
|
||
-- 商品详情内容表(富文本、图文混排)
|
||
CREATE TABLE IF NOT EXISTS public.mall_product_details (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
product_id UUID NOT NULL REFERENCES public.mall_products(id) ON DELETE CASCADE,
|
||
|
||
-- 详情内容
|
||
detail_type VARCHAR(50) DEFAULT 'rich_text', -- 类型:rich_text/markdown/html
|
||
content TEXT, -- 详情内容
|
||
images TEXT[], -- 详情图片
|
||
|
||
-- 显示控制
|
||
section_title VARCHAR(200), -- 区块标题
|
||
sort_order INTEGER DEFAULT 0, -- 排序
|
||
is_active BOOLEAN DEFAULT true, -- 是否显示
|
||
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||
);
|
||
|
||
-- 商品参数表
|
||
CREATE TABLE IF NOT EXISTS public.mall_product_attributes (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
product_id UUID NOT NULL REFERENCES public.mall_products(id) ON DELETE CASCADE,
|
||
|
||
-- 参数信息
|
||
attribute_name VARCHAR(200) NOT NULL, -- 参数名称
|
||
attribute_value TEXT NOT NULL, -- 参数值
|
||
attribute_group VARCHAR(100), -- 参数分组
|
||
|
||
-- 显示控制
|
||
sort_order INTEGER DEFAULT 0, -- 排序
|
||
is_key_attribute BOOLEAN DEFAULT false, -- 是否关键参数
|
||
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
|
||
UNIQUE(product_id, attribute_name)
|
||
);
|
||
|
||
-- 索引
|
||
CREATE INDEX IF NOT EXISTS idx_mall_product_details_product ON public.mall_product_details(product_id, sort_order);
|
||
CREATE INDEX IF NOT EXISTS idx_mall_product_attributes_product ON public.mall_product_attributes(product_id, attribute_group, sort_order);
|
||
|
||
-- ===================================================================
|
||
-- 7. 视图和函数
|
||
-- ===================================================================
|
||
|
||
-- 商品列表视图(包含完整信息)
|
||
CREATE OR REPLACE VIEW public.vw_mall_products_full AS
|
||
SELECT
|
||
p.*,
|
||
c.name as category_name,
|
||
c.path as category_full_path,
|
||
b.name as brand_name,
|
||
b.logo_url as brand_logo_url,
|
||
|
||
-- SKU汇总信息
|
||
(SELECT MIN(price) FROM public.mall_product_skus WHERE product_id = p.id AND is_active = true) as min_price,
|
||
(SELECT MAX(price) FROM public.mall_product_skus WHERE product_id = p.id AND is_active = true) as max_price,
|
||
(SELECT SUM(stock_quantity) FROM public.mall_product_skus WHERE product_id = p.id AND is_active = true) as total_stock,
|
||
|
||
-- 默认SKU信息
|
||
default_sku.id as default_sku_id,
|
||
default_sku.sku_code as default_sku_code,
|
||
default_sku.price as default_price,
|
||
default_sku.stock_quantity as default_stock
|
||
|
||
FROM public.mall_products p
|
||
LEFT JOIN public.mall_categories c ON p.category_id = c.id
|
||
LEFT JOIN public.mall_brands b ON p.brand_id = b.id
|
||
LEFT JOIN public.mall_product_skus default_sku ON p.id = default_sku.product_id AND default_sku.is_default = true
|
||
WHERE p.status != 'deleted';
|
||
|
||
COMMENT ON VIEW public.vw_mall_products_full IS '商品完整信息视图';
|
||
|
||
-- ===================================================================
|
||
-- 8. 触发器(维护统计数据)
|
||
-- ===================================================================
|
||
|
||
-- 更新商品SKU统计的触发器函数
|
||
CREATE OR REPLACE FUNCTION public.update_product_sku_stats()
|
||
RETURNS TRIGGER AS $$
|
||
BEGIN
|
||
-- 更新商品的库存统计
|
||
UPDATE public.mall_products
|
||
SET
|
||
stock_quantity = (
|
||
SELECT COALESCE(SUM(stock_quantity), 0)
|
||
FROM public.mall_product_skus
|
||
WHERE product_id = COALESCE(NEW.product_id, OLD.product_id) AND is_active = true
|
||
),
|
||
available_quantity = (
|
||
SELECT COALESCE(SUM(available_quantity), 0)
|
||
FROM public.mall_product_skus
|
||
WHERE product_id = COALESCE(NEW.product_id, OLD.product_id) AND is_active = true
|
||
),
|
||
updated_at = NOW()
|
||
WHERE id = COALESCE(NEW.product_id, OLD.product_id);
|
||
|
||
RETURN COALESCE(NEW, OLD);
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
-- 创建触发器
|
||
DO $$
|
||
BEGIN
|
||
DROP TRIGGER IF EXISTS trigger_update_product_sku_stats ON public.mall_product_skus;
|
||
CREATE TRIGGER trigger_update_product_sku_stats
|
||
AFTER INSERT OR UPDATE OR DELETE ON public.mall_product_skus
|
||
FOR EACH ROW EXECUTE FUNCTION public.update_product_sku_stats();
|
||
END
|
||
$$;
|
||
|
||
-- ===================================================================
|
||
-- 9. 初始化数据
|
||
-- ===================================================================
|
||
|
||
-- 插入基础商品分类
|
||
INSERT INTO public.mall_categories (name, slug, level, sort_order) VALUES
|
||
('服装鞋包', 'fashion', 0, 1),
|
||
('数码家电', 'electronics', 0, 2),
|
||
('食品生鲜', 'food', 0, 3),
|
||
('家居日用', 'home', 0, 4),
|
||
('美妆护肤', 'beauty', 0, 5),
|
||
('运动户外', 'sports', 0, 6),
|
||
('图书文娱', 'books', 0, 7),
|
||
('医药保健', 'health', 0, 8)
|
||
ON CONFLICT (slug) DO NOTHING;
|
||
|
||
-- 插入基础规格
|
||
INSERT INTO public.mall_specifications (name, slug, type, sort_order) VALUES
|
||
('颜色', 'color', 'color', 1),
|
||
('尺寸', 'size', 'select', 2),
|
||
('款式', 'style', 'select', 3),
|
||
('容量', 'capacity', 'select', 4),
|
||
('材质', 'material', 'select', 5)
|
||
ON CONFLICT (slug) DO NOTHING;
|
||
|
||
-- 输出完成信息
|
||
DO $$
|
||
BEGIN
|
||
RAISE NOTICE '商品管理数据库结构创建完成!';
|
||
RAISE NOTICE '已创建以下核心表:';
|
||
RAISE NOTICE '- mall_products: 商品基础信息';
|
||
RAISE NOTICE '- mall_product_skus: 商品SKU';
|
||
RAISE NOTICE '- mall_categories: 商品分类';
|
||
RAISE NOTICE '- mall_brands: 商品品牌';
|
||
RAISE NOTICE '- mall_specifications: 商品规格';
|
||
RAISE NOTICE '可以开始添加商品数据了!';
|
||
END
|
||
$$;
|