9.6 KiB
9.6 KiB
测试数据生成与验证记录
本文档记录了在本项目中为配送端页面生成并验证测试数据库数据的全过程,包含关键表结构要点、执行的幂等 SQL、遇到的问题及解决办法,以及前端验证步骤,便于回溯和复现。
概述
- 目标:让配送端页面
pages/mall/delivery/index.uvue能读取真实 DB 中的配送任务(ml_delivery_tasks)并在附近订单 / 当前任务中展示;为此需要在 DB 中创建或复用ak_users、ml_delivery_drivers、ml_orders、ml_delivery_tasks的测试数据。 - 环境:Supabase(Postgres)。建议在 Supabase SQL Editor 中以
Role = postgres执行 SQL 以避免 RLS/触发器引起的权限问题。
关键表与约束摘要
public.ak_users:项目用户表,id为主键,auth_id对应auth.users.id。public.ml_delivery_drivers:配送员表,重要列:id、user_id(引用ak_users.id,UNIQUE NOT NULL)、real_name、id_card。注意:此表没有phone列(以前曾误以为存在)。public.ml_orders:订单表,重要列:id、order_no(UNIQUE NOT NULL)、user_id、merchant_id、shipping_address(JSONB NOT NULL)、order_status。public.ml_delivery_tasks:配送任务表,重要列:id、order_id(UNIQUE NOT NULL,引用ml_orders.id)、driver_id(引用ml_delivery_drivers.id)、pickup_address/delivery_address(JSONB)、status(CHECK in (1..6))。注意:联系人信息应内嵌到地址 JSON 中(没有单独pickup_contact字段)。
我执行的主要步骤(已实现的幂等脚本)
- 查找或创建
ak_users(按auth_id唯一):避免重复插入,若已存在则复用其id。 - 查找或创建
ml_delivery_drivers(以ak_users.id为user_id):注意去掉对不存在列的引用(例如phone)。 - 插入两个测试订单(使用唯一
order_no标识,若已存在则跳过),shipping_address使用 JSONB 格式且包含contact/phone/province/city/detail等字段。 - 为每个订单创建对应的
ml_delivery_tasks:一个保持status = 1(可接单,driver_id = NULL),另一个设置status = 4并分配上步骤创建或找到的driver_id。
下面是我实际使用的幂等 SQL(已去除不存在列并兼容 schema)。在 Supabase SQL Editor 中以 Role = postgres 运行整段脚本即可。
-- 替换 auth_id 为你的 auth.users.id(示例值可替换)
WITH
found_user AS (
SELECT id FROM public.ak_users WHERE auth_id = 'dae9f45b-3955-43ae-992f-a3e24beaa520'
),
ins_user AS (
INSERT INTO public.ak_users (id, auth_id, email, username, created_at)
SELECT uuid_generate_v4(), 'dae9f45b-3955-43ae-992f-a3e24beaa520', 'test+delivery@example.com', 'test_delivery_user', NOW()
WHERE NOT EXISTS (SELECT 1 FROM found_user)
RETURNING id
),
user_id AS (
SELECT id FROM ins_user
UNION ALL
SELECT id FROM found_user
LIMIT 1
),
found_driver AS (
SELECT id, user_id FROM public.ml_delivery_drivers WHERE user_id = (SELECT id FROM user_id) LIMIT 1
),
ins_driver AS (
INSERT INTO public.ml_delivery_drivers (id, user_id, real_name, id_card, created_at)
SELECT uuid_generate_v4(), (SELECT id FROM user_id), '张师傅', 'ID-TEST-0001', NOW()
WHERE NOT EXISTS (SELECT 1 FROM found_driver)
RETURNING id, user_id
),
driver_row AS (
SELECT id, user_id FROM ins_driver
UNION ALL
SELECT id, user_id FROM found_driver
LIMIT 1
),
ins_order_1 AS (
INSERT INTO public.ml_orders (
order_no, user_id, merchant_id,
product_amount, shipping_fee, total_amount,
shipping_address, created_at, updated_at
)
SELECT
'TEST-DELIV-20260202-001',
(SELECT id FROM user_id),
(SELECT id FROM user_id),
88.00, 12.00, 100.00,
('{"contact":"李小明","phone":"13800000002","province":"上海市","city":"上海市","district":"浦东新区","street":"测试路100号","detail":"5楼502室","lat":31.2000,"lng":121.5000}')::jsonb,
NOW(), NOW()
WHERE NOT EXISTS (SELECT 1 FROM public.ml_orders WHERE order_no = 'TEST-DELIV-20260202-001')
RETURNING id, order_no, order_status
),
sel_order_1 AS (
SELECT id, order_no FROM ins_order_1
UNION ALL
SELECT id, order_no FROM public.ml_orders WHERE order_no = 'TEST-DELIV-20260202-001'
LIMIT 1
),
ins_task_1 AS (
INSERT INTO public.ml_delivery_tasks (
order_id, pickup_address, delivery_address, delivery_fee, status, created_at, updated_at
)
SELECT
(SELECT id FROM sel_order_1),
('{"contact":"商家小二","phone":"13900000002","street":"商家路1號","city":"上海市","detail":"商家门店A"}')::jsonb,
('{"contact":"李小明","phone":"13800000002","street":"测试路100号","city":"上海市","detail":"5楼502室"}')::jsonb,
12.00,
1,
NOW(), NOW()
WHERE NOT EXISTS (
SELECT 1 FROM public.ml_delivery_tasks dt WHERE dt.order_id = (SELECT id FROM sel_order_1)
)
RETURNING id, order_id, status, driver_id
),
ins_order_2 AS (
INSERT INTO public.ml_orders (
order_no, user_id, merchant_id,
product_amount, shipping_fee, total_amount,
shipping_address, created_at, updated_at
)
SELECT
'TEST-DELIV-20260202-002',
(SELECT id FROM user_id),
(SELECT id FROM user_id),
59.00, 8.00, 67.00,
('{"contact":"王小红","phone":"13800000003","province":"上海市","city":"上海市","district":"闵行区","street":"示例街20号","detail":"2幢101室","lat":31.1000,"lng":121.4000}')::jsonb,
NOW(), NOW()
WHERE NOT EXISTS (SELECT 1 FROM public.ml_orders WHERE order_no = 'TEST-DELIV-20260202-002')
RETURNING id, order_no, order_status
),
sel_order_2 AS (
SELECT id, order_no FROM ins_order_2
UNION ALL
SELECT id, order_no FROM public.ml_orders WHERE order_no = 'TEST-DELIV-20260202-002'
LIMIT 1
),
ins_task_2 AS (
INSERT INTO public.ml_delivery_tasks (
order_id, driver_id, pickup_address, delivery_address,
delivery_fee, status, assigned_at, picked_at, created_at, updated_at
)
SELECT
(SELECT id FROM sel_order_2),
(SELECT id FROM driver_row),
('{"contact":"商家B","phone":"13900000003","street":"商家街2號","city":"上海市","detail":"商家门店B"}')::jsonb,
('{"contact":"王小红","phone":"13800000003","street":"示例街20号","city":"上海市","detail":"2幢101室"}')::jsonb,
8.00,
4,
NOW(), NOW(), NOW(), NOW()
WHERE NOT EXISTS (
SELECT 1 FROM public.ml_delivery_tasks dt WHERE dt.order_id = (SELECT id FROM sel_order_2)
)
RETURNING id, order_id, status, driver_id
)
SELECT
(SELECT id FROM user_id) AS ak_user_id,
(SELECT id FROM driver_row) AS delivery_driver_id,
(SELECT id FROM sel_order_1) AS order1_id,
(SELECT order_no FROM sel_order_1) AS order1_no,
(SELECT id FROM sel_order_2) AS order2_id,
(SELECT order_no FROM sel_order_2) AS order2_no,
(SELECT id FROM ins_task_1) AS task1_id,
(SELECT id FROM ins_task_2) AS task2_id;
常见错误与处理
- 错误:列不存在(例如
address/phone/pickup_contact)。处理:核对complete_mall_database.sql中的表结构,确认应使用shipping_address、并将联系人内嵌到 JSON 中。 - 错误:插入触发 FK 或 NOT NULL 违规(23503 / 23502)。处理:按顺序插入依赖表或使用已存在的 FK 值(例如先查找
ak_users再插入 driver)。 - 错误:唯一约束冲突(23505,例如
ml_delivery_tasks.order_id唯一)。处理:脚本使用WHERE NOT EXISTS与ORDER_NO检查以避免重复插入。 - 无行返回(UPDATE/SELECT 返回 “Success. No rows returned”):可能因为复制 id 时包含不可见字符,或 WHERE 条件不匹配。建议先用
SELECT按order_no查找 task,再用UPDATE ... FROM public.ml_orders WHERE order_no = '...' RETURNING ...更新并检查返回值。
前端验证(我在 pages/mall/delivery/index.uvue 已加入日志)
-
刷新配送端页面(或重新打开),观察控制台日志:
loadDriverInfo日志:应输出driverInfo,例如打印loadDriverInfo: try user_id=... res=...。loadCurrentTask日志:输出查询结果loadCurrentTask: driverId=... res=...,若 driver 有未完成任务(status < 5),currentTask会被设置。loadAvailableOrders日志:输出loadAvailableOrders: query result=...,用于验证status = 1且driver_id IS NULL的任务是否列出。
-
若需要把某条
ml_delivery_tasks的status改为 4(分配给司机),可运行:
UPDATE public.ml_delivery_tasks dt
SET status = 4,
driver_id = '<DRIVER_ID>',
assigned_at = NOW(),
updated_at = NOW()
FROM public.ml_orders o
WHERE dt.order_id = o.id
AND o.order_no = 'TEST-DELIV-20260202-001'
RETURNING dt.id, dt.order_id, dt.status, dt.driver_id, dt.assigned_at, dt.updated_at;
执行后刷新前端并贴回 loadCurrentTask / loadAvailableOrders 的日志,以便确认页面行为。
附:运行建议与注意事项
- 优先在 Supabase SQL Editor 中以
Role = postgres执行插入与更新脚本,能避免 RLS 导致的“无行返回”。 - 若需要创建
ml_order_items,需先确保ml_products存在或用最小 mock 产品插入,否则会触发 FK 约束错误。为减少依赖,我先仅创建ml_orders与ml_delivery_tasks。 - 保持
order_no的唯一性(测试用的order_no推荐加时间戳或前缀TEST-)。
如需我把脚本扩展为同时创建 ml_products / ml_order_items(以便测试完整订单页),或希望我直接在 repo 中加入一个可执行的 SQL 脚本文件,请回复我想要的范围,我来补充。
作者:自动化助手(配合用户执行并记录) 日期:2026-02-02