Files
agenciapsilmno/development/02-auditoria/PADRONIZACAO.md
T
Leonardo 661790d577 wiki + padronizacao: agenda Fase 4 residual 70% fechada
Atualiza PADRONIZACAO.md marcando Fase 4 da agenda em sua maior
parte fechada: popover snapshot + reverse transition (ja feitos
em C11) + decomposicao A+B1+B2 (-991L useMelissaAgenda) + Fases
C+D (Rail/Clinica adotam billing core via useAgendaStatusChange) +
C12 UX iter.

Pendente: indicadores visuais 3 canais em Rail/Clinica + popover
Rail antecipar/revogar/trocar metodo + doc de ajuda.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 09:49:14 -03:00

19 KiB

Padronização — Sweep estrutural pré-MVP

Iniciado: 2026-05-20 Deadline MVP: 3+ meses (lançamento limpo, sem usuários) Escopo MVP: Pacientes + Agenda + Billing + Prontuário + Financeiro avançado + Multi-tenant


Diagnóstico

Sistema tem ~487 arquivos Vue, ~75-80% MVP-ready, padronização irregular. Agenda passou por C1-C13 + análise sênior — é o único módulo com profundidade arquitetural. Outros módulos têm divergências (composables sem tenant_id consistente, SELECTs inline, page layouts inconsistentes, dialogs que não seguem o blueprint).

Sem padronizar antes de escalar features novas (Fase 1 do ROADMAP), cada gap vira dívida composta.


Estratégia em 1 frase

Agenda é a referência madura. Extrair seus padrões em blueprints → propagar módulo a módulo → tracking em dev_auditoria_items com tag padronizacao:<modulo>. Não tocar agenda até a Fase 4 (apenas pendências residuais).


Fases

Fase 0 — Fundação (3-5 dias)

Extrair os blueprints faltantes a partir da agenda:

  • melissa-page-blueprint.md — já existe
  • melissa-table-page-blueprint.md — já existe
  • dialog-blueprint.md — já existe
  • repository-blueprint.md — entregável 1 (2026-05-20)
  • composable-blueprint.md — entregável 2 (2026-05-20)
  • quick-create-overlay-blueprint.md — entregável 3 (2026-05-20). Documentado como agenda-only com promotion criteria explícito.

E baseline:

  • Update graphify do código atual (graphify update src/ rodou 2026-05-20)
  • Audit baseline por módulo → ver development/02-auditoria/AUDIT_BASELINE.md (2026-05-20). 51 divergências catalogadas + 4 surpresas estruturais. Pendente: popular dev_auditoria_items no banco (decisão de batch insert vs UI).

Fase 0.5 — Pré-Fase 1 setups (pós-audit baseline)

Decisões 6-9 introduzem 4 entregáveis novos antes da Fase 1:

  • 0.5.A Atualizar quick-create-overlay-blueprint.md de "agenda-only" pra universal (2026-05-20) — header reescrito, seção 9 virou "Promotion History", path convention adicionada, checklist generalizado, memória feedback_agenda_inline_quick_create marcada como superseded
  • 0.5.B Schema clínico modelado (2026-05-20). 4 migrations + 1 seed escritos em database-novo/migrations/20260520000001..4_clinical_notes_*.sql e database-novo/seeds/seed_040_clinical_note_templates.sql. Não executado — aguardando review do user pra rodar node db.cjs migrate. Tabelas: clinical_notes + clinical_note_versions (audit trail via trigger snapshot) + clinical_note_templates (6 templates do sistema: anamnese, SOAP, DAP, BIRP, evolução livre, plano padrão). FK órfã documents.session_note_id renomeada pra clinical_note_id com constraint. RLS: owner-only (CFP sigilo).
  • 0.5.C Design doc useBillingOrchestrator (2026-05-20) — development/02-auditoria/DESIGN_BILLING_ORCHESTRATOR.md. State machine de 10 transições, dependências em 4 composables/5 repositories, plano de migração faseado em 4 fases (A/B/C/D), checklist de implementação. 4 decisões resolvidas: (1) applyStatusChange só financeiro, agenda separada; (2) reverse confirm via needsConfirmation no return; (3) transação via RPC dedicada apply_billing_status_transition; (4) sessão dedicada pra decisões billing #2/#3/#6 antes do Módulo 4.
  • 0.5.D Scaffold da feature tenantship/ (2026-05-20). 7 arquivos criados em src/features/tenantship/: _tenantGuards.js, tenantInvitesSelects.js + Repository.js, tenantMembersSelects.js + Repository.js, useTenantInvites.js, useTenantMembers.js. Funções funcionais (não-stub) usando tabela existente tenant_invites + view v_tenant_members_with_profiles. 2 pendências documentadas no código: (1) acceptInvite() é stub PT-BR explicando que precisa de RPC accept_tenant_invite(p_token uuid) — migration a criar; (2) sendInvite() só insere row — envio de email/WhatsApp fica pra Módulo 6 (Notificações).

Fase 1 — Padronização módulo a módulo (4-6 semanas) — em andamento

Ordem confirmada com usuário:

# Módulo Por que aqui Status
1 Home/Dashboard + Components base Alta visibilidade. Inclui refactor dos 3 quick-creates promovidos (decisão 6). Concluído 2026-05-20 (exceto M1.6 — MelissaLayout decomposition, deferida)
2 Pacientes Núcleo de dados — alimenta agenda, prontuário, financeiro. Concluído 2026-05-20 (aguarda teste batch)
3 Prontuário/Evolução Schema clínico já modelado (decisão 7). Foundation 2026-05-20 — repositories + composables prontos. Ativa quando migrations 0.5.B rodarem. UI da aba "Prontuário evolutivo" fica pra sessão dedicada.
4 Financeiro/Billing useBillingOrchestrator desenhado (decisão 8). Foundation 2026-05-20 — 3 repositories + 4 composables novos. State machine completa + migração dos 3 callers BLOQUEADA pelas decisões #2/#3/#6 — fica pra sessão dedicada. Old useAgendaFinanceiro.js + useFinancialRecords.js continuam em paralelo.
5 Multi-tenant + Tenantship Inclui implementar feature tenantship/ (decisão 9). Concluído 2026-05-20. MembersPage em src/views/pages/admin/MembersPage.vue (CRUD de membros + convites) + rota /admin/members registrada em routes.clinic.js. Migration 20260520000005_accept_tenant_invite_rpc.sql criada (RPC SECURITY DEFINER com lock FOR UPDATE anti-race). tenantInvitesRepository.acceptInvite agora chama RPC real (não mais stub). SaasTenantFeaturesPage refatorada — 4 queries inline + 1 RPC extraídos pra src/services/tenantFeatureAdminService.js. SetupWizardPage (2648 linhas) deferido — refator de arquivo monolítico precisa sessão dedicada.
6 Notificações (WhatsApp/Email) Depende de tudo acima. Foundation 2026-05-20noticesSelects.js criado + noticeService.js refatorado pra usar constantes. features/conversations/services/ com repository + selects. Channel factory + refactor de useConversations.js (fat composable) deferidos — sessão dedicada. SMS send ainda stub.

Módulo 1 — sub-entregáveis

  • M1.1 Criar features/medicos/ (_tenantGuards.js, medicosSelects.js, medicosRepository.js, useMedicos.js) + refatorar CadastroRapidoMedico.vue pra usar repository (2026-05-20). Caller único (PatientsCadastroPage) — props/emits preservados. Zero referências supabase/useTenantStore/getOwnerId/getTenantId legacy no componente. Testado pelo user
  • M1.2 Criar features/insurance/ (_tenantGuards.js, insurancePlansSelects.js, insurancePlansRepository.js com findByName pra uniqueness check, useInsurancePlans.js) + refatorar CadastroRapidoConvenio.vue + InsurancePlanQuickCreateDialog.vue (bônus da agenda) (2026-05-20). Repository agora faz duplicate check case-insensitive antes de criar — quick-create blueprint compliance. Aguardando teste.
  • M1.3 Refatorado ComponentCadastroRapido.vue pra usar usePatients composable + getMyActiveMember() (novo helper em tenantship/services/tenantMembersRepository.js) (2026-05-20). Path NÃO mudou (continua em src/components/) — move pra features/patients/components/ fica pra cleanup de M2. Props deprecated mantidas pra backwards-compat dos 8 callers. Spillover M2: fix patientsRepository.createPatient (audit alta — sempre injeta owner_id do uid logado, ignora payload) + usePatients.error: ref('') (audit média — canon). Aguardando teste.
  • M1.4 Extraído TEST_ACCOUNTS de HomeCards.vue pra src/config/devTestAccounts.js (2026-05-20). HomeCards importa do novo arquivo; 6 usages funcionam idênticos.
  • M1.5 Deletado AgendaEventDialog.vue.bak (não estava no git, 155KB órfão no disco) (2026-05-20).
  • M1.6 Decomposição parcial MelissaLayout.vue (sessão dedicada — pode ficar pra depois)

Módulo 2 — sub-entregáveis (2026-05-20, sem pausas de teste)

  • M2.1 Criar patientsSelects.js (11 constantes — PATIENTS_SELECT_BASE + cross-feature: sessões, financial, documents, messages, recurrences, support_contacts, groups, tags). Estender patientsRepository.js com 15 funções novas + resolveTenantId helper local. Cross-feature reads ficam no patients até M4/M6 padronizarem (documentado nos comments).
  • M2.2 usePatientDetail.js refatorado — 4 funções internas (getPatientById, getPatientRelations, getGroupsByIds, getTagsByIds) movidas pra repository. Composable agora é thin wrapper.
  • M2.3 usePatientFinancial.js refatorado — _lastPatientId movido DENTRO da function (audit alta resolvida: state não vaza mais entre instâncias). 4 mutations (load/markPaid/markUnpaid/createRecord) delegam ao repository.
  • M2.4 usePatientSessions.js refatorado — list+create+updateStatus via repository. Pattern virtual→materialize preservado usando findSessionByRecurrence + createPatientSession com recurrence_id/date. Recurrence expansion (useRecurrence) intacta. supabase.auth.getUser() mantido como context resolution (não é data query).
  • M2.5 Quatro composables simples refatorados em paralelo: usePatientMessages, usePatientDocuments, usePatientRecurrences, usePatientSupportContacts. Cada um delega list+mutations ao repository.
  • M2.6 Cleanups: usePatients.js upgraded pra Tipo A canônico completo (load/getById/create/update/remove com loading/error/re-throw consistente).

Resultado: zero supabase.from(...) em qualquer composable de features/patients/composables/. Todos os 8 composables seguem Tipo A do blueprint. _lastPatientId não vaza mais. | 2 | Pacientes | Núcleo de dados — alimenta agenda, prontuário, financeiro. | | 3 | Prontuário/Evolução | Schema clínico já modelado (decisão 7). Migration já aplicada. | | 4 | Financeiro/Billing | useBillingOrchestrator já desenhado (decisão 8). | | 5 | Multi-tenant + Tenantship | Inclui implementar feature tenantship/ (decisão 9). | | 6 | Notificações (WhatsApp/Email) | Depende de tudo acima. |

Por módulo, sempre:

  1. Ler estado atual
  2. Diff vs blueprints
  3. Listar divergências em dev_auditoria_items (tag padronizacao:<modulo> + severidade)
  4. Plano de fix
  5. Executar
  6. Testar (persistir HANDOFF+wiki+memória antes do teste manual)
  7. Commit
  8. Atualizar tracker
  9. Log no wiki

Fase 2 — Hotspots Graphify (paralela)

Do project_graphify_findings_20260504:

  • convertToPatient duplicado
  • Supabase client triplo
  • 348 nós fracos
  • Setup Wizard cohesion 0.05

Fase 3 — Gaps de MVP (Fase 1 do ROADMAP)

  • [🟡] Gateway Asaas (Fase A foundation 2026-05-21) — Design doc + 2 migrations (tables + RLS) + client service + 3 Edge Function stubs (create-payment-record, cancel-payment, sync-payment). Schema: asaas_customers, asaas_payments, asaas_webhook_events + 5 colunas em payment_settings. Fase B (implementação real) depende de credenciais + decisão modelo negócio (A/B/C). Ver development/02-auditoria/DESIGN_ASAAS_GATEWAY.md.
  • Compliance CFP (#5/#6/#7/#8/#9 todos done · 2026-05-21)
    • #5 (registro profissional): migration 20260521000003_profiles_professional_registration.sql — adiciona professional_registration_type (CHECK 8 conselhos) + _number + _uf.
    • #6 (consent forms editáveis): migration 20260521000005_document_templates_consent_types.sql estende CHECK com termo_lgpd + autorizacao_gravacao. seed_060_consent_forms_extra.sql insere 2 templates novos (LGPD + Gravação) + UPDATE no tcle_online adicionando cláusula LGPD. Biblioteca completa: TCLE base, tcle_online (telehealth), autorizacao_menor, termo_sigilo, termo_lgpd, autorizacao_gravacao + UI já existente (DocumentTemplatesPage + DocumentTemplateEditor).
    • #7 (assinatura eletrônica no portal): 2 migrations RPC — 20260521000006 cria sign_document_by_signature_id + sign_document_by_token + get_signable_document_by_token (IP/UA capturados server-side via inet_client_addr() + current_setting('request.headers')); 20260521000007 cria list_my_signatures (cruzamento auth.uid() por 3 caminhos). DocumentSignatures.service estendido. useDocumentSignatures composable novo. PortalDocumentos.vue lista pendências do paciente logado. SharedDocumentPage.vue estendida com painel azul de assinatura (aviso LGPD + checkbox aceite + Assinar/Recusar). DocumentSignatureDialog (terapeuta-side, já existia) ganha checkbox "Gerar link público" + select de validade + bloco com URL gerado/copy.
    • #8 (nome social): JÁ INTEGRADO — patients.nome_social schema existia + UI em 7 arquivos.
    • #9 (especialidades): 20260521000004_specialties.sql (tabela + profile_specialties M:N + RLS) + seed_050_specialties.sql (33 specialties) + src/services/specialtiesService.js.
  • Recibo profissional PDF (#14 · 2026-05-21)valorExtenso.js helper pt-BR. DocumentGenerate.service puxa registro profissional do profile (auto-formato CRP 12345/SP), formata cpf_cnpj do tenant, computa valor+valor_extenso, mapeia templateTipotipo_documento (recibo_pagamento → 'recibo'). Migration 20260521000008 substitui {{terapeuta_crp}} por {{terapeuta_registro}} no template — universal pra qualquer conselho. emitirReciboParaSessao(eventoId, opts) é quick path one-call. Botão "Emitir recibo" no AgendaEventoFinanceiroPanel quando record.status === 'paid'. #15 NFS-e ainda em aberto.
  • §1.3 UX block 3/4 (#10 + #11 + #13 · 2026-05-21)
    • #10 Busca global: GlobalSearch.vue (RPC search_global) já estava completo no AppTopbar/Rail. MelissaBusca promovida de client-side preview pra RPC com debounce 200ms + searchSeq. 3 grupos novos (rpc-appointments, rpc-documents, rpc-intakes). @paciente no MelissaLayout corrigido pra navegar pro paciente clicado (era bug — ignorava payload).
    • #11 Recently viewed: composables/useRecentPatients.js (localStorage por user_id, max 5, dedup, eventos sync entre instâncias). registerPatientVisit chamado em MelissaPaciente.loadAll + PatientProntuario.loadDetail. Grupo "Acessados recentemente" no GlobalSearch + MelissaBusca quando query vazia.
    • #13 Relatórios export: services/reportExport.service.js com 3 funções (PDF via pdf.service, Excel via exceljs com import dinâmico, CSV vanilla). 3 botões no header de RelatoriosPage.vue e MelissaRelatorios.vue.
  • #12 Papel timbrado (BLOQUEADO) — código no UniaoApp (projeto externo). Quando user importar o código, plugar como variável cabecalho_html/rodape_html global em document_templates ou criar setting tenants.letterhead_html.
  • NFS-e emissão (#15) — Esforço L, decisão de provider pendente (Focus NF-e vs prefeitura direta).
  • E2E Playwright crítico (#16)
  • Sentry (#18)

Fase 4 — Agenda residual

  • Popover snapshot stale (commit f83315b durante C11) — watch em MelissaLayout cobre virtual→materializada.
  • Reverse transition confirm dialogs (commit 5684297 durante C11) — ctx.reverseArtifacts + dialog.
  • Decomposição agenda (Fases A+B1+B2 · 2026-05-21)useMelissaAgenda.js saiu de 3033L → 2042L (-991L, ~33%). 3 utils + 1 service novo (agendaBilling.service).
    • Fase A: features/agenda/utils/{eventoTipo,dbFields,timeHelpers,colors}.js
    • Fase B1 (commit e7e3d1b): service ganha computeSeriePrice, generateOccurrenceDates, loadStatusChangeContext, needsStatusConfirmDialog.
    • Fase B2 (commit 049dd91): service ganha applyStatusDecisions, createPackageContract, materializeAndChargePerSession.
  • Replicação Rail + Clínica (Fases C+D · 2026-05-21)
    • Composable novo useAgendaStatusChange (Tipo A wrapper) reusável em qualquer page.
    • Fase C (commit 034c2c0): AgendaTerapeutaPage.onUpdateSeriesEvent refatorado + AgendaStatusChangeConfirmDialog plugado. Antes era update(id, {status}) cru; agora cobre multa + pacote saldo + reverse.
    • Fase D (commit 6807b44): AgendaClinicaPage espelha Fase C com adaptações (updateClinic+createClinic recebem tenantId arg).
  • C12 antecipar UX iter (commits 9c518a2 + b7f3c23) — "Trocar método" pattern (UPDATE em vez de cancel cycle) + filtro cancelled no dialog Lançamentos.
  • Indicadores visuais 3 canais (barra esquerda verde / badge $ amber / neutro) — replicar no Rail/Clínica. Custom event classNames do FullCalendar, requer _paymentStateMap bulk-load igual ao Melissa.
  • Popover Rail antecipar/revogar/trocar método — Rail não tem popover separado (usa AgendaEventDialog direto), precisa refactor maior pra acomodar.
  • Doc de ajuda completa — user enviará prompt específico.

Decisões tomadas

Estratégicas iniciais (2026-05-20)

  1. Ordem dos módulos Confirmada acima
  2. Tracker Reusar dev_auditoria_items com tag padronizacao:<modulo>. Zero migration. View materializada agrupa por módulo se virar útil pra UI.
  3. Cadência Validação por entregável (cada blueprint vira sessão antes de propagar)
  4. Agenda intocada Até Fase 4
  5. Skills novas/audit-module <nome> — minimalista. Outras só se emergir necessidade.

Pós-audit baseline (2026-05-20)

  1. Quick-create blueprint Promover pra universal (3 candidates já existem fora da agenda). Refatorar CadastroRapidoMedico.vue + CadastroRapidoConvenio.vue + ComponentCadastroRapido.vue em paralelo no módulo 1.
  2. Schema clínico do prontuário Modelar agora (sessão dedicada antes da Fase 1). Sai com migration pronta de patient_notes/clinic_sessions/anamnese/evolução/plano terapêutico.
  3. Overlap billing agenda ↔ financeiro Consolidar em 1 composable orquestrador (useBillingOrchestrator). Resolve risco double-billing antes do refactor de Financeiro.
  4. Convites/membership Feature separada tenantship/ com services + composables + página /admin/members. Semântica clara: gestão de membership.

Antipadrão a evitar

  • Refatorar tudo de uma vez (= nunca lançar)
  • Tocar agenda durante a sweep (= regressão garantida)
  • Pular o tracking em dev_auditoria_items (= perder rastreabilidade)
  • Aplicar blueprint sem antes auditar divergências (= refazer trabalho)

Referências

  • Blueprints: D:\leonohama\AgenciaPsi.com.br\Sistema\agenciapsi-primesakai\blueprints/
  • Agenda canônica: src/features/agenda/services/ + src/features/agenda/composables/useAgendaEvents.js
  • Tracker: tabela dev_auditoria_items (UI em /saas/desenvolvimento)
  • Memória: project_padronizacao_sweep.md
  • ROADMAP de features (não confundir): development/04-roadmap/ROADMAP.md