Actualizar server.js
This commit is contained in:
74
server.js
74
server.js
@@ -471,6 +471,7 @@ app.post("/public/assignment/respond", async (req, res) => {
|
|||||||
app.get("/public/portal/:token", async (req, res) => {
|
app.get("/public/portal/:token", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { token } = req.params;
|
const { token } = req.params;
|
||||||
|
// 1. Identificamos al cliente
|
||||||
const clientQ = await pool.query(`
|
const clientQ = await pool.query(`
|
||||||
SELECT c.id, c.full_name, c.phone, c.addresses, c.owner_id,
|
SELECT c.id, c.full_name, c.phone, c.addresses, c.owner_id,
|
||||||
u.company_slug, u.full_name as company_name
|
u.company_slug, u.full_name as company_name
|
||||||
@@ -482,22 +483,49 @@ app.get("/public/portal/:token", async (req, res) => {
|
|||||||
if (clientQ.rowCount === 0) return res.status(404).json({ ok: false, error: "Enlace no válido o caducado" });
|
if (clientQ.rowCount === 0) return res.status(404).json({ ok: false, error: "Enlace no válido o caducado" });
|
||||||
const clientData = clientQ.rows[0];
|
const clientData = clientQ.rows[0];
|
||||||
|
|
||||||
const servicesQ = await pool.query(`
|
// 2. Buscamos los expedientes en el Panel Operativo (scraped_services)
|
||||||
SELECT s.id, s.title, s.description, s.scheduled_date, s.scheduled_time, s.created_at,
|
const phoneRaw = clientData.phone.replace('+34', '');
|
||||||
st.name as status_name, st.color as status_color, st.is_final,
|
const scrapedQ = await pool.query(`
|
||||||
u.full_name as assigned_worker
|
SELECT id, service_ref as title, raw_data->>'Descripción' as description,
|
||||||
FROM services s
|
raw_data->>'scheduled_date' as scheduled_date,
|
||||||
LEFT JOIN service_statuses st ON s.status_id = st.id
|
raw_data->>'scheduled_time' as scheduled_time,
|
||||||
LEFT JOIN users u ON s.assigned_to = u.id
|
created_at,
|
||||||
WHERE s.client_id = $1
|
raw_data->>'status_operativo' as estado_operativo,
|
||||||
ORDER BY s.created_at DESC
|
(SELECT full_name FROM users WHERE id = scraped_services.assigned_to) as assigned_worker
|
||||||
`, [clientData.id]);
|
FROM scraped_services
|
||||||
|
WHERE owner_id = $1
|
||||||
|
AND (raw_data->>'Teléfono' ILIKE $2 OR raw_data->>'TELEFONO' ILIKE $2 OR raw_data->>'TELEFONOS' ILIKE $2)
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
`, [clientData.owner_id, `%${phoneRaw}%`]);
|
||||||
|
|
||||||
|
// Adaptamos el formato visual de los estados
|
||||||
|
const services = scrapedQ.rows.map(s => {
|
||||||
|
let statusName = "Pendiente de Asignar"; let color = "gray";
|
||||||
|
if (s.estado_operativo === 'asignado_operario') { statusName = "Asignado a Técnico"; color = "blue"; }
|
||||||
|
if (s.estado_operativo === 'citado') { statusName = "Visita Agendada"; color = "emerald"; }
|
||||||
|
if (s.estado_operativo === 'de_camino') { statusName = "Técnico de Camino"; color = "indigo"; }
|
||||||
|
if (s.estado_operativo === 'trabajando') { statusName = "En Reparación"; color = "amber"; }
|
||||||
|
if (s.estado_operativo === 'incidencia') { statusName = "Pausado / Incidencia"; color = "red"; }
|
||||||
|
if (s.estado_operativo === 'terminado') { statusName = "Terminado"; color = "purple"; }
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: s.id,
|
||||||
|
title: "Expediente #" + s.title,
|
||||||
|
description: s.description || "Avería reportada.",
|
||||||
|
scheduled_date: s.scheduled_date,
|
||||||
|
scheduled_time: s.scheduled_time,
|
||||||
|
created_at: s.created_at,
|
||||||
|
status_name: statusName,
|
||||||
|
status_color: color,
|
||||||
|
assigned_worker: s.assigned_worker || "Pendiente"
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
ok: true,
|
ok: true,
|
||||||
client: { name: clientData.full_name, phone: clientData.phone, addresses: clientData.addresses },
|
client: { name: clientData.full_name, phone: clientData.phone, addresses: clientData.addresses },
|
||||||
company: { name: clientData.company_name, slug: clientData.company_slug },
|
company: { name: clientData.company_name, slug: clientData.company_slug },
|
||||||
services: servicesQ.rows
|
services: services
|
||||||
});
|
});
|
||||||
} catch (e) { res.status(500).json({ ok: false, error: "Error de servidor" }); }
|
} catch (e) { res.status(500).json({ ok: false, error: "Error de servidor" }); }
|
||||||
});
|
});
|
||||||
@@ -873,10 +901,30 @@ app.post("/discovery/save", authMiddleware, async (req, res) => {
|
|||||||
} catch (e) { await client.query('ROLLBACK'); res.status(500).json({ ok: false }); } finally { client.release(); }
|
} catch (e) { await client.query('ROLLBACK'); res.status(500).json({ ok: false }); } finally { client.release(); }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// AÑADIDO: Asegura que el cliente exista. Si no existe, lo crea y le asigna un token.
|
||||||
|
app.post("/clients/ensure", authMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { phone, name, address } = req.body;
|
||||||
|
const p = normalizePhone(phone);
|
||||||
|
if(!p) return res.status(400).json({ok: false, error: "Sin teléfono"});
|
||||||
|
|
||||||
|
// 1. Buscamos si ya existe
|
||||||
|
const q = await pool.query("SELECT * FROM clients WHERE phone=$1 AND owner_id=$2 LIMIT 1", [p, req.user.accountId]);
|
||||||
|
if (q.rowCount > 0) return res.json({ ok: true, client: q.rows[0] });
|
||||||
|
|
||||||
|
// 2. Si no existe, lo creamos al vuelo en la agenda para que se genere su portal_token
|
||||||
|
const insert = await pool.query(
|
||||||
|
"INSERT INTO clients (owner_id, full_name, phone, addresses) VALUES ($1, $2, $3, $4) RETURNING *",
|
||||||
|
[req.user.accountId, name || 'Asegurado', p, JSON.stringify(address ? [address] : [])]
|
||||||
|
);
|
||||||
|
res.json({ ok: true, client: insert.rows[0] });
|
||||||
|
} catch (e) { res.status(500).json({ ok: false }); }
|
||||||
|
});
|
||||||
|
|
||||||
app.get("/clients", authMiddleware, async (req, res) => {
|
app.get("/clients", authMiddleware, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { search } = req.query;
|
const { search } = req.query;
|
||||||
let query = `SELECT c.*, (SELECT COUNT(*) FROM services s WHERE s.client_id = c.id) as service_count FROM clients c WHERE c.owner_id = $1`;
|
let query = `SELECT c.*, c.portal_token, (SELECT COUNT(*) FROM services s WHERE s.client_id = c.id) as service_count FROM clients c WHERE c.owner_id = $1`;
|
||||||
const params = [req.user.accountId];
|
const params = [req.user.accountId];
|
||||||
if (search) { query += ` AND (c.full_name ILIKE $2 OR c.phone ILIKE $2)`; params.push(`%${search}%`); }
|
if (search) { query += ` AND (c.full_name ILIKE $2 OR c.phone ILIKE $2)`; params.push(`%${search}%`); }
|
||||||
query += ` ORDER BY c.created_at DESC LIMIT 50`;
|
query += ` ORDER BY c.created_at DESC LIMIT 50`;
|
||||||
@@ -888,7 +936,7 @@ app.get("/clients", authMiddleware, async (req, res) => {
|
|||||||
app.get("/clients/:id/details", authMiddleware, async (req, res) => {
|
app.get("/clients/:id/details", authMiddleware, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const clientId = req.params.id;
|
const clientId = req.params.id;
|
||||||
const clientQ = await pool.query("SELECT * FROM clients WHERE id=$1 AND owner_id=$2", [clientId, req.user.accountId]);
|
const clientQ = await pool.query("SELECT id, full_name, phone, addresses, email, notes, portal_token, created_at FROM clients WHERE id=$1 AND owner_id=$2", [clientId, req.user.accountId]);
|
||||||
if (clientQ.rowCount === 0) return res.status(404).json({ ok: false });
|
if (clientQ.rowCount === 0) return res.status(404).json({ ok: false });
|
||||||
const servicesQ = await pool.query(`SELECT s.*, st.name as status_name, st.color as status_color, u.full_name as assigned_name FROM services s LEFT JOIN service_statuses st ON s.status_id = st.id LEFT JOIN users u ON s.assigned_to = u.id WHERE s.client_id = $1 ORDER BY s.created_at DESC`, [clientId]);
|
const servicesQ = await pool.query(`SELECT s.*, st.name as status_name, st.color as status_color, u.full_name as assigned_name FROM services s LEFT JOIN service_statuses st ON s.status_id = st.id LEFT JOIN users u ON s.assigned_to = u.id WHERE s.client_id = $1 ORDER BY s.created_at DESC`, [clientId]);
|
||||||
res.json({ ok: true, client: clientQ.rows[0], services: servicesQ.rows });
|
res.json({ ok: true, client: clientQ.rows[0], services: servicesQ.rows });
|
||||||
|
|||||||
Reference in New Issue
Block a user