diff --git a/server.js b/server.js index 1b7131e..5b33dd7 100644 --- a/server.js +++ b/server.js @@ -751,74 +751,77 @@ app.get("/providers/scraped", authMiddleware, async (req, res) => { } }); +// ========================================== +// 🤖 RUTA DE AUTOMATIZACIÓN (CORREGIDA) +// ========================================== app.post("/providers/automate/:id", authMiddleware, async (req, res) => { + const { id } = req.params; + console.log(`\n🤖 [AUTOMATE] Iniciando proceso para ID: ${id}`); + try { - const { id } = req.params; const { guild_id, cp, useDelay } = req.body; - if (!guild_id || !cp) return res.status(400).json({ ok: false, error: "Faltan datos (Gremio o CP)" }); + if (!guild_id || !cp) { + console.error("❌ [AUTOMATE] Faltan datos: guild_id o CP"); + return res.status(400).json({ ok: false, error: "Faltan datos (Gremio o CP)" }); + } - const serviceQ = await pool.query("SELECT raw_data, provider FROM scraped_services WHERE id = $1", [id]); - if (serviceQ.rowCount === 0) return res.status(404).json({ ok: false, error: "Expediente no encontrado" }); + // 1. Verificar si el expediente existe + const serviceQ = await pool.query("SELECT raw_data, provider, owner_id FROM scraped_services WHERE id = $1", [id]); + if (serviceQ.rowCount === 0) { + console.error(`❌ [AUTOMATE] Expediente ${id} no encontrado en la DB`); + return res.status(404).json({ ok: false, error: "Expediente no encontrado" }); + } - const raw = serviceQ.rows[0].raw_data; - const nombreCliente = raw["Nombre Cliente"] || raw["CLIENTE"] || "Cliente"; - const poblacion = raw["Población"] || raw["POBLACION-PROVINCIA"] || "---"; - const gremioNombre = raw["Gremio"] || "Servicio General"; - - const direccionCompleta = raw["Dirección"] || raw["DOMICILIO"] || ""; - const direccionLimpia = direccionCompleta.split(/[0-9]/)[0].trim(); + const serviceData = serviceQ.rows[0]; + const raw = serviceData.raw_data; + // 2. Buscar operarios que cumplan Gremio + Zona (CP) + Activos const workersQ = await pool.query(` SELECT u.id, u.full_name, u.phone FROM users u JOIN user_guilds ug ON u.id = ug.user_id - WHERE u.owner_id = $1 AND u.role = 'operario' AND u.status = 'active' - AND ug.guild_id = $2 AND u.zones::jsonb @> $3::jsonb + WHERE u.owner_id = $1 + AND u.role = 'operario' + AND u.status = 'active' + AND ug.guild_id = $2 + AND u.zones::jsonb @> $3::jsonb `, [req.user.accountId, guild_id, JSON.stringify([{ cps: cp.toString() }])]); - if (workersQ.rowCount === 0) return res.status(404).json({ ok: false, error: "No hay operarios disponibles" }); + if (workersQ.rowCount === 0) { + console.warn(`⚠️ [AUTOMATE] No hay operarios activos para Gremio:${guild_id} y CP:${cp}`); + return res.status(404).json({ ok: false, error: "No hay operarios disponibles para esta zona/gremio" }); + } + // 3. Marcar como "En progreso" await pool.query("UPDATE scraped_services SET automation_status = 'in_progress' WHERE id = $1", [id]); const worker = workersQ.rows[Math.floor(Math.random() * workersQ.rows.length)]; const token = crypto.randomBytes(16).toString('hex'); + // 4. Crear el Ping de asignación (5 minutos) await pool.query(` INSERT INTO assignment_pings (scraped_id, user_id, token, expires_at) VALUES ($1, $2, $3, CURRENT_TIMESTAMP + INTERVAL '5 minutes') `, [id, worker.id, token]); - // CÁLCULO DE HORA 100% FIABLE: Se lo pedimos a Node forzando a España - // Así siempre saldrá "0:40" en lugar de "23:40" en el texto de WhatsApp + // 5. Preparar mensaje const horaCaducidad = new Date(Date.now() + 5 * 60 * 1000).toLocaleTimeString('es-ES', { - hour: '2-digit', - minute: '2-digit', - timeZone: 'Europe/Madrid' + hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Madrid' }); const link = `https://web.integrarepara.es/aceptar.html?t=${token}`; - const mensaje = `🛠️ *NUEVO SERVICIO ASIGNADO A TI* - -👤 *Operario:* ${worker.full_name} -📋 *Gremio:* ${gremioNombre} + const mensaje = `🛠️ *NUEVO SERVICIO DISPONIBLE*\n\n👤 *Operario:* ${worker.full_name}\n📍 *Zona:* ${cp}\n⏱️ *Expira:* ${horaCaducidad}\n\nRevisa y acepta aquí:\n🔗 ${link}`; -*DATOS DEL CLIENTE:* -👤 *Nombre:* ${nombreCliente} -📍 *Zona:* ${direccionLimpia} -🏙️ *Población:* ${poblacion} (CP: ${cp}) - -⚠️ *ATENCIÓN:* Tienes hasta las *${horaCaducidad}* para revisar los datos completos y ACEPTAR el servicio en el siguiente enlace: - -🔗 ${link}`; - - // SAAS: INSTANCIA DE CLIENTE ESPECÍFICA SIN AWAIT PARA NO BLOQUEAR + // 6. Envío WA (Sandbox 667248132 activo en sendWhatsAppAuto) const instanceName = `cliente_${req.user.accountId}`; - sendWhatsAppAuto(worker.phone, mensaje, instanceName, useDelay).catch(console.error); + sendWhatsAppAuto(worker.phone, mensaje, instanceName, useDelay).catch(e => console.error("Error WA Automate:", e.message)); + console.log(`✅ [AUTOMATE] Asignación enviada a ${worker.full_name}`); res.json({ ok: true, message: "Automatismo iniciado con " + worker.full_name }); + } catch (e) { - console.error("Error Automate:", e.message); + console.error("❌ [AUTOMATE] Error Crítico:", e.message); res.status(500).json({ ok: false, error: e.message }); } });