import * as v from 'valibot' export const VisualGameAdminBillingActionPolicy = v.object({ action: v.string(), points: v.number(), period_kind: v.picklist(['daily', 'none']), timezone: v.nullable(v.string()), enabled: v.boolean(), updated_by: v.nullable(v.string()), }) export const VisualGameAdminBillingProduct = v.object({ id: v.string(), kind: v.literal('points_pack'), title: v.string(), points: v.number(), paid_points: v.number(), bonus_points: v.number(), price_cents: v.number(), price_usd: v.number(), currency: v.string(), stripe_price_id: v.nullable(v.string()), active: v.boolean(), }) export const VisualGameAdminBillingOrder = v.object({ id: v.string(), user_id: v.string(), product_id: v.string(), provider: v.string(), status: v.picklist(['pending', 'paid', 'canceled', 'failed', 'refunded', 'disputed']), amount_cents: v.number(), currency: v.string(), paid_points: v.number(), bonus_points: v.number(), total_points: v.number(), points_reversed: v.number(), reversal_shortfall_points: v.number(), created_at: v.string(), }) export const VisualGameAdminBillingReference = v.object({ label: v.string(), href: v.string(), }) export const VisualGameAdminBillingLedgerEntry = v.object({ id: v.string(), user_id: v.string(), type: v.picklist(['grant', 'deduct']), amount: v.number(), balance_after: v.number(), source: v.string(), credit_kind: v.nullable(v.string()), reason: v.string(), ref_type: v.nullable(v.string()), ref_id: v.nullable(v.string()), note: v.nullable(v.string()), failure_code: v.nullable(v.string()), reference: v.nullable(VisualGameAdminBillingReference), created_at: v.string(), }) export const VisualGameAdminBillingPolicyList = v.object({ items: v.array(VisualGameAdminBillingActionPolicy), }) export const VisualGameAdminBillingProductList = v.object({ items: v.array(VisualGameAdminBillingProduct), }) export const VisualGameAdminBillingOrderPage = v.object({ items: v.array(VisualGameAdminBillingOrder), next_cursor: v.nullable(v.string()), }) export const VisualGameAdminBillingLedgerPage = v.object({ items: v.array(VisualGameAdminBillingLedgerEntry), next_cursor: v.nullable(v.string()), }) export const VisualGameAdminBillingDashboardDay = v.object({ date: v.string(), start_at: v.string(), end_at: v.string(), revenue_cents: v.number(), paid_orders: v.number(), refund_orders: v.number(), points_granted: v.number(), points_spent: v.number(), }) export const VisualGameAdminBillingDashboardProduct = v.object({ product_id: v.string(), title: v.nullable(v.string()), orders: v.number(), revenue_cents: v.number(), points: v.number(), }) /** 消耗按 reason + 业务类型分块:model_usage 这种按调用计费的流水靠 ref_type 才分得出 LLM / 语音 / 图片。 */ export const VisualGameAdminBillingDashboardSpend = v.object({ reason: v.string(), ref_type: v.nullable(v.string()), points: v.number(), }) /** 商业化看板:一个时间窗内的收入、积分、转化、风控汇总 + 按自然日的序列。比率分母为 0 时给 null。 */ export const VisualGameAdminBillingDashboard = v.object({ since: v.string(), until: v.string(), start_at: v.string(), end_at: v.string(), timezone: v.string(), generated_at: v.string(), revenue: v.object({ gross_cents: v.number(), refund_cents: v.number(), net_cents: v.number(), paid_orders: v.number(), paying_users: v.number(), first_time_buyers: v.number(), }), points: v.object({ purchased_paid: v.number(), purchased_bonus: v.number(), daily_claim: v.number(), signup_reward: v.number(), admin_grant: v.number(), turn_spent: v.number(), video_spent: v.number(), other_spent: v.number(), turn_refunded: v.number(), video_refunded: v.number(), }), conversion: v.object({ new_users: v.number(), new_users_paid: v.number(), signup_to_paid_rate: v.nullable(v.number()), claim_users: v.number(), active_users: v.number(), claim_rate: v.nullable(v.number()), }), risk: v.object({ refunded_orders: v.number(), disputed_orders: v.number(), refund_rate: v.nullable(v.number()), dispute_rate: v.nullable(v.number()), turn_refunds: v.number(), video_refunds: v.number(), shortfall_orders: v.number(), shortfall_points: v.number(), }), daily: v.array(VisualGameAdminBillingDashboardDay), products: v.array(VisualGameAdminBillingDashboardProduct), spend_mix: v.array(VisualGameAdminBillingDashboardSpend), })