admin接入数据库

This commit is contained in:
comlibmb
2026-02-16 15:19:17 +08:00
parent e648ff0c22
commit 5acda05134
18 changed files with 1736 additions and 470 deletions

View File

@@ -0,0 +1,31 @@
-- RPC: rpc_admin_delete_agent
-- 管理端删除代理商
CREATE OR REPLACE FUNCTION public.rpc_admin_delete_agent(
p_uid uuid
)
RETURNS boolean
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_ok boolean;
BEGIN
-- 仅管理员可操作
IF NOT EXISTS (
SELECT 1 FROM public.ak_users u
WHERE u.id = auth.uid() AND u.role = 'admin'
) THEN
RAISE EXCEPTION 'permission denied';
END IF;
DELETE FROM public.ak_distribution_agents WHERE uid = p_uid;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
REVOKE ALL ON FUNCTION public.rpc_admin_delete_agent(uuid) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_delete_agent(uuid) TO authenticated;

View File

@@ -0,0 +1,38 @@
-- RPC: rpc_admin_delete_division
-- 管理端删除事业部
CREATE OR REPLACE FUNCTION public.rpc_admin_delete_division(
p_uid uuid
)
RETURNS boolean
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_ok boolean;
BEGIN
-- 仅管理员可操作
IF NOT EXISTS (
SELECT 1 FROM public.ak_users u
WHERE u.id = auth.uid() AND u.role = 'admin'
) THEN
RAISE EXCEPTION 'permission denied';
END IF;
-- 检查是否有关联代理商
IF EXISTS (
SELECT 1 FROM public.ak_distribution_agents WHERE division_uid = p_uid
) THEN
RAISE EXCEPTION 'cannot delete division with associated agents';
END IF;
DELETE FROM public.ak_distribution_divisions WHERE uid = p_uid;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
REVOKE ALL ON FUNCTION public.rpc_admin_delete_division(uuid) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_delete_division(uuid) TO authenticated;

View File

@@ -0,0 +1,68 @@
-- RPC: rpc_admin_get_agent_apply_list
-- 管理端获取代理商申请列表
-- 支持按状态过滤all, pending, approved, rejected
CREATE OR REPLACE FUNCTION public.rpc_admin_get_agent_apply_list(
p_status text DEFAULT 'all',
p_search text DEFAULT NULL,
p_page integer DEFAULT 1,
p_page_size integer DEFAULT 20
)
RETURNS TABLE (
id uuid,
uid uuid,
name text,
phone text,
dept_uid uuid,
dept_name text,
proof_images jsonb,
status text,
refusal_reason text,
time timestamptz,
invite_code text
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_page integer := GREATEST(1, COALESCE(p_page, 1));
v_page_size integer := LEAST(200, GREATEST(1, COALESCE(p_page_size, 20)));
v_offset integer := (v_page - 1) * v_page_size;
BEGIN
-- 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users u
WHERE u.id = auth.uid() AND u.role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'permission denied';
END IF;
RETURN QUERY
SELECT
a.id,
a.uid,
a.agent_name AS name,
a.agent_phone AS phone,
a.division_uid AS dept_uid,
d.name AS dept_name,
a.proof_images,
a.status,
a.refusal_reason,
a.created_at AS time,
d.invite_code
FROM public.ak_distribution_agent_applications a
JOIN public.ak_distribution_divisions d ON d.uid = a.division_uid
WHERE (p_status = 'all' OR a.status = p_status)
AND (
p_search IS NULL OR p_search = ''
OR a.agent_name ILIKE ('%' || p_search || '%')
OR a.uid::text ILIKE ('%' || p_search || '%')
)
ORDER BY a.created_at DESC
LIMIT v_page_size OFFSET v_offset;
END;
$$;
REVOKE ALL ON FUNCTION public.rpc_admin_get_agent_apply_list(text, text, integer, integer) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_agent_apply_list(text, text, integer, integer) TO authenticated;

View File

@@ -0,0 +1,62 @@
-- RPC: rpc_admin_get_agent_list
-- 管理端获取代理商列表
-- 支持搜索代理商名称或负责人UID并关联显示所属事业部信息
CREATE OR REPLACE FUNCTION public.rpc_admin_get_agent_list(
p_search text DEFAULT NULL,
p_page integer DEFAULT 1,
p_page_size integer DEFAULT 20
)
RETURNS TABLE (
uid uuid,
name text,
division_uid uuid,
division_name text,
commission_ratio numeric,
is_enabled boolean,
end_time timestamptz,
created_at timestamptz,
"staffCount" bigint
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_page integer := GREATEST(1, COALESCE(p_page, 1));
v_page_size integer := LEAST(200, GREATEST(1, COALESCE(p_page_size, 20)));
v_offset integer := (v_page - 1) * v_page_size;
BEGIN
-- 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users u
WHERE u.id = auth.uid() AND u.role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'permission denied';
END IF;
RETURN QUERY
SELECT
a.uid,
a.name,
a.division_uid,
d.name AS division_name,
a.commission_ratio,
a.is_enabled,
a.end_time,
a.created_at,
(SELECT COUNT(*) FROM public.ak_promoter_relations r WHERE r.inviter_uid = a.uid)::bigint AS "staffCount"
FROM public.ak_distribution_agents a
JOIN public.ak_distribution_divisions d ON d.uid = a.division_uid
WHERE (
p_search IS NULL OR p_search = ''
OR a.name ILIKE ('%' || p_search || '%')
OR a.uid::text ILIKE ('%' || p_search || '%')
)
ORDER BY a.created_at DESC
LIMIT v_page_size OFFSET v_offset;
END;
$$;
REVOKE ALL ON FUNCTION public.rpc_admin_get_agent_list(text, integer, integer) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_agent_list(text, integer, integer) TO authenticated;

View File

@@ -0,0 +1,59 @@
-- RPC: rpc_admin_get_division_list
-- 管理端获取事业部列表
-- 支持搜索事业部名称或负责人UID
CREATE OR REPLACE FUNCTION public.rpc_admin_get_division_list(
p_search text DEFAULT NULL,
p_page integer DEFAULT 1,
p_page_size integer DEFAULT 20
)
RETURNS TABLE (
uid uuid,
name text,
invite_code text,
commission_ratio numeric,
is_enabled boolean,
end_time timestamptz,
created_at timestamptz,
"agentCount" bigint
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_page integer := GREATEST(1, COALESCE(p_page, 1));
v_page_size integer := LEAST(200, GREATEST(1, COALESCE(p_page_size, 20)));
v_offset integer := (v_page - 1) * v_page_size;
BEGIN
-- 仅管理员或分析员可调用
IF NOT EXISTS (
SELECT 1 FROM public.ak_users u
WHERE u.id = auth.uid() AND u.role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'permission denied';
END IF;
RETURN QUERY
SELECT
d.uid,
d.name,
d.invite_code,
d.commission_ratio,
d.is_enabled,
d.end_time,
d.created_at,
(SELECT COUNT(*) FROM public.ak_distribution_agents a WHERE a.division_uid = d.uid)::bigint AS "agentCount"
FROM public.ak_distribution_divisions d
WHERE (
p_search IS NULL OR p_search = ''
OR d.name ILIKE ('%' || p_search || '%')
OR d.uid::text ILIKE ('%' || p_search || '%')
)
ORDER BY d.created_at DESC
LIMIT v_page_size OFFSET v_offset;
END;
$$;
REVOKE ALL ON FUNCTION public.rpc_admin_get_division_list(text, integer, integer) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_division_list(text, integer, integer) TO authenticated;

View File

@@ -0,0 +1,69 @@
-- RPC: rpc_admin_process_agent_apply
-- 管理端审核代理商申请
-- 若通过(approved),则同步在 ak_distribution_agents 中创建或更新记录
CREATE OR REPLACE FUNCTION public.rpc_admin_process_agent_apply(
p_id uuid,
p_status text, -- approved / rejected
p_refusal_reason text DEFAULT NULL
)
RETURNS boolean
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_uid uuid;
v_division_uid uuid;
v_agent_name text;
BEGIN
-- 仅管理员可审核
IF NOT EXISTS (
SELECT 1 FROM public.ak_users u
WHERE u.id = auth.uid() AND u.role = 'admin'
) THEN
RAISE EXCEPTION 'permission denied';
END IF;
-- 1. 获取并锁定申请记录
SELECT uid, division_uid, agent_name
INTO v_uid, v_division_uid, v_agent_name
FROM public.ak_distribution_agent_applications
WHERE id = p_id;
IF v_uid IS NULL THEN
RAISE EXCEPTION 'application record not found';
END IF;
-- 2. 更新申请状态
UPDATE public.ak_distribution_agent_applications
SET
status = p_status,
refusal_reason = CASE WHEN p_status = 'rejected' THEN p_refusal_reason ELSE NULL END,
approved_at = now(),
approved_by = auth.uid(),
updated_at = now()
WHERE id = p_id;
-- 3. 如果通过,则同步到代理商正式表
IF p_status = 'approved' THEN
INSERT INTO public.ak_distribution_agents (
uid, division_uid, name, commission_ratio, is_enabled, updated_at, updated_by
)
VALUES (
v_uid, v_division_uid, v_agent_name, 0, true, now(), auth.uid()
)
ON CONFLICT (uid) DO UPDATE
SET
division_uid = EXCLUDED.division_uid,
name = EXCLUDED.name,
updated_at = now(),
updated_by = auth.uid();
END IF;
RETURN true;
END;
$$;
REVOKE ALL ON FUNCTION public.rpc_admin_process_agent_apply(uuid, text, text) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_process_agent_apply(uuid, text, text) TO authenticated;

View File

@@ -0,0 +1,54 @@
-- RPC: rpc_admin_save_agent
-- 管理端新增或更新代理商
CREATE OR REPLACE FUNCTION public.rpc_admin_save_agent(
p_uid uuid,
p_division_uid uuid,
p_name text,
p_commission_ratio numeric,
p_is_enabled boolean DEFAULT true,
p_end_time timestamptz DEFAULT NULL
)
RETURNS uuid
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
-- 仅管理员可操作
IF NOT EXISTS (
SELECT 1 FROM public.ak_users u
WHERE u.id = auth.uid() AND u.role = 'admin'
) THEN
RAISE EXCEPTION 'permission denied';
END IF;
-- 确保事业部存在
IF NOT EXISTS (
SELECT 1 FROM public.ak_distribution_divisions WHERE uid = p_division_uid
) THEN
RAISE EXCEPTION 'parent division not found';
END IF;
INSERT INTO public.ak_distribution_agents (
uid, division_uid, name, commission_ratio, is_enabled, end_time, updated_at, updated_by
)
VALUES (
p_uid, p_division_uid, p_name, p_commission_ratio, p_is_enabled, p_end_time, now(), auth.uid()
)
ON CONFLICT (uid) DO UPDATE
SET
division_uid = EXCLUDED.division_uid,
name = EXCLUDED.name,
commission_ratio = EXCLUDED.commission_ratio,
is_enabled = EXCLUDED.is_enabled,
end_time = EXCLUDED.end_time,
updated_at = now(),
updated_by = auth.uid();
RETURN p_uid;
END;
$$;
REVOKE ALL ON FUNCTION public.rpc_admin_save_agent(uuid, uuid, text, numeric, boolean, timestamptz) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_save_agent(uuid, uuid, text, numeric, boolean, timestamptz) TO authenticated;

View File

@@ -0,0 +1,47 @@
-- RPC: rpc_admin_save_division
-- 管理端新增或更新事业部
CREATE OR REPLACE FUNCTION public.rpc_admin_save_division(
p_uid uuid,
p_name text,
p_invite_code text,
p_commission_ratio numeric,
p_is_enabled boolean DEFAULT true,
p_end_time timestamptz DEFAULT NULL
)
RETURNS uuid
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
-- 仅管理员可操作
IF NOT EXISTS (
SELECT 1 FROM public.ak_users u
WHERE u.id = auth.uid() AND u.role = 'admin'
) THEN
RAISE EXCEPTION 'permission denied';
END IF;
INSERT INTO public.ak_distribution_divisions (
uid, name, invite_code, commission_ratio, is_enabled, end_time, updated_at, updated_by
)
VALUES (
p_uid, p_name, p_invite_code, p_commission_ratio, p_is_enabled, p_end_time, now(), auth.uid()
)
ON CONFLICT (uid) DO UPDATE
SET
name = EXCLUDED.name,
invite_code = EXCLUDED.invite_code,
commission_ratio = EXCLUDED.commission_ratio,
is_enabled = EXCLUDED.is_enabled,
end_time = EXCLUDED.end_time,
updated_at = now(),
updated_by = auth.uid();
RETURN p_uid;
END;
$$;
REVOKE ALL ON FUNCTION public.rpc_admin_save_division(uuid, text, text, numeric, boolean, timestamptz) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_save_division(uuid, text, text, numeric, boolean, timestamptz) TO authenticated;