import { env as processEnv } from "node:process"; import { Pool } from "pg"; function required(value, fallback) { return value || fallback; } const pool = processEnv.DATABASE_URL ? new Pool({ connectionString: processEnv.DATABASE_URL }) : new Pool({ host: required(processEnv.PGHOST, "127.0.0.1"), port: Number(required(processEnv.PGPORT, "5432")), user: required(processEnv.PGUSER, "postgres"), password: processEnv.PGPASSWORD || "", database: required(processEnv.PGDATABASE, "qris_soundbox_platform") }); async function main() { const client = await pool.connect(); try { await client.query("BEGIN"); const auditTable = await client.query("SELECT to_regclass('public.audit_logs') AS name"); const idsResult = await client.query(` SELECT id FROM transactions WHERE partner_reference LIKE 'PR-%' OR partner_reference LIKE 'DYN-%' UNION SELECT id FROM devices WHERE device_code LIKE 'DEV-%' UNION SELECT id FROM merchants WHERE legal_name LIKE 'Smoke Merchant %' UNION SELECT outlets.id FROM outlets JOIN merchants ON merchants.id = outlets.merchant_id WHERE merchants.legal_name LIKE 'Smoke Merchant %' UNION SELECT terminals.id FROM terminals JOIN outlets ON outlets.id = terminals.outlet_id JOIN merchants ON merchants.id = outlets.merchant_id WHERE merchants.legal_name LIKE 'Smoke Merchant %' UNION SELECT device_bindings.id FROM device_bindings JOIN devices ON devices.id = device_bindings.device_id WHERE devices.device_code LIKE 'DEV-%' `); const auditIds = idsResult.rows.map((row) => row.id); const auditResult = auditTable.rows[0]?.name && auditIds.length ? await client.query("DELETE FROM audit_logs WHERE entity_id = ANY($1::text[])", [auditIds]) : { rowCount: 0 }; const txResult = await client.query("DELETE FROM transactions WHERE partner_reference LIKE 'PR-%' OR partner_reference LIKE 'DYN-%' RETURNING id"); const devResult = await client.query("DELETE FROM devices WHERE device_code LIKE 'DEV-%' RETURNING id"); const merchantResult = await client.query("DELETE FROM merchants WHERE legal_name LIKE 'Smoke Merchant %' RETURNING id"); await client.query("COMMIT"); console.log(JSON.stringify({ transactions_deleted: txResult.rowCount, devices_deleted: devResult.rowCount, merchants_deleted: merchantResult.rowCount, audit_logs_deleted: auditResult.rowCount, note: "outlets/terminals are removed via merchant cascade" })); } catch (error) { await client.query("ROLLBACK"); console.error("cleanup failed", error instanceof Error ? error.message : String(error)); process.exitCode = 1; } finally { client.release(); await pool.end(); } } main().catch((error) => { console.error("cleanup failed", error instanceof Error ? error.message : String(error)); process.exitCode = 1; });