diff --git a/server.js b/server.js index 6c28c81..dec239e 100644 --- a/server.js +++ b/server.js @@ -1848,6 +1848,107 @@ app.get("/public/portal/:token/location/:serviceId", async (req, res) => { }); +// ========================================== +// 馃敆 RUTAS PARA ACEPTAR/RECHAZAR AVISOS (PANTALLA OPERARIOS) +// ========================================== + +app.get("/public/assignment/:token", async (req, res) => { + try { + const { token } = req.params; + const q = await pool.query(` + SELECT ap.*, s.raw_data, s.service_ref, s.is_urgent, u.full_name + FROM assignment_pings ap + JOIN scraped_services s ON ap.scraped_id = s.id + JOIN users u ON ap.user_id = u.id + WHERE ap.token = $1 + `, [token]); + + if (q.rowCount === 0) return res.status(404).json({ ok: false, error: "Asignaci贸n no encontrada" }); + + const assign = q.rows[0]; + + if (assign.status !== 'pending') { + return res.json({ ok: false, error: "Este aviso ya fue " + (assign.status === 'accepted' ? 'aceptado' : 'rechazado o ha caducado.') }); + } + + if (new Date() > new Date(assign.expires_at)) { + // Lo marcamos como expirado si ya pas贸 el tiempo + await pool.query("UPDATE assignment_pings SET status = 'expired' WHERE id = $1", [assign.id]); + return res.json({ ok: false, error: "El tiempo para aceptar este aviso ha caducado." }); + } + + res.json({ ok: true, assignment: assign }); + } catch (e) { + console.error("Error al obtener asignaci贸n:", e); + res.status(500).json({ ok: false }); + } +}); + +app.post("/public/assignment/:token/accept", async (req, res) => { + const client = await pool.connect(); + try { + const { token } = req.params; + await client.query('BEGIN'); + + // 1. Validar ping bloqueando la fila para evitar dobles clicks + const qPing = await client.query("SELECT * FROM assignment_pings WHERE token = $1 AND status = 'pending' FOR UPDATE", [token]); + if (qPing.rowCount === 0) { + await client.query('ROLLBACK'); + return res.status(400).json({ ok: false, error: "Este aviso ya no est谩 disponible." }); + } + + const ping = qPing.rows[0]; + + // 2. Marcar ping como aceptado + await client.query("UPDATE assignment_pings SET status = 'accepted' WHERE id = $1", [ping.id]); + + // 3. Sacar datos del servicio + const sQ = await client.query("SELECT owner_id, raw_data FROM scraped_services WHERE id = $1", [ping.scraped_id]); + const ownerId = sQ.rows[0].owner_id; + let rawData = sQ.rows[0].raw_data || {}; + + // 4. Poner el estado en "Asignado" si existe + const statusQ = await client.query("SELECT id, name FROM service_statuses WHERE owner_id=$1 AND name ILIKE '%asignado%' LIMIT 1", [ownerId]); + const statusAsignadoId = statusQ.rows[0]?.id || null; + + if (statusAsignadoId) { + rawData.status_operativo = statusAsignadoId; + } + + // 5. Actualizar el expediente oficial con el t茅cnico + await client.query(` + UPDATE scraped_services + SET assigned_to = $1, automation_status = 'completed', raw_data = $2 + WHERE id = $3 + `, [ping.user_id, JSON.stringify(rawData), ping.scraped_id]); + + await client.query('COMMIT'); + + // 6. 隆Magia! Le enviamos un WhatsApp autom谩tico al cliente diciendo que ya tiene t茅cnico + triggerWhatsAppEvent(ownerId, ping.scraped_id, 'wa_evt_assigned').catch(e => console.error(e)); + + res.json({ ok: true }); + } catch (e) { + await client.query('ROLLBACK'); + console.error("Error aceptando asignaci贸n:", e); + res.status(500).json({ ok: false, error: "Error interno del servidor" }); + } finally { + client.release(); + } +}); + +app.post("/public/assignment/:token/reject", async (req, res) => { + try { + const { token } = req.params; + // Si lo rechaza, el reloj (setInterval) se encargar谩 de buscar al siguiente t茅cnico libre al instante + await pool.query("UPDATE assignment_pings SET status = 'rejected' WHERE token = $1 AND status = 'pending'", [token]); + res.json({ ok: true }); + } catch (e) { + console.error("Error rechazando asignaci贸n:", e); + res.status(500).json({ ok: false }); + } +}); + // ========================================== // 馃晵 EL RELOJ DEL SISTEMA (Ejecutar cada minuto) // ==========================================