mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-06 17:37:47 +08:00
Add dashboard and overview analytics, health monitoring, provider expense tracking, and announcement updates across the gateway and frontend. Keep schema migrations free of historical backfills while preserving automatic backfill execution. Bound migration deadlines, run schema preparation before Compose replacement, and anonymize deleted dashboard users. Include the current documentation cleanup and regression coverage.
98 lines
3.4 KiB
TypeScript
98 lines
3.4 KiB
TypeScript
import client from './client'
|
|
import type { OverviewRange } from './overview'
|
|
|
|
export type ProviderExpenseKind = 'recharge' | 'subscription' | 'other'
|
|
export interface ProviderExpense {
|
|
id: string
|
|
provider_id: string
|
|
provider_name: string
|
|
kind: ProviderExpenseKind
|
|
amount: string
|
|
currency: string
|
|
paid_at: string
|
|
period_start: string | null
|
|
period_end: string | null
|
|
note: string | null
|
|
external_reference: string | null
|
|
status: 'recorded' | 'void'
|
|
created_at: string
|
|
created_by: string | null
|
|
voided_at: string | null
|
|
}
|
|
export interface ProviderExpenseInput {
|
|
client_request_id: string
|
|
provider_id: string
|
|
kind: ProviderExpenseKind
|
|
amount: string
|
|
currency: string
|
|
paid_at: string
|
|
period_start?: string | null
|
|
period_end?: string | null
|
|
note?: string | null
|
|
external_reference?: string | null
|
|
}
|
|
export interface ProviderExpenseTotals {
|
|
currency: string
|
|
amount: string
|
|
entry_count: number
|
|
recharge_amount: string
|
|
subscription_amount: string
|
|
other_amount: string
|
|
}
|
|
export interface ProviderExpenses {
|
|
items: ProviderExpense[]
|
|
total: number
|
|
limit: number
|
|
offset: number
|
|
totals: ProviderExpenseTotals[]
|
|
providers: { provider_id: string; provider_name: string; currency: string; amount: string; entry_count: number }[]
|
|
}
|
|
export interface ProviderAccountSubscription {
|
|
group_name: string | null
|
|
status: string | null
|
|
daily_used_usd: number | null
|
|
daily_limit_usd: number | null
|
|
weekly_used_usd: number | null
|
|
weekly_limit_usd: number | null
|
|
monthly_used_usd: number | null
|
|
monthly_limit_usd: number | null
|
|
expires_at: string | null
|
|
}
|
|
export interface ProviderAccount {
|
|
provider_id: string
|
|
provider_name: string
|
|
is_active: boolean
|
|
billing_type: string | null
|
|
quota: { limit: number | string | null; used: number | string | null; remaining: number | string | null; currency: string; period_start: string | null; expires_at: string | null } | null
|
|
balance: {
|
|
status: string
|
|
observed_at: string | null
|
|
currency: string | null
|
|
available: number | string | null
|
|
used: number | string | null
|
|
granted: number | string | null
|
|
plan_name: string | null
|
|
subscriptions: ProviderAccountSubscription[]
|
|
} | null
|
|
}
|
|
export interface ProviderAccounts { observed_at: string; items: ProviderAccount[] }
|
|
export type ProviderExpensesQuery = OverviewRange & { limit?: number; offset?: number }
|
|
const base = '/api/admin/billing'
|
|
export const providerFinanceApi = {
|
|
async accounts(signal?: AbortSignal): Promise<ProviderAccounts> {
|
|
return (await client.get<ProviderAccounts>(`${base}/provider-accounts`, { signal })).data
|
|
},
|
|
async expenses(params: ProviderExpensesQuery, signal?: AbortSignal): Promise<ProviderExpenses> {
|
|
return (await client.get<ProviderExpenses>(`${base}/provider-expenses`, { params, signal })).data
|
|
},
|
|
async record(input: ProviderExpenseInput): Promise<{ item: ProviderExpense }> {
|
|
return (await client.post<{ item: ProviderExpense }>(`${base}/provider-expenses`, input)).data
|
|
},
|
|
async void(id: string): Promise<{ item: ProviderExpense }> {
|
|
return (await client.post<{ item: ProviderExpense }>(`${base}/provider-expenses/${encodeURIComponent(id)}/void`, {})).data
|
|
},
|
|
async exportExpenses(range: OverviewRange, signal?: AbortSignal): Promise<Blob> {
|
|
return (await client.get<Blob>(`${base}/provider-expenses`, { params: { ...range, format: 'csv' }, responseType: 'blob', signal })).data
|
|
},
|
|
}
|