import { computeDateRange, toDateOnly } from './dateRange.uts' import { rpcOrEmptyArray, rpcOrNull } from './rpc.uts' export type ProductOverview = { total_products: number product_growth: number hot_products: number turnover_rate: number turnover_growth: number avg_stock: number stock_growth: number } export type ProductRank = { id: string; rank: number; name: string; sales: number; growth: number } export type ProductTrendRow = { date: string; gmv: number; qty: number; orders: number } function safeNumber(v: any): number { const n = Number(v) return isFinite(n) ? n : 0 } export async function fetchProductOverview(period: string, range?: { start: string; end: string } | null): Promise { let startIso: string; let endIso: string; if (range != null && range.start && range.end) { startIso = range.start; endIso = range.end; } else { const computedRange = computeDateRange(period) startIso = computedRange.startIso endIso = computedRange.endIso } const row = await rpcOrNull('rpc_product_insights_overview', { p_start: toDateOnly(startIso), p_end: toDateOnly(endIso) } as any) const obj: any = row != null ? row : ({} as any) return { total_products: safeNumber(obj.getAny?.('total_products') ?? 0), product_growth: safeNumber(obj.getAny?.('product_growth') ?? 0), hot_products: safeNumber(obj.getAny?.('hot_products') ?? 0), turnover_rate: safeNumber(obj.getAny?.('turnover_rate') ?? 0), turnover_growth: safeNumber(obj.getAny?.('turnover_growth') ?? 0), avg_stock: safeNumber(obj.getAny?.('avg_stock') ?? 0), stock_growth: safeNumber(obj.getAny?.('stock_growth') ?? 0) } } export async function fetchTopProducts(period: string, limit: number = 10, range?: { start: string; end: string } | null): Promise> { let startIso: string; let endIso: string; if (range != null && range.start && range.end) { startIso = range.start; endIso = range.end; } else { const computedRange = computeDateRange(period) startIso = computedRange.startIso endIso = computedRange.endIso } const rows = await rpcOrEmptyArray('rpc_analytics_top_products', { p_start_date: toDateOnly(startIso), p_end_date: toDateOnly(endIso), p_limit: limit } as any) const list: Array = [] for (let i = 0; i < rows.length; i++) { const r: any = rows[i] list.push({ id: `${r.getAny?.('id') ?? i}`, rank: i + 1, name: `${r.getAny?.('name') ?? '未知商品'}`, sales: safeNumber(r.getAny?.('sales') ?? 0), growth: safeNumber(r.getAny?.('growth') ?? 0) }) } return list } export async function fetchProductTrend(period: string, productId: string, range?: { start: string; end: string } | null): Promise> { let startIso: string; let endIso: string; if (range != null && range.start && range.end) { startIso = range.start; endIso = range.end; } else { const computedRange = computeDateRange(period) startIso = computedRange.startIso endIso = computedRange.endIso } const rows = await rpcOrEmptyArray('rpc_analytics_product_trend', { p_start_date: toDateOnly(startIso), p_end_date: toDateOnly(endIso), p_product_id: productId } as any) const out: Array = [] for (let i = 0; i < rows.length; i++) { const r: any = rows[i] const date = `${r.getAny?.('date') ?? ''}` out.push({ date, gmv: safeNumber(r.getAny?.('gmv') ?? 0), qty: safeNumber(r.getAny?.('qty') ?? 0), orders: safeNumber(r.getAny?.('orders') ?? 0) }) } return out } export async function fetchCategorySales(period: string, range?: { start: string; end: string } | null): Promise> { let startIso: string; let endIso: string; if (range != null && range.start && range.end) { startIso = range.start; endIso = range.end; } else { const computedRange = computeDateRange(period) startIso = computedRange.startIso endIso = computedRange.endIso } return await rpcOrEmptyArray('rpc_analytics_category_sales', { p_start_date: toDateOnly(startIso), p_end_date: toDateOnly(endIso) } as any) } export async function fetchStockInsights(period: string): Promise> { return await rpcOrEmptyArray('rpc_product_insights_stock', {} as any) } export async function fetchPriceTrend(period: string, range?: { start: string; end: string } | null): Promise> { let startIso: string; let endIso: string; if (range != null && range.start && range.end) { startIso = range.start; endIso = range.end; } else { const computedRange = computeDateRange(period) startIso = computedRange.startIso endIso = computedRange.endIso } return await rpcOrEmptyArray('rpc_analytics_price_trend', { p_start: startIso, p_end: endIso } as any) } export async function fetchReviewInsights(): Promise> { return await rpcOrEmptyArray('rpc_product_insights_reviews', {} as any) }