feat(agenda-bridge): /responsavel-contato p/ consultar o dono (com janela)

Resolve o contato do dono/responsável p/ decisões da clínica: por nome (pessoa da
lista de contatos — cobre o dono cujo número está na conta de dentista) ou por papel
(dono/responsável). Mesma forma do /dentista-contato (contato_agora, bloqueado_por_janela,
proxima_janela[_ts]). Verificado: por nome resolve o número compartilhado.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Builder
2026-07-07 23:00:39 +02:00
parent b253feb4aa
commit e8d1a5547e
+41
View File
@@ -472,6 +472,47 @@ export function createAgendaBridge(pool) {
} catch (e) { res.status(500).json({ error: e.message }); }
});
// ── GET /responsavel-contato ────────────────────────────────────────────────────
// Resolve o contato do DONO/RESPONSÁVEL p/ uma decisão da clínica, com a janela.
// nome? = pessoa específica (da lista de contatos — cobre o caso do dono cujo número
// está na conta de dentista); sem nome = dono/responsável por papel. Mesma forma do
// /dentista-contato (contato_agora / bloqueado_por_janela / proxima_janela[_ts]).
router.get('/responsavel-contato', async (req, res) => {
const clinicaId = String(req.query.clinica_id || '');
if (!clinicaId) return res.status(400).json({ error: 'clinica_id obrigatório' });
try {
let row = null;
if (req.query.nome) {
const { rows } = await pool.query(
`SELECT pc.usuario_id, pc.numeros, u.nome, v.role
FROM pessoa_comunicacao pc
LEFT JOIN usuarios u ON u.id = pc.usuario_id
LEFT JOIN vinculos v ON v.usuario_id = pc.usuario_id AND v.clinica_id = pc.clinica_id
WHERE pc.clinica_id = $1 AND lower(u.nome) LIKE '%'||lower($2)||'%' LIMIT 1`,
[clinicaId, String(req.query.nome)]);
row = rows[0] || null;
}
if (!row) {
const { rows } = await pool.query(
`SELECT pc.usuario_id, pc.numeros, u.nome, v.role
FROM pessoa_comunicacao pc
JOIN vinculos v ON v.usuario_id = pc.usuario_id AND v.clinica_id = pc.clinica_id
LEFT JOIN usuarios u ON u.id = pc.usuario_id
WHERE pc.clinica_id = $1 AND v.role IN ('donoclinica','donoconsultorio','admin')
ORDER BY v.role LIMIT 1`,
[clinicaId]);
row = rows[0] || null;
}
if (!row) return res.json({ encontrado: false });
const numeros = Array.isArray(row.numeros) ? row.numeros : [];
const agora = contatoPermitidoAgora(numeros);
const prox = agora ? null : proximaJanela(numeros);
res.json({ encontrado: true, usuario_id: row.usuario_id, nome: row.nome, papel: row.role,
telefone: agora ? agora.numero : null, contato_agora: agora,
bloqueado_por_janela: !agora, proxima_janela: prox ? prox.label : null, proxima_janela_ts: prox ? prox.ts : null });
} catch (e) { res.status(500).json({ error: e.message }); }
});
// ── GET /contatos ─────────────────────────────────────────────────────────────
// "Agenda de contatos internos" p/ roteamento por SITUAÇÃO. Lista todas as pessoas da
// clínica (dono/dentista/funcionário) com o papel, as situações de cada número e se pode