忽略本地报错信息文件

This commit is contained in:
2026-06-17 10:20:43 +08:00
parent 6b11144366
commit 090362c32d
191 changed files with 5434 additions and 76452 deletions

View File

@@ -0,0 +1,309 @@
-- ============================================================
-- 淇锛歳pc_homecare_auto_dispatch_optimized 瀛楁鍚嶉敊璇?
-- 鏃ユ湡锛?026-06-10
-- 闂锛欼NSERT INTO hss_service_order_status_logs 浣跨敤浜嗕笉瀛樺湪鐨勫瓧娈?operator_type
-- 淇锛氬皢 operator_type 鏀逛负 operator_role锛堣〃涓疄闄呭瓧娈靛悕锛?
-- ============================================================
-- 鍒犻櫎鏃х増鏈嚱鏁帮紙蹇呴』鎸囧畾鍙傛暟鍒楄〃锛?
DROP FUNCTION IF EXISTS public.rpc_homecare_auto_dispatch_optimized(TEXT, TEXT);
DROP FUNCTION IF EXISTS public.rpc_homecare_auto_dispatch_optimized(UUID, TEXT);
-- 鍒涘缓淇鍚庣殑浼樺寲鐗堣嚜鍔ㄦ淳鍗?RPC
CREATE OR REPLACE FUNCTION public.rpc_homecare_auto_dispatch_optimized(
p_order_id TEXT,
p_operator_type TEXT DEFAULT 'system'
)
RETURNS JSONB
LANGUAGE plpgsql
AS $$
DECLARE
v_order RECORD;
v_assignment RECORD;
v_assignment_id TEXT;
v_staff_id UUID;
v_current_user_id UUID;
v_now TIMESTAMPTZ;
v_failure_code TEXT;
v_failure_message TEXT;
v_retryable BOOLEAN;
v_status_log_id TEXT;
v_attempt_log_id TEXT;
v_distance_km NUMERIC;
v_order_lat NUMERIC;
v_order_lng NUMERIC;
v_staff_lat NUMERIC;
v_staff_lng NUMERIC;
v_scheduled_start_at TIMESTAMPTZ;
v_scheduled_end_at TIMESTAMPTZ;
BEGIN
v_now := now();
BEGIN
v_current_user_id := gen_random_uuid();
EXCEPTION WHEN OTHERS THEN
v_current_user_id := NULL;
END;
SELECT * INTO v_order
FROM public.hss_service_orders
WHERE id = p_order_id
AND deleted_at IS NULL
AND status = 'paid'
AND dispatch_status = 'pending';
IF NOT FOUND THEN
RETURN jsonb_build_object(
'success', FALSE,
'code', 'ORDER_NOT_FOUND_OR_NOT_ELIGIBLE',
'message', '璁㈠崟涓嶅瓨鍦ㄦ垨涓嶇鍚堟淳鍗曟潯浠?,
'display_type', 'toast',
'retryable', FALSE
);
END IF;
v_order_lat := v_order.service_lat;
v_order_lng := v_order.service_lng;
IF v_order_lat IS NULL OR v_order_lng IS NULL THEN
RETURN jsonb_build_object(
'success', FALSE,
'code', 'ORDER_MISSING_COORDINATES',
'message', '',
'display_type', 'toast',
'retryable', FALSE
);
END IF;
IF v_order.dispatch_station_id IS NOT NULL THEN
SELECT * INTO v_assignment
FROM (
SELECT
s.id AS staff_id,
s.staff_name,
s.online_status,
s.station_id,
s.latitude AS staff_lat,
s.longitude AS staff_lng,
distance_calc.distance_km(s.latitude, s.longitude, v_order_lat, v_order_lng) AS distance_km,
ROW_NUMBER() OVER (ORDER BY distance_calc.distance_km(s.latitude, s.longitude, v_order_lat, v_order_lng) ASC) AS rn
FROM public.ml_delivery_staff s
WHERE s.station_id::TEXT = v_order.dispatch_station_id
AND s.online_status = 'online'
AND s.latitude IS NOT NULL
AND s.longitude IS NOT NULL
AND (
v_order.required_qualification_code IS NULL
OR EXISTS (
SELECT 1
FROM public.hc_worker_qualifications q
WHERE q.staff_id::TEXT = s.id::TEXT
AND q.qualification_code = v_order.required_qualification_code
AND q.deleted_at IS NULL
AND q.status::TEXT IN ('1', 'active', 'approved', 'valid')
AND (q.valid_from IS NULL OR q.valid_from <= v_now)
AND (q.valid_until IS NULL OR q.valid_until >= v_now)
)
)
AND distance_calc.distance_km(s.latitude, s.longitude, v_order_lat, v_order_lng) <= COALESCE(s.dispatch_radius_km, 20)
AND NOT EXISTS (
SELECT 1
FROM public.hss_service_assignments sa
WHERE sa.staff_id = s.id
AND sa.status IN ('assigned', 'accepted', 'in_progress')
AND sa.deleted_at IS NULL
AND sa.start_time <= v_now
AND sa.end_time > v_now
)
) AS ranked_candidates
WHERE rn = 1
LIMIT 1;
ELSE
SELECT * INTO v_assignment
FROM (
SELECT
s.id AS staff_id,
s.staff_name,
s.online_status,
s.station_id,
s.latitude AS staff_lat,
s.longitude AS staff_lng,
distance_calc.distance_km(s.latitude, s.longitude, v_order_lat, v_order_lng) AS distance_km,
ROW_NUMBER() OVER (ORDER BY distance_calc.distance_km(s.latitude, s.longitude, v_order_lat, v_order_lng) ASC) AS rn
FROM public.ml_delivery_staff s
WHERE s.online_status = 'online'
AND s.latitude IS NOT NULL
AND s.longitude IS NOT NULL
AND (
v_order.dispatch_station_id IS NULL
OR s.station_id::TEXT = v_order.dispatch_station_id
)
AND (
v_order.required_qualification_code IS NULL
OR EXISTS (
SELECT 1
FROM public.hc_worker_qualifications q
WHERE q.staff_id::TEXT = s.id::TEXT
AND q.qualification_code = v_order.required_qualification_code
AND q.deleted_at IS NULL
AND q.status::TEXT IN ('1', 'active', 'approved', 'valid')
AND (q.valid_from IS NULL OR q.valid_from <= v_now)
AND (q.valid_until IS NULL OR q.valid_until >= v_now)
)
)
AND distance_calc.distance_km(s.latitude, s.longitude, v_order_lat, v_order_lng) <= COALESCE(s.dispatch_radius_km, 20)
AND NOT EXISTS (
SELECT 1
FROM public.hss_service_assignments sa
WHERE sa.staff_id = s.id
AND sa.status IN ('assigned', 'accepted', 'in_progress')
AND sa.deleted_at IS NULL
AND sa.start_time <= v_now
AND sa.end_time > v_now
)
) AS ranked_candidates
WHERE rn = 1
LIMIT 1;
END IF;
IF FOUND AND v_assignment.staff_id IS NOT NULL THEN
v_staff_id := v_assignment.staff_id;
v_assignment_id := 'asgn-' || floor(extract(epoch FROM v_now) * 1000)::BIGINT::TEXT || '-' || upper(substr(md5(p_order_id || ':' || v_staff_id::TEXT), 1, 10));
INSERT INTO public.hss_service_assignments (
id, order_id, staff_id, status, assigned_at, start_time, end_time, created_at
) VALUES (
v_assignment_id, p_order_id, v_staff_id, 'assigned', v_now, v_now, v_now + INTERVAL '2 hours', v_now
);
UPDATE public.hss_service_orders
SET dispatch_status = 'assigned',
current_staff_id = v_staff_id,
assigned_at = v_now,
updated_at = v_now
WHERE id = p_order_id;
v_status_log_id := 'slg-' || floor(extract(epoch FROM v_now) * 1000)::BIGINT::TEXT || '-' || upper(substr(md5(p_order_id || ':assigned'), 1, 10));
INSERT INTO public.hss_service_order_status_logs (
id, order_id, from_status, to_status, operator_role, operator_id, remark, created_at
) VALUES (
v_status_log_id, p_order_id, 'created', 'assigned', 'system', v_current_user_id, '', v_now
);
v_attempt_log_id := 'dalog-' || floor(extract(epoch FROM v_now) * 1000)::BIGINT::TEXT || '-' || upper(substr(md5(p_order_id || ':attempt'), 1, 10));
INSERT INTO public.hss_service_dispatch_attempt_logs (
id, order_id, requested_by_user_id, selected_staff_id, selected_station_id, success, assigned_at, created_at
) VALUES (
v_attempt_log_id, p_order_id, v_current_user_id, v_staff_id, v_assignment.station_id::TEXT, TRUE, v_now, v_now
);
RETURN jsonb_build_object(
'success', TRUE,
'code', 'DISPATCH_ASSIGNED',
'message', '?,
'display_type', 'none',
'retryable', FALSE,
'dispatch_status', 'assigned',
'order_id', p_order_id,
'assignment_id', v_assignment_id,
'staff_name', v_assignment.staff_name,
'distance_km', v_assignment.distance_km
);
END IF;
v_failure_code := 'NO_ONLINE_STAFF';
v_failure_message := '鏆傛棤鍦ㄧ嚎鏈嶅姟浜哄憳锛岃绋嶅悗閲嶈瘯';
v_retryable := TRUE;
IF NOT EXISTS (
SELECT 1 FROM public.ml_delivery_staff
WHERE online_status = 'online'
AND deleted_at IS NULL
AND latitude IS NOT NULL
AND longitude IS NOT NULL
) THEN
v_failure_code := 'NO_ONLINE_STAFF';
v_failure_message := '鏆傛棤鍦ㄧ嚎浜哄憳锛岃绋嶅悗閲嶈瘯鎴栬仈绯诲鏈?;
ELSIF v_order.dispatch_station_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM public.ml_delivery_staff s
WHERE s.station_id::TEXT = v_order.dispatch_station_id
AND s.online_status = 'online'
AND s.deleted_at IS NULL
) THEN
v_failure_code := 'NO_STAFF_IN_SERVICE_STATION';
v_failure_message := '?;
ELSIF v_order.required_qualification_code IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM public.hc_worker_qualifications q
WHERE q.qualification_code = v_order.required_qualification_code
AND q.deleted_at IS NULL
AND q.status::TEXT IN ('1', 'active', 'approved', 'valid')
AND (q.valid_from IS NULL OR q.valid_from <= v_now)
AND (q.valid_until IS NULL OR q.valid_until >= v_now)
) THEN
v_failure_code := 'NO_QUALIFIED_STAFF';
v_failure_message := '鏆傛棤鍏峰璇ヨ祫璐ㄧ殑鏈嶅姟浜哄憳锛岃绋嶅悗閲嶈瘯鎴栬仈绯诲鏈?;
ELSIF NOT EXISTS (
SELECT 1 FROM public.ml_delivery_staff s
WHERE s.online_status = 'online'
AND s.latitude IS NOT NULL
AND s.longitude IS NOT NULL
AND distance_calc.distance_km(s.latitude, s.longitude, v_order_lat, v_order_lng) <= COALESCE(s.dispatch_radius_km, 20)
) THEN
v_failure_code := 'NO_NEARBY_STAFF';
v_failure_message := '';
ELSIF EXISTS (
SELECT 1 FROM public.ml_delivery_staff s
WHERE s.online_status = 'online'
AND s.latitude IS NOT NULL
AND s.longitude IS NOT NULL
AND distance_calc.distance_km(s.latitude, s.longitude, v_order_lat, v_order_lng) <= COALESCE(s.dispatch_radius_km, 20)
AND EXISTS (
SELECT 1 FROM public.hss_service_assignments sa
WHERE sa.staff_id = s.id
AND sa.status IN ('assigned', 'accepted', 'in_progress')
AND sa.deleted_at IS NULL
AND sa.start_time <= v_now
AND sa.end_time > v_now
)
) THEN
v_failure_code := 'ALL_ELIGIBLE_STAFF_BUSY';
v_failure_message := '';
END IF;
UPDATE public.hss_service_orders
SET dispatch_status = 'failed',
dispatch_error_code = v_failure_code,
dispatch_error_message = v_failure_message,
dispatch_failed_at = v_now,
updated_at = v_now
WHERE id = p_order_id;
v_attempt_log_id := 'dalog-' || floor(extract(epoch FROM v_now) * 1000)::BIGINT::TEXT || '-' || upper(substr(md5(p_order_id || ':failed'), 1, 10));
INSERT INTO public.hss_service_dispatch_attempt_logs (
id, order_id, requested_by_user_id, selected_staff_id, selected_station_id, success, failure_code, failure_message, retryable, created_at
) VALUES (
v_attempt_log_id, p_order_id, v_current_user_id, NULL, NULL, FALSE, v_failure_code, v_failure_message, v_retryable, v_now
);
RETURN jsonb_build_object(
'success', FALSE,
'code', v_failure_code,
'message', v_failure_message,
'display_type', 'modal',
'retryable', v_retryable,
'dispatch_status', 'failed',
'order_id', p_order_id
);
END;
$$;
COMMENT ON FUNCTION public.rpc_homecare_auto_dispatch_optimized IS '¤PC - perator_role瀛楁?;