156 lines
5.7 KiB
JavaScript
156 lines
5.7 KiB
JavaScript
const express = require('express');
|
|
const crypto = require('crypto');
|
|
const { requireRole } = require('../middleware/auth');
|
|
const { recordActivity } = require('../services/activityService');
|
|
|
|
const requireApiKey = (req, res) => {
|
|
if (req.user.is_api_key) return true;
|
|
res.status(403).json({ error: 'Endpoint restrito a chaves de API.' });
|
|
return false;
|
|
};
|
|
|
|
const createIntegrationsRouter = ({ pool }) => {
|
|
const router = express.Router();
|
|
|
|
router.get('/integration/users', requireRole(['admin']), async (req, res) => {
|
|
if (!requireApiKey(req, res)) return;
|
|
try {
|
|
const [rows] = await pool.query(
|
|
'SELECT u.id, u.name, u.email, t.name as team_name FROM users u LEFT JOIN teams t ON u.team_id = t.id WHERE u.tenant_id = ? AND u.status = "active"',
|
|
[req.user.tenant_id]
|
|
);
|
|
res.json(rows);
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
router.get('/integration/origins', requireRole(['admin']), async (req, res) => {
|
|
if (!requireApiKey(req, res)) return;
|
|
try {
|
|
const [groups] = await pool.query('SELECT id, name FROM origin_groups WHERE tenant_id = ?', [req.user.tenant_id]);
|
|
if (groups.length === 0) return res.json([]);
|
|
|
|
const [items] = await pool.query('SELECT origin_group_id, name FROM origin_items WHERE origin_group_id IN (?) ORDER BY created_at ASC', [groups.map(g => g.id)]);
|
|
const [teams] = await pool.query('SELECT id as team_id, name as team_name, origin_group_id FROM teams WHERE tenant_id = ? AND origin_group_id IS NOT NULL', [req.user.tenant_id]);
|
|
|
|
const result = groups.map(g => ({
|
|
group_name: g.name,
|
|
origins: items.filter(i => i.origin_group_id === g.id).map(i => i.name),
|
|
assigned_teams: teams.filter(t => t.origin_group_id === g.id).map(t => ({ id: t.team_id, name: t.team_name }))
|
|
}));
|
|
|
|
res.json(result);
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
router.get('/integration/funnels', requireRole(['admin']), async (req, res) => {
|
|
if (!requireApiKey(req, res)) return;
|
|
try {
|
|
const [funnels] = await pool.query('SELECT id, name FROM funnels WHERE tenant_id = ?', [req.user.tenant_id]);
|
|
if (funnels.length === 0) return res.json([]);
|
|
|
|
const [stages] = await pool.query('SELECT funnel_id, name, order_index FROM funnel_stages WHERE funnel_id IN (?) ORDER BY order_index ASC', [funnels.map(f => f.id)]);
|
|
const [teams] = await pool.query('SELECT id as team_id, name as team_name, funnel_id FROM teams WHERE tenant_id = ? AND funnel_id IS NOT NULL', [req.user.tenant_id]);
|
|
|
|
const result = funnels.map(f => ({
|
|
funnel_name: f.name,
|
|
stages: stages.filter(s => s.funnel_id === f.id).map(s => s.name),
|
|
assigned_teams: teams.filter(t => t.funnel_id === f.id).map(t => ({ id: t.team_id, name: t.team_name }))
|
|
}));
|
|
|
|
res.json(result);
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
router.post('/integration/attendances', requireRole(['admin']), async (req, res) => {
|
|
if (!requireApiKey(req, res)) return;
|
|
|
|
const {
|
|
user_id,
|
|
origin,
|
|
funnel_stage,
|
|
title,
|
|
full_summary,
|
|
score,
|
|
first_response_time_min,
|
|
handling_time_min,
|
|
product_requested,
|
|
product_sold,
|
|
converted,
|
|
attention_points,
|
|
improvement_points
|
|
} = req.body;
|
|
|
|
if (!user_id || !origin || !funnel_stage || !title) {
|
|
return res.status(400).json({ error: 'Campos obrigatórios ausentes: user_id, origin, funnel_stage, title' });
|
|
}
|
|
|
|
try {
|
|
const [users] = await pool.query('SELECT id FROM users WHERE id = ? AND tenant_id = ? AND status = "active"', [user_id, req.user.tenant_id]);
|
|
if (users.length === 0) return res.status(400).json({ error: 'user_id inválido, inativo ou não pertence a esta organização.' });
|
|
|
|
const attId = `att_${crypto.randomUUID().split('-')[0]}`;
|
|
await pool.query(
|
|
`INSERT INTO attendances (
|
|
id, tenant_id, user_id, title, full_summary, score,
|
|
first_response_time_min, handling_time_min,
|
|
funnel_stage, origin, product_requested, product_sold,
|
|
converted, attention_points, improvement_points
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
[
|
|
attId,
|
|
req.user.tenant_id,
|
|
user_id,
|
|
title,
|
|
full_summary || null,
|
|
score || 0,
|
|
first_response_time_min || 0,
|
|
handling_time_min || 0,
|
|
funnel_stage,
|
|
origin,
|
|
product_requested || null,
|
|
product_sold || null,
|
|
converted ? 1 : 0,
|
|
attention_points ? JSON.stringify(attention_points) : null,
|
|
improvement_points ? JSON.stringify(improvement_points) : null
|
|
]
|
|
);
|
|
|
|
if (converted) {
|
|
const [managers] = await pool.query(
|
|
"SELECT id FROM users WHERE tenant_id = ? AND role IN ('admin', 'manager') AND id != ?",
|
|
[req.user.tenant_id, user_id]
|
|
);
|
|
const [agentInfo] = await pool.query("SELECT name FROM users WHERE id = ?", [user_id]);
|
|
const agentName = agentInfo[0]?.name || 'Um agente';
|
|
|
|
for (const m of managers) {
|
|
await recordActivity(pool, {
|
|
userId: m.id,
|
|
type: 'success',
|
|
title: 'Venda Fechada!',
|
|
message: `${agentName} converteu um lead em ${funnel_stage}.`,
|
|
link: `/attendances/${attId}`,
|
|
});
|
|
}
|
|
}
|
|
|
|
res.status(201).json({ id: attId, message: 'Atendimento registrado com sucesso.' });
|
|
} catch (error) {
|
|
console.error('Integration Error:', error);
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
return router;
|
|
};
|
|
|
|
module.exports = {
|
|
createIntegrationsRouter,
|
|
};
|