10 KiB
- 创建正确的触发器和函数 CREATE OR REPLACE FUNCTION ensure_ak_user() RETURNS TRIGGER AS $$ BEGIN INSERT INTO public.ak_users (user_id, email, nickname) VALUES (NEW.id, NEW.email, COALESCE(NEW.email, '新用户')) ON CONFLICT (user_id) DO UPDATE SET email = EXCLUDED.email, nickname = EXCLUDED.nickname; RETURN NEW; END; $$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_ensure_ak_user AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION ensure_ak_user();
-- ============================================= -- 0. 创建 ak_users 表(你的核心用户表) -- ============================================= CREATE TABLE IF NOT EXISTS public.ak_users ( id BIGSERIAL PRIMARY KEY, user_id UUID UNIQUE NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, email VARCHAR(255) UNIQUE, phone VARCHAR(20), nickname VARCHAR(100), avatar_url TEXT, gender CHAR(1) DEFAULT 'U', birthday DATE, address TEXT, user_type INTEGER DEFAULT 1, -- 1:普通用户, 2:配送员 status VARCHAR(20) DEFAULT 'active', created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() );
-- ============================================= -- 1. 配送员资料表 (delivery_drivers) -- ============================================= CREATE TABLE IF NOT EXISTS public.delivery_drivers ( id BIGSERIAL PRIMARY KEY, user_id UUID UNIQUE NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, real_name VARCHAR(100) NOT NULL, id_card VARCHAR(18), driver_license VARCHAR(50), vehicle_type INTEGER DEFAULT 1, -- 1:电动车, 2:摩托车, 3:汽车 vehicle_number VARCHAR(20), work_status INTEGER DEFAULT 1, -- 1:空闲, 2:忙碌, 3:休息 current_location JSONB, -- {lat: 22.5431, lng: 114.0579, address: "深圳市南山区"} service_areas TEXT[], -- 服务区域数组 ["南山", "福田", "罗湖"] rating DECIMAL(3,2) DEFAULT 5.00, -- 平均评分 total_orders INTEGER DEFAULT 0, -- 总完成订单数 auth_status INTEGER DEFAULT 1, -- 1:未认证, 2:审核中, 3:已认证 online_status BOOLEAN DEFAULT FALSE, -- 是否在线 created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() );
-- ============================================= -- 2. 订单表 (orders) -- ============================================= CREATE TABLE IF NOT EXISTS public.orders ( id BIGSERIAL PRIMARY KEY, order_no VARCHAR(50) UNIQUE NOT NULL, -- 订单号,如 D202501081234 user_id UUID NOT NULL REFERENCES auth.users(id), -- 下单用户 status INTEGER DEFAULT 1, -- 1:待支付, 2:待接单, 3:配送中, 4:已完成, 5:已取消 total_amount DECIMAL(10,2) NOT NULL, -- 订单总金额 delivery_fee DECIMAL(10,2) NOT NULL, -- 配送费 payable_amount DECIMAL(10,2) NOT NULL, -- 实付金额 pickup_address JSONB NOT NULL, -- 取货地址 delivery_address JSONB NOT NULL, -- 配送地址 pickup_contact JSONB NOT NULL, -- 取货联系人 delivery_contact JSONB NOT NULL, -- 配送联系人 created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() );
-- ============================================= -- 3. 配送任务表 (delivery_tasks) -- ============================================= CREATE TABLE IF NOT EXISTS public.delivery_tasks ( id BIGSERIAL PRIMARY KEY, order_id BIGINT NOT NULL REFERENCES orders(id), driver_id BIGINT NOT NULL REFERENCES delivery_drivers(id), task_status INTEGER DEFAULT 1, -- 1:待接取, 2:已接取, 3:取货中, 4:已取货, 5:配送中, 6:已完成 pickup_address JSONB NOT NULL, -- 取货地址 {detail: "", area: "", lat: 0, lng: 0} delivery_address JSONB NOT NULL, -- 配送地址 {detail: "", area: "", lat: 0, lng: 0} pickup_contact JSONB NOT NULL, -- 取货联系人 {name: "", phone: ""} delivery_contact JSONB NOT NULL, -- 配送联系人 {name: "", phone: ""} delivery_fee DECIMAL(10,2) NOT NULL, -- 配送费 distance DECIMAL(8,2) DEFAULT 0, -- 配送距离(km) estimated_time INTEGER DEFAULT 0, -- 预计配送时间(分钟) pickup_time TIMESTAMP WITH TIME ZONE, -- 实际取货时间 delivery_time TIMESTAMP WITH TIME ZONE, -- 实际配送时间 created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() );
-- ============================================= -- 4. 今日统计表 (daily_stats) -- ============================================= CREATE TABLE IF NOT EXISTS public.daily_stats ( id BIGSERIAL PRIMARY KEY, driver_id BIGINT NOT NULL REFERENCES delivery_drivers(id), stat_date DATE NOT NULL, completed_orders INTEGER DEFAULT 0, total_earning DECIMAL(10,2) DEFAULT 0.00, total_distance DECIMAL(8,2) DEFAULT 0.00, avg_rating DECIMAL(3,2) DEFAULT 5.00, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(driver_id, stat_date) -- 每个司机每天只有一条统计记录 );
-- ============================================= -- 5. 启用 RLS -- ============================================= ALTER TABLE public.ak_users ENABLE ROW LEVEL SECURITY; ALTER TABLE public.delivery_drivers ENABLE ROW LEVEL SECURITY; ALTER TABLE public.orders ENABLE ROW LEVEL SECURITY; ALTER TABLE public.delivery_tasks ENABLE ROW LEVEL SECURITY; ALTER TABLE public.daily_stats ENABLE ROW LEVEL SECURITY;
-- ============================================= -- 6. 创建 RLS 策略 -- ============================================= CREATE POLICY "Users can view own profile" ON public.ak_users FOR SELECT USING (auth.uid() = user_id);
CREATE POLICY "Drivers can view own profile" ON public.delivery_drivers FOR SELECT USING (auth.uid() = user_id);
CREATE POLICY "Users can view own orders" ON public.orders FOR SELECT USING (auth.uid() = user_id);
CREATE POLICY "Drivers can view own tasks" ON public.delivery_tasks FOR SELECT USING (EXISTS ( SELECT 1 FROM delivery_drivers dd WHERE dd.id = delivery_tasks.driver_id AND dd.user_id = auth.uid() ));
CREATE POLICY "Drivers can view own stats" ON public.daily_stats FOR SELECT USING (EXISTS ( SELECT 1 FROM delivery_drivers dd WHERE dd.id = daily_stats.driver_id AND dd.user_id = auth.uid() ));
-- ============================================= -- 7. 创建索引 -- ============================================= CREATE INDEX IF NOT EXISTS idx_ak_users_user_id ON public.ak_users(user_id); CREATE INDEX IF NOT EXISTS idx_ak_users_email ON public.ak_users(email); CREATE INDEX IF NOT EXISTS idx_delivery_drivers_user_id ON public.delivery_drivers(user_id); CREATE INDEX IF NOT EXISTS idx_orders_user_id ON public.orders(user_id); CREATE INDEX IF NOT EXISTS idx_delivery_tasks_driver_id ON public.delivery_tasks(driver_id); CREATE INDEX IF NOT EXISTS idx_daily_stats_driver_date ON public.daily_stats(driver_id, stat_date);
-- ============================================= -- 8. 创建触发器:当新用户注册时自动创建 ak_users 记录 -- ============================================= -- 先删除已存在的(防止重复创建错误) DROP TRIGGER IF EXISTS trigger_ensure_ak_user ON auth.users; DROP FUNCTION IF EXISTS ensure_ak_user();
-- 创建新的触发器和函数 CREATE OR REPLACE FUNCTION ensure_ak_user() RETURNS TRIGGER AS $$ BEGIN INSERT INTO public.ak_users (user_id, email, nickname, user_type) VALUES (NEW.id, NEW.email, COALESCE(NEW.email, '新用户'), 1) ON CONFLICT (user_id) DO UPDATE SET email = EXCLUDED.email, nickname = EXCLUDED.nickname; RETURN NEW; END; $$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_ensure_ak_user AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION ensure_ak_user();
-- ============================================= -- 9. 创建测试数据 -- ============================================= DO $$ DECLARE test_user_id UUID; test_driver_id UUID; test_driver_record_id BIGINT; test_order_id BIGINT; BEGIN -- 创建配送员用户 INSERT INTO auth.users ( instance_id, id, aud, role, email, encrypted_password, email_confirmed_at, created_at, updated_at ) VALUES ( '00000000-0000-0000-0000-000000000000', gen_random_uuid(), 'authenticated', 'authenticated', '123@example.com', crypt('Test123456', gen_salt('bf')), NOW(), NOW(), NOW() ) RETURNING id INTO test_driver_id;
-- 创建配送员资料 INSERT INTO public.delivery_drivers ( user_id, real_name, vehicle_number, online_status, rating, total_orders ) VALUES ( test_driver_id, '张师傅', '粤B12345', TRUE, 4.8, 1250 ) RETURNING id INTO test_driver_record_id;
-- 创建今日统计数据 INSERT INTO public.daily_stats ( driver_id, stat_date, completed_orders, total_earning, total_distance, avg_rating ) VALUES ( test_driver_record_id, CURRENT_DATE, 8, 245.60, 45.0, 4.9 );
-- 创建测试订单 INSERT INTO public.orders ( order_no, user_id, status, total_amount, delivery_fee, payable_amount, pickup_address, delivery_address, pickup_contact, delivery_contact ) VALUES ( 'D202501081234', test_driver_id, -- 为了测试,暂时让司机自己下单 2, -- 已接单 125.50, 8.50, 134.00, '{"detail": "华强北商业区华强电子世界2楼A205", "area": "华强北", "lat": 22.5431, "lng": 114.0579}', '{"detail": "南山区科技园深南大道9999号", "area": "科技园", "lat": 22.5350, "lng": 113.9490}', '{"name": "商家联系人", "phone": "1385678"}', '{"name": "张先生", "phone": "1391234"}' ) RETURNING id INTO test_order_id;
-- 创建配送任务 INSERT INTO public.delivery_tasks ( order_id, driver_id, task_status, pickup_address, delivery_address, pickup_contact, delivery_contact, delivery_fee, distance, estimated_time ) VALUES ( test_order_id, test_driver_record_id, 2, -- 已接取 '{"detail": "华强北商业区华强电子世界2楼A205", "area": "华强北", "lat": 22.5431, "lng": 114.0579}', '{"detail": "南山区科技园深南大道9999号", "area": "科技园", "lat": 22.5350, "lng": 113.9490}', '{"name": "商家联系人", "phone": "1385678"}', '{"name": "张先生", "phone": "1391234"}', 8.50, 12.5, 35 );
RAISE NOTICE '✅ 配送系统数据库创建完成!'; END $$;