remove users, chats, etc
This commit is contained in:
244
scripts/reset-tenant-data.mjs
Normal file
244
scripts/reset-tenant-data.mjs
Normal file
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* Script para resetear datos de conversación de un tenant
|
||||
*
|
||||
* Uso:
|
||||
* node scripts/reset-tenant-data.mjs --tenant-key piaf
|
||||
* node scripts/reset-tenant-data.mjs --tenant-key piaf --keep-audit
|
||||
* node scripts/reset-tenant-data.mjs --tenant-key piaf --yes # Sin confirmación
|
||||
*
|
||||
* Tablas que se limpian (en orden):
|
||||
* 1. human_takeovers
|
||||
* 2. wa_messages
|
||||
* 3. conversation_runs
|
||||
* 4. wa_conversation_state
|
||||
* 5. wa_identity_map
|
||||
* 6. audit_log (opcional, se borra por defecto)
|
||||
*/
|
||||
|
||||
import "dotenv/config";
|
||||
import readline from "readline";
|
||||
import { pool } from "../src/modules/shared/db/pool.js";
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Args parsing
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
function parseArgs() {
|
||||
const args = process.argv.slice(2);
|
||||
const out = {
|
||||
tenantKey: null,
|
||||
keepAudit: false,
|
||||
yes: false,
|
||||
};
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const a = args[i];
|
||||
if (a === "--tenant-key") out.tenantKey = args[++i];
|
||||
else if (a === "--keep-audit") out.keepAudit = true;
|
||||
else if (a === "--yes" || a === "-y") out.yes = true;
|
||||
else if (a === "--help" || a === "-h") {
|
||||
printHelp();
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!out.tenantKey) {
|
||||
console.error("Error: --tenant-key es requerido\n");
|
||||
printHelp();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
console.log(`
|
||||
Uso: node scripts/reset-tenant-data.mjs [opciones]
|
||||
|
||||
Opciones:
|
||||
--tenant-key <key> Clave del tenant (requerido)
|
||||
--keep-audit No borrar audit_log
|
||||
--yes, -y Confirmar automáticamente (sin prompt)
|
||||
--help, -h Mostrar esta ayuda
|
||||
|
||||
Ejemplos:
|
||||
node scripts/reset-tenant-data.mjs --tenant-key piaf
|
||||
node scripts/reset-tenant-data.mjs --tenant-key piaf --keep-audit
|
||||
node scripts/reset-tenant-data.mjs --tenant-key piaf --yes
|
||||
`);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Confirmación interactiva
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
async function askConfirmation(message) {
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
return new Promise((resolve) => {
|
||||
rl.question(message, (answer) => {
|
||||
rl.close();
|
||||
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes" || answer.toLowerCase() === "si");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Reset de datos
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
async function getTenantByKey(tenantKey) {
|
||||
const { rows } = await pool.query(
|
||||
`SELECT id, key, name FROM tenants WHERE key = $1`,
|
||||
[tenantKey]
|
||||
);
|
||||
return rows[0] || null;
|
||||
}
|
||||
|
||||
async function getStats(tenantId) {
|
||||
const queries = [
|
||||
{ name: "human_takeovers", sql: `SELECT COUNT(*) as count FROM human_takeovers WHERE tenant_id = $1` },
|
||||
{ name: "wa_messages", sql: `SELECT COUNT(*) as count FROM wa_messages WHERE tenant_id = $1` },
|
||||
{ name: "conversation_runs", sql: `SELECT COUNT(*) as count FROM conversation_runs WHERE tenant_id = $1` },
|
||||
{ name: "wa_conversation_state", sql: `SELECT COUNT(*) as count FROM wa_conversation_state WHERE tenant_id = $1` },
|
||||
{ name: "wa_identity_map", sql: `SELECT COUNT(*) as count FROM wa_identity_map WHERE tenant_id = $1` },
|
||||
{ name: "audit_log", sql: `SELECT COUNT(*) as count FROM audit_log WHERE tenant_id = $1` },
|
||||
];
|
||||
|
||||
const stats = {};
|
||||
for (const q of queries) {
|
||||
const { rows } = await pool.query(q.sql, [tenantId]);
|
||||
stats[q.name] = parseInt(rows[0].count, 10);
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
async function resetTenantData({ tenantId, keepAudit = false }) {
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
await client.query("BEGIN");
|
||||
|
||||
// 1. human_takeovers
|
||||
const r1 = await client.query(
|
||||
`DELETE FROM human_takeovers WHERE tenant_id = $1`,
|
||||
[tenantId]
|
||||
);
|
||||
console.log(` - human_takeovers: ${r1.rowCount} registros eliminados`);
|
||||
|
||||
// 2. wa_messages
|
||||
const r2 = await client.query(
|
||||
`DELETE FROM wa_messages WHERE tenant_id = $1`,
|
||||
[tenantId]
|
||||
);
|
||||
console.log(` - wa_messages: ${r2.rowCount} registros eliminados`);
|
||||
|
||||
// 3. conversation_runs
|
||||
const r3 = await client.query(
|
||||
`DELETE FROM conversation_runs WHERE tenant_id = $1`,
|
||||
[tenantId]
|
||||
);
|
||||
console.log(` - conversation_runs: ${r3.rowCount} registros eliminados`);
|
||||
|
||||
// 4. wa_conversation_state
|
||||
const r4 = await client.query(
|
||||
`DELETE FROM wa_conversation_state WHERE tenant_id = $1`,
|
||||
[tenantId]
|
||||
);
|
||||
console.log(` - wa_conversation_state: ${r4.rowCount} registros eliminados`);
|
||||
|
||||
// 5. wa_identity_map
|
||||
const r5 = await client.query(
|
||||
`DELETE FROM wa_identity_map WHERE tenant_id = $1`,
|
||||
[tenantId]
|
||||
);
|
||||
console.log(` - wa_identity_map: ${r5.rowCount} registros eliminados`);
|
||||
|
||||
// 6. audit_log (opcional)
|
||||
if (!keepAudit) {
|
||||
const r6 = await client.query(
|
||||
`DELETE FROM audit_log WHERE tenant_id = $1`,
|
||||
[tenantId]
|
||||
);
|
||||
console.log(` - audit_log: ${r6.rowCount} registros eliminados`);
|
||||
} else {
|
||||
console.log(` - audit_log: conservado (--keep-audit)`);
|
||||
}
|
||||
|
||||
await client.query("COMMIT");
|
||||
|
||||
return { ok: true };
|
||||
} catch (err) {
|
||||
await client.query("ROLLBACK");
|
||||
throw err;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Main
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
async function main() {
|
||||
const args = parseArgs();
|
||||
|
||||
console.log("\n🔄 Reset de datos de tenant\n");
|
||||
|
||||
// Buscar tenant
|
||||
const tenant = await getTenantByKey(args.tenantKey);
|
||||
if (!tenant) {
|
||||
console.error(`Error: No se encontró tenant con key "${args.tenantKey}"`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Tenant: ${tenant.name} (${tenant.key})`);
|
||||
console.log(`ID: ${tenant.id}\n`);
|
||||
|
||||
// Mostrar estadísticas
|
||||
console.log("Registros actuales:");
|
||||
const stats = await getStats(tenant.id);
|
||||
for (const [table, count] of Object.entries(stats)) {
|
||||
console.log(` - ${table}: ${count}`);
|
||||
}
|
||||
console.log("");
|
||||
|
||||
const total = Object.values(stats).reduce((a, b) => a + b, 0);
|
||||
if (total === 0) {
|
||||
console.log("No hay datos para eliminar.");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Confirmación
|
||||
if (!args.yes) {
|
||||
const confirm = await askConfirmation(
|
||||
`⚠️ Se eliminarán ${total} registros. ¿Continuar? (y/N): `
|
||||
);
|
||||
if (!confirm) {
|
||||
console.log("Operación cancelada.");
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("\nEliminando datos...\n");
|
||||
|
||||
// Ejecutar reset
|
||||
await resetTenantData({
|
||||
tenantId: tenant.id,
|
||||
keepAudit: args.keepAudit
|
||||
});
|
||||
|
||||
console.log("\n✅ Reset completado exitosamente.\n");
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((err) => {
|
||||
console.error("\n❌ Error:", err.message);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(() => {
|
||||
pool.end();
|
||||
});
|
||||
@@ -100,12 +100,8 @@ export async function upsertSettings({ tenantId, settings }) {
|
||||
pickup_hours_end || null,
|
||||
];
|
||||
|
||||
console.log("[settingsRepo] upsertSettings params:", params);
|
||||
|
||||
const { rows } = await pool.query(sql, params);
|
||||
|
||||
console.log("[settingsRepo] upsertSettings result:", rows[0]);
|
||||
|
||||
return rows[0];
|
||||
}
|
||||
|
||||
|
||||
@@ -44,8 +44,6 @@ export async function handleGetSettings({ tenantId }) {
|
||||
* Guarda la configuración del tenant
|
||||
*/
|
||||
export async function handleSaveSettings({ tenantId, settings }) {
|
||||
console.log("[settings] handleSaveSettings", { tenantId, settings });
|
||||
|
||||
// Validaciones básicas
|
||||
if (!settings.store_name?.trim()) {
|
||||
throw new Error("store_name is required");
|
||||
|
||||
Reference in New Issue
Block a user