274 lines
11 KiB
PL/PgSQL
274 lines
11 KiB
PL/PgSQL
-- 商城系统用户兼容性实施方案
|
||
-- 基于混合方案:复用 ak_users 主表 + 商城扩展表
|
||
|
||
-- 1. 商城用户扩展表
|
||
CREATE TABLE public.mall_user_profiles (
|
||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
user_id uuid UNIQUE REFERENCES public.ak_users(id) ON DELETE CASCADE,
|
||
user_type INTEGER DEFAULT 1, -- 1:消费者 2:商家 3:配送员 4:客服 5:管理员
|
||
status INTEGER DEFAULT 1, -- 1:正常 2:冻结 3:注销 4:待审核
|
||
real_name VARCHAR(64), -- 真实姓名(商家认证、配送员必填)
|
||
id_card VARCHAR(32), -- 身份证号(商家认证、配送员必填)
|
||
credit_score INTEGER DEFAULT 100, -- 信用分数 0-1000
|
||
mall_role VARCHAR(32) DEFAULT 'consumer', -- 商城角色标识
|
||
verification_status INTEGER DEFAULT 0, -- 认证状态 0:未认证 1:已认证 2:认证失败
|
||
verification_data JSONB, -- 认证相关数据
|
||
business_license VARCHAR(128), -- 营业执照号(商家)
|
||
shop_category VARCHAR(64), -- 店铺类别(商家)
|
||
service_areas JSONB, -- 服务区域(配送员)
|
||
emergency_contact VARCHAR(128), -- 紧急联系人(配送员)
|
||
preferences JSONB, -- 用户偏好设置
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE public.mall_user_profiles IS '商城用户扩展信息表';
|
||
COMMENT ON COLUMN public.mall_user_profiles.user_id IS '关联ak_users表的用户ID';
|
||
COMMENT ON COLUMN public.mall_user_profiles.user_type IS '用户类型:1消费者 2商家 3配送员 4客服 5管理员';
|
||
COMMENT ON COLUMN public.mall_user_profiles.status IS '用户状态:1正常 2冻结 3注销 4待审核';
|
||
COMMENT ON COLUMN public.mall_user_profiles.credit_score IS '信用分数,影响交易权限';
|
||
COMMENT ON COLUMN public.mall_user_profiles.verification_status IS '认证状态:0未认证 1已认证 2认证失败';
|
||
|
||
-- 创建索引
|
||
CREATE INDEX idx_mall_user_profiles_user_id ON public.mall_user_profiles(user_id);
|
||
CREATE INDEX idx_mall_user_profiles_user_type ON public.mall_user_profiles(user_type);
|
||
CREATE INDEX idx_mall_user_profiles_status ON public.mall_user_profiles(status);
|
||
CREATE INDEX idx_mall_user_profiles_mall_role ON public.mall_user_profiles(mall_role);
|
||
|
||
-- 2. 用户地址表
|
||
CREATE TABLE public.ak_user_addresses (
|
||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
user_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE,
|
||
receiver_name VARCHAR(64) NOT NULL, -- 收货人姓名
|
||
receiver_phone VARCHAR(32) NOT NULL, -- 收货人手机
|
||
province VARCHAR(64) NOT NULL, -- 省份
|
||
city VARCHAR(64) NOT NULL, -- 城市
|
||
district VARCHAR(64) NOT NULL, -- 区县
|
||
address_detail TEXT NOT NULL, -- 详细地址
|
||
postal_code VARCHAR(16), -- 邮编
|
||
is_default BOOLEAN DEFAULT false, -- 是否默认地址
|
||
label VARCHAR(32), -- 地址标签:home/office/school/other
|
||
coordinates POINT, -- 经纬度坐标,用于配送距离计算
|
||
delivery_instructions TEXT, -- 配送说明
|
||
business_hours VARCHAR(128), -- 可配送时间(如:9:00-18:00)
|
||
status INTEGER DEFAULT 1, -- 地址状态:1正常 2禁用
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE public.ak_user_addresses IS '用户地址表';
|
||
COMMENT ON COLUMN public.ak_user_addresses.coordinates IS '经纬度坐标,格式:POINT(longitude latitude)';
|
||
COMMENT ON COLUMN public.ak_user_addresses.label IS '地址标签:home家 office公司 school学校 other其他';
|
||
|
||
-- 创建索引
|
||
CREATE INDEX idx_user_addresses_user_id ON public.ak_user_addresses(user_id);
|
||
CREATE INDEX idx_user_addresses_city ON public.ak_user_addresses(city);
|
||
CREATE INDEX idx_user_addresses_district ON public.ak_user_addresses(district);
|
||
CREATE INDEX idx_user_addresses_is_default ON public.ak_user_addresses(is_default);
|
||
|
||
-- 创建地理位置索引(用于附近配送查询)
|
||
CREATE INDEX idx_user_addresses_coordinates ON public.ak_user_addresses USING GIST(coordinates);
|
||
|
||
-- 3. 用户收藏表
|
||
CREATE TABLE public.mall_user_favorites (
|
||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
user_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE,
|
||
target_type VARCHAR(32) NOT NULL, -- 收藏类型:product/shop
|
||
target_id uuid NOT NULL, -- 目标ID
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE public.mall_user_favorites IS '用户收藏表';
|
||
COMMENT ON COLUMN public.mall_user_favorites.target_type IS '收藏类型:product商品 shop店铺';
|
||
|
||
-- 创建索引和唯一约束
|
||
CREATE INDEX idx_mall_user_favorites_user_id ON public.mall_user_favorites(user_id);
|
||
CREATE INDEX idx_mall_user_favorites_target ON public.mall_user_favorites(target_type, target_id);
|
||
CREATE UNIQUE INDEX idx_mall_user_favorites_unique ON public.mall_user_favorites(user_id, target_type, target_id);
|
||
|
||
-- 4. 用户搜索历史表
|
||
CREATE TABLE public.mall_user_search_history (
|
||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
user_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE,
|
||
keyword VARCHAR(256) NOT NULL, -- 搜索关键词
|
||
search_count INTEGER DEFAULT 1, -- 搜索次数
|
||
last_search_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE public.mall_user_search_history IS '用户搜索历史表';
|
||
|
||
-- 创建索引
|
||
CREATE INDEX idx_mall_search_history_user_id ON public.mall_user_search_history(user_id);
|
||
CREATE INDEX idx_mall_search_history_keyword ON public.mall_user_search_history(keyword);
|
||
CREATE UNIQUE INDEX idx_mall_search_history_unique ON public.mall_user_search_history(user_id, keyword);
|
||
|
||
-- 5. 用户浏览历史表
|
||
CREATE TABLE public.mall_user_browse_history (
|
||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
user_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE,
|
||
product_id uuid NOT NULL, -- 浏览的商品ID
|
||
browse_count INTEGER DEFAULT 1, -- 浏览次数
|
||
browse_duration INTEGER DEFAULT 0, -- 浏览时长(秒)
|
||
last_browse_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE public.mall_user_browse_history IS '用户浏览历史表';
|
||
|
||
-- 创建索引
|
||
CREATE INDEX idx_mall_browse_history_user_id ON public.mall_user_browse_history(user_id);
|
||
CREATE INDEX idx_mall_browse_history_product_id ON public.mall_user_browse_history(product_id);
|
||
CREATE INDEX idx_mall_browse_history_last_browse ON public.mall_user_browse_history(last_browse_at);
|
||
CREATE UNIQUE INDEX idx_mall_browse_history_unique ON public.mall_user_browse_history(user_id, product_id);
|
||
|
||
-- 6. 触发器:确保每个用户只有一个默认地址
|
||
CREATE OR REPLACE FUNCTION ensure_single_default_address()
|
||
RETURNS TRIGGER AS $$
|
||
BEGIN
|
||
-- 如果新插入/更新的地址设为默认
|
||
IF NEW.is_default = true THEN
|
||
-- 将该用户的其他地址的默认状态设为false
|
||
UPDATE public.ak_user_addresses
|
||
SET is_default = false
|
||
WHERE user_id = NEW.user_id AND id != NEW.id;
|
||
END IF;
|
||
|
||
RETURN NEW;
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
-- 创建触发器
|
||
CREATE TRIGGER trigger_ensure_single_default_address
|
||
BEFORE INSERT OR UPDATE ON public.ak_user_addresses
|
||
FOR EACH ROW
|
||
EXECUTE FUNCTION ensure_single_default_address();
|
||
|
||
-- 7. 触发器:自动更新 updated_at 字段
|
||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||
RETURNS TRIGGER AS $$
|
||
BEGIN
|
||
NEW.updated_at = now();
|
||
RETURN NEW;
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
-- 为相关表创建更新时间触发器
|
||
CREATE TRIGGER trigger_mall_user_profiles_updated_at
|
||
BEFORE UPDATE ON public.mall_user_profiles
|
||
FOR EACH ROW
|
||
EXECUTE FUNCTION update_updated_at_column();
|
||
|
||
CREATE TRIGGER trigger_user_addresses_updated_at
|
||
BEFORE UPDATE ON public.ak_user_addresses
|
||
FOR EACH ROW
|
||
EXECUTE FUNCTION update_updated_at_column();
|
||
|
||
-- 8. 数据迁移:为现有 ak_users 用户创建默认商城档案
|
||
INSERT INTO public.mall_user_profiles (user_id, user_type, status, mall_role)
|
||
SELECT
|
||
id,
|
||
1, -- 默认为消费者
|
||
1, -- 默认状态正常
|
||
'consumer' -- 默认角色消费者
|
||
FROM public.ak_users
|
||
WHERE id NOT IN (SELECT user_id FROM public.mall_user_profiles WHERE user_id IS NOT NULL);
|
||
|
||
-- 9. 创建视图:商城用户完整信息视图
|
||
CREATE VIEW public.mall_users_view AS
|
||
SELECT
|
||
u.id,
|
||
u.username,
|
||
u.email,
|
||
u.phone,
|
||
u.avatar_url,
|
||
u.gender,
|
||
u.birthday,
|
||
u.bio,
|
||
u.created_at as user_created_at,
|
||
u.updated_at as user_updated_at,
|
||
mp.user_type,
|
||
mp.status,
|
||
mp.real_name,
|
||
mp.credit_score,
|
||
mp.mall_role,
|
||
mp.verification_status,
|
||
mp.created_at as profile_created_at,
|
||
mp.updated_at as profile_updated_at
|
||
FROM public.ak_users u
|
||
INNER JOIN public.mall_user_profiles mp ON u.id = mp.user_id;
|
||
|
||
COMMENT ON VIEW public.mall_users_view IS '商城用户完整信息视图';
|
||
|
||
-- 10. 权限设置(根据实际需要调整)
|
||
-- 创建商城相关的RLS策略
|
||
ALTER TABLE public.mall_user_profiles ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE public.ak_user_addresses ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE public.mall_user_favorites ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE public.mall_user_search_history ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE public.mall_user_browse_history ENABLE ROW LEVEL SECURITY;
|
||
|
||
-- 用户只能访问自己的数据
|
||
CREATE POLICY mall_user_profiles_policy ON public.mall_user_profiles
|
||
FOR ALL USING (auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id));
|
||
|
||
CREATE POLICY user_addresses_policy ON public.ak_user_addresses
|
||
FOR ALL USING (auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id));
|
||
|
||
CREATE POLICY mall_user_favorites_policy ON public.mall_user_favorites
|
||
FOR ALL USING (auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id));
|
||
|
||
CREATE POLICY mall_user_search_history_policy ON public.mall_user_search_history
|
||
FOR ALL USING (auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id));
|
||
|
||
CREATE POLICY mall_user_browse_history_policy ON public.mall_user_browse_history
|
||
FOR ALL USING (auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id));
|
||
|
||
-- 11. 示例查询函数
|
||
-- 获取用户默认地址
|
||
CREATE OR REPLACE FUNCTION get_user_default_address(p_user_id uuid)
|
||
RETURNS TABLE (
|
||
id uuid,
|
||
receiver_name varchar,
|
||
receiver_phone varchar,
|
||
full_address text,
|
||
coordinates point
|
||
) AS $$
|
||
BEGIN
|
||
RETURN QUERY
|
||
SELECT
|
||
a.id,
|
||
a.receiver_name,
|
||
a.receiver_phone,
|
||
(a.province || a.city || a.district || a.address_detail) as full_address,
|
||
a.coordinates
|
||
FROM public.ak_user_addresses a
|
||
WHERE a.user_id = p_user_id AND a.is_default = true AND a.status = 1
|
||
LIMIT 1;
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
-- 检查用户是否为商城认证商家
|
||
CREATE OR REPLACE FUNCTION is_verified_merchant(p_user_id uuid)
|
||
RETURNS boolean AS $$
|
||
DECLARE
|
||
result boolean := false;
|
||
BEGIN
|
||
SELECT (user_type = 2 AND verification_status = 1) INTO result
|
||
FROM public.mall_user_profiles
|
||
WHERE user_id = p_user_id;
|
||
|
||
RETURN COALESCE(result, false);
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
-- 12. 完成提示
|
||
DO $$
|
||
BEGIN
|
||
RAISE NOTICE '商城用户兼容性方案部署完成!';
|
||
RAISE NOTICE '已创建表:mall_user_profiles, ak_user_addresses, mall_user_favorites, mall_user_search_history, mall_user_browse_history';
|
||
RAISE NOTICE '已创建视图:mall_users_view';
|
||
RAISE NOTICE '已设置触发器和RLS策略';
|
||
RAISE NOTICE '已为现有用户创建默认商城档案';
|
||
END $$;
|