feat(comunicacao-interna): notificação de número compartilhado + agenda de contatos

Opção (b) — mesma pessoa/número servindo a papéis diferentes, roteando por situação:
- GET /api/comunicacao/numero-lookup: ao digitar um número, avisa se ele já é de outra
  conta/papel da clínica (ex.: número na conta dentista aparece ao editar a de dono).
  Modal mostra banner "pode compartilhar — descreva as situações; a Secretária roteia".
- Bridge GET /contatos: agenda de contatos internos (nome, papel, situações de cada
  número, janela atual) p/ a Secretária rotear por assunto. Não expõe o número cru.

Verificado E2E: lookup como dono acha o nº na conta dentista; /contatos lista papel+situações.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Builder
2026-07-07 22:48:42 +02:00
parent eafc1578e3
commit b253feb4aa
3 changed files with 81 additions and 1 deletions
+26
View File
@@ -7585,6 +7585,32 @@ async function podeEditarComunicacao(reqUserId, alvoUserId, clinicaId) {
return ['donoclinica', 'donoconsultorio', 'admin'].includes(rows[0]?.role || '');
}
// Lookup: este número já está cadastrado por OUTRA pessoa da clínica? (notificação de
// número compartilhado — a mesma pessoa pode ter contas/papéis diferentes).
// Definido ANTES de /:usuarioId para não ser capturado pela rota-parâmetro.
app.get('/api/comunicacao/numero-lookup', authGuard, async (req, res) => {
try {
const clinicaId = String(req.query.clinicaId || '');
const tel = String(req.query.numero || '').replace(/\D/g, '').slice(-8);
if (!clinicaId || tel.length < 8) return res.json({ encontrados: [] });
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 pc.usuario_id <> $2`,
[clinicaId, req.authUser.userId]);
const encontrados = [];
for (const r of rows) {
const nums = Array.isArray(r.numeros) ? r.numeros : [];
if (nums.some((n) => String(n.numero || '').replace(/\D/g, '').slice(-8) === tel)) {
encontrados.push({ usuario_id: r.usuario_id, nome: r.nome, role: r.role });
}
}
res.json({ encontrados });
} catch (e) { res.status(500).json({ error: e.message }); }
});
app.get('/api/comunicacao/:usuarioId', authGuard, async (req, res) => {
try {
const alvo = req.params.usuarioId === 'me' ? req.authUser.userId : req.params.usuarioId;