Files
agenciapsilmno/supabase/functions/save-intake-progress
Leonardo b8ea292ef1 Grupo 8: agenda ↔ WhatsApp completo (8.2 lembrar manual, 8.3 status→msg, 8.4 lead)
=== 8.2 Botão "Lembrar paciente" na agenda ===

Edge nova send-session-reminder-manual:
- Recebe {event_id}, autoriza (member ativo do tenant), resolve template
  lembrete_sessao (custom → default global), envia via Evolution, registra
  outbound em conversation_messages + log em session_reminder_logs com
  reminder_type='manual'.
- Reusa lógica do cron reminders (sanitização, fmt datas, render template)
  mas sem janela/dedup — terapeuta pode redisparar quantas vezes quiser
  (log usa UPSERT; UNIQUE (event_id, reminder_type) sobrescreve).

Migration 20260423000008 adiciona 'manual' ao CHECK constraint de
session_reminder_logs.reminder_type.

UI: botão verde pi-whatsapp no footer do AgendaEventDialog (só em edit
de sessão com paciente vinculado). Confirm dialog + toast + erros
amigáveis (no_phone, invalid_phone, no_active_channel, template_not_found,
forbidden, send_failed).

=== 8.3 Status sessão dispara mensagem ===

Migration 20260423000009 cria trigger AFTER UPDATE OF status em
agenda_eventos: quando status muda pra cancelado/remarcado/confirmado,
dispara edge send-session-status-notification via pg_net (não bloqueia
o UPDATE). Settings app.settings.supabase_url/service_role_key reusadas.

Edge nova send-session-status-notification:
- Body {event_id, old_status, new_status}
- STATUS_TEMPLATE_MAP: cancelado→cancelamento_sessao, remarcado→
  remarcacao_sessao, confirmado→confirmacao_sessao.
- Respeita opt-out (conversation_optouts), canal ativo, template
  existente (tenant-specific → global default). Skip silencioso em
  caso de falta de config.
- Insere outbound em conversation_messages (sem log unique — múltiplas
  mudanças de status geram múltiplas mensagens por design).

=== 8.4 Intake abandonado vira lead no CRM ===

Migration 20260423000010:
- Adiciona 'in_progress' e 'abandoned_lead' ao CHECK de
  patient_intake_requests.status. Colunas last_progress_at e
  lead_thread_key.
- RPC convert_abandoned_intake_to_lead(intake_id): cria mensagem
  placeholder inbound no CRM do tenant (thread_key anon:{phone}) +
  conversation_notes com resumo dos dados coletados + marca status.

Edge save-intake-progress:
- POST {token, nome_completo?, telefone?, email_principal?, ...}
- Whitelist de campos (ALLOWED_FIELDS) pra proteger contra POST
  malicioso tentar setar status/owner/etc.
- Busca por token, set status='in_progress' se era 'new', atualiza
  campos enviados + last_progress_at.

Edge convert-abandoned-intakes (cron):
- Body opcional {idle_minutes} (default 30).
- Varre patient_intake_requests status='in_progress' + last_progress_at
  mais antigo que cutoff. Filtra só os com nome_completo OU telefone
  (contato mínimo pra valer lead). Chama RPC pra cada um.

Hook no form público CadastroPacienteExterno:
- Watch em nome_completo, telefone, email_principal, onde_nos_conheceu
  dispara scheduleProgressSave() com debounce 1.5s.
- savePartialProgress só chama a edge se tem nome OU telefone.
- Silent fail — autosave não é crítico.

Cron do convert-abandoned-intakes NÃO ativado automaticamente (igual
heartbeat/SLA). Template comentado não está na migration — admin
descomenta SELECT cron.schedule manualmente quando quiser ligar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 22:25:33 -03:00
..