From af4a94fdca21cf3c280a9af0a3ceee11d03f9156 Mon Sep 17 00:00:00 2001 From: marsalva Date: Sun, 29 Mar 2026 10:18:42 +0000 Subject: [PATCH] Actualizar server.js --- server.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index d9cab69..fca2d35 100644 --- a/server.js +++ b/server.js @@ -1278,11 +1278,12 @@ app.get("/public/portal/:token", async (req, res) => { const client = qClient.rows[0]; const ownerId = client.owner_id; - // 2. Buscamos los datos de la empresa - const qConfig = await pool.query("SELECT full_name, company_logo FROM users WHERE id = $1", [ownerId]); + // 2. Buscamos los datos de la empresa Y SUS DATOS FISCALES (Para el PDF) + const qConfig = await pool.query("SELECT full_name, company_logo, billing_settings FROM users WHERE id = $1", [ownerId]); const company = { name: qConfig.rows[0]?.full_name || "IntegraRepara", - logo: qConfig.rows[0]?.company_logo || null + logo: qConfig.rows[0]?.company_logo || null, + billing_settings: qConfig.rows[0]?.billing_settings || null }; // 3. CONSULTA SEGURA (Con o sin ID) @@ -1330,6 +1331,83 @@ app.get("/public/portal/:token", async (req, res) => { }; }); + // 💰 4. BUSCAR PRESUPUESTOS CON TODOS LOS DETALLES PARA EL PDF + let cleanPhoneSearch = String(client.phone || "").replace(/[^0-9]/g, ""); + if (cleanPhoneSearch.length > 9) cleanPhoneSearch = cleanPhoneSearch.slice(-9); + + let formattedQuotes = []; + if (cleanPhoneSearch.length >= 9) { + const qBudgets = await pool.query(` + SELECT id, client_name, client_phone, client_address, items, subtotal, tax, total, status, created_at + FROM budgets + WHERE owner_id = $1 + AND client_phone LIKE $2 + ORDER BY created_at DESC + `, [ownerId, `%${cleanPhoneSearch}%`]); + + formattedQuotes = qBudgets.rows.map(b => ({ + id: b.id, + quote_ref: `PRE-${b.id}`, + title: "Presupuesto de Reparación", + amount: parseFloat(b.total).toFixed(2), + created_at: b.created_at, + // Datos puros para el PDF: + items: b.items, + subtotal: b.subtotal, + tax: b.tax, + client_name: b.client_name, + client_phone: b.client_phone, + client_address: b.client_address + })); + } + + res.json({ ok: true, client: { name: client.full_name }, company, services: formattedServices, quotes: formattedQuotes }); + + // 3. CONSULTA SEGURA (Con o sin ID) + let qServices; + if (serviceId && !isNaN(parseInt(serviceId))) { + qServices = await pool.query(` + SELECT s.id, s.service_ref, s.is_urgent, s.raw_data, s.created_at, + st.name as real_status_name, st.is_final as is_status_final, + u.full_name as worker_name, u.phone as worker_phone + FROM scraped_services s + LEFT JOIN users u ON u.id = s.assigned_to + LEFT JOIN service_statuses st ON st.id::text = (s.raw_data->>'status_operativo')::text + WHERE s.id = $1 AND s.owner_id = $2 AND s.provider != 'SYSTEM_BLOCK' + `, [parseInt(serviceId), ownerId]); + } else { + let phoneMatch = String(client.phone || "").replace(/[^0-9]/g, ""); + if (phoneMatch.length > 9) phoneMatch = phoneMatch.slice(-9); + if (phoneMatch.length < 6) phoneMatch = "TELEFONO_FALSO_123"; + + qServices = await pool.query(` + SELECT s.id, s.service_ref, s.is_urgent, s.raw_data, s.created_at, + st.name as real_status_name, st.is_final as is_status_final, + u.full_name as worker_name, u.phone as worker_phone + FROM scraped_services s + LEFT JOIN users u ON u.id = s.assigned_to + LEFT JOIN service_statuses st ON st.id::text = (s.raw_data->>'status_operativo')::text + WHERE s.owner_id = $1 AND s.provider != 'SYSTEM_BLOCK' + AND s.raw_data::text ILIKE $2 + ORDER BY s.created_at DESC + `, [ownerId, `%${phoneMatch}%`]); + } + + const formattedServices = qServices.rows.map(s => { + return { + id: s.id, + title: s.is_urgent ? `🚨 URGENTE: #${s.service_ref}` : `Expediente #${s.service_ref}`, + description: s.raw_data?.["Descripción"] || s.raw_data?.["DESCRIPCION"] || "Aviso de reparación", + status_name: s.real_status_name || "En gestión", + is_final: s.is_status_final || false, + scheduled_date: s.raw_data?.scheduled_date || "", + scheduled_time: s.raw_data?.scheduled_time || "", + assigned_worker: s.worker_name || null, + worker_phone: s.worker_phone || null, + raw_data: s.raw_data + }; + }); + // 💰 4. AÑADIDO SAAS: BUSCAR PRESUPUESTOS DEL CLIENTE // Comparamos el teléfono del cliente quitándole los prefijos para asegurar que caza let cleanPhoneSearch = String(client.phone || "").replace(/[^0-9]/g, "");