c23d0a574f
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>
database-novo
Banco de dados do AgenciaPsi — organizado, documentado e com CLI para gerenciamento.
Quick Start
cd database-novo
# Instalação do zero (schema + fixes + seeds + backup)
node db.cjs setup
# Ver estado do banco
node db.cjs status
# Backup
node db.cjs backup
# Restaurar (perdi o banco!)
node db.cjs restore
Para o guia completo, veja docs/setup_guide.md.
Comandos do CLI
| Comando | O que faz |
|---|---|
node db.cjs setup |
Instala do zero (schema + fixes + seeds) |
node db.cjs backup |
Exporta backup com data para backups/ |
node db.cjs restore [data] |
Restaura de um backup |
node db.cjs migrate |
Aplica migrations pendentes |
node db.cjs seed [grupo] |
Roda seeds (all, users, system, test_data) |
node db.cjs status |
Estado do banco, backups, migrations |
node db.cjs diff |
Compara schema atual vs último backup |
node db.cjs reset |
Reseta e reinstala tudo |
node db.cjs verify |
Verifica integridade dos dados |
Estrutura
database-novo/
│
├── db.cjs # CLI de gerenciamento do banco
├── db.config.json # Configuração (container, seeds, fixes)
│
├── schema/ # Schema SQL separado por seção
│ ├── 00_full/schema.sql # Schema completo (referência)
│ ├── 01_extensions/ # Schemas + extensões PostgreSQL
│ ├── 02_types/ # Enums (auth, public, infra)
│ ├── 03_functions/ # 11 arquivos por domínio
│ ├── 04_tables/ # 10 arquivos por domínio
│ ├── 05_views/ # 24 views
│ ├── 06_indexes/ # Índices
│ ├── 07_foreign_keys/ # PKs, FKs, constraints
│ ├── 08_triggers/ # Triggers
│ ├── 09_policies/ # 217 RLS policies
│ └── 10_grants/ # Grants
│
├── seeds/ # Seeds de dados
│ ├── seed_001_fixed.sql # 6 usuários base + tenants
│ ├── seed_002.sql # Supervisor + Editor
│ ├── seed_003.sql # Therapist2, Therapist3, Secretary
│ ├── seed_010_plans.sql # 7 planos + 4 preços
│ ├── seed_011_features.sql # 26 features
│ ├── seed_012_plan_features.sql # 85 vínculos plano↔feature
│ ├── seed_013_subscriptions.sql # 9 subscriptions + compromissos
│ ├── seed_014_global_data.sql # 11 email + 16 notif templates + 3 slides
│ ├── seed_020_test_data.sql # Dados de teste (50 pacientes, eventos, etc.)
│ ├── seed_020_test_data_cleanup.sql # Limpeza dos dados de teste
│ └── run_all_seeds.sh # Script bash alternativo
│
├── migrations/ # Migrations incrementais
│
├── fixes/ # 7 correções aplicadas
│
├── backups/ # Backups com data (auto-gerenciados)
│ └── 2026-03-23/ # schema.sql + data.sql + full_dump.sql
│
└── docs/ # Documentação
├── setup_guide.md # Guia completo de instalação e uso
├── schema_map.md # Mapa das 84 tabelas
├── business_rules.md # Regras de negócio
└── users_test.md # 11 usuários de teste (UUIDs + vínculos)
Planos
| Key | Target | Preço | Limites |
|---|---|---|---|
patient_free |
patient | R$0 | — |
therapist_free |
therapist | R$0 | 40 agendamentos/mês, 50 lembretes/mês |
therapist_pro |
therapist | R$49/mês · R$490/ano | Ilimitado |
clinic_free |
clinic | R$0 | 30 pacientes, 5 terapeutas, 40 agend/mês |
clinic_pro |
clinic | R$149/mês · R$1490/ano | Ilimitado |
supervisor_free |
supervisor | R$0 | Até 3 supervisionados |
supervisor_pro |
supervisor | R$0 | Até 20 supervisionados |
Usuários de Teste
Senha de todos: Teste@123
| Plano | Tipo | |
|---|---|---|
| paciente@agenciapsi.com.br | patient_free | Paciente |
| terapeuta@agenciapsi.com.br | therapist_free | Terapeuta solo + Clínica 3 |
| clinica1@agenciapsi.com.br | clinic_free | Clínica coworking |
| clinica2@agenciapsi.com.br | clinic_free | Clínica recepção |
| clinica3@agenciapsi.com.br | clinic_free | Clínica full |
| saas@agenciapsi.com.br | — | Admin plataforma |
| supervisor@agenciapsi.com.br | supervisor_free | Supervisor |
| editor@agenciapsi.com.br | therapist_free | Editor |
| therapist2@agenciapsi.com.br | therapist_free | Terapeuta |
| therapist3@agenciapsi.com.br | therapist_free | Terapeuta |
| secretary@agenciapsi.com.br | — | Secretária (Clínica 2) |
Idempotência
Todos os seeds são idempotentes (ON CONFLICT DO UPDATE ou DELETE + INSERT). Podem ser re-executados quantas vezes necessário.