diff --git a/server.js b/server.js index 26ee67f..0d3427e 100644 --- a/server.js +++ b/server.js @@ -331,13 +331,13 @@ async function ensureInstance(instanceName) { app.get("/public/assignment/:token", async (req, res) => { try { const { token } = req.params; - const q = await pool.query(` + const q = await pool.query(` SELECT ap.*, s.raw_data, u.full_name as worker_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 AND ap.status = 'pending' AND ap.expires_at > NOW() - `, [token]); + WHERE ap.token = $1 AND ap.status = 'pending' AND ap.expires_at > CAST($2 AS TIMESTAMP) + `, [token, new Date().toISOString()]); if (q.rowCount === 0) return res.status(404).json({ ok: false, error: "Enlace caducado" }); res.json({ ok: true, service: q.rows[0].raw_data, worker: q.rows[0].worker_name }); } catch (e) { res.status(500).json({ ok: false }); } @@ -350,9 +350,9 @@ app.post("/public/assignment/respond", async (req, res) => { await client.query('BEGIN'); const q = await client.query( -            "SELECT * FROM assignment_pings WHERE token = $1 AND status = 'pending' AND expires_at > $2",  -            [token, new Date()] -        ); + "SELECT * FROM assignment_pings WHERE token = $1 AND status = 'pending' AND expires_at > CAST($2 AS TIMESTAMP)", + [token, new Date().toISOString()] + ); if (q.rowCount === 0) throw new Error("Acción caducada"); const ping = q.rows[0]; @@ -371,8 +371,8 @@ app.post("/public/assignment/respond", async (req, res) => { `, [ping.user_id, ping.scraped_id]); } else { -            await client.query("UPDATE assignment_pings SET status = 'rejected', expires_at = $2 WHERE id = $1", [ping.id, new Date()]); -        } + await client.query("UPDATE assignment_pings SET status = 'rejected', expires_at = CAST($2 AS TIMESTAMP) WHERE id = $1", [ping.id, new Date().toISOString()]); + } await client.query('COMMIT'); res.json({ ok: true }); @@ -494,16 +494,14 @@ app.post("/providers/automate/:id", authMiddleware, async (req, res) => { const worker = workersQ.rows[Math.floor(Math.random() * workersQ.rows.length)]; const token = crypto.randomBytes(16).toString('hex'); -// A) Delegamos la inserción y el cálculo del tiempo a PostgreSQL -// Usamos NOW() de la base de datos + 5 minutos y devolvemos la hora exacta calculada // Calculamos la caducidad puramente en Node (+5 min) const expiresAt = new Date(Date.now() + 5 * 60 * 1000); - // Insertamos el valor exacto de Node en la DB + // Insertamos el valor exacto de Node convertido a ISO en la DB await pool.query(` INSERT INTO assignment_pings (scraped_id, user_id, token, expires_at) - VALUES ($1, $2, $3, $4) - `, [id, worker.id, token, expiresAt]); + VALUES ($1, $2, $3, CAST($4 AS TIMESTAMP)) + `, [id, worker.id, token, expiresAt.toISOString()]); // Formateamos para WhatsApp forzando la hora de España const horaCaducidad = expiresAt.toLocaleTimeString('es-ES', { @@ -778,12 +776,12 @@ app.delete("/services/:id", authMiddleware, async (req, res) => { try { await po setInterval(async () => { try { const expiredPings = await pool.query(` -            SELECT ap.id, ap.scraped_id, ap.user_id, s.owner_id, s.raw_data -            FROM assignment_pings ap -            JOIN scraped_services s ON ap.scraped_id = s.id -            WHERE ap.status = 'pending' AND ap.expires_at < $1 -            AND s.automation_status = 'in_progress' -        `, [new Date()]); // <-- El reloj busca comparando con la hora actual de Node + SELECT ap.id, ap.scraped_id, ap.user_id, s.owner_id, s.raw_data + FROM assignment_pings ap + JOIN scraped_services s ON ap.scraped_id = s.id + WHERE ap.status = 'pending' AND ap.expires_at < CAST($1 AS TIMESTAMP) + AND s.automation_status = 'in_progress' + `, [new Date().toISOString()]); for (const ping of expiredPings.rows) { await pool.query("UPDATE assignment_pings SET status = 'expired' WHERE id = $1", [ping.id]); @@ -800,7 +798,7 @@ setInterval(async () => { const nextW = nextWorkerQ.rows[0]; const newToken = crypto.randomBytes(16).toString('hex'); const expiresAt = new Date(Date.now() + 5 * 60 * 1000); - await pool.query(`INSERT INTO assignment_pings (scraped_id, user_id, token, expires_at) VALUES ($1, $2, $3, $4)`, [ping.scraped_id, nextW.id, newToken, expiresAt]); + await pool.query(`INSERT INTO assignment_pings (scraped_id, user_id, token, expires_at) VALUES ($1, $2, $3, CAST($4 AS TIMESTAMP))`, [ping.scraped_id, nextW.id, newToken, expiresAt.toISOString()]); await sendWhatsAppAuto(nextW.phone, `🛠️ *SERVICIO DISPONIBLE*\nEl anterior compañero no respondió. Es tu turno:\n🔗 https://integrarepara.es/aceptar.html?t=${newToken}`); } else { await pool.query("UPDATE scraped_services SET automation_status = 'failed' WHERE id = $1", [ping.scraped_id]);