-- ============================================ -- 数据分析模块测试数据 Seed(Supabase/Postgres) -- ============================================ -- 用途:为 `pages/mall/analytics/*` 页面提供可联调的模拟数据 -- 参考:`docs/ANALYTICS_DB_DESIGN.md` -- -- 执行顺序: -- 1. 先执行基础业务表的 seed(users/merchants/products/orders等) -- 2. 再执行本文档(analytics_* 表 + 基础表补充数据) -- -- ⚠️ 重要(RLS): -- 本脚本会写入已启用 RLS 的表(orders/user_sessions/page_views/analytics_*)。 -- 请使用 Supabase Dashboard SQL Editor(等价于 postgres/service_role)执行, -- 不要用 anon/authenticated 直接执行,否则会被 RLS 策略拦截。 -- ============================================ -- ============================================ -- 1. 基础业务表补充数据(如果还没有) -- ============================================ -- 1.1 确保有测试用户(分析师) -- 注意:如果 users 表已通过 02_insert_test_data.sql 插入数据,这里可以跳过或补充 INSERT INTO users (id, phone, email, nickname, last_login_at, created_at) VALUES ('00000000-0000-0000-0000-000000000001', '13800001001', 'analyst1@test.com', '分析师张三', NOW() - INTERVAL '1 day', NOW() - INTERVAL '30 days'), ('00000000-0000-0000-0000-000000000002', '13800001002', 'analyst2@test.com', '分析师李四', NOW() - INTERVAL '2 days', NOW() - INTERVAL '20 days') ON CONFLICT (id) DO NOTHING; -- 1.2 确保有测试商家 -- 注意:如果 merchants 表已通过 02_insert_test_data.sql 插入数据,这里可以跳过或补充 INSERT INTO merchants (id, shop_name, created_at) VALUES ('10000000-0000-0000-0000-000000000001', '测试商家A', NOW() - INTERVAL '60 days'), ('10000000-0000-0000-0000-000000000002', '测试商家B', NOW() - INTERVAL '50 days') ON CONFLICT (id) DO NOTHING; -- 1.3 确保有测试商品 -- 注意:如果 products 表已通过 02_insert_test_data.sql 插入数据,这里可以跳过或补充 INSERT INTO products (id, merchant_id, name, price, sales, status, created_at) VALUES ('20000000-0000-0000-0000-000000000001', '10000000-0000-0000-0000-000000000001', '测试商品1', 99.00, 50, 1, NOW() - INTERVAL '40 days'), ('20000000-0000-0000-0000-000000000002', '10000000-0000-0000-0000-000000000001', '测试商品2', 199.00, 30, 1, NOW() - INTERVAL '35 days'), ('20000000-0000-0000-0000-000000000003', '10000000-0000-0000-0000-000000000002', '测试商品3', 299.00, 20, 1, NOW() - INTERVAL '30 days') ON CONFLICT (id) DO NOTHING; -- 1.4 生成过去30天的测试订单(用于首页实时KPI和趋势) DO $$ DECLARE i INTEGER; j INTEGER; order_date DATE; order_id UUID; user_id_val UUID := '00000000-0000-0000-0000-000000000001'; merchant_id_val UUID := '10000000-0000-0000-0000-000000000001'; product_id_val UUID := '20000000-0000-0000-0000-000000000001'; BEGIN FOR i IN 0..29 LOOP order_date := CURRENT_DATE - (29 - i); -- 每天生成 5-15 个订单 FOR j IN 1..(5 + (i % 11)) LOOP order_id := gen_random_uuid(); -- 插入订单(状态2=已支付/已完成) INSERT INTO orders ( id, user_id, merchant_id, status, total_amount, payment_method, created_at ) VALUES ( order_id, user_id_val, merchant_id_val, 2, -- 已支付/已完成 (50 + (j * 10) + (i * 2))::numeric(10,2), 'alipay', order_date + (random() * INTERVAL '1 day') ) ON CONFLICT (id) DO NOTHING; -- 插入订单商品 INSERT INTO order_items ( id, order_id, product_id, quantity, price, total_amount, created_at ) VALUES ( gen_random_uuid(), order_id, product_id_val, 1, (50 + (j * 10))::numeric(10,2), (50 + (j * 10))::numeric(10,2), order_date + (random() * INTERVAL '1 day') ) ON CONFLICT (id) DO NOTHING; END LOOP; END LOOP; END $$; -- 1.5 插入 user_sessions(在线用户/访问用户统计) INSERT INTO user_sessions (id, user_id, created_at, last_active_at, is_active) VALUES (gen_random_uuid(), '00000000-0000-0000-0000-000000000001', NOW() - INTERVAL '10 minutes', NOW() - INTERVAL '1 minutes', TRUE), (gen_random_uuid(), '00000000-0000-0000-0000-000000000002', NOW() - INTERVAL '8 minutes', NOW() - INTERVAL '2 minutes', TRUE), (gen_random_uuid(), '00000000-0000-0000-0000-000000000001', NOW() - INTERVAL '20 minutes', NOW() - INTERVAL '6 minutes', FALSE) ON CONFLICT DO NOTHING; -- 1.6 插入 page_views(流量来源统计) DO $$ DECLARE i INTEGER; v_date DATE; v_source TEXT; BEGIN FOR i IN 0..29 LOOP v_date := CURRENT_DATE - (29 - i); v_source := CASE WHEN (i % 4) = 0 THEN 'direct' WHEN (i % 4) = 1 THEN 'search' WHEN (i % 4) = 2 THEN 'social' ELSE 'ad' END; INSERT INTO page_views (id, user_id, path, source, created_at) VALUES (gen_random_uuid(), '00000000-0000-0000-0000-000000000001', '/pages/mall/analytics/index', v_source, v_date + (random() * INTERVAL '1 day')) ON CONFLICT DO NOTHING; END LOOP; END $$; -- ============================================ -- 2. Analytics 表数据 -- ============================================ -- 2.1 分析师偏好设置 INSERT INTO analytics_user_preferences (id, user_id, default_period, timezone, currency, kpi_cards, created_at, updated_at) VALUES ( gen_random_uuid(), '00000000-0000-0000-0000-000000000001', '7d', 'Asia/Shanghai', 'CNY', '["gmv", "orders", "users", "conversion"]'::jsonb, NOW() - INTERVAL '10 days', NOW() ), ( gen_random_uuid(), '00000000-0000-0000-0000-000000000002', '30d', 'Asia/Shanghai', 'CNY', '["gmv", "orders"]'::jsonb, NOW() - INTERVAL '5 days', NOW() ) ON CONFLICT (user_id) DO UPDATE SET default_period = EXCLUDED.default_period, updated_at = NOW(); -- 2.2 报表定义(3个示例报表) INSERT INTO analytics_reports ( id, owner_user_id, merchant_id, title, description, type, period, date_start, date_end, status, generated_at, created_at, updated_at ) VALUES ( 'a0000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000001', NULL, '销售报表 - 近7天', '展示近7天的销售趋势和核心指标', 'sales', '7d', CURRENT_DATE - 7, CURRENT_DATE, 'ready', NOW() - INTERVAL '1 hour', NOW() - INTERVAL '2 days', NOW() - INTERVAL '1 hour' ), ( 'a0000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000001', NULL, '用户分析报表 - 近30天', '用户增长、活跃度、留存率分析', 'users', '30d', CURRENT_DATE - 30, CURRENT_DATE, 'ready', NOW() - INTERVAL '2 hours', NOW() - INTERVAL '5 days', NOW() - INTERVAL '2 hours' ), ( 'a0000000-0000-0000-0000-000000000003', '00000000-0000-0000-0000-000000000001', '10000000-0000-0000-0000-000000000001', '商家销售报表 - 近90天', '商家A的销售表现分析', 'sales', '90d', CURRENT_DATE - 90, CURRENT_DATE, 'ready', NOW() - INTERVAL '30 minutes', NOW() - INTERVAL '10 days', NOW() - INTERVAL '30 minutes' ) ON CONFLICT (id) DO NOTHING; -- 2.3 报表核心指标(为第一个报表生成) INSERT INTO analytics_report_metrics ( id, report_id, metric_key, metric_label, metric_value_num, metric_value_text, format, change_pct, icon, color, created_at ) VALUES ( gen_random_uuid(), 'a0000000-0000-0000-0000-000000000001', 'gmv', 'GMV', 125680.50, NULL, 'currency', 15.6, 'money', '#3b82f6', NOW() ), ( gen_random_uuid(), 'a0000000-0000-0000-0000-000000000001', 'orders', '订单量', 856, NULL, 'number', 12.3, 'list', '#10b981', NOW() ), ( gen_random_uuid(), 'a0000000-0000-0000-0000-000000000001', 'conversion_rate', '转化率', 3.45, NULL, 'percent', 0.8, 'trend', '#f59e0b', NOW() ), ( gen_random_uuid(), 'a0000000-0000-0000-0000-000000000001', 'avg_order_amount', '客单价', 146.82, NULL, 'currency', -2.1, 'wallet', '#8b5cf6', NOW() ) ON CONFLICT DO NOTHING; -- 2.4 报表明细行(趋势数据,为第一个报表生成过去7天的数据) DO $$ DECLARE i INTEGER; row_date DATE; report_id_val UUID := 'a0000000-0000-0000-0000-000000000001'; BEGIN FOR i IN 0..6 LOOP row_date := CURRENT_DATE - (6 - i); INSERT INTO analytics_report_rows ( id, report_id, row_date, gmv, orders, users, conversion, avg_order_amount, extra, created_at ) VALUES ( gen_random_uuid(), report_id_val, row_date, (15000 + (i * 2000) + (random() * 3000))::numeric(10,2), (100 + (i * 15) + floor(random() * 30))::integer, (80 + (i * 10) + floor(random() * 20))::integer, (3.0 + (i * 0.1) + (random() * 0.5))::numeric(5,2), (140 + (i * 2) + (random() * 20))::numeric(10,2), '{}'::jsonb, NOW() ) ON CONFLICT DO NOTHING; END LOOP; END $$; -- 2.5 数据洞察(为第一个报表生成3条洞察) INSERT INTO analytics_insights ( id, report_id, owner_user_id, type, impact, title, content, tags, created_at ) VALUES ( gen_random_uuid(), 'a0000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000001', 'positive', 'high', 'GMV持续增长', '近7天GMV较上周期增长15.6%,主要得益于新用户增长和促销活动', ARRAY['销售', '增长']::text[], NOW() - INTERVAL '1 hour' ), ( gen_random_uuid(), 'a0000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000001', 'warning', 'medium', '客单价略有下降', '客单价较上周期下降2.1%,建议关注高价值商品推广', ARRAY['客单价', '预警']::text[], NOW() - INTERVAL '1 hour' ), ( gen_random_uuid(), 'a0000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000001', 'info', 'low', '转化率稳定', '转化率保持在3.45%,与行业平均水平相当', ARRAY['转化率']::text[], NOW() - INTERVAL '1 hour' ) ON CONFLICT DO NOTHING; -- 2.6 报表收藏 INSERT INTO analytics_report_favorites (id, user_id, report_id, created_at) VALUES ( gen_random_uuid(), '00000000-0000-0000-0000-000000000001', 'a0000000-0000-0000-0000-000000000001', NOW() - INTERVAL '1 day' ), ( gen_random_uuid(), '00000000-0000-0000-0000-000000000001', 'a0000000-0000-0000-0000-000000000002', NOW() - INTERVAL '2 days' ) ON CONFLICT (user_id, report_id) DO NOTHING; -- 2.7 导出任务历史 INSERT INTO analytics_export_jobs ( id, user_id, report_id, format, status, file_path, error_message, created_at, finished_at ) VALUES ( gen_random_uuid(), '00000000-0000-0000-0000-000000000001', 'a0000000-0000-0000-0000-000000000001', 'xlsx', 'done', 'exports/report_001.xlsx', '', NOW() - INTERVAL '3 days', NOW() - INTERVAL '3 days' + INTERVAL '5 minutes' ), ( gen_random_uuid(), '00000000-0000-0000-0000-000000000001', 'a0000000-0000-0000-0000-000000000002', 'pdf', 'done', 'exports/report_002.pdf', '', NOW() - INTERVAL '1 day', NOW() - INTERVAL '1 day' + INTERVAL '2 minutes' ), ( gen_random_uuid(), '00000000-0000-0000-0000-000000000001', 'a0000000-0000-0000-0000-000000000003', 'csv', 'running', NULL, '', NOW() - INTERVAL '10 minutes', NULL ) ON CONFLICT DO NOTHING; -- ============================================ -- 3. 补充报表明细行(为其他报表生成数据) -- ============================================ -- 为第二个报表(用户分析报表)生成过去30天的趋势数据 DO $$ DECLARE i INTEGER; row_date DATE; report_id_val UUID := 'a0000000-0000-0000-0000-000000000002'; BEGIN FOR i IN 0..29 LOOP row_date := CURRENT_DATE - (29 - i); INSERT INTO analytics_report_rows ( id, report_id, row_date, gmv, orders, users, conversion, avg_order_amount, extra, created_at ) VALUES ( gen_random_uuid(), report_id_val, row_date, (18000 + (i * 500) + (random() * 2000))::numeric(10,2), (120 + (i * 3) + floor(random() * 20))::integer, (90 + (i * 2) + floor(random() * 15))::integer, (3.2 + (i * 0.05) + (random() * 0.3))::numeric(5,2), (150 + (i * 1) + (random() * 30))::numeric(10,2), '{}'::jsonb, NOW() ) ON CONFLICT DO NOTHING; END LOOP; END $$; -- 为第三个报表(商家销售报表)生成过去90天的趋势数据 DO $$ DECLARE i INTEGER; row_date DATE; report_id_val UUID := 'a0000000-0000-0000-0000-000000000003'; BEGIN FOR i IN 0..89 LOOP row_date := CURRENT_DATE - (89 - i); INSERT INTO analytics_report_rows ( id, report_id, row_date, gmv, orders, users, conversion, avg_order_amount, extra, created_at ) VALUES ( gen_random_uuid(), report_id_val, row_date, (20000 + (i * 100) + (random() * 3000))::numeric(10,2), (150 + (i * 1) + floor(random() * 30))::integer, (100 + (i * 1) + floor(random() * 20))::integer, (3.5 + (i * 0.01) + (random() * 0.4))::numeric(5,2), (130 + (i * 0.5) + (random() * 40))::numeric(10,2), '{}'::jsonb, NOW() ) ON CONFLICT DO NOTHING; END LOOP; END $$; -- ============================================ -- 完成 -- ============================================ SELECT 'Analytics test data seed completed!' AS message;