feat(admin): merge stash changes into comclib-analytics (order/finance/product + rpc sql)

This commit is contained in:
comlibmb
2026-02-10 18:49:21 +08:00
parent bf394eb65d
commit 80e5a1ddeb
23 changed files with 1599 additions and 143 deletions

View File

@@ -0,0 +1,46 @@
-- =====================================================================================
-- Admin 商品模块 - 删除分类 RPC
-- 位置docs/sql/30_rpc/product/
-- 对象类型RPC 函数SECURITY DEFINER
-- 方案:方案 1有子项禁止删除
-- 版本v1
-- 依赖ml_categories, ak_users 表已存在
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_category_delete(
p_id UUID
)
RETURNS BOOLEAN
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 检查是否有子分类 (方案 1)
IF EXISTS (
SELECT 1 FROM public.ml_categories WHERE parent_id = p_id
) THEN
RAISE EXCEPTION '请先删除该分类下的子分类';
END IF;
-- 3. 检查是否有商品关联 (可选,通常作为安全保障)
IF EXISTS (
SELECT 1 FROM public.ml_products WHERE category_id = p_id AND status != 4
) THEN
RAISE EXCEPTION '该分类下仍有商品,无法删除';
END IF;
-- 4. 执行删除
DELETE FROM public.ml_categories WHERE id = p_id;
RETURN FOUND;
END;
$$;

View File

@@ -0,0 +1,105 @@
-- =====================================================================================
-- Admin 商品模块 - 商品统计概况 RPC
-- 位置docs/sql/30_rpc/product/
-- 对象类型RPC 函数SECURITY DEFINER
-- 版本v1
-- 依赖ml_products, ml_orders, ml_browse_history, ak_users
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_product_stats(
p_start_time TIMESTAMP WITH TIME ZONE,
p_end_time TIMESTAMP WITH TIME ZONE
)
RETURNS JSONB
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_stats JSONB;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 统计核心指标
-- 商品浏览量 (PV), 访客数 (UV), 支付件数, 支付金额, 退款件数, 退款金额
WITH stats AS (
SELECT
(SELECT COALESCE(SUM(browse_duration), 0) FROM public.ml_browse_history WHERE created_at BETWEEN p_start_time AND p_end_time) as total_views,
(SELECT COUNT(DISTINCT user_id) FROM public.ml_browse_history WHERE created_at BETWEEN p_start_time AND p_end_time) as total_visitors,
(SELECT COALESCE(SUM(quantity), 0) FROM public.ml_order_items oi JOIN public.ml_orders o ON oi.order_id = o.id
WHERE o.created_at BETWEEN p_start_time AND p_end_time AND o.order_status NOT IN (1, 5)) as pay_count,
(SELECT COALESCE(SUM(paid_amount), 0) FROM public.ml_orders
WHERE created_at BETWEEN p_start_time AND p_end_time AND order_status NOT IN (1, 5)) as pay_amount,
(SELECT COUNT(*) FROM public.ml_orders WHERE created_at BETWEEN p_start_time AND p_end_time AND order_status = 7) as refund_count,
(SELECT COALESCE(SUM(total_amount), 0) FROM public.ml_orders WHERE created_at BETWEEN p_start_time AND p_end_time AND order_status = 7) as refund_amount
)
SELECT jsonb_build_object(
'views', total_views,
'visitors', total_visitors,
'pay_count', pay_count,
'pay_amount', pay_amount,
'refund_count', refund_count,
'refund_amount', refund_amount
) INTO v_stats FROM stats;
RETURN v_stats;
END;
$$;
-- =====================================================================================
-- Admin 商品模块 - 商品排行 RPC
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_product_ranking(
p_start_time TIMESTAMP WITH TIME ZONE,
p_end_time TIMESTAMP WITH TIME ZONE,
p_sort_by TEXT DEFAULT 'sales', -- views, sales, amount
p_limit INTEGER DEFAULT 10
)
RETURNS JSONB
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_items JSONB;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 获取排行数据
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
p.id,
p.name,
p.main_image_url as image,
COALESCE(p.view_count, 0) as views,
(SELECT COUNT(DISTINCT user_id) FROM public.ml_browse_history bh WHERE bh.product_id = p.id AND bh.created_at BETWEEN p_start_time AND p_end_time) as visitors,
(SELECT COALESCE(SUM(quantity), 0) FROM public.ml_order_items oi JOIN public.ml_orders o ON oi.order_id = o.id
WHERE oi.product_id = p.id AND o.created_at BETWEEN p_start_time AND p_end_time AND o.order_status NOT IN (1, 5)) as sales,
(SELECT COALESCE(SUM(oi.total_amount), 0) FROM public.ml_order_items oi JOIN public.ml_orders o ON oi.order_id = o.id
WHERE oi.product_id = p.id AND o.created_at BETWEEN p_start_time AND p_end_time AND o.order_status NOT IN (1, 5)) as amount
FROM public.ml_products p
WHERE p.status != 4
ORDER BY
CASE WHEN p_sort_by = 'views' THEN 4
WHEN p_sort_by = 'sales' THEN 6
WHEN p_sort_by = 'amount' THEN 7
ELSE 6 END DESC
LIMIT p_limit
) t;
RETURN COALESCE(v_items, '[]'::jsonb);
END;
$$;