mall数据库文件
This commit is contained in:
127
services/analytics/salesReportService.uts
Normal file
127
services/analytics/salesReportService.uts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { computeDateRange, toDateOnly } from './dateRange.uts'
|
||||
import { rpcOrEmptyArray, rpcOrNull } from './rpc.uts'
|
||||
|
||||
export type TrendData = { x: Array<string>; gmv: Array<number>; orders: Array<number> }
|
||||
|
||||
export type SalesKpis = {
|
||||
gmv: number
|
||||
gmv_growth: number
|
||||
orders: number
|
||||
order_growth: number
|
||||
conversion_rate: number
|
||||
conversion_growth: number
|
||||
avg_order_amount: number
|
||||
avg_order_growth: number
|
||||
}
|
||||
|
||||
export type ProductRank = { id: string; rank: number; name: string; sales: number }
|
||||
export type MerchantRank = { id: string; rank: number; name: string; sales: number; growth: number }
|
||||
|
||||
function safeNumber(v: any): number {
|
||||
const n = Number(v)
|
||||
return isFinite(n) ? n : 0
|
||||
}
|
||||
|
||||
export async function fetchSalesKpis(period: string): Promise<SalesKpis> {
|
||||
const { startIso, endIso } = computeDateRange(period)
|
||||
const days = period === '7d' ? 7 : period === '30d' ? 30 : period === '90d' ? 90 : 365
|
||||
|
||||
const startDateObj = new Date(startIso)
|
||||
const endDateObj = new Date(endIso)
|
||||
|
||||
const periodStart = new Date(startDateObj.getFullYear(), startDateObj.getMonth(), startDateObj.getDate())
|
||||
const periodEnd = new Date(endDateObj.getFullYear(), endDateObj.getMonth(), endDateObj.getDate() + 1)
|
||||
const prevStart = new Date(periodStart.getTime() - days * 24 * 60 * 60 * 1000)
|
||||
const prevEnd = new Date(periodStart.getTime())
|
||||
|
||||
const row = await rpcOrNull('rpc_analytics_realtime_kpis', {
|
||||
p_start: periodStart.toISOString(),
|
||||
p_end: periodEnd.toISOString(),
|
||||
p_compare_start: prevStart.toISOString(),
|
||||
p_compare_end: prevEnd.toISOString(),
|
||||
p_merchant_id: null
|
||||
} as any)
|
||||
|
||||
const obj: any = row != null ? row : ({} as any)
|
||||
const gmv = safeNumber(obj.getAny?.('gmv') ?? 0)
|
||||
const orders = safeNumber(obj.getAny?.('orders') ?? 0)
|
||||
const avgOrder = orders > 0 ? gmv / orders : 0
|
||||
|
||||
return {
|
||||
gmv: Math.round(gmv),
|
||||
gmv_growth: safeNumber(obj.getAny?.('gmv_growth') ?? 0),
|
||||
orders: Math.round(orders),
|
||||
order_growth: safeNumber(obj.getAny?.('order_growth') ?? 0),
|
||||
conversion_rate: safeNumber(obj.getAny?.('conversion_rate') ?? 0),
|
||||
conversion_growth: safeNumber(obj.getAny?.('conversion_growth') ?? 0),
|
||||
avg_order_amount: avgOrder,
|
||||
avg_order_growth: safeNumber(obj.getAny?.('avg_order_growth') ?? obj.getAny?.('gmv_growth') ?? 0)
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchSalesTrend(period: string): Promise<TrendData> {
|
||||
const { startIso, endIso } = computeDateRange(period)
|
||||
const rows = await rpcOrEmptyArray('rpc_analytics_trend_data', {
|
||||
p_start_date: toDateOnly(startIso),
|
||||
p_end_date: toDateOnly(endIso),
|
||||
p_merchant_id: null
|
||||
} as any)
|
||||
|
||||
const x: Array<string> = []
|
||||
const gmvArr: Array<number> = []
|
||||
const orderArr: Array<number> = []
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
const r: any = rows[i]
|
||||
const d = `${r.getAny?.('date') ?? ''}`
|
||||
x.push(d.length >= 10 ? d.slice(5) : d)
|
||||
gmvArr.push(safeNumber(r.getAny?.('gmv') ?? 0))
|
||||
orderArr.push(safeNumber(r.getAny?.('orders') ?? 0))
|
||||
}
|
||||
|
||||
return { x, gmv: gmvArr, orders: orderArr }
|
||||
}
|
||||
|
||||
export async function fetchSalesTopProducts(period: string, limit: number = 50): Promise<Array<ProductRank>> {
|
||||
const { startIso, endIso } = computeDateRange(period)
|
||||
const rows = await rpcOrEmptyArray('rpc_analytics_top_products', {
|
||||
p_start_date: toDateOnly(startIso),
|
||||
p_end_date: toDateOnly(endIso),
|
||||
p_limit: limit,
|
||||
p_merchant_id: null
|
||||
} as any)
|
||||
|
||||
const list: Array<ProductRank> = []
|
||||
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)
|
||||
})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
export async function fetchSalesTopMerchants(period: string, limit: number = 50): Promise<Array<MerchantRank>> {
|
||||
const { startIso, endIso } = computeDateRange(period)
|
||||
const rows = await rpcOrEmptyArray('rpc_analytics_top_merchants', {
|
||||
p_start_date: toDateOnly(startIso),
|
||||
p_end_date: toDateOnly(endIso),
|
||||
p_limit: limit
|
||||
} as any)
|
||||
|
||||
const list: Array<MerchantRank> = []
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user