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>
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á existemelissa-table-page-blueprint.md— já existedialog-blueprint.md— já existerepository-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: populardev_auditoria_itemsno 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.mdde "agenda-only" pra universal (2026-05-20) — header reescrito, seção 9 virou "Promotion History", path convention adicionada, checklist generalizado, memóriafeedback_agenda_inline_quick_createmarcada 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_*.sqledatabase-novo/seeds/seed_040_clinical_note_templates.sql. Não executado — aguardando review do user pra rodarnode 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_idrenomeada praclinical_note_idcom 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)applyStatusChangesó financeiro, agenda separada; (2) reverse confirm vianeedsConfirmationno return; (3) transação via RPC dedicadaapply_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 emsrc/features/tenantship/:_tenantGuards.js,tenantInvitesSelects.js+Repository.js,tenantMembersSelects.js+Repository.js,useTenantInvites.js,useTenantMembers.js. Funções funcionais (não-stub) usando tabela existentetenant_invites+ viewv_tenant_members_with_profiles. 2 pendências documentadas no código: (1)acceptInvite()é stub PT-BR explicando que precisa de RPCaccept_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-20 — noticesSelects.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) + refatorarCadastroRapidoMedico.vuepra usar repository (2026-05-20). Caller único (PatientsCadastroPage) — props/emits preservados. Zero referênciassupabase/useTenantStore/getOwnerId/getTenantIdlegacy no componente. Testado pelo user ✅ - M1.2 Criar
features/insurance/(_tenantGuards.js,insurancePlansSelects.js,insurancePlansRepository.jscomfindByNamepra uniqueness check,useInsurancePlans.js) + refatorarCadastroRapidoConvenio.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.vuepra usarusePatientscomposable +getMyActiveMember()(novo helper emtenantship/services/tenantMembersRepository.js) (2026-05-20). Path NÃO mudou (continua emsrc/components/) — move prafeatures/patients/components/fica pra cleanup de M2. Props deprecated mantidas pra backwards-compat dos 8 callers. Spillover M2: fixpatientsRepository.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_ACCOUNTSdeHomeCards.vueprasrc/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). EstenderpatientsRepository.jscom 15 funções novas +resolveTenantIdhelper local. Cross-feature reads ficam no patients até M4/M6 padronizarem (documentado nos comments). - M2.2
usePatientDetail.jsrefatorado — 4 funções internas (getPatientById, getPatientRelations, getGroupsByIds, getTagsByIds) movidas pra repository. Composable agora é thin wrapper. - M2.3
usePatientFinancial.jsrefatorado —_lastPatientIdmovido 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.jsrefatorado — list+create+updateStatus via repository. Pattern virtual→materialize preservado usandofindSessionByRecurrence+createPatientSessioncom 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.jsupgraded 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:
- Ler estado atual
- Diff vs blueprints
- Listar divergências em
dev_auditoria_items(tagpadronizacao:<modulo>+ severidade) - Plano de fix
- Executar
- Testar (persistir HANDOFF+wiki+memória antes do teste manual)
- Commit
- Atualizar tracker
- Log no wiki
Fase 2 — Hotspots Graphify (paralela)
Do project_graphify_findings_20260504:
convertToPatientduplicado- 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 empayment_settings. Fase B (implementação real) depende de credenciais + decisão modelo negócio (A/B/C). Verdevelopment/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— adicionaprofessional_registration_type(CHECK 8 conselhos) +_number+_uf. - #6 (consent forms editáveis): migration
20260521000005_document_templates_consent_types.sqlestende CHECK comtermo_lgpd+autorizacao_gravacao.seed_060_consent_forms_extra.sqlinsere 2 templates novos (LGPD + Gravação) + UPDATE notcle_onlineadicionando 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 —
20260521000006criasign_document_by_signature_id+sign_document_by_token+get_signable_document_by_token(IP/UA capturados server-side viainet_client_addr()+current_setting('request.headers'));20260521000007crialist_my_signatures(cruzamento auth.uid() por 3 caminhos).DocumentSignatures.serviceestendido.useDocumentSignaturescomposable novo.PortalDocumentos.vuelista pendências do paciente logado.SharedDocumentPage.vueestendida 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_socialschema 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.
- #5 (registro profissional): migration
- Recibo profissional PDF (#14 · 2026-05-21) —
valorExtenso.jshelper pt-BR.DocumentGenerate.servicepuxa registro profissional do profile (auto-formatoCRP 12345/SP), formatacpf_cnpjdo tenant, computavalor+valor_extenso, mapeiatemplateTipo→tipo_documento(recibo_pagamento → 'recibo'). Migration20260521000008substitui{{terapeuta_crp}}por{{terapeuta_registro}}no template — universal pra qualquer conselho.emitirReciboParaSessao(eventoId, opts)é quick path one-call. Botão "Emitir recibo" noAgendaEventoFinanceiroPanelquandorecord.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(RPCsearch_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).@pacienteno 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).registerPatientVisitchamado emMelissaPaciente.loadAll+PatientProntuario.loadDetail. Grupo "Acessados recentemente" no GlobalSearch + MelissaBusca quando query vazia. - #13 Relatórios export:
services/reportExport.service.jscom 3 funções (PDF via pdf.service, Excel via exceljs com import dinâmico, CSV vanilla). 3 botões no header deRelatoriosPage.vueeMelissaRelatorios.vue.
- #10 Busca global:
- #12 Papel timbrado (BLOQUEADO) — código no UniaoApp (projeto externo). Quando user importar o código, plugar como variável
cabecalho_html/rodape_htmlglobal emdocument_templatesou criar settingtenants.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
f83315bdurante C11) — watch emMelissaLayoutcobre virtual→materializada. - Reverse transition confirm dialogs (commit
5684297durante C11) —ctx.reverseArtifacts+ dialog. - Decomposição agenda (Fases A+B1+B2 · 2026-05-21) —
useMelissaAgenda.jssaiu 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 ganhacomputeSeriePrice,generateOccurrenceDates,loadStatusChangeContext,needsStatusConfirmDialog. - Fase B2 (commit
049dd91): service ganhaapplyStatusDecisions,createPackageContract,materializeAndChargePerSession.
- Fase A:
- 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.onUpdateSeriesEventrefatorado +AgendaStatusChangeConfirmDialogplugado. Antes eraupdate(id, {status})cru; agora cobre multa + pacote saldo + reverse. - Fase D (commit
6807b44):AgendaClinicaPageespelha Fase C com adaptações (updateClinic+createClinicrecebemtenantIdarg).
- Composable novo
- 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
_paymentStateMapbulk-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)
- Ordem dos módulos ✅ Confirmada acima
- Tracker ✅ Reusar
dev_auditoria_itemscom tagpadronizacao:<modulo>. Zero migration. View materializada agrupa por módulo se virar útil pra UI. - Cadência ✅ Validação por entregável (cada blueprint vira sessão antes de propagar)
- Agenda intocada ✅ Até Fase 4
- Skills novas Só
/audit-module <nome>— minimalista. Outras só se emergir necessidade.
Pós-audit baseline (2026-05-20)
- Quick-create blueprint ✅ Promover pra universal (3 candidates já existem fora da agenda). Refatorar
CadastroRapidoMedico.vue+CadastroRapidoConvenio.vue+ComponentCadastroRapido.vueem paralelo no módulo 1. - 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. - Overlap billing agenda ↔ financeiro ✅ Consolidar em 1 composable orquestrador (
useBillingOrchestrator). Resolve risco double-billing antes do refactor de Financeiro. - 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