feat(superadmin): página "Secretária IA" com motivos de liga/desliga por sessão
Nova aba no super admin (/superadmin/secretaria): tabela com quem ligou/desligou a Secretária de cada número, quando e o MOTIVO do desligamento. Endpoint /api/superadmin/secretaria-desligamentos (superadminGuard) busca o log global no motor (resolve um e-mail de dono pareado; log é global). Item no Sidebar + rotas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -9438,6 +9438,27 @@ app.get('/api/superadmin/login-log', superadminGuard, async (req, res) => {
|
||||
} catch (err) { res.status(500).json({ error: err.message }); }
|
||||
});
|
||||
|
||||
// Super admin: motivos de LIGAR/DESLIGAR a Secretária por sessão (histórico global,
|
||||
// vem do motor — sec_session_power_log). Requer integração newwhats configurada.
|
||||
app.get('/api/superadmin/secretaria-desligamentos', superadminGuard, async (req, res) => {
|
||||
try {
|
||||
const { getConfig } = await import('./newwhats/config.js');
|
||||
const cfg = getConfig();
|
||||
if (!cfg.motorUrl || !cfg.integrationKey) return res.json({ configurado: false, log: [] });
|
||||
// O log é GLOBAL no motor; qualquer conta de dono pareada serve para autenticar.
|
||||
const { rows } = await pool.query(`SELECT u.email FROM usuarios u JOIN vinculos v ON v.usuario_id = u.id WHERE v.role IN ('donoclinica','donoconsultorio') ORDER BY u.email LIMIT 1`);
|
||||
const email = rows[0]?.email;
|
||||
if (!email) return res.json({ configurado: true, log: [] });
|
||||
const limit = Math.min(500, Math.max(1, parseInt(String(req.query.limit || '150'), 10)));
|
||||
const r = await fetch(`${cfg.motorUrl}/api/ext/v1/secretaria/session-power/log?limit=${limit}`, {
|
||||
headers: { 'x-nw-key': cfg.integrationKey, 'x-nw-email': email },
|
||||
});
|
||||
if (!r.ok) return res.status(502).json({ error: 'Motor indisponível', status: r.status });
|
||||
const log = await r.json();
|
||||
res.json({ configurado: true, log: Array.isArray(log) ? log : [] });
|
||||
} catch (err) { res.status(500).json({ error: err.message }); }
|
||||
});
|
||||
|
||||
// Defaults mesclados sob o JSON salvo: chaves novas (biomedico, add-ons de plugin)
|
||||
// aparecem na tabela mesmo p/ configs gravadas antes delas existirem.
|
||||
const PRICING_DEFAULTS = {
|
||||
|
||||
Reference in New Issue
Block a user