Actualizar server.js
This commit is contained in:
78
server.js
78
server.js
@@ -353,6 +353,84 @@ app.delete("/statuses/:id", authMiddleware, async (req, res) => {
|
|||||||
app.get("/templates", authMiddleware, async (req, res) => { try { const q = await pool.query("SELECT * FROM message_templates WHERE owner_id=$1", [req.user.accountId]); res.json({ ok: true, templates: q.rows }); } catch (e) { res.status(500).json({ ok: false }); } });
|
app.get("/templates", authMiddleware, async (req, res) => { try { const q = await pool.query("SELECT * FROM message_templates WHERE owner_id=$1", [req.user.accountId]); res.json({ ok: true, templates: q.rows }); } catch (e) { res.status(500).json({ ok: false }); } });
|
||||||
app.post("/templates", authMiddleware, async (req, res) => { try { const { type, content } = req.body; await pool.query(`INSERT INTO message_templates (owner_id, type, content) VALUES ($1, $2, $3) ON CONFLICT (owner_id, type) DO UPDATE SET content = EXCLUDED.content`, [req.user.accountId, type, content]); res.json({ ok: true }); } catch (e) { res.status(500).json({ ok: false }); } });
|
app.post("/templates", authMiddleware, async (req, res) => { try { const { type, content } = req.body; await pool.query(`INSERT INTO message_templates (owner_id, type, content) VALUES ($1, $2, $3) ON CONFLICT (owner_id, type) DO UPDATE SET content = EXCLUDED.content`, [req.user.accountId, type, content]); res.json({ ok: true }); } catch (e) { res.status(500).json({ ok: false }); } });
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 👥 GESTIÓN DE CLIENTES (CRM)
|
||||||
|
// =========================
|
||||||
|
|
||||||
|
// 1. Obtener lista de clientes con contador de servicios
|
||||||
|
app.get("/clients", authMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { search } = req.query;
|
||||||
|
let query = `
|
||||||
|
SELECT c.*,
|
||||||
|
(SELECT COUNT(*) FROM services s WHERE s.client_id = c.id) as service_count,
|
||||||
|
(SELECT MAX(created_at) FROM services s WHERE s.client_id = c.id) as last_service
|
||||||
|
FROM clients c
|
||||||
|
WHERE c.owner_id = $1
|
||||||
|
`;
|
||||||
|
const params = [req.user.accountId];
|
||||||
|
|
||||||
|
if (search) {
|
||||||
|
query += ` AND (c.full_name ILIKE $2 OR c.phone ILIKE $2 OR c.email ILIKE $2)`;
|
||||||
|
params.push(`%${search}%`);
|
||||||
|
}
|
||||||
|
|
||||||
|
query += ` ORDER BY c.created_at DESC LIMIT 50`; // Limitamos a 50 para no saturar
|
||||||
|
|
||||||
|
const q = await pool.query(query, params);
|
||||||
|
res.json({ ok: true, clients: q.rows });
|
||||||
|
} catch (e) { res.status(500).json({ ok: false, error: e.message }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Obtener un cliente DETALLADO (con direcciones y servicios)
|
||||||
|
app.get("/clients/:id/details", authMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const clientId = req.params.id;
|
||||||
|
|
||||||
|
// Datos del cliente
|
||||||
|
const clientQ = await pool.query("SELECT * FROM clients WHERE id=$1 AND owner_id=$2", [clientId, req.user.accountId]);
|
||||||
|
if (clientQ.rowCount === 0) return res.status(404).json({ ok: false });
|
||||||
|
|
||||||
|
// Historial de servicios
|
||||||
|
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 });
|
||||||
|
} catch (e) { res.status(500).json({ ok: false }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. Crear cliente manual (sin crear servicio)
|
||||||
|
app.post("/clients", authMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { full_name, phone, email, address, notes } = req.body;
|
||||||
|
const p = normalizePhone(phone);
|
||||||
|
const addrs = address ? JSON.stringify([address]) : '[]';
|
||||||
|
|
||||||
|
const q = await pool.query(
|
||||||
|
"INSERT INTO clients (owner_id, full_name, phone, email, addresses, notes) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id",
|
||||||
|
[req.user.accountId, full_name, p, email, addrs, notes]
|
||||||
|
);
|
||||||
|
res.json({ ok: true, id: q.rows[0].id });
|
||||||
|
} catch (e) { res.status(500).json({ ok: false }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. Actualizar notas o datos del cliente
|
||||||
|
app.put("/clients/:id", authMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { full_name, email, notes, addresses } = req.body;
|
||||||
|
await pool.query(
|
||||||
|
"UPDATE clients SET full_name=$1, email=$2, notes=$3, addresses=$4 WHERE id=$5 AND owner_id=$6",
|
||||||
|
[full_name, email, notes, JSON.stringify(addresses), req.params.id, req.user.accountId]
|
||||||
|
);
|
||||||
|
res.json({ ok: true });
|
||||||
|
} catch (e) { res.status(500).json({ ok: false }); }
|
||||||
|
});
|
||||||
|
|
||||||
// RESTO DE RUTAS CRUD...
|
// RESTO DE RUTAS CRUD...
|
||||||
app.get("/clients/search", authMiddleware, async (req, res) => { try { const { phone } = req.query; const p = normalizePhone(phone); if(!p) return res.json({ok:true,client:null}); const q = await pool.query("SELECT * FROM clients WHERE phone=$1 AND owner_id=$2 LIMIT 1", [p, req.user.accountId]); res.json({ ok: true, client: q.rows[0] || null }); } catch (e) { res.status(500).json({ ok: false }); } });
|
app.get("/clients/search", authMiddleware, async (req, res) => { try { const { phone } = req.query; const p = normalizePhone(phone); if(!p) return res.json({ok:true,client:null}); const q = await pool.query("SELECT * FROM clients WHERE phone=$1 AND owner_id=$2 LIMIT 1", [p, req.user.accountId]); res.json({ ok: true, client: q.rows[0] || null }); } catch (e) { res.status(500).json({ ok: false }); } });
|
||||||
app.get("/companies", authMiddleware, async (req, res) => { try { const q = await pool.query("SELECT * FROM companies WHERE owner_id=$1 ORDER BY name ASC", [req.user.accountId]); res.json({ ok: true, companies: q.rows }); } catch (e) { res.status(500).json({ ok: false }); } });
|
app.get("/companies", authMiddleware, async (req, res) => { try { const q = await pool.query("SELECT * FROM companies WHERE owner_id=$1 ORDER BY name ASC", [req.user.accountId]); res.json({ ok: true, companies: q.rows }); } catch (e) { res.status(500).json({ ok: false }); } });
|
||||||
|
|||||||
Reference in New Issue
Block a user