Actualizar server.js
This commit is contained in:
101
server.js
101
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)
|
||||
// ==========================================
|
||||
|
||||
Reference in New Issue
Block a user