import type { RowDataPacket } from 'mysql2' import { db, DB } from './db' import { buildConcept } from './tx-concept' /** Una transacción de pago (Stripe o SumUp) registrada en stripelog. */ export interface PaymentTx { id: string // referencia de la pasarela (session_id / checkout_reference) platform: 'Stripe' | 'SumUp' status: 'PAID' | 'PENDING' createdAt: Date amount: number // importe en € // Concepto traducible (clave + args) con reserva de texto libre. conceptKey: string | null conceptArgs: Record conceptRaw: string } /** * Transacciones de pago de una cuenta desde `stripelog`, limitadas a las * dos pasarelas activas: **Stripe** (mode test/live) y **SumUp** (mode sumup). * `fulfilled` 1 -> PAID (pagado y entregado), 0 -> PENDING. Orden por fecha desc. */ export async function getPaymentTransactions(accountId: number, limit = 200): Promise { if (!accountId) return [] try { const [rows] = await db(DB.default).query( 'SELECT session_id, product_name, character_name, amount, mode, service, metadata, fulfilled, timestamp FROM stripelog ' + "WHERE account_id = ? AND mode IN ('sumup', 'test', 'live') ORDER BY timestamp DESC LIMIT ?", [accountId, limit], ) return rows.map((r) => { const c = buildConcept( String(r.product_name || '—'), r.service ? String(r.service) : null, String(r.character_name || ''), r.metadata ? String(r.metadata) : null, ) return { id: String(r.session_id || ''), platform: r.mode === 'sumup' ? 'SumUp' : 'Stripe', status: r.fulfilled ? 'PAID' : 'PENDING', createdAt: new Date(r.timestamp), amount: Number(r.amount), conceptKey: c.conceptKey, conceptArgs: c.conceptArgs, conceptRaw: c.conceptRaw, } }) } catch { return [] } }