8601ac0d70dd3db79f3e185f1bd15d08c0c6708b
29 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8601ac0d70 |
compliance CFP #6: consent forms LGPD + Gravacao + tcle_online amend
ROADMAP item #1.2 #6 — biblioteca de consent forms editaveis. Migration 20260521000005 estende CHECK constraint document_templates.tipo com 2 valores novos: - termo_lgpd — consentimento de tratamento de dados pessoais - autorizacao_gravacao — autorizacao gravacao sessao (audio/video) Seed seed_060 adiciona 2 templates globais novos (is_global=true) + faz UPDATE no template tcle_online existente acrescentando clausula LGPD explicita (Art. 18 direitos do titular + contato exercer direitos). Templates anteriores (TCLE base, autorizacao_menor, termo_sigilo) ja referenciavam LGPD adequadamente. Sobra #7 (portal de assinatura) pra fechar Fase 1.2 Compliance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
cd67f7e9f5 |
compliance CFP: #5 registro profissional + #9 especialidades
ROADMAP Fase 1.2 (Compliance basico BR). Item #5: profiles ganha 3 colunas (professional_registration_type/number/uf) com CHECK constraint dos conselhos comuns (CRP, CRM, CRFa, CREFITO, CRESS, CRN, RMS, outro). Item #9: catalogo public.specialties + join M:N profile_specialties + RLS. Seed seed_050 popula 33 especialidades is_system=true (clinica, jurídica, neuropsicologia, ABA, TCC, psicanalise etc). Service specialtiesService.js no src/services pra consumo na UI. Item #8 (nome social) ja estava integrado. #6 (consent forms UI) e #7 (assinatura no portal) adiados — schemas document_templates e document_signatures existem, falta workflow UI dedicado. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
de3898878a |
asaas: Tier 1 Fase A foundation — migrations + service + edge function stubs
DESIGN_ASAAS_GATEWAY.md documenta arquitetura. Schema novo: 2 migrations (tables + RLS) cobrindo asaas_customers + asaas_payments + asaas_webhook_events. Client service asaasGatewayService.js no features/financeiro. 3 Edge Function stubs (create-payment-record, cancel-payment, sync-payment) — webhook financial_records eh Fase B. Bloqueadores Fase B (implementacao real): user precisa criar conta Asaas, gerar API keys, configurar webhook, setar ENV vars no Supabase. Decisao modelo de negocio (A/B/C) tambem pendente. Stops marcados claramente no DESIGN. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
0956e4facc |
M5: tenantship + admin members + accept_invite RPC
Modulo 5 da Fase 1 + quick wins fechados. features/tenantship/ com 2 services + 2 composables (members + invites). MembersPage.vue nova em views/pages/admin/ + rota /admin/members em routes.clinic. Migration 20260520000005 cria RPC accept_tenant_invite (SECURITY DEFINER + lock FOR UPDATE) — tenantInvitesRepository.acceptInvite agora chama RPC real (nao mais stub). SaasTenantFeaturesPage refatorada pra usar novo tenantFeatureAdminService. SetupWizardPage 2648 linhas deferido pra sessao dedicada. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
f94a4ae97f |
padronizacao: foundation Fase 0+0.5 — blueprints + auditoria + clinical_notes
Pre-MVP: 3 blueprints canonicos (repository, composable, quick-create overlay), AUDIT_BASELINE com 51 divergencias em 6 modulos, estrategia PADRONIZACAO de 4 fases, DESIGN_BILLING_ORCHESTRATOR. Schema clinical notes pronto pra Fase B (4 migrations + seed templates). AgendaEvent Dialog.vue.bak deletado (lixo de refator anterior). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c23d0a574f |
agenda: C5+C6 testes OK + atalho Gerar fatura + RPC idempotência fix
DB - migration 20260519000001: create_financial_record_for_session passa a ignorar status='cancelled' na idempotência (era bug — cancelar e tentar regerar travava silencioso retornando o cancelado) Cenário 5 (convênio) — fixes pra save + visualização - Convênio: amount lia 'price' (null) → agora detecta via insurance_plan_id e usa insurance_value. payment_method forçado 'convenio' (era 'asaas') - Popover: ev.price era null em convênio → normalize expõe insurance_value e paymentLabel faz fallback. Linha mostra "A receber R$ X" corretamente - /financeiro: branch novo pra payment_method='convenio' → pill violeta com pi-id-card (antes ficava sem indicador, igual particular) Cenário 6 (recorrente sem pacote, Maria Magali) — materialização - chargeMode='none' não materializava a 1ª (todas viravam virtuais, sem badge $). Agora materializa a 1ª no fluxo de criação recorrente - Bug intermediário: usei 'paciente_id' (Portuguese) mas agendaRepository dropa esse campo. Corrigido pra 'patient_id' (English DB column) Atalho "Gerar fatura" no popover - Pill amber pequeno ao lado de "A cobrar R$ X" no popover (paymentVariant ='none' + sessão materializada) - Wire em MelissaLayout via emit gerar-cobranca + handler onGerarCobrancaQuick (chama gerarCobrancaManual, fecha popover pra impedir double-click) - Bulk-load do useMelissaAgenda e fetchRecord do AgendaEventoFinanceiroPanel agora filtram status='cancelled' (resolve badge $ residual + botão sumido) Header do popover: info de pacote/série - "Sessão · Pacote · N sessões" ou "Sessão X de Y" abaixo do tipo (computed seriesLabel lê do _raw da rule) Título do dialog "Sessão do Pacote · Sessão" - Quando commitment name é "Sessão" (default), drop pra evitar duplicação - Outros nomes (Avaliação, etc) permanecem com forma completa Excluir série inteira (popover) - Novo botão "Excluir série" no popover quando evento pertence a recorrência - Hard delete: financial_records pendentes → agenda_eventos materializados → recurrence_rules (CASCADE leva exceptions + rule_services) - Bloqueia se algum record tem status='paid' (estornar primeiro) cancel_session some da agenda - useRecurrence.expandRules agora pula occurrence com exception type= 'cancel_session' (era visível com status cancelado; doc dizia "some da agenda" mas código mantinha. Honra a promessa do diálogo) - patient_missed / therapist_canceled / holiday_block permanecem visíveis como histórico UX outros - "+ Novo convênio" toolbar em ConfiguracoesConveniosPage (botão faltava — empty state mandava clicar em botão inexistente) - InsurancePlanServiceQuickCreateDialog: cadastrar procedimento POR CIMA do AgendaEventDialog sem sair da agenda. Auto-seleciona quando nada estava selecionado antes - Hint contextual abaixo do card Sessão/Honorários: convênio = "Nº guia opcional"; gratuito = "sem cobrança". Particular sem hint - recurrence_exceptions cancel agora usa upsert com onConflict (idempotente, não quebra com unique violation em re-cancel) - goToConveniosConfig removida (dead code após quick-create inline) CSS - .aed-row-50 perdeu margin-bottom (user request) - .field-card.mb-4 ganhou margin-top: 1rem (scoped a composer wrappers) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e95ed9b585 |
agenda: Fase 5 (status change/edit cobrada) + indicadores visuais + UX convenio
DB
- drop agenda_excecoes (substituida por financial_exceptions + lock-edit
baseado em financial_records)
- financial_records.payment_link (Asaas + link compartilhavel)
- financial_exceptions.consume_on_miss (rotular nao-show consome ou nao)
- billing_contracts.charging_style (upfront/saldo/per_session)
Payment refactor
- paymentSettlement -> paymentMethod (string) + markPaidNow (bool).
Handler aplica payment_method sempre; status='paid'+paid_at apenas
quando markPaidNow=true && method != 'link'. Asaas (link) sempre
liquida via webhook, nunca nasce paid.
- create_financial_record_for_session com pos-RPC patch pra payment_method
e (opcional) status='paid' quando user marca "ja recebi".
Indicadores visuais (3 canais distintos por estado)
- Paid: barra esquerda emerald-500 4px na agenda (MelissaAgenda),
pi-check-circle no popover/Resumo.
- Pending: badge \$ amber canto direito (mantido); linha amber no popover/
Resumo "A receber R\$ X (cobranca pendente)".
- Neutro: sem badge nem barra (compromisso pessoal, bloqueio, ou
ocorrencia virtual de pacote upfront/saldo).
- Bulk-load de paymentState em _reloadRange etapa 4 (1 query unica em
financial_records mapeada por agenda_evento_id).
- AgendaEventDialog Resumo lateral ganha linha entre pi-clock e
pi-map-marker via novo sessionPaymentRecord (sem guard de
occurrenceMode, contrario ao occFinancialRecord que continua so pra
Rail/Clinica). 5 estados: paid+paid_at, overdue+venceu, pending+vence,
sem cobranca c/ valor, sem cobranca s/ valor.
UX de convenio
- InsurancePlanServiceQuickCreateDialog novo: cadastra procedimento
POR CIMA do AgendaEventDialog sem sair da agenda. Auto-seleciona
novo procedimento so quando nada estava selecionado antes.
- Caixa cinza "Cadastrar procedimento" sempre visivel quando convenio
selecionado, com copy variavel (0 procedimentos: chamada urgente;
1+: "se quiser adicionar mais").
- "+ Novo convenio" toolbar em ConfiguracoesConveniosPage (botao
estava faltando, empty state mandava clicar em botao inexistente).
- Hint contextual abaixo do card Sessao/Honorarios: convenio = "N da
guia eh opcional", gratuito = "sem cobranca", particular = sem hint.
Label "N da Guia" tambem ganhou "(opcional)" no service-picker dialog.
Bug fixes
- pickDbFields whitelist faltando 'modalidade' (useMelissaAgenda.js:74)
— sessoes avulsas eram salvas como presencial independente da
escolha visual. Adicionado.
- goToConveniosConfig removida — fazia router.push("/therapist/
configuracoes/convenios") mas /configuracoes/* eh rota raiz, nao
filha. Substituida pelo quick-create inline (#1).
- bloqueioCobrindo + dialogBlockOverlap passados via deps em
_buildHandlers (refs do useMelissaAgenda nao sao acessiveis no
escopo de _buildHandlers).
Fase 5 (status change + edit cobrada)
- AgendaStatusChangeConfirmDialog: confirm dialog quando user muda
status pra realizada/faltou/cancelado, com opcoes de markPaid ou
gerar cobranca conforme o caso.
- useAgendaBloqueios novo composable: extrai logica de bloqueios
cinza (background events) do MelissaAgenda.
Doc viva
- src/docs/agenda-compromisso-financeiro-cenarios.html: 13 cenarios
de teste manual. C1-C4 ja validados. Cada teste validado vira parte
da doc final pra area de ajuda (pos-Fase 9).
Wiki/handoff
- agenda-compromisso-fluxo e agenda-billing-pesquisa-mercado (decisoes
arquiteturais sobre billing).
- HANDOFF.md atualizado.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
dba595fd2d |
db: migration session_default_notes_field + schema regenerado
Migration 20260511000001 adiciona campo 'notes' (Observacao, textarea, sort_order=30) como campo extra default no commitment determinado 'Sessao'. Antes Sessao era a unica excecao entre os nativos — Leitura/Supervisao/ Aula/Analise ja tinham. Padroniza pra que a Observacao da sessao siga o mesmo mecanismo de extra_fields dos outros, e o frontend remova a textarea hardcoded do AgendaEventDialog (proximo commit). Backfill: insere 'notes' em TODOS os commitments Sessao ja existentes (idempotente). Forward-fix: substitui a funcao seed_determined_commitments incluindo o bloco de Sessao + 'notes' pra novos tenants. Schema regenerado via db.cjs schema-export pra refletir o estado pos- migration. agenciapsi-db-dashboard.html regenerado pelo generate-dashboard.cjs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
15103eded5 |
Cleanup: backups antigos removidos + dashboard config + HANDOFF/log
- Remove database-novo/backups/2026-03-27 e 2026-03-29 (deveriam estar no gitignore, mas haviam sido tracked antes) - Atualiza db.config.json + generate-dashboard.cjs + dashboard.html - HANDOFF.md atualizado com estado de 05-05 (sprint blueprint tabular + arquivamento de pacientes) - Obsidian/Brain/log.md: entrada da sessao 05-05 adicionada Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
957e912a7f |
Melissa polish + Prontuario Visao Geral + agenda historico
Sprints B (05-03) e C (05-04) acumulados: - NotificationDrawer/Item redesign (visual mais limpo, ações inline) - Dock pins compose (useMelissaDockPins) + cache store global (melissaCacheStore) - MelissaAgenda: timeline FullCalendar parity + cards resumo, histórico card com useMelissaAgendaHistorico, MelissaEventoPanel ajustado - useFeriados: cache opt-in pra evitar fetch redundante de feriados - PatientProntuario: aba Visão Geral nova; PatientConversationsTab polish - AgendaClinicMosaic / AgendaTerapeutaPage / useAgendaSettings: ajustes de paridade com Melissa - DocumentsListPage: pequenos ajustes - DB migration 20260504000001: fix do trigger pra status 'excluido' nas cancel_notifications Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
86311ef305 |
Melissa: hub Configuracoes + Embed + 9 Pages novas + dialog blueprint dark
Sprints 04-29 + 04-30 acumuladas. - MelissaConfiguracoes: hub 2-col com 6 grupos (Layout/Conta/Agenda/ Financeiro/WhatsApp/Sistema), tudo embedado via MelissaEmbed. - MelissaEmbed: wrapper generico que injeta layout-variant=melissa e remove cromos pra reaproveitar Pages tradicionais. - 9 Melissa Pages novas: CadastrosRecebidos, Compromissos, Configuracoes, Conversas, Embed, Grupos, Medicos, Recorrencias, Tags. - Dialog blueprint atualizado: bg-gray-100 (hardcoded light) -> bg-[var(--surface-ground)] (tema-aware). 22 dialogs migrados em 9 arquivos. Anti-pattern documentado. - PatientsCadastroPage: bug fix dropdown Grupo (optionLabel nome->name), toggle vertical/abas com persist localStorage, sticky margin-top. - Surface picker no popover do MelissaLayout (8 swatches). - useTopbarPlanMenu, useMelissaWhatsapp, useMelissaPacientesAside novos. - Migration: status agenda remarcado/confirmado. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
629e7ce18e |
DB: melissa_prefs em user_settings + 'melissa' como layout_variant
Migration nova (database-novo/migrations/20260427000001_*):
- ALTER TABLE user_settings ADD COLUMN melissa_prefs jsonb DEFAULT '{}'
NOT NULL — guarda toqueTermino, overlayOpacity, bgImageOpacity, use24h,
cardsAtivos[] e cardsLayout. Sanitizacao no client antes do upsert.
- bgUrl (data URL da foto, MBs) NAO entra aqui — segue em localStorage
ate migrarmos pra Supabase Storage.
Schema canonico (tenants_multi_tenant.sql) atualizado em paralelo:
- mesma coluna melissa_prefs jsonb
- check de layout_variant agora aceita 'melissa' alem de 'classic' e
'rail' (precondicao pra plugar o tema Direcao B no preference real)
Leitura/escrita no client ainda pendente — feita em sessao separada.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
f2b15ce0f7 |
HANDOFF + cleanup: bug Teleport resolvido, backups antigos removidos
- HANDOFF.md atualizado: bug do chip do cronômetro resolvido em 2026-04-27. Causa-raiz documentada (múltiplos Teleports compartilhando target + Transition>Element v-if gera comment placeholder VNode → emitsOptions:null no shouldUpdateComponent) e fix oficial (Transition envolvendo Teleport). - Backups locais 2026-03-23 removidos do índice (já estavam .gitignored, apenas saneamento). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
1bcb969f72 |
Layout Melissa (Direção B): preview, /profile, Agenda, dock, cadastro
Sandbox completo do novo layout Win11 lockscreen-style. Não troca o
AppLayout atual — Fase 5 (router wire-up) fica pra sessão dedicada.
Estrutura
- src/layout/melissa/ — MelissaLayout (bg+ψ+overlays), MelissaCronometro,
MelissaAgenda (fullscreen), MelissaCard, MelissaMenu, MelissaBusca
- composables/useMelissaEventos.js — semana real do FC + range mensal
pros dots do mini-cal
- composables/useMelissaPacientes.js — agora retorna created_at p/ "novo"
- melissaToques.js — toques Web Audio do término
Rota e persistência
- /preview/melissa (sem auth, sem AppLayout)
- /account/profile ganha 3º card "Melissa" com badge "Em construção"
- bootstrapUserSettings + layout composable aceitam variant='melissa'
- Migration: CHECK constraint user_settings.layout_variant aceita 'melissa'
Light mode
- Gradiente Bloom flipa via CSS vars (--bloom-c1/c2/base-1/base-2)
Dark: 400/300/950 · Light: 200/100/0
- Cronômetro/Personalização: color: white → var(--m-text)
- Pílula psi-kbd ganha tokens --m-kbd-bg/--m-kbd-text
- Override mapeia text-X-200/300/400 → text-X-600 (17 cores Tailwind)
Agenda fullscreen
- Mini-cal funcional: click pula FC, range visível destacado, dots reais
- Feriados nacional/municipal/personalizado (rose/amber/violet)
- Dias fechados (workRules) cinza apagado, mutex feriado vence
- Card "Hoje" (stats+sessões) mesclado e movido pra sidebar esquerda
- ProximosFeriadosCard reaproveitado entre mini-cal e Hoje
- Avatar paciente: bg --m-accent-strong → --m-accent (saturado em light)
- Cores light: 12 substituições color:white → var(--m-text)
Dock taskbar Win11-style
- .melissa-dock 76px fixed bottom (CSS global, não scoped — Vue static
hoisting perderia data-v-{hash})
- ψ centralizado vertical na faixa (bottom:10px)
- Chip cronômetro teleportado pro dock + animação minimize macOS
(dialog encolhe + voa pro canto bottom-left, 340ms cubic-bezier)
- transform-origin: 96px calc(100% - 38px) (posição do chip no dock)
Pacientes na sidebar
- Botão fake "+" no topo abre PatientCreatePopover (rápido/completo/link)
- Reaproveita PatientCadastroDialog + ComponentCadastroRapido
- Pacientes criados nos últimos 7d sobem pro topo + badge "novo"
Dock contextual (ações do paciente selecionado)
- Avatar + nome + count + 5 ações (sessões/whatsapp/prontuário/editar/fechar)
- Teleportado pro .melissa-dock quando há paciente selecionado
- Em mobile, ações vivem em <Menu> kebab por linha
- Pattern <Transition><Teleport v-if> obrigatório (NUNCA o contrário)
pra evitar comment placeholder + emitsOptions:null no reconciler
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
f1c97ee906 |
Dashboard SaaS ganha seção de receita de créditos WhatsApp (Asaas)
Fecha o gap de analytics que faltava: MRR/ARR de assinatura já existia, mas não havia visão de receita dos créditos WhatsApp comprados via Asaas. Banco (migration 20260423000011) — 4 RPCs saas_admin only: - saas_wa_credits_revenue_stats(from, to): total arrecadado, count de compras, tenants únicos, créditos vendidos, ticket médio. - saas_wa_credits_top_packages(from, to): ranking top 10 pacotes por revenue, consolida nome atual se pacote foi renomeado. - saas_wa_credits_usage_summary(): snapshot atual de lifetime_purchased vs lifetime_used vs current_balance + taxa de consumo. - saas_wa_credits_revenue_evolution(from, to, bucket_days): série temporal pra sparkline. Todas com check is_saas_admin() no início + SECURITY DEFINER. Frontend: - useSaasCreditsAnalytics composable orquestra as 4 RPCs em paralelo com seleção de período (30d/90d/6m/12m) que ajusta bucket_days automaticamente. - SaasCreditsRevenueCard.vue: 4 KPIs (receita + ticket médio, compras + tenants, créditos vendidos, % consumo global), sparkline SVG com indicador de tendência, ranking top 5 pacotes. - Integrado no SaasDashboard logo antes da tabela "Distribuição por plano". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
c2c42a1620 |
3.7 Bot auto-triagem WhatsApp: config por tenant + hook nos inbound
Bot que coleta nome, motivo de busca e preferências ANTES do paciente
entrar no fluxo humano. Terapeuta abre a conversa e já encontra
resumo em conversation_notes.
Banco (migration 20260423000007):
- conversation_bots: config 1 por tenant. enabled, greeting/closing
messages, steps (JSONB array de {prompt, variable, type}), trigger_mode
(new_contact | all_unassigned | keyword), trigger_keywords[],
idle_timeout_minutes, respect_optout.
Defaults vêm com 4 perguntas úteis: nome, motivo, modalidade,
horário preferido.
- conversation_bot_sessions: estado por thread. current_step,
collected_data JSONB, status (active | completed | abandoned_idle |
abandoned_manual | opted_out). UNIQUE parcial garante 1 ativa por
(tenant, thread).
- RLS: leitura tenant/saas_admin, escrita admins (config) + service_role
(sessions, só edge altera).
Shared (_shared/whatsapp-hooks.ts):
- maybeProcessBot: carrega config, busca sessão ativa, avança step
com resposta, envia próxima pergunta via SendFn. Ao esgotar steps,
envia closing + cria conversation_notes com resumo das variáveis
coletadas. Se humano assume (conversation_assignments preenchido),
sessão marca 'abandoned_manual' e bot sai.
- Trigger modes:
- 'new_contact' (default): só inicia pra thread sem histórico bot
E sem paciente vinculado (lead real).
- 'all_unassigned': qualquer thread sem assignee.
- 'keyword': matched contra lista; normalizeForMatch já existe.
Integração nos inbound (ambos providers):
- evolution-whatsapp-inbound: chama maybeProcessBot após opt-in/opt-out,
ANTES do auto-reply. Se bot processou, skip auto-reply (senão duas
respostas sobrepostas).
- twilio-whatsapp-inbound: idem, usando makeTwilioCreditedSendFn pra
cobrar crédito de cada mensagem enviada pelo bot.
UI (/configuracoes/conversas-bots):
- Toggle enabled + Select trigger_mode + (se keyword) chips de keywords.
- Textareas greeting/closing.
- Editor de steps: reordenar (up/down), remover, add, editor com prompt
e variable (regex /^[a-z_][a-z0-9_]*$/).
- Botão "Padrão" restaura mensagens/steps default.
- InputNumber idle_timeout + toggle respect_optout.
- Card inferior: últimas 30 sessões (7 dias) com status, contato,
nome coletado (primeiro campo), progresso (step X/N), início.
- Entrada na landing de configurações + rota /configuracoes/conversas-bots.
Caveat conhecido: a resolução de conversation_notes.created_by usa
o primeiro admin ativo do tenant (pickAnyAdmin). Pra uma v2 seria
ideal ter um user "bot" sintético dedicado.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
adf9208d2d |
Analytics 7.1: tempo médio de 1ª resposta WhatsApp no dashboard
Card novo pra clínica e terapeuta com 3 métricas + sparkline: - Tempo médio (e mediana) de 1ª resposta no período - Taxa de SLA cumprido — % de respostas dentro do threshold configurado - Contagem total de respostas no período - Sparkline da evolução com indicador de tendência (melhorando/piorando) - Ranking top 5 terapeutas (só no ClinicDashboard) Filtro de período: 7/30/90 dias (muda granularidade do bucket: 1/7/15 dias pra sparkline com ~5-6 pontos). Banco (migration 20260423000006): - Helper interno _first_response_runs: identifica "runs" de inbound (sequências do paciente sem outbound entre) e calcula delta até a próxima outbound. Evita contar múltiplas mensagens repetidas do paciente. responder_id vem de conversation_assignments. - first_response_stats: agregados (count, avg, median, min, max, sla_compliance_rate baseado em conversation_sla_rules). - first_response_by_therapist: ranking com avg e count por assigned_to. - first_response_evolution: série temporal com bucket alinhado a p_from (p_from + bucket_index * N days). Parâmetro p_bucket_days deixa o frontend escolher granularidade por período. Todas SECURITY DEFINER + GRANT authenticated/service_role. Filtro opcional por therapist_id nas funções que aplicam. Frontend: - useFirstResponseAnalytics composable wraps as 3 RPCs com cache via Promise.all paralelo. Helper formatSeconds (Ns/Xmin/Xh). - FirstResponseCard.vue renderiza sparkline SVG nativo (sem lib extra), cor da taxa SLA por threshold (verde ≥80%, âmbar ≥50%, vermelho). - Integrado em ClinicDashboard (visão global) e TherapistDashboard (filtrado por ownerId, sem ranking). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
771b636cee |
SLA de conversas WhatsApp (Grupo 3.4): config + detecção + alerta
Completa o Grupo 3 do CRM com alerta de conversa sem resposta além do tempo configurado — reutiliza o pipeline system_alert (toast vermelho sticky + sininho + drawer). Banco (migration 20260423000005): - conversation_sla_rules: 1 linha por tenant com threshold global (1-1440 min), respect_business_hours, business_hours_start/end, business_days (ISO 1=seg..7=dom), alert_scope (assigned_only|all), notify_admin_on_breach. Default: enabled=false. - conversation_sla_breaches: incidents com UNIQUE parcial (tenant_id, thread_key) WHERE resolved_at IS NULL — idempotência. - Trigger AFTER INSERT em conversation_messages resolve o breach automaticamente quando chega nova outbound na thread. - RPCs service_role: sla_open_breach (idempotente), sla_mark_notified. - RLS: membros do tenant leem; clinic_admin/tenant_admin/saas_admin escrevem na config; service_role escreve em breaches. Edge function conversation-sla-check (cron 5min): - Varre tenants com enabled=true. - Query conversation_threads onde last_message_direction='inbound' (+ assigned_to NOT NULL se scope='assigned_only'). - Se respect_business_hours: calcula businessMinutesElapsed em TS iterando dia por dia a interseção da janela [start,end] com [last_inbound_at, now], só em dias marcados em business_days. TZ fixa em America/Sao_Paulo via Intl.DateTimeFormat. - Se elapsed >= threshold: sla_open_breach (idempotente) + notifica assigned_to sempre + admins se notify_admin_on_breach (deduplicado via Set). - Anti-spam: só notifica 1x por incident (checa notified_at). - Notification leva deeplink pra /crm/conversas e payload.thread_key pro frontend destacar a conversa (fora de escopo deste commit). UI em /configuracoes/conversas-sla: - Toggle enabled + InputNumber threshold com preview "≈ Xh Ymin". - Toggle respect_business_hours → revela start/end + seletor de dias úteis (pills toggleáveis Seg..Dom, ISO order). - Select scope. - Toggle notify_admin_on_breach. - Card abaixo com breaches dos últimos 7 dias (status aberto/resolvido, thread_key, limite configurado no momento do breach, duração). - Adicionada na ConfiguracoesPage landing + rota /configuracoes/conversas-sla. Cron template comentado no fim da migration (mesmo padrão do heartbeat). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e409ba64ef |
Saldo baixo WhatsApp: trigger dispara notificação ao cruzar threshold
Fecha o loop do Marco B — tenant não zera mais saldo sem aviso. Nova função fn_whatsapp_low_balance_notify + trigger BEFORE UPDATE em whatsapp_credits_balance: - Dispara quando NEW.balance < NEW.low_balance_threshold e NEW.low_balance_alerted_at IS NULL - Insere system_alert pros stakeholders do tenant (owner do canal WhatsApp ativo + clinic_admin + tenant_admin, deduplicado via UNION) - Deeplink direto pra /configuracoes/creditos-whatsapp - Seta NEW.low_balance_alerted_at = now() pra anti-spam Reset do anti-spam já existia: add_whatsapp_credits seta low_balance_alerted_at=NULL ao creditar (purchase/topup/refund). Assim o ciclo completo funciona: cai abaixo → alerta → compra recrédita → cai de novo futuramente → alerta de novo. Toast no frontend já é sticky vermelho pra type='system_alert' (commit anterior). Config de threshold já existia na UI em /configuracoes/creditos-whatsapp. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
881fa16c27 |
Fluxo de reativação de canal WhatsApp + alerta toast sticky + notify owner
Cadeia de fixes descoberta ao testar o heartbeat 6.1 num tenant que migrou
de Evolution → Twilio e precisava voltar pro Evolution.
1. RLS notification_channels (migration 20260423000003)
- Policy antiga tinha `deleted_at IS NULL` como primeira condição AND,
bloqueando leitura de soft-deleted até pro próprio owner/saas_admin.
- Isso fazia o chooser nunca detectar "canal antigo pra reativar".
- Relaxada: owner/membro/saas_admin leem inclusive soft-deleted.
- Filtro de deleted_at fica no código aplicativo (todos os queries já
filtram explicitamente quando querem apenas ativos).
2. Edge function reactivate-notification-channel (nova)
- Espelho da deactivate existente; service_role bypass RLS.
- Aceita {channel_id} OU {tenant_id + provider}.
- Autoriza saas_admin OU membro ativo do tenant.
- Garante exclusividade: soft-deleta qualquer OUTRO canal ativo do
mesmo tenant+channel.
- Reseta metadata.first_unhealthy_at + connection_status=disconnected
(heartbeat começa do zero).
3. SaasWhatsappPage (/saas/whatsapp)
- loadChannel busca soft-deleted como fallback quando não tem ativo.
- saveCredentials detecta soft-deleted e chama reactivate edge,
depois atualiza credentials+display_name.
- Banner âmbar "Canal configurado anteriormente" + botão vira
"Reativar e salvar".
4. ConfiguracoesWhatsappPage tenant (/configuracoes/whatsapp-pessoal)
- loadCredentials busca soft-deleted como fallback.
- Card âmbar "WhatsApp Pessoal foi usado anteriormente" com botão
"Reativar WhatsApp Pessoal" em vez de mostrar apenas "chame o suporte".
5. ChooserPage (/configuracoes/whatsapp)
- Fix bug lateral: comparava activeProvider === 'evolution' (template)
com 'evolution_api' (DB) — card nunca mostrava estado ativo. Agora
normaliza via computed activeProviderKey.
- softDeletedByProvider map carregado no mount; cards que têm row
soft-deleted mostram "Reativar" em vez de "Ativar".
- handleChoose chama reactivate edge antes de goSetup se detecta
soft-deleted do provider escolhido.
6. whatsapp-heartbeat-check: notifica owner do channel + admins
- notifyChannelStakeholders substitui notifyTenantAdmins.
- Set dedupa o owner_id do channel + clinic_admin + tenant_admin.
- Em tenant solo: 1 notificação; em clínica com canal de terapeuta
específico: terapeuta (owner) + admin recebem; em clínica com canal
do próprio admin: 1 (owner=admin).
7. Toast frontend para system_alert
- notificationStore.subscribeRealtime aceita callback onInsert.
- useNotifications registra callback que dispara toast PrimeVue
(severity error, life 24h, closable) para type='system_alert'.
- Usuário precisa fechar manualmente — alerta crítico de infra
não pode sumir sozinho.
Cron heartbeat ativado em runtime local via cron.schedule()
(não vai neste commit — é config de ambiente, não migration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
e1f756ea82 |
Heartbeat WhatsApp Evolution (Grupo 6.1): detecção + incident + alerta admin
Detecta celular desconectado antes de falhar envios silenciosamente.
Banco (migration 20260423000002):
- Tabela whatsapp_connection_incidents (tenant_id, channel_id, kind,
started_at, resolved_at, duration_seconds, notified_at, details).
UNIQUE parcial garante no máximo 1 incident aberto por channel.
- RPCs whatsapp_heartbeat_open_incident (idempotente), _resolve_open_incidents
e _mark_notified. Service_role only.
- RLS: membros do tenant leem, saas_admin tudo.
- ALTER notifications.type pra aceitar 'system_alert' (usado pelo alerta).
Edge function whatsapp-heartbeat-check:
- Varre notification_channels provider=evolution_api e ativos.
- GET {api_url}/instance/connectionState/{instance} (timeout 8s, rewrite
localhost → host.docker.internal pra containers).
- Mapeia state pra connection_status (open/connecting/qr_pending/
disconnected/error), persiste + last_health_check.
- Lógica de threshold: marca first_unhealthy_at em metadata na primeira
falha; só abre incident após heartbeat_threshold_minutes (default 5).
- Notifica admins ativos (clinic_admin/tenant_admin) do tenant via
insert em notifications. Anti-spam: só notifica 1x por incident.
- Aceita ?channel_id=X pra check on-demand de um tenant específico.
UI tenant (/configuracoes/whatsapp-pessoal):
- Novo card "Monitoramento de conexão" com toggle alerts_enabled +
InputNumber threshold (1-60 min). Persiste em
notification_channels.metadata.
- Histórico últimos 7 dias: kind (tag colorida), aberto/resolvido,
início → fim, duração formatada (Ns/Xmin Ys/Nh Xmin).
UI SaaS (/saas/whatsapp):
- Badge "N incidents abertos" no header quando há algum.
- Botão "Verificar tudo agora" invoca a edge function e atualiza a lista.
- Tabela enriquecida: coluna Status ganha pill "Incident aberto",
colunas novas Última check e Incidents 7d (em laranja se > 0).
Cron template no final da migration (comentado — descomentar
cron.schedule pra ativar 2min periódico).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
f76a2e3033 |
Admin SaaS: ajuste manual de créditos WhatsApp (+/-) com proteção de compras
Fecha polimento do Marco B (créditos/Asaas) entregue em 21/04.
Nova RPC admin_adjust_whatsapp_credits(tenant, amount_signed, admin_id, note):
- |amount| <= 1000 por operação (anti dedo-gordo). Valores maiores → repetir.
- Em remoção (amount < 0), aplica regra FIFO cortesia primeiro:
removable = max(0, sum(topup_manual+adjustment+refund) - usage_total).
Créditos de 'purchase' (Asaas/PIX) são intocáveis — estorno real vai pelo
fluxo financeiro do Asaas.
- Protegida por is_saas_admin() — authenticated comum não consegue chamar.
- Registra como kind='adjustment' com amount signed (+ ou -).
Helper get_whatsapp_removable_balance(tenant) retorna {balance, removable,
protected_amount, topup_net, usage_total} pra UI mostrar breakdown.
Aba 4 (Pacotes WhatsApp):
- Desativação dispara ConfirmDialog com histórico (N compras, M tenants
distintos) + aviso forte se é o único pacote ativo + nota que créditos já
adquiridos continuam válidos.
- Fix visual: :key no ToggleSwitch força re-mount durante confirm pra não
desligar visualmente antes do accept.
Aba 5 (Topup → Ajuste):
- Substituído Select de kind por SelectButton Adicionar/Remover.
- InputNumber max 1000 · label e botão dinâmicos.
- Modo Remover: card laranja com breakdown removível/protegido, botão
vermelho, confirm obrigatório com saldo resultante.
- Error mapping friendly pt-BR pros códigos da RPC.
ConfirmDialog com v-html habilitado pra suportar <br><br> entre frases
e <strong>/cores. Inputs livres (row.name, tenantName) passam por
escapeHtml() antes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
2644e60bb6 |
CRM WhatsApp Grupo 3 completo + Marco A/B (Asaas) + admin SaaS + refactors polimórficos
Sessão 11+: fechamento do CRM de WhatsApp com dois providers (Evolution/Twilio),
sistema de créditos com Asaas/PIX, polimorfismo de telefones/emails, e integração
admin SaaS no /saas/addons existente.
═══════════════════════════════════════════════════════════════════════════
GRUPO 3 — WORKFLOW / CRM (completo)
═══════════════════════════════════════════════════════════════════════════
3.1 Tags · migration conversation_tags + seed de 5 system tags · composable
useConversationTags.js · popover + pills no drawer e nos cards do Kanban.
3.2 Atribuição de conversa a terapeuta · migration 20260421000012 com PK
(tenant_id, thread_key), UPSERT, RLS que valida assignee como membro ativo
do mesmo tenant · view conversation_threads expandida com assigned_to +
assigned_at · composable useConversationAssignment.js · drawer com Select
filtrável + botão "Assumir" · inbox com filtro aside (Todas/Minhas/Não
atribuídas) e chip do responsável em cada card (destaca "Eu" em azul).
3.3 Notas internas · migration conversation_notes · composable + seção
colapsável no drawer · apenas o criador pode editar/apagar (RLS).
3.5 Converter desconhecido em paciente · botão + dialog quick-cadastro ·
"Vincular existente" com Select filter de até 500 pacientes · cria
telefone WhatsApp (vinculado) via upsertWhatsappForExisting.
3.6 Histórico de conversa no prontuário · nova aba "Conversas" em
PatientProntuario.vue · PatientConversationsTab.vue com stats (total /
recebidas / enviadas / primeira / última), SelectButton de filtro, timeline
com bolhas por direção, mídia inline (imagem/áudio/vídeo/doc via signed
URL), indicadores ✓ ✓✓ de delivery, botão "Abrir no CRM".
═══════════════════════════════════════════════════════════════════════════
MARCO A — UNIFICAÇÃO WHATSAPP (dois providers mutuamente exclusivos)
═══════════════════════════════════════════════════════════════════════════
- Página chooser ConfiguracoesWhatsappChooserPage.vue com 2 cards (Pessoal/
Oficial), deactivate via edge function deactivate-notification-channel
- send-whatsapp-message refatorada com roteamento por provider; Twilio deduz
1 crédito antes do envio e refunda em falha
- Paridade Twilio (novo): módulo compartilhado supabase/functions/_shared/
whatsapp-hooks.ts com lógica provider-agnóstica (opt-in, opt-out, auto-
reply, schedule helpers em TZ São Paulo, makeTwilioCreditedSendFn que
envolve envio em dedução atômica + rollback). Consumido por Evolution E
Twilio inbound. Evolution refatorado (~290 linhas duplicadas removidas).
- Bucket privado whatsapp-media · decrypt via Evolution getBase64From
MediaMessage · upload com path tenant/yyyy/mm · signed URLs on-demand
═══════════════════════════════════════════════════════════════════════════
MARCO B — SISTEMA DE CRÉDITOS WHATSAPP + ASAAS
═══════════════════════════════════════════════════════════════════════════
Banco:
- Migration 20260421000007_whatsapp_credits (4 tabelas: balance,
transactions, packages, purchases) + RPCs add_whatsapp_credits e
deduct_whatsapp_credits (atômicas com SELECT FOR UPDATE)
- Migration 20260421000013_tenant_cpf_cnpj (coluna em tenants com CHECK
de 11 ou 14 dígitos)
Edge functions:
- create-whatsapp-credit-charge · Asaas v3 (sandbox + prod) · PIX com
QR code · getOrCreateAsaasCustomer patcha customer existente com CPF
quando está faltando
- asaas-webhook · recebe PAYMENT_RECEIVED/CONFIRMED e credita balance
Frontend (tenant):
- Página /configuracoes/creditos-whatsapp com saldo + loja + histórico
- Dialog de confirmação com CPF/CNPJ (validação via isValidCPF/CNPJ de
utils/validators, formatação on-blur, pré-fill de tenants.cpf_cnpj,
persiste no primeiro uso) · fallback sandbox 24971563792 REMOVIDO
- Composable useWhatsappCredits extrai erros amigáveis via
error.context.json()
Frontend (SaaS admin):
- Em /saas/addons (reuso do pattern existente, não criou página paralela):
- Aba 4 "Pacotes WhatsApp" — CRUD whatsapp_credit_packages com DataTable,
toggle is_active inline, dialog de edição com validação
- Aba 5 "Topup WhatsApp" — tenant Select com saldo ao vivo · RPC
add_whatsapp_credits com p_admin_id = auth.uid() (auditoria) · histórico
das últimas 20 transações topup/adjustment/refund
═══════════════════════════════════════════════════════════════════════════
GRUPO 2 — AUTOMAÇÃO
═══════════════════════════════════════════════════════════════════════════
2.3 Auto-reply · conversation_autoreply_settings + conversation_autoreply_
log · 3 modos de schedule (agenda das regras semanais, business_hours
custom, custom_window) · cooldown por thread · respeita opt-out · agora
funciona em Evolution E Twilio (hooks compartilhados)
2.4 Lembretes de sessão · conversation_session_reminders_settings +
_logs · edge send-session-reminders (cron) · janelas 24h e 2h antes ·
Twilio deduz crédito com rollback em falha
═══════════════════════════════════════════════════════════════════════════
GRUPO 5 — COMPLIANCE (LGPD Art. 18 §2)
═══════════════════════════════════════════════════════════════════════════
5.2 Opt-out · conversation_optouts + conversation_optout_keywords (10 system
seed + custom por tenant) · detecção por regex word-boundary e normalização
(lowercase + strip acentos + pontuação) · ack automático (deduz crédito em
Twilio) · opt-in via "voltar", "retornar", "reativar", "restart" ·
página /configuracoes/conversas-optouts com CRUD de keywords
═══════════════════════════════════════════════════════════════════════════
REFACTOR POLIMÓRFICO — TELEFONES + EMAILS
═══════════════════════════════════════════════════════════════════════════
- contact_types + contact_phones (entity_type + entity_id) — migration
20260421000008 · contact_email_types + contact_emails — 20260421000011
- Componentes ContactPhonesEditor.vue e ContactEmailsEditor.vue (add/edit/
remove com confirm, primary selector, WhatsApp linked badge)
- Composables useContactPhones.js + useContactEmails.js com
unsetOtherPrimaries() e validação
- Trocado em PatientsCadastroPage.vue e MedicosPage.vue (removidos campos
legados telefone/telefone_alternativo e email_principal/email_alternativo)
- Migration retroativa v2 (20260421000010) detecta conversation_messages
e cria/atualiza phone como WhatsApp vinculado
═══════════════════════════════════════════════════════════════════════════
POLIMENTO VISUAL + INFRA
═══════════════════════════════════════════════════════════════════════════
- Skeletons simplificados no dashboard do terapeuta
- Animações fade-up com stagger via [--delay:Xms] (fix specificity sobre
.dash-card box-shadow transition)
- ConfirmDialog com group="conversation-drawer" (evita montagem duplicada)
- Image preview PrimeVue com botão de download injetado via MutationObserver
(fetch + blob para funcionar cross-origin)
- Áudio/vídeo com preload="metadata" e controles de velocidade do browser
- friendlySendError() mapeia códigos do edge pra mensagens pt-BR via
error.context.json()
- Teleport #cfg-page-actions para ações globais de Configurações
- Brotli/Gzip + auto-import Vue/PrimeVue + bundle analyzer
- AppLayout consolidado (removidas duplicatas por área) + RouterPassthrough
- Removido console.trace debug que estava em watch de router e queries
Supabase (degradava perf pra todos)
- Realtime em conversation_messages via publication supabase_realtime
- Notifier global flutuante com beep + toggle mute (4 camadas: badge +
sino + popup + browser notification)
═══════════════════════════════════════════════════════════════════════════
MIGRATIONS NOVAS (13)
═══════════════════════════════════════════════════════════════════════════
20260420000001_patient_intake_invite_info_rpc
20260420000002_audit_logs_lgpd
20260420000003_audit_logs_unified_view
20260420000004_lgpd_export_patient_rpc
20260420000005_conversation_messages
20260420000005_search_global_rpc
20260420000006_conv_messages_notifications
20260420000007_notif_channels_saas_admin_insert
20260420000008_conv_messages_realtime
20260420000009_conv_messages_delivery_status
20260421000001_whatsapp_media_bucket
20260421000002_conversation_notes
20260421000003_conversation_tags
20260421000004_conversation_autoreply
20260421000005_conversation_optouts
20260421000006_session_reminders
20260421000007_whatsapp_credits
20260421000008_contact_phones
20260421000009_retroactive_whatsapp_link
20260421000010_retroactive_whatsapp_link_v2
20260421000011_contact_emails
20260421000012_conversation_assignments
20260421000013_tenant_cpf_cnpj
═══════════════════════════════════════════════════════════════════════════
EDGE FUNCTIONS NOVAS / MODIFICADAS
═══════════════════════════════════════════════════════════════════════════
Novas:
- _shared/whatsapp-hooks.ts (módulo compartilhado)
- asaas-webhook
- create-whatsapp-credit-charge
- deactivate-notification-channel
- evolution-webhook-provision
- evolution-whatsapp-inbound
- get-intake-invite-info
- notification-webhook
- send-session-reminders
- send-whatsapp-message
- submit-patient-intake
- twilio-whatsapp-inbound
═══════════════════════════════════════════════════════════════════════════
FRONTEND — RESUMO
═══════════════════════════════════════════════════════════════════════════
Composables novos: useAddonExtrato, useAuditoria, useAutoReplySettings,
useClinicKPIs, useContactEmails, useContactPhones, useConversationAssignment,
useConversationNotes, useConversationOptouts, useConversationTags,
useConversations, useLgpdExport, useSessionReminders, useWhatsappCredits
Stores: conversationDrawerStore
Componentes novos: ConversationDrawer, GlobalInboundNotifier, GlobalSearch,
ContactEmailsEditor, ContactPhonesEditor
Páginas novas: CRMConversasPage, PatientConversationsTab, AddonsExtratoPage,
AuditoriaPage, NotificationsHistoryPage, ConfiguracoesWhatsappChooserPage,
ConfiguracoesConversasAutoreplyPage, ConfiguracoesConversasOptoutsPage,
ConfiguracoesConversasTagsPage, ConfiguracoesCreditosWhatsappPage,
ConfiguracoesLembretesSessaoPage
Utils novos: addonExtratoExport, auditoriaExport, excelExport,
lgpdExportFormats
Páginas existentes alteradas: ClinicDashboard, PatientsCadastroPage,
PatientCadastroDialog, PatientsListPage, MedicosPage, PatientProntuario,
ConfiguracoesWhatsappPage, SaasWhatsappPage, ConfiguracoesRecursosExtrasPage,
ConfiguracoesPage, AgendaTerapeutaPage, AgendaClinicaPage, NotificationItem,
NotificationDrawer, AppLayout, AppTopbar, useMenuBadges,
patientsRepository, SaasAddonsPage (aba 4 + 5 WhatsApp)
Routes: routes.clinic, routes.configs, routes.therapist atualizados
Menus: clinic.menu, therapist.menu, saas.menu atualizados
═══════════════════════════════════════════════════════════════════════════
NOTAS
- Após subir, rodar supabase functions serve --no-verify-jwt
--env-file supabase/functions/.env pra carregar o módulo _shared
- WHATSAPP_SETUP.md reescrito (~400 linhas) com setup completo dos 3
providers + troubleshooting + LGPD
- HANDOFF.md atualizado com estado atual e próximos passos
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
d6eb992f71 |
Sessoes 6cont-10: hardening em 6 areas + scan completo do SaaS
Continuacao de
|
||
|
|
7c20b518d4 |
Sessoes 1-6 acumuladas: hardening B2, defesa em camadas, +192 testes
Repositorio estava ha ~5 sessoes sem commit. Consolida tudo desde
|
||
|
|
d088a89fb7 | Documentos Pacientes, Template Documentos Pacientes Saas, Documentos prontuários, Documentos Externos, Visualização Externa, Permissão de Visualização, Render Otimização | ||
|
|
3f1786c9bf | + Menu Hover no Layout Rail, Twilio, Sms, Email, Templates, LNovo Layout Configurações | ||
|
|
53a4980396 | Correcao Sidebar Classico e Rail, Correcao Layout, Ajuste de Breakpoint para Tailwind, Ajuste AppTopbar, Ajuste Menu PopOver, Recriado Paleta de Cores, Inserido algumas animações leves, Reajuste Cor items NOVOS da tabela, Drawer Ajuda Corrigido no Logout, Whatsapp, sms, email, recursos extras |