183 lines
8.0 KiB
SQL
183 lines
8.0 KiB
SQL
-- =============================================
|
||
-- 优惠券分析测试数据 Seed(至少 20 条样本)
|
||
-- 说明:
|
||
-- - 依赖表:coupon_templates, user_coupons, coupon_usage_logs, users, merchants, orders
|
||
-- - 用于驱动 /pages/mall/analytics/coupon-analysis.uvue 页面联调
|
||
-- - 设计目标:
|
||
-- - 8 种券类型覆盖(满减/折扣/免运费/新人/会员/品类/商家/限时)
|
||
-- - 6 种发放渠道覆盖(manual/auto/campaign/invite/cs/points)
|
||
-- - 最近 30 天有发放 + 使用 + 未使用 + 即将到期券
|
||
-- - 可重复执行:通过 WHERE NOT EXISTS / 固定模板名称 避免重复插入
|
||
-- =============================================
|
||
|
||
-- 1) 准备一个测试商家(如不存在则创建)
|
||
INSERT INTO public.merchants (id, shop_name, created_at)
|
||
SELECT
|
||
'30000000-0000-0000-0000-000000000001'::uuid,
|
||
'优惠券测试商家',
|
||
now() - interval '60 days'
|
||
WHERE NOT EXISTS (
|
||
SELECT 1 FROM public.merchants WHERE id = '30000000-0000-0000-0000-000000000001'
|
||
);
|
||
|
||
-- 2) 准备 3 个测试用户(如不存在则创建)
|
||
INSERT INTO public.users (id, phone, email, nickname, created_at)
|
||
VALUES
|
||
('40000000-0000-0000-0000-000000000001'::uuid, '13900001001', 'coupon_user1@test.com', '券用户1', now() - interval '30 days'),
|
||
('40000000-0000-0000-0000-000000000002'::uuid, '13900001002', 'coupon_user2@test.com', '券用户2', now() - interval '20 days'),
|
||
('40000000-0000-0000-0000-000000000003'::uuid, '13900001003', 'coupon_user3@test.com', '券用户3', now() - interval '10 days')
|
||
ON CONFLICT (id) DO NOTHING;
|
||
|
||
-- 3) 插入 8 个优惠券模板(覆盖 mall.md 的 8 种类型)
|
||
INSERT INTO public.coupon_templates (
|
||
id, name, description, coupon_type, discount_type, discount_value,
|
||
min_order_amount, max_discount_amount, total_quantity, per_user_limit,
|
||
usage_limit, merchant_id, start_time, end_time, status, created_at
|
||
)
|
||
VALUES
|
||
('50000000-0000-0000-0000-000000000001'::uuid, '满100减20', '满100减20元', 1, 1, 20.00, 100.00, NULL, 1000, 3, 1,
|
||
'30000000-0000-0000-0000-000000000001', now() - interval '30 days', now() + interval '30 days', 1, now() - interval '30 days'),
|
||
('50000000-0000-0000-0000-000000000002'::uuid, '9折优惠券', '全场9折', 2, 2, 9.00, 0.00, 50.00, 1000, 3, 1,
|
||
'30000000-0000-0000-0000-000000000001', now() - interval '30 days', now() + interval '30 days', 1, now() - interval '30 days'),
|
||
('50000000-0000-0000-0000-000000000003'::uuid, '免运费券', '免配送费', 3, 3, 0.00, 0.00, 10.00, 1000, 5, 1,
|
||
'30000000-0000-0000-0000-000000000001', now() - interval '30 days', now() + interval '30 days', 1, now() - interval '30 days'),
|
||
('50000000-0000-0000-0000-000000000004'::uuid, '新人专享满50减25', '新用户首单优惠', 4, 1, 25.00, 50.00, NULL, 500, 1, 1,
|
||
'30000000-0000-0000-0000-000000000001', now() - interval '15 days', now() + interval '45 days', 1, now() - interval '15 days'),
|
||
('50000000-0000-0000-0000-000000000005'::uuid, '会员折扣券', '会员专享8.5折', 5, 2, 8.50, 0.00, 80.00, 500, 5, 1,
|
||
'30000000-0000-0000-0000-000000000001', now() - interval '20 days', now() + interval '40 days', 1, now() - interval '20 days'),
|
||
('50000000-0000-0000-0000-000000000006'::uuid, '生鲜品类券', '生鲜类满60减15', 6, 1, 15.00, 60.00, NULL, 500, 3, 1,
|
||
'30000000-0000-0000-0000-000000000001', now() - interval '25 days', now() + interval '35 days', 1, now() - interval '25 days'),
|
||
('50000000-0000-0000-0000-000000000007'::uuid, '商家专属券', '指定商家满80减30', 7, 1, 30.00, 80.00, NULL, 300, 3, 1,
|
||
'30000000-0000-0000-0000-000000000001', now() - interval '10 days', now() + interval '50 days', 1, now() - interval '10 days'),
|
||
('50000000-0000-0000-0000-000000000008'::uuid, '限时秒杀券', '限时满40减10', 8, 1, 10.00, 40.00, NULL, 300, 2, 1,
|
||
'30000000-0000-0000-0000-000000000001', now() - interval '5 days', now() + interval '10 days', 1, now() - interval '5 days')
|
||
ON CONFLICT (id) DO NOTHING;
|
||
|
||
|
||
-- 4) 生成用户优惠券 + 使用数据
|
||
DO $$
|
||
DECLARE
|
||
v_users uuid[] := ARRAY[
|
||
'40000000-0000-0000-0000-000000000001'::uuid,
|
||
'40000000-0000-0000-0000-000000000002'::uuid,
|
||
'40000000-0000-0000-0000-000000000003'::uuid
|
||
];
|
||
v_templates uuid[] := ARRAY[
|
||
'50000000-0000-0000-0000-000000000001'::uuid,
|
||
'50000000-0000-0000-0000-000000000002'::uuid,
|
||
'50000000-0000-0000-0000-000000000003'::uuid,
|
||
'50000000-0000-0000-0000-000000000004'::uuid,
|
||
'50000000-0000-0000-0000-000000000005'::uuid,
|
||
'50000000-0000-0000-0000-000000000006'::uuid,
|
||
'50000000-0000-0000-0000-000000000007'::uuid,
|
||
'50000000-0000-0000-0000-000000000008'::uuid
|
||
];
|
||
v_channels text[] := ARRAY['manual','auto','campaign','invite','cs','points'];
|
||
|
||
i int;
|
||
j int;
|
||
v_uc_id uuid;
|
||
v_user uuid;
|
||
v_tpl uuid;
|
||
v_channel text;
|
||
v_received_at timestamptz;
|
||
v_expire_at timestamptz;
|
||
v_order_id uuid;
|
||
v_order_amount numeric;
|
||
v_discount_amount numeric;
|
||
v_used_at timestamptz;
|
||
BEGIN
|
||
-- 为最近 30 天生成多条券(部分使用,部分未使用,部分即将到期)
|
||
FOR i IN 0..29 LOOP
|
||
-- 当天发放 2~4 条券
|
||
FOR j IN 1..(2 + (i % 3)) LOOP
|
||
v_user := v_users[1 + (i + j) % array_length(v_users, 1)];
|
||
v_tpl := v_templates[1 + (i + j) % array_length(v_templates, 1)];
|
||
v_channel := v_channels[1 + (i + j) % array_length(v_channels, 1)];
|
||
|
||
v_received_at := (now() - (i || ' days')::interval);
|
||
v_expire_at := v_received_at + interval '20 days';
|
||
|
||
-- 通过 coupon_code 幂等插入,并返回最终 id(避免 ON CONFLICT DO NOTHING 导致 v_uc_id 无对应记录)
|
||
INSERT INTO public.user_coupons (
|
||
id, user_id, template_id, coupon_code, status,
|
||
received_at, expire_at, obtain_channel, merchant_id
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
v_user,
|
||
v_tpl,
|
||
'TESTCOUPON-' || i || '-' || j,
|
||
1, -- 初始未使用
|
||
v_received_at,
|
||
v_expire_at,
|
||
v_channel,
|
||
'30000000-0000-0000-0000-000000000001'::uuid
|
||
)
|
||
ON CONFLICT (coupon_code) DO UPDATE
|
||
SET user_id = EXCLUDED.user_id,
|
||
template_id = EXCLUDED.template_id,
|
||
received_at = EXCLUDED.received_at,
|
||
expire_at = EXCLUDED.expire_at,
|
||
obtain_channel= EXCLUDED.obtain_channel,
|
||
merchant_id = EXCLUDED.merchant_id
|
||
RETURNING id INTO v_uc_id;
|
||
|
||
-- 约一半的券会在 0~10 天内被使用,生成对应订单和使用记录
|
||
IF (i + j) % 2 = 0 THEN
|
||
v_order_id := gen_random_uuid();
|
||
v_order_amount := 50 + (10 * ((i + j) % 5)); -- 50~90 的订单金额
|
||
v_discount_amount := CASE
|
||
WHEN (i + j) % 4 = 0 THEN 10
|
||
WHEN (i + j) % 4 = 1 THEN 15
|
||
WHEN (i + j) % 4 = 2 THEN 20
|
||
ELSE 5
|
||
END;
|
||
v_used_at := v_received_at + ( (1 + (i % 5)) || ' days')::interval;
|
||
|
||
-- 插入订单
|
||
INSERT INTO public.orders (
|
||
id, user_id, merchant_id, total_amount, status, created_at, updated_at
|
||
) VALUES (
|
||
v_order_id,
|
||
v_user,
|
||
'30000000-0000-0000-0000-000000000001'::uuid,
|
||
v_order_amount,
|
||
2, -- 已完成
|
||
v_used_at,
|
||
v_used_at
|
||
)
|
||
ON CONFLICT (id) DO NOTHING;
|
||
|
||
-- 更新 user_coupons 为已使用(确认对应记录存在)
|
||
UPDATE public.user_coupons
|
||
SET status = 2,
|
||
used_at = v_used_at,
|
||
order_id = v_order_id
|
||
WHERE id = v_uc_id;
|
||
|
||
-- 插入使用流水(仅当对应 user_coupon 存在时生效)
|
||
INSERT INTO public.coupon_usage_logs (
|
||
id, user_coupon_id, order_id, discount_amount, used_at,
|
||
user_id, template_id, merchant_id, order_amount, created_at
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
v_uc_id,
|
||
v_order_id,
|
||
v_discount_amount,
|
||
v_used_at,
|
||
v_user,
|
||
v_tpl,
|
||
'30000000-0000-0000-0000-000000000001'::uuid,
|
||
v_order_amount,
|
||
v_used_at
|
||
);
|
||
END IF;
|
||
END LOOP;
|
||
END LOOP;
|
||
END;
|
||
$$;
|
||
|
||
-- 完成
|
||
SELECT 'coupon test data seed completed!' AS message;
|
||
|