diff --git a/backend/newwhats/agenda-bridge.js b/backend/newwhats/agenda-bridge.js index 957eacd..3976dcf 100644 --- a/backend/newwhats/agenda-bridge.js +++ b/backend/newwhats/agenda-bridge.js @@ -451,6 +451,12 @@ export function createAgendaBridge(pool) { const { rows } = await pool.query(`SELECT texto FROM agenda_situacoes WHERE clinica_id = $1 AND ativo = 1 ORDER BY ordem, created_at`, [clinicaId]); situacoes = rows.map((r) => r.texto); } catch { /* tabela pode não existir ainda */ } + // Procedimentos que a clínica NÃO atende → a Secretária responde com o script. + let procedimentos_nao_atende = []; + try { + const { rows } = await pool.query(`SELECT nome, motivo, como_falar FROM agenda_procedimentos WHERE clinica_id = $1 AND atende = 0 ORDER BY ordem, nome`, [clinicaId]); + procedimentos_nao_atende = rows.map((r) => ({ nome: r.nome, motivo: r.motivo || null, como_falar: r.como_falar || null })); + } catch { /* tabela pode não existir ainda */ } // Cautelas do checklist do dono (declaração × dados reais) → a IA não chuta. let cautelas = []; try { @@ -466,6 +472,7 @@ export function createAgendaBridge(pool) { especialidades: Array.isArray(d.especialidades) ? d.especialidades : (d.especialidade ? [d.especialidade] : []), })), situacoes, + procedimentos_nao_atende, cautelas, }); } catch (e) { res.status(500).json({ error: e.message }); } diff --git a/backend/newwhats/agenda-config.js b/backend/newwhats/agenda-config.js index 197cf91..108e0aa 100644 --- a/backend/newwhats/agenda-config.js +++ b/backend/newwhats/agenda-config.js @@ -243,6 +243,50 @@ export function createAgendaConfig(pool) { finally { client.release(); } }); + // ── Procedimentos que a clínica atende / não atende (dono) ──────────────────── + router.get('/clinica/:clinicaId/procedimentos-atende', async (req, res) => { + const clinicaId = req.params.clinicaId; + try { + let { rows } = await pool.query( + `SELECT id, nome, atende, motivo, como_falar, ordem FROM agenda_procedimentos WHERE clinica_id = $1 ORDER BY ordem, nome`, [clinicaId]); + // Primeira vez: semeia a lista a partir do catálogo de procedimentos da clínica (atende=1). + if (!rows.length) { + const { rows: cat } = await pool.query( + `SELECT DISTINCT nome FROM procedimentos WHERE (clinica_id = $1 OR clinica_id IS NULL) AND ativo IS DISTINCT FROM false AND nome IS NOT NULL AND nome <> '' ORDER BY nome`, [clinicaId]); + const client = await pool.connect(); + try { + await client.query('BEGIN'); + let i = 0; + for (const c of cat) await client.query(`INSERT INTO agenda_procedimentos (id, clinica_id, nome, atende, ordem) VALUES ($1,$2,$3,1,$4)`, [uid('prc'), clinicaId, c.nome, i++]); + await client.query('COMMIT'); + } catch { try { await client.query('ROLLBACK'); } catch {} } finally { client.release(); } + ({ rows } = await pool.query(`SELECT id, nome, atende, motivo, como_falar, ordem FROM agenda_procedimentos WHERE clinica_id = $1 ORDER BY ordem, nome`, [clinicaId])); + } + res.json({ procedimentos: rows }); + } catch (e) { res.status(500).json({ error: e.message }); } + }); + // Substitui toda a lista. Body: { procedimentos: [{nome, atende, motivo, como_falar}] } + router.put('/clinica/:clinicaId/procedimentos-atende', async (req, res) => { + const clinicaId = req.params.clinicaId; + if (!(await isDono(pool, clinicaId, req.nwUser.userId))) return res.status(403).json({ error: 'Apenas o dono pode configurar os procedimentos.' }); + const linhas = Array.isArray(req.body?.procedimentos) ? req.body.procedimentos : []; + const client = await pool.connect(); + try { + await client.query('BEGIN'); + await client.query('DELETE FROM agenda_procedimentos WHERE clinica_id = $1', [clinicaId]); + let i = 0; + for (const p of linhas) { + const nome = String(p?.nome || '').trim(); if (!nome) continue; + const atende = (p?.atende === false || p?.atende === 0) ? 0 : 1; + await client.query( + `INSERT INTO agenda_procedimentos (id, clinica_id, nome, atende, motivo, como_falar, ordem) VALUES ($1,$2,$3,$4,$5,$6,$7)`, + [uid('prc'), clinicaId, nome, atende, atende ? null : (String(p?.motivo || '').trim() || null), atende ? null : (String(p?.como_falar || '').trim() || null), i++]); + } + await client.query('COMMIT'); res.json({ ok: true }); + } catch (e) { try { await client.query('ROLLBACK'); } catch {} res.status(500).json({ error: e.message }); } + finally { client.release(); } + }); + // ── Checklist do DONO + pendências (só o dono do workspace) ─────────────────── // Conta dentistas/pacientes reais da clínica p/ conferir contra as respostas. async function contagens(clinicaId) { diff --git a/backend/newwhats/agenda-schema.js b/backend/newwhats/agenda-schema.js index c07ba0e..b33f077 100644 --- a/backend/newwhats/agenda-schema.js +++ b/backend/newwhats/agenda-schema.js @@ -98,6 +98,21 @@ export async function ensureAgendaSchema(pool) { )`); await pool.query(`CREATE INDEX IF NOT EXISTS idx_agenda_situacoes_clinica ON agenda_situacoes (clinica_id)`); + // ── agenda_procedimentos — o que a clínica ATENDE ou não. Desmarcado (atende=0) + // = não atende: guarda o motivo e o "como_falar" (script p/ a Secretária responder). + await pool.query(` + CREATE TABLE IF NOT EXISTS agenda_procedimentos ( + id varchar PRIMARY KEY, + clinica_id varchar NOT NULL, + nome text NOT NULL, + atende smallint DEFAULT 1, + motivo text, + como_falar text, + ordem integer DEFAULT 0, + created_at timestamptz DEFAULT now() + )`); + await pool.query(`CREATE INDEX IF NOT EXISTS idx_agenda_procedimentos_clinica ON agenda_procedimentos (clinica_id)`); + // ── agenda_checklist — respostas Sim/Não do DONO sobre a clínica (ver // checklist-defs.js). Conferidas contra o banco → geram pendências de config // e deixam a Secretária cautelosa. resposta: 1=sim, 0=não, NULL=não respondido.