Files
scoreodonto.com/backend/newwhats/checklist-defs.js
T
VPS 4 Builder ec76dfeec2 feat(newwhats): checklist trata telefone compartilhado e profissional não cadastrado
Fecha furos de identificação relatados:
- Telefone compartilhado na família: nova pergunta telefone_compartilhado +
  cautelas IDENTIDADE/TELEFONE COMPARTILHADO — a IA nunca assume quem fala pelo
  número (ex.: cadastrado no filho, mas quem fala é a mãe; ou pergunta do marido)
  e confirma nome + para quem é antes de agendar; se não bater, encaminha ao humano.
- Profissional não cadastrado: cautela para citações de dentista fora da lista
  (ex.: prótese com Dr. de fora) — encaminha ao humano e pede no resumo que o
  dono cadastre o profissional.
- Pendência de config quando telefone_compartilhado=Sim (completar cadastro dos familiares).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 15:51:09 +02:00

100 lines
6.7 KiB
JavaScript

// Checklist do DONO do workspace: perguntas Sim/Não sobre a clínica que a
// Secretária IA usa para saber quando PODE agendar sozinha e quando deve ter
// cautela. As respostas são conferidas contra o banco (dentistas/pacientes):
// quando a declaração do dono não bate com os dados, geramos uma PENDÊNCIA
// para ele configurar/cadastrar — e a IA fica cautelosa (encaminha ao humano).
//
// Fonte única: config (UI), consistência (pendências) e injeção no cérebro
// (cautelas) consomem esta mesma definição para nunca divergirem.
export const CHECKLIST_QUESTOES = [
{
chave: 'multi_dentista',
pergunta: 'A clínica tem mais de um dentista?',
ajuda: 'Se sim, a Secretária não pode assumir um único dentista nem "clínico geral" por padrão — precisa saber quem atende cada paciente.',
},
{
chave: 'pacientes_cadastrados',
pergunta: 'Os pacientes já estão cadastrados no sistema (/pacientes)?',
ajuda: 'Mesmo que sim, o cadastro pode estar INCOMPLETO (nem todos os familiares). A Secretária confirma a identidade antes de agendar e encaminha ao humano quando não reconhece quem fala.',
},
{
chave: 'telefone_compartilhado',
pergunta: 'Um mesmo telefone pode ser de vários pacientes (família)?',
ajuda: 'Ex.: o número está no cadastro do filho, mas quem manda mensagem é a mãe. Se sim, a Secretária SEMPRE confirma com quem está falando e para quem é o atendimento — nunca assume pelo número.',
},
{
chave: 'dentista_fixo',
pergunta: 'Cada paciente tem um dentista de referência (fixo)?',
ajuda: 'Se sim, um paciente de retorno deve voltar para o MESMO dentista — a IA não deve agendá-lo no clínico geral.',
},
];
const sim = (r, k) => r[k] === 1;
const nao = (r, k) => r[k] === 0;
// Pendências de CONFIG do dono: a declaração não bate com o banco.
// counts = { dentistas, pacientes }.
export function pendenciasDeConfig(respostas, counts) {
const r = respostas || {};
const dentistas = Number(counts?.dentistas || 0);
const pacientes = Number(counts?.pacientes || 0);
const P = [];
if (sim(r, 'multi_dentista') && dentistas <= 1)
P.push({ chave: 'multi_dentista', severidade: 'alta', titulo: 'Cadastre os demais dentistas',
detalhe: `Você indicou que a clínica tem mais de um dentista, mas há apenas ${dentistas} cadastrado. A Secretária não consegue direcionar cada paciente ao dentista certo — cadastre os outros dentistas.` });
if (nao(r, 'multi_dentista') && dentistas > 1)
P.push({ chave: 'multi_dentista', severidade: 'media', titulo: 'Confirme quantos dentistas atendem',
detalhe: `Você indicou um único dentista, mas há ${dentistas} cadastrados no sistema. Ajuste a resposta ou os cadastros.` });
if (sim(r, 'pacientes_cadastrados') && pacientes === 0)
P.push({ chave: 'pacientes_cadastrados', severidade: 'alta', titulo: 'Cadastre os pacientes',
detalhe: 'Você indicou que os pacientes estão cadastrados, mas não há nenhum paciente no sistema. A Secretária não reconhece quem já é paciente.' });
if (r['pacientes_cadastrados'] == null || nao(r, 'pacientes_cadastrados'))
P.push({ chave: 'pacientes_cadastrados', severidade: 'media', titulo: 'Complete o cadastro de pacientes',
detalhe: 'Enquanto os pacientes não estiverem cadastrados, a Secretária vai encaminhar todo retorno para a secretária humana confirmar (não agenda sozinha).' });
if (sim(r, 'dentista_fixo') && dentistas <= 1 && sim(r, 'multi_dentista'))
P.push({ chave: 'dentista_fixo', severidade: 'media', titulo: 'Cadastre os dentistas de referência',
detalhe: 'Você indicou que cada paciente tem um dentista fixo, mas o sistema ainda não tem os dentistas todos cadastrados para fazer esse vínculo.' });
if (sim(r, 'telefone_compartilhado'))
P.push({ chave: 'telefone_compartilhado', severidade: 'media', titulo: 'Complete o cadastro de cada familiar',
detalhe: 'Como um mesmo telefone pode ser de vários pacientes (ex.: cadastrado só no filho, mas quem fala é a mãe), a Secretária vai SEMPRE confirmar quem está falando e não assume pelo número. Mantenha cada familiar cadastrado e vinculado ao número para ela acertar mais e encaminhar menos ao humano.' });
return P;
}
// Cautelas para injetar no cérebro da IA (texto direto no system prompt).
export function cautelasParaIA(respostas, counts) {
const r = respostas || {};
const dentistas = Number(counts?.dentistas || 0);
const pacientes = Number(counts?.pacientes || 0);
const C = [];
const multi = sim(r, 'multi_dentista') || dentistas > 1;
const temPacientes = pacientes > 0 || sim(r, 'pacientes_cadastrados');
const telShared = sim(r, 'telefone_compartilhado') || (temPacientes && r['telefone_compartilhado'] == null);
if (multi)
C.push('A clínica tem MAIS DE UM dentista: NUNCA assuma um dentista nem "clínico geral" por padrão para quem já é paciente. Descubra/pergunte qual dentista atende. Sem certeza → encaminhe ao humano.');
if (sim(r, 'multi_dentista') && dentistas <= 1)
C.push('ATENÇÃO: o sistema ainda não tem todos os dentistas cadastrados. Para pacientes de retorno ou que pedem um dentista específico, encaminhe ao humano — NÃO agende no clínico geral.');
if (sim(r, 'dentista_fixo'))
C.push('Cada paciente tem um dentista fixo: um retorno deve voltar ao MESMO dentista. Se você não sabe qual é (falta cadastro), encaminhe ao humano.');
// Identidade de quem fala — o cadastro é incompleto e o telefone é ambíguo.
if (temPacientes)
C.push('IDENTIDADE: o cadastro pode estar INCOMPLETO. Ao achar um paciente pelo telefone, NÃO assuma que é quem está falando — confirme o NOME de quem fala e PARA QUEM é o atendimento antes de qualquer coisa.');
if (telShared)
C.push('TELEFONE COMPARTILHADO: um mesmo número pode ser de vários da família (ex.: está no cadastro do filho, mas quem fala é a mãe; ou perguntam pelo tratamento do marido). SEMPRE pergunte com quem você fala e de quem é o atendimento; se a pessoa/atendimento não bater com o cadastro do número, encaminhe ao humano — não agende no paciente errado.');
if (pacientes === 0 || nao(r, 'pacientes_cadastrados'))
C.push('O cadastro de pacientes está incompleto: você NÃO consegue confirmar histórico nem o dentista de quem diz já ser paciente. Nesses casos, encaminhe ao humano em vez de agendar.');
// Profissional citado que não existe na lista de dentistas (sempre possível).
C.push('PROFISSIONAL NÃO CADASTRADO: se o cliente citar um dentista/profissional que NÃO está na lista de dentistas acima (ex.: prótese com um Dr. de fora), NÃO invente nem agende — encaminhe ao humano com encaminhar_humano e diga NO RESUMO que o profissional citado não está cadastrado, para o dono cadastrá-lo.');
return C;
}