Files
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

178 lines
19 KiB
Markdown

# 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:
- [x] `melissa-page-blueprint.md` — já existe
- [x] `melissa-table-page-blueprint.md` — já existe
- [x] `dialog-blueprint.md` — já existe
- [x] `repository-blueprint.md` — entregável 1 (2026-05-20)
- [x] `composable-blueprint.md` — entregável 2 (2026-05-20)
- [x] `quick-create-overlay-blueprint.md` — entregável 3 (2026-05-20). Documentado como **agenda-only** com promotion criteria explícito.
E baseline:
- [x] Update graphify do código atual (`graphify update src/` rodou 2026-05-20)
- [x] 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:
- [x] **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
- [x] **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).
- [x] **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.
- [x] **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-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
- [x] **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 ✅**
- [x] **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.
- [x] **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.
- [x] **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.
- [x] **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)
- [x] **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).
- [x] **M2.2** `usePatientDetail.js` refatorado — 4 funções internas (getPatientById, getPatientRelations, getGroupsByIds, getTagsByIds) movidas pra repository. Composable agora é thin wrapper.
- [x] **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.
- [x] **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).
- [x] **M2.5** Quatro composables simples refatorados em paralelo: `usePatientMessages`, `usePatientDocuments`, `usePatientRecurrences`, `usePatientSupportContacts`. Cada um delega list+mutations ao repository.
- [x] **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`.
- [x] **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`.
- [x] **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 `templateTipo``tipo_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.
- [x] **§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
- [x] **Popover snapshot stale** (commit `f83315b` durante C11) — watch em `MelissaLayout` cobre virtual→materializada.
- [x] **Reverse transition confirm dialogs** (commit `5684297` durante C11) — `ctx.reverseArtifacts` + dialog.
- [x] **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`.
- [x] **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).
- [x] **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)
6. **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.
7. **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.
8. **Overlap billing agenda ↔ financeiro****Consolidar em 1 composable orquestrador** (`useBillingOrchestrator`). Resolve risco double-billing antes do refactor de Financeiro.
9. **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`