Actualizar server.js
This commit is contained in:
58
server.js
58
server.js
@@ -2099,7 +2099,7 @@ app.patch("/budgets/:id/status", authMiddleware, async (req, res) => {
|
|||||||
// Convertir Presupuesto en Servicio Activo
|
// Convertir Presupuesto en Servicio Activo
|
||||||
app.post("/budgets/:id/convert", authMiddleware, async (req, res) => {
|
app.post("/budgets/:id/convert", authMiddleware, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { date, time } = req.body;
|
const { date, time, guild_id, assigned_to, use_automation } = req.body;
|
||||||
const bq = await pool.query("SELECT * FROM budgets WHERE id=$1 AND owner_id=$2", [req.params.id, req.user.accountId]);
|
const bq = await pool.query("SELECT * FROM budgets WHERE id=$1 AND owner_id=$2", [req.params.id, req.user.accountId]);
|
||||||
if (bq.rowCount === 0) return res.status(404).json({ok: false});
|
if (bq.rowCount === 0) return res.status(404).json({ok: false});
|
||||||
const budget = bq.rows[0];
|
const budget = bq.rows[0];
|
||||||
@@ -2111,28 +2111,70 @@ app.post("/budgets/:id/convert", authMiddleware, async (req, res) => {
|
|||||||
"Dirección": budget.client_address,
|
"Dirección": budget.client_address,
|
||||||
"Compañía": "Particular",
|
"Compañía": "Particular",
|
||||||
"Descripción": "PRESUPUESTO ACEPTADO.\n" + budget.items.map(i => `${i.qty}x ${i.concept}`).join("\n"),
|
"Descripción": "PRESUPUESTO ACEPTADO.\n" + budget.items.map(i => `${i.qty}x ${i.concept}`).join("\n"),
|
||||||
"scheduled_date": date,
|
"guild_id": guild_id || null,
|
||||||
"scheduled_time": time
|
"assigned_to": assigned_to || null,
|
||||||
|
"scheduled_date": date || "",
|
||||||
|
"scheduled_time": time || ""
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2. Insertamos en el Panel Operativo (Buzón)
|
// 2. Insertamos en el Panel Operativo (Buzón)
|
||||||
const insertSvc = await pool.query(
|
const insertSvc = await pool.query(
|
||||||
"INSERT INTO scraped_services (owner_id, provider, service_ref, status, automation_status, raw_data) VALUES ($1, 'particular', $2, 'pending', 'manual', $3) RETURNING id",
|
"INSERT INTO scraped_services (owner_id, provider, service_ref, status, automation_status, assigned_to, raw_data) VALUES ($1, 'particular', $2, 'pending', $3, $4, $5) RETURNING id",
|
||||||
[req.user.accountId, `PRE-${budget.id}`, JSON.stringify(rawData)]
|
[
|
||||||
|
req.user.accountId,
|
||||||
|
`PRE-${budget.id}`,
|
||||||
|
use_automation ? 'manual' : 'manual', // Empezamos en manual siempre
|
||||||
|
assigned_to || null,
|
||||||
|
JSON.stringify(rawData)
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const newServiceId = insertSvc.rows[0].id;
|
||||||
|
|
||||||
// 3. Marcamos presupuesto como convertido y le enlazamos la ficha financiera por el total
|
// 3. Marcamos presupuesto como convertido y le enlazamos la ficha financiera por el total
|
||||||
await pool.query("UPDATE budgets SET status='converted' WHERE id=$1", [budget.id]);
|
await pool.query("UPDATE budgets SET status='converted' WHERE id=$1", [budget.id]);
|
||||||
await pool.query(
|
await pool.query(
|
||||||
"INSERT INTO service_financials (scraped_id, amount, payment_method) VALUES ($1, $2, 'Pendiente')",
|
"INSERT INTO service_financials (scraped_id, amount, payment_method) VALUES ($1, $2, 'Pendiente')",
|
||||||
[insertSvc.rows[0].id, budget.total]
|
[newServiceId, budget.total]
|
||||||
);
|
);
|
||||||
|
|
||||||
// 4. Mandamos WhatsApp de confirmación
|
// 4. Si pide automatización, la disparamos internamente simulando la llamada
|
||||||
if (budget.client_phone) {
|
if (use_automation && guild_id) {
|
||||||
|
// Buscamos código postal por si acaso para la automatización
|
||||||
|
const cpMatch = budget.client_address ? budget.client_address.match(/\b\d{5}\b/) : null;
|
||||||
|
const cp = cpMatch ? cpMatch[0] : "00000"; // Fallback si no hay CP
|
||||||
|
|
||||||
|
// Reutilizamos la lógica de automatización (hacemos un fetch a nosotros mismos para aprovechar el motor existente)
|
||||||
|
const port = process.env.PORT || 3000;
|
||||||
|
const autoUrl = `http://localhost:${port}/providers/automate/${newServiceId}`;
|
||||||
|
|
||||||
|
// Lo lanzamos sin esperar (asíncrono) para no bloquear la respuesta
|
||||||
|
fetch(autoUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${req.headers.authorization.split(' ')[1]}` },
|
||||||
|
body: JSON.stringify({ guild_id, cp, useDelay: false })
|
||||||
|
}).catch(e => console.error("Error lanzando automatización interna:", e));
|
||||||
|
|
||||||
|
// Si va a la bolsa, no avisamos al cliente de la fecha (aún no se sabe)
|
||||||
|
if (budget.client_phone) {
|
||||||
|
const msg = `✅ *PRESUPUESTO ACEPTADO*\n\nHola ${budget.client_name}, confirmamos la aceptación del presupuesto por un total de *${budget.total}€*.\n\nEn breve un técnico se pondrá en contacto contigo para agendar la cita. ¡Gracias por confiar en nosotros!`;
|
||||||
|
sendWhatsAppAuto(budget.client_phone, msg, `cliente_${req.user.accountId}`, false).catch(console.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 5. Si se asigna manual con fecha
|
||||||
|
else if (budget.client_phone && date && time) {
|
||||||
const [y, m, d] = date.split('-');
|
const [y, m, d] = date.split('-');
|
||||||
const msg = `✅ *PRESUPUESTO ACEPTADO*\n\nHola ${budget.client_name}, confirmamos la aceptación del presupuesto por un total de *${budget.total}€*.\n\nEl servicio ha sido agendado para el *${d}/${m}/${y} a las ${time}*. ¡Gracias por confiar en nosotros!`;
|
const msg = `✅ *PRESUPUESTO ACEPTADO*\n\nHola ${budget.client_name}, confirmamos la aceptación del presupuesto por un total de *${budget.total}€*.\n\nEl servicio ha sido agendado para el *${d}/${m}/${y} a las ${time}*. ¡Gracias por confiar en nosotros!`;
|
||||||
sendWhatsAppAuto(budget.client_phone, msg, `cliente_${req.user.accountId}`, false).catch(console.error);
|
sendWhatsAppAuto(budget.client_phone, msg, `cliente_${req.user.accountId}`, false).catch(console.error);
|
||||||
|
|
||||||
|
// Forzar estado Asignado si hay un técnico
|
||||||
|
if (assigned_to) {
|
||||||
|
const statusQ = await pool.query("SELECT id FROM service_statuses WHERE owner_id=$1 AND name ILIKE '%asignado%' LIMIT 1", [req.user.accountId]);
|
||||||
|
if (statusQ.rowCount > 0) {
|
||||||
|
rawData.status_operativo = statusQ.rows[0].id;
|
||||||
|
await pool.query("UPDATE scraped_services SET raw_data = $1 WHERE id = $2", [JSON.stringify(rawData), newServiceId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json({ ok: true });
|
res.json({ ok: true });
|
||||||
|
|||||||
Reference in New Issue
Block a user