diff --git a/server.js b/server.js index a911cd9..28ba61d 100644 --- a/server.js +++ b/server.js @@ -1856,7 +1856,7 @@ async function dispatchToBolsa(serviceId, guildId, cp, accountId, userId) { } // ========================================== -// 📥 RECEPCIÓN DE SERVICIOS (EL DETECTOR DEFINITIVO Y MÁS LIMPIO) +// 📥 RECEPCIÓN DE SERVICIOS (DETECTOR MODO DIOS + AUTO-BOLSA) // ========================================== app.post("/providers/scraped", authMiddleware, async (req, res) => { try { @@ -1866,42 +1866,27 @@ app.post("/providers/scraped", authMiddleware, async (req, res) => { return res.status(400).json({ ok: false, error: "Formato de datos inválido" }); } - let count = 0; - const credsQ = await pool.query( "SELECT auto_dispatch FROM provider_credentials WHERE owner_id = $1 AND provider = $2", [req.user.accountId, provider] ); - // 🐛 ¡AQUÍ ESTABA EL BUG DEL INTERRUPTOR! 🐛 + // CORRECCIÓN INTERRUPTOR (Acepta el '1' de la base de datos) let autoDispatchEnabled = false; if (credsQ.rowCount > 0) { const val = credsQ.rows[0].auto_dispatch; autoDispatchEnabled = (val === true || val === 1 || val === '1' || val === 't'); } + let count = 0; for (const svc of services) { - - const ref = svc['service_ref'] - || svc['SERVICIO'] - || svc['Referencia'] - || svc['Nº Siniestro'] - || svc['Expediente'] - || svc['expediente'] - || (svc.raw_data && (svc.raw_data['SERVICIO'] || svc.raw_data['Referencia'] || svc.raw_data['Nº Siniestro'] || svc.raw_data['Expediente'] || svc.raw_data['expediente'])); - - if (!ref) { - console.log("⚠️ Se omitió un servicio por no encontrar referencia."); - continue; - } + const ref = svc['service_ref'] || svc['SERVICIO'] || svc['Referencia'] || svc['Expediente'] || (svc.raw_data && (svc.raw_data['SERVICIO'] || svc.raw_data['Referencia'])); + if (!ref) continue; let esUrgente = false; const todoElTexto = JSON.stringify(svc).toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/\n/g, " "); - if (todoElTexto.includes("atencion presencial urgencias") || todoElTexto.includes("atencion de la urgencia") || todoElTexto.includes("por atencion")) { - esUrgente = true; - } - if (todoElTexto.includes('"urgente":"si"') || todoElTexto.includes('"urgencia":"si"')) { + if (todoElTexto.includes("atencion presencial urgencias") || todoElTexto.includes("atencion de la urgencia") || todoElTexto.includes("por atencion") || todoElTexto.includes('"urgente":"si"') || todoElTexto.includes('"urgencia":"si"')) { esUrgente = true; } @@ -1920,18 +1905,14 @@ app.post("/providers/scraped", authMiddleware, async (req, res) => { const newSvcId = insertRes.rows[0].id; const autoStatus = insertRes.rows[0].automation_status; + // CHIVATO DE CONSOLA console.log(`[DEBUG-BOLSA] Ref: ${ref} | Urgente: ${esUrgente} | Gremio: ${guildId} | Auto_ON: ${autoDispatchEnabled} | Estado: ${autoStatus}`); - // 🔥 DISPARO AUTOMÁTICO REPARADO 🔥 + // LANZAMIENTO AUTOMÁTICO if (esUrgente && guildId && autoDispatchEnabled && (autoStatus === 'manual' || autoStatus === 'pending')) { - console.log(`⚡ [AUTO-DISPATCH] Lanzando urgencia ${ref} a la bolsa internamente...`); const cpMatch = todoElTexto.match(/\b\d{5}\b/); - const cpFinal = cpMatch ? cpMatch[0] : "00000"; - - // Llamamos directamente a la función, pasando el ownerId y userId (para los logs) - dispatchToBolsa(newSvcId, guildId, cpFinal, req.user.accountId, req.user.sub); + dispatchToBolsa(newSvcId, guildId, cpMatch ? cpMatch[0] : "00000", req.user.accountId, req.user.sub); } - count++; } res.json({ ok: true, inserted: count }); @@ -1942,34 +1923,24 @@ app.post("/providers/scraped", authMiddleware, async (req, res) => { }); // ========================================== -// 📤 OBTENER SERVICIOS PARA EL BUZÓN (RUTA GET - NO BORRAR) +// 📤 OBTENER SERVICIOS PARA EL BUZÓN // ========================================== app.get("/providers/scraped", authMiddleware, async (req, res) => { try { const q = await pool.query(` - SELECT - s.*, - ap.token as active_token, + SELECT s.*, ap.token as active_token, EXTRACT(EPOCH FROM (ap.expires_at - CURRENT_TIMESTAMP)) as seconds_left, u.full_name as current_worker_name, (SELECT json_agg(json_build_object('name', u2.full_name, 'phone', u2.phone)) - FROM assignment_pings ap2 - JOIN users u2 ON ap2.user_id = u2.id + FROM assignment_pings ap2 JOIN users u2 ON ap2.user_id = u2.id WHERE ap2.scraped_id = s.id AND ap2.status IN ('expired', 'rejected')) as attempted_workers_data FROM scraped_services s LEFT JOIN assignment_pings ap ON s.id = ap.scraped_id AND ap.status = 'pending' LEFT JOIN users u ON ap.user_id = u.id - WHERE s.owner_id = $1 - ORDER BY s.created_at DESC + WHERE s.owner_id = $1 ORDER BY s.created_at DESC `, [req.user.accountId]); - const services = q.rows.map(row => { - if (row.seconds_left && row.seconds_left > 0) { - row.token_expires_at = new Date(Date.now() + (row.seconds_left * 1000)); - } else if (row.seconds_left <= 0) { - row.token_expires_at = new Date(Date.now() - 1000); - } - delete row.seconds_left; + if (row.seconds_left && row.seconds_left > 0) row.token_expires_at = new Date(Date.now() + (row.seconds_left * 1000)); return row; }); res.json({ ok: true, services }); @@ -1977,26 +1948,19 @@ app.get("/providers/scraped", authMiddleware, async (req, res) => { }); // ========================================== -// 🤖 RUTA DE AUTOMATIZACIÓN (MEJORADA) +// 🤖 RUTA DE AUTOMATIZACIÓN (BOTÓN DEL RAYO) // ========================================== app.post("/providers/automate/:id", authMiddleware, async (req, res) => { - const { id } = req.params; try { - const { guild_id, cp } = req.body; - if (!guild_id) return res.status(400).json({ ok: false, error: "Falta Gremio" }); - - const serviceQ = await pool.query("SELECT raw_data, provider, owner_id FROM scraped_services WHERE id = $1", [id]); - if (serviceQ.rowCount === 0) return res.status(404).json({ ok: false, error: "Expediente no encontrado" }); - - // Llamamos a nuestra nueva función reutilizable - const result = await dispatchToBolsa(id, guild_id, cp, req.user.accountId, req.user.sub); - + const { guild_id, cp } = req.body; + const result = await dispatchToBolsa(req.params.id, guild_id, cp, req.user.accountId, req.user.sub); if (result.ok) res.json({ ok: true }); else res.status(404).json(result); - } catch (e) { res.status(500).json({ ok: false }); } }); +// [EL RESTO DEL CÓDIGO PERMANECE IGUAL DESDE app.put('/providers/scraped/:id'...] + app.put('/providers/scraped/:id', authMiddleware, async (req, res) => { const { id } = req.params; // Extraemos todos los datos que vienen del frontend