Actualizar server.js

This commit is contained in:
2026-03-14 20:42:40 +00:00
parent 598c46a8ef
commit 7d9d3ddc45

View File

@@ -915,8 +915,12 @@ app.post("/public/new-request", async (req, res) => {
if (!phone || !guild_id) return res.status(400).json({ ok: false, error: "Faltan datos clave" }); if (!phone || !guild_id) return res.status(400).json({ ok: false, error: "Faltan datos clave" });
const targetOwnerId = owner_id || 1; // 🛡️ CONVERSIÓN ESTRICTA DE DATOS (Para que PostgreSQL no lance Error 500)
const cleanPhone = phone.replace(/\D/g, ""); const targetOwnerId = parseInt(owner_id) || 1;
const safeGuildId = parseInt(guild_id) || 0;
const isUrgentBool = is_urgent === true || is_urgent === 'true';
const cleanPhone = String(phone).replace(/\D/g, "");
if (cleanPhone.length < 9) return res.status(400).json({ ok: false, error: "Teléfono inválido" }); if (cleanPhone.length < 9) return res.status(400).json({ ok: false, error: "Teléfono inválido" });
await clientDb.query('BEGIN'); await clientDb.query('BEGIN');
@@ -939,13 +943,13 @@ app.post("/public/new-request", async (req, res) => {
// 2. BUSCAR OPERARIO AL AZAR (Si es NORMAL) // 2. BUSCAR OPERARIO AL AZAR (Si es NORMAL)
let assignedWorkerId = null; let assignedWorkerId = null;
if (!is_urgent) { if (!isUrgentBool) {
let qWorker = await clientDb.query(` let qWorker = await clientDb.query(`
SELECT u.id FROM users u SELECT u.id FROM users u
JOIN user_guilds ug ON u.id = ug.user_id JOIN user_guilds ug ON u.id = ug.user_id
WHERE u.owner_id = $1 AND u.status = 'active' AND ug.guild_id = $2 WHERE u.owner_id = $1 AND u.status = 'active' AND ug.guild_id = $2
ORDER BY RANDOM() LIMIT 1 ORDER BY RANDOM() LIMIT 1
`, [targetOwnerId, guild_id]); `, [targetOwnerId, safeGuildId]);
// 🛡️ FALLBACK: Si nadie tiene ese gremio, coge a CUALQUIERA activo // 🛡️ FALLBACK: Si nadie tiene ese gremio, coge a CUALQUIERA activo
if (qWorker.rowCount === 0) { if (qWorker.rowCount === 0) {
@@ -955,6 +959,7 @@ app.post("/public/new-request", async (req, res) => {
if (qWorker.rowCount > 0) { if (qWorker.rowCount > 0) {
assignedWorkerId = qWorker.rows[0].id; assignedWorkerId = qWorker.rows[0].id;
} else { } else {
await clientDb.query('ROLLBACK'); // ⚠️ VITAL para no bloquear la BD
return res.status(400).json({ ok: false, error: "No hay técnicos disponibles. Llama a la oficina." }); return res.status(400).json({ ok: false, error: "No hay técnicos disponibles. Llama a la oficina." });
} }
} }
@@ -965,7 +970,7 @@ app.post("/public/new-request", async (req, res) => {
"Teléfono": phone, "Teléfono": phone,
"Dirección": address || "", "Dirección": address || "",
"Descripción": description || "Aviso desde Web", "Descripción": description || "Aviso desde Web",
"guild_id": guild_id, "guild_id": safeGuildId,
"Compañía": "Particular", "Compañía": "Particular",
"Origen": "Web Público" "Origen": "Web Público"
}; };
@@ -978,25 +983,25 @@ app.post("/public/new-request", async (req, res) => {
`, [ `, [
targetOwnerId, targetOwnerId,
ref, ref,
is_urgent ? 'in_progress' : 'manual', isUrgentBool ? 'in_progress' : 'manual',
assignedWorkerId, assignedWorkerId,
is_urgent, isUrgentBool,
JSON.stringify(rawData) JSON.stringify(rawData)
]); ]);
const newServiceId = qSvc.rows[0].id; const newServiceId = qSvc.rows[0].id;
// 4. SI ES URGENTE, DISPARAMOS EL WHATSAPP DIRECTAMENTE // 4. SI ES URGENTE, DISPARAMOS EL WHATSAPP DIRECTAMENTE
if (is_urgent) { if (isUrgentBool) {
// Buscamos un operario activo de ese gremio // Buscamos un operario activo de ese gremio
let workersQ = await clientDb.query(` let workersQ = await clientDb.query(`
SELECT u.id, u.full_name, u.phone FROM users u SELECT u.id, u.full_name, u.phone FROM users u
JOIN user_guilds ug ON u.id = ug.user_id JOIN user_guilds ug ON u.id = ug.user_id
WHERE u.owner_id = $1 AND u.status = 'active' AND ug.guild_id = $2 WHERE u.owner_id = $1 AND u.status = 'active' AND ug.guild_id = $2
ORDER BY RANDOM() LIMIT 1 ORDER BY RANDOM() LIMIT 1
`, [targetOwnerId, guild_id]); `, [targetOwnerId, safeGuildId]);
// 🛡️ FALLBACK URGENCIA: Si nadie tiene ese gremio (o es admin), coge a CUALQUIERA activo. ¡Es urgente! // 🛡️ FALLBACK URGENCIA: Si nadie tiene ese gremio, coge a CUALQUIERA activo
if (workersQ.rowCount === 0) { if (workersQ.rowCount === 0) {
workersQ = await clientDb.query(` workersQ = await clientDb.query(`
SELECT id, full_name, phone FROM users SELECT id, full_name, phone FROM users
@@ -1015,33 +1020,30 @@ app.post("/public/new-request", async (req, res) => {
VALUES ($1, $2, $3, CURRENT_TIMESTAMP + INTERVAL '5 minutes') VALUES ($1, $2, $3, CURRENT_TIMESTAMP + INTERVAL '5 minutes')
`, [newServiceId, worker.id, token]); `, [newServiceId, worker.id, token]);
// Extraemos solo la calle (Corta al encontrar el primer número o un s/n) // 🛑 EXTRAEMOS LA CALLE OCULTA (Sin números)
let calleOculta = "Zona por determinar"; let calleOculta = "Zona asignada";
if (address) { if (address) {
calleOculta = address.replace(/\s*,?\s*(\d+|s\/n).*$/i, '').trim(); calleOculta = address.replace(/\s*,?\s*(\d+|s\/n).*$/i, '').trim();
} }
// Enviamos el WA al operario // Enviamos el WA al operario
const msg = `🚨 *URGENCIA PARTICULAR (WEB)*\n📍 Calle: ${calleOculta}\n🔗 https://web.integrarepara.es/aceptar.html?t=${token}`; const msg = `🚨 *URGENCIA PARTICULAR (WEB)*\n📍 Calle: ${calleOculta}\n🔗 https://web.integrarepara.es/aceptar.html?t=${token}`;
sendWhatsAppAuto(worker.phone, msg, `cliente_${targetOwnerId}`, false).catch(console.error); sendWhatsAppAuto(worker.phone, msg, `cliente_${targetOwnerId}`, false).catch(console.error);
// Dejamos huella
await clientDb.query( await clientDb.query(
"INSERT INTO scraped_service_logs (scraped_id, user_name, action, details) VALUES ($1, 'Sistema Automático', 'Bolsa de Urgencias', $2)", "INSERT INTO scraped_service_logs (scraped_id, user_name, action, details) VALUES ($1, 'Sistema Automático', 'Bolsa de Urgencias', $2)",
[newServiceId, `Notificación enviada a: ${worker.full_name} (${worker.phone})`] [newServiceId, `Notificación enviada a: ${worker.full_name}`]
); );
} else { } else {
// Solo fallará si literalmente tienes 0 usuarios activos en el sistema
await clientDb.query("UPDATE scraped_services SET automation_status = 'failed' WHERE id = $1", [newServiceId]); await clientDb.query("UPDATE scraped_services SET automation_status = 'failed' WHERE id = $1", [newServiceId]);
} }
await clientDb.query('COMMIT'); await clientDb.query('COMMIT');
res.json({ ok: true, action: 'queued', message: "Aviso urgente en cola." }); return res.json({ ok: true, action: 'queued', message: "Aviso urgente en cola." });
} else { } else {
await clientDb.query('COMMIT'); await clientDb.query('COMMIT');
// Devolvemos el token del cliente y el ID del servicio para redirigirlo al calendario // Devolvemos el token del cliente para llevarlo a pedir Cita Normal
res.json({ return res.json({
ok: true, ok: true,
action: 'calendar', action: 'calendar',
redirectUrl: `https://portal.integrarepara.es/?token=${clientToken}&service=${newServiceId}` redirectUrl: `https://portal.integrarepara.es/?token=${clientToken}&service=${newServiceId}`
@@ -1050,7 +1052,7 @@ app.post("/public/new-request", async (req, res) => {
} catch (e) { } catch (e) {
await clientDb.query('ROLLBACK'); await clientDb.query('ROLLBACK');
console.error("Error en Web Pública:", e); console.error("🚨 CRASH EN WEB PÚBLICA (NUEVO AVISO):", e.message);
res.status(500).json({ ok: false, error: "Error procesando solicitud" }); res.status(500).json({ ok: false, error: "Error procesando solicitud" });
} finally { } finally {
clientDb.release(); clientDb.release();