import { randomUUID } from "node:crypto"; import { getPool } from "../db/pool"; function nowIso() { return new Date().toISOString(); } function mapLedgerEntry(row) { return { id: row.id, transaction_id: row.transaction_id, merchant_id: row.merchant_id, entry_type: row.entry_type, amount: Number(row.amount), currency: row.currency, direction: row.direction, status: row.status, metadata_json: row.metadata_json || {}, created_at: row.created_at }; } export async function createPaidLedgerPlaceholder(tx) { const { rows } = await getPool().query(`INSERT INTO ledger_entries ( id, transaction_id, merchant_id, entry_type, amount, currency, direction, status, metadata_json, created_at ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) ON CONFLICT (transaction_id, entry_type) DO UPDATE SET amount = EXCLUDED.amount, currency = EXCLUDED.currency, metadata_json = ledger_entries.metadata_json || EXCLUDED.metadata_json RETURNING *`, [ randomUUID(), tx.id, tx.merchant_id, "gross_income", tx.amount, tx.currency, "credit", "posted", { placeholder: true, source: "fase1_paid_transaction", partner_reference: tx.partner_reference }, nowIso() ]); return mapLedgerEntry(rows[0]); } export async function listLedgerEntries(filter) { const clauses = []; const params = []; let i = 1; if (filter?.transaction_id) { clauses.push(`transaction_id = $${i++}`); params.push(filter.transaction_id); } if (filter?.merchant_id) { clauses.push(`merchant_id = $${i++}`); params.push(filter.merchant_id); } const limit = Math.min(Math.max(filter?.limit || 100, 1), 500); const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : ""; const { rows } = await getPool().query(`SELECT * FROM ledger_entries ${where} ORDER BY created_at DESC LIMIT ${limit}`, params); return rows.map(mapLedgerEntry); } export function toLedgerEntryPayload(entry) { return { ...entry }; }