Actualizar server.js
This commit is contained in:
72
server.js
72
server.js
@@ -618,7 +618,7 @@ app.get("/whatsapp/status", authMiddleware, (req, res, next) => requirePlan(req,
|
|||||||
// 🧠 MOTOR INTELIGENTE DE AGENDAMIENTO Y AGENDA ADMIN
|
// 🧠 MOTOR INTELIGENTE DE AGENDAMIENTO Y AGENDA ADMIN
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|
||||||
// 1. Obtener huecos disponibles inteligentes (Bloqueando por duración)
|
// 1. Obtener huecos disponibles inteligentes (Bloqueando por duración y GREMIO)
|
||||||
app.get("/public/portal/:token/slots", async (req, res) => {
|
app.get("/public/portal/:token/slots", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { token } = req.params;
|
const { token } = req.params;
|
||||||
@@ -636,14 +636,17 @@ app.get("/public/portal/:token/slots", async (req, res) => {
|
|||||||
|
|
||||||
const raw = service.raw_data || {};
|
const raw = service.raw_data || {};
|
||||||
const targetZone = (raw["Población"] || raw["POBLACION-PROVINCIA"] || raw["Código Postal"] || "").toLowerCase().trim();
|
const targetZone = (raw["Población"] || raw["POBLACION-PROVINCIA"] || raw["Código Postal"] || "").toLowerCase().trim();
|
||||||
|
const targetGuildId = raw["guild_id"]; // Extraemos el gremio del servicio actual
|
||||||
|
|
||||||
// Extraemos la agenda respetando la duración (duration_minutes)
|
// Extraemos la agenda respetando la duración (duration_minutes) y el gremio bloqueado
|
||||||
const agendaQ = await pool.query(`
|
const agendaQ = await pool.query(`
|
||||||
SELECT raw_data->>'scheduled_date' as date,
|
SELECT raw_data->>'scheduled_date' as date,
|
||||||
raw_data->>'scheduled_time' as time,
|
raw_data->>'scheduled_time' as time,
|
||||||
raw_data->>'duration_minutes' as duration,
|
raw_data->>'duration_minutes' as duration,
|
||||||
raw_data->>'Población' as poblacion,
|
raw_data->>'Población' as poblacion,
|
||||||
raw_data->>'Código Postal' as cp
|
raw_data->>'Código Postal' as cp,
|
||||||
|
provider,
|
||||||
|
raw_data->>'blocked_guild_id' as blocked_guild_id
|
||||||
FROM scraped_services
|
FROM scraped_services
|
||||||
WHERE assigned_to = $1
|
WHERE assigned_to = $1
|
||||||
AND raw_data->>'scheduled_date' IS NOT NULL
|
AND raw_data->>'scheduled_date' IS NOT NULL
|
||||||
@@ -652,6 +655,13 @@ app.get("/public/portal/:token/slots", async (req, res) => {
|
|||||||
|
|
||||||
const agendaMap = {};
|
const agendaMap = {};
|
||||||
agendaQ.rows.forEach(row => {
|
agendaQ.rows.forEach(row => {
|
||||||
|
// INTELIGENCIA DE GREMIOS:
|
||||||
|
// Si es un bloqueo de agenda que tiene un gremio específico, y NO coincide con el gremio del servicio actual...
|
||||||
|
// ¡Lo ignoramos! (El hueco sigue libre para este servicio)
|
||||||
|
if (row.provider === 'SYSTEM_BLOCK' && row.blocked_guild_id && String(row.blocked_guild_id) !== String(targetGuildId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!agendaMap[row.date]) agendaMap[row.date] = { times: [], zone: (row.poblacion || row.cp || "").toLowerCase().trim() };
|
if (!agendaMap[row.date]) agendaMap[row.date] = { times: [], zone: (row.poblacion || row.cp || "").toLowerCase().trim() };
|
||||||
|
|
||||||
// Calculamos cuántas horas bloquea este servicio según su duración
|
// Calculamos cuántas horas bloquea este servicio según su duración
|
||||||
@@ -704,7 +714,7 @@ app.get("/public/portal/:token/slots", async (req, res) => {
|
|||||||
d.setDate(d.getDate() + 1);
|
d.setDate(d.getDate() + 1);
|
||||||
}
|
}
|
||||||
res.json({ ok: true, days: availableDays });
|
res.json({ ok: true, days: availableDays });
|
||||||
} catch (e) { res.status(500).json({ ok: false }); }
|
} catch (e) { console.error("Error Slots:", e); res.status(500).json({ ok: false }); }
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2. Guardar la cita como "SOLICITUD PENDIENTE"
|
// 2. Guardar la cita como "SOLICITUD PENDIENTE"
|
||||||
@@ -820,6 +830,60 @@ app.post("/agenda/requests/:id/reject", authMiddleware, async (req, res) => {
|
|||||||
} catch (e) { res.status(500).json({ok: false}); }
|
} catch (e) { res.status(500).json({ok: false}); }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 6. RUTAS DE BLOQUEOS (AGENDA) CON SOPORTE PARA GREMIOS
|
||||||
|
app.post("/agenda/blocks", authMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { worker_id, date, time, duration, reason, guild_id, guild_name } = req.body;
|
||||||
|
|
||||||
|
const raw = {
|
||||||
|
"Nombre Cliente": "BLOQUEO DE AGENDA",
|
||||||
|
"Descripción": reason,
|
||||||
|
scheduled_date: date,
|
||||||
|
scheduled_time: time,
|
||||||
|
duration_minutes: duration,
|
||||||
|
blocked_guild_id: guild_id || null, // Guardamos el gremio
|
||||||
|
blocked_guild_name: guild_name || null
|
||||||
|
};
|
||||||
|
|
||||||
|
await pool.query(`
|
||||||
|
INSERT INTO scraped_services (owner_id, provider, service_ref, status, assigned_to, raw_data)
|
||||||
|
VALUES ($1, 'SYSTEM_BLOCK', 'BLOCK-' || extract(epoch from now())::int, 'pending', $2, $3)
|
||||||
|
`, [req.user.accountId, worker_id, JSON.stringify(raw)]);
|
||||||
|
|
||||||
|
res.json({ ok: true });
|
||||||
|
} catch(e) { res.status(500).json({ ok: false }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get("/agenda/blocks", authMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const q = await pool.query(`
|
||||||
|
SELECT s.id, u.full_name as worker_name,
|
||||||
|
s.raw_data->>'scheduled_date' as date,
|
||||||
|
s.raw_data->>'scheduled_time' as time,
|
||||||
|
s.raw_data->>'duration_minutes' as duration,
|
||||||
|
s.raw_data->>'Descripción' as reason,
|
||||||
|
s.raw_data->>'blocked_guild_name' as guild_name
|
||||||
|
FROM scraped_services s
|
||||||
|
JOIN users u ON s.assigned_to = u.id
|
||||||
|
WHERE s.owner_id = $1 AND s.provider = 'SYSTEM_BLOCK'
|
||||||
|
AND s.raw_data->>'scheduled_date' >= CURRENT_DATE::text
|
||||||
|
ORDER BY s.raw_data->>'scheduled_date' ASC
|
||||||
|
`, [req.user.accountId]);
|
||||||
|
|
||||||
|
res.json({ ok: true, blocks: q.rows });
|
||||||
|
} catch(e) { res.status(500).json({ ok: false }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
app.delete("/agenda/blocks/:id", authMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
await pool.query("DELETE FROM scraped_services WHERE id=$1 AND owner_id=$2 AND provider='SYSTEM_BLOCK'", [req.params.id, req.user.accountId]);
|
||||||
|
res.json({ ok: true });
|
||||||
|
} catch(e) { res.status(500).json({ ok: false }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// ⚙️ MOTOR AUTOMÁTICO DE WHATSAPP
|
// ⚙️ MOTOR AUTOMÁTICO DE WHATSAPP
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|||||||
Reference in New Issue
Block a user