document_generated.documento_id (FK pra documents) estava sempre NULL
no INSERT — sem isso nao da pra rastrear qual generated belongs to
qual documents row, impossibilitando re-edicao.
DocumentGenerate.service saveGeneratedDocument:
- Modo create (default): INSERT em documents PRIMEIRO pra capturar
doc.id, depois INSERT em document_generated com documento_id setado.
- Modo edit (editingDocId param novo): UPDATE in-place — substitui
PDF no Storage (novo path), atualiza bucket_path/tamanho/nome em
documents (preserva id+audit), atualiza dados_preenchidos+pdf_path
em document_generated. Se nao houver registro generated (doc legado),
INSERT vinculando ao documents.id. Cleanup best-effort do PDF antigo.
- Nova fn loadGeneratedFromDocId(documentoId): busca template_id +
dados_preenchidos pra pre-popular o dialog de edicao.
useDocumentGenerate.generateAndSave: ganha 2o param editingDocId que
passa pro service.
Backfill SQL pra docs antigos: match dg.pdf_path = d.bucket_path +
tenant/patient guard. 3 docs linkados no DB local, 5 ficaram orfaos
(paths que nao existem mais em documents — cleanup antigo).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dois problemas reportados no dialog "Gerar documento":
1. Inputs usavam <label> + <InputText> simples, fora do padrao
FloatLabel adotado no resto do app.
2. Quando o auto-preenchimento vinha vazio o user nao tinha onde
ir cadastrar o dado.
Mudancas:
- TEMPLATE_VARIABLES ganha campo `source` em cada entrada com a
descricao de onde o dado eh cadastrado (ex: "Perfil -> Registro
Profissional"). Map canonico no DocumentTemplates.service.js.
- DocumentGenerateDialog refatorado:
* FloatLabel variant="on" em todos os inputs
* Banner no topo com contagem "X de Y preenchidos" (verde se 100%,
amber se faltam dados)
* Hint (`pi pi-link` + texto source) embaixo de cada campo vazio
apontando onde cadastrar
* Erro de carregamento renderizado dentro do step edit
* Input ganha `invalid` quando vazio (borda destaque)
- useDocumentGenerate.loadVariables:
* console.error em caso de excecao (era engolido em silencio)
* mensagem amigavel quando loadAllVariables retorna tudo vazio
(caso comum quando paciente/perfil/clinica estao incompletos)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ROADMAP item #1.4 #14. Fecha Fase 1.4 Fiscal minimo (parcial — #15
NFS-e fica pra depois).
DocumentGenerate.service estendido:
- loadTherapistData puxa registro profissional (#5 migration) e
expoe terapeuta_registro auto-formatado ("CRP 12345/SP", "CRM
98765/RJ"). terapeuta_crp legacy mantido por compat — preenche
somente quando tipo=CRP.
- loadClinicData formata tenants.cpf_cnpj (11 ou 14 digitos) em
CPF (XXX.XXX.XXX-XX) ou CNPJ (XX.XXX.XXX/XXXX-XX).
- loadAllVariables aceita {extras} (valor, formaPagamento) e
computa valor_extenso via novo helper utils/valorExtenso.js
(pt-BR completo ate 999 milhoes).
- saveGeneratedDocument ganha templateTipo + usa
TEMPLATE_TYPE_TO_DOC_TYPE mapping (recibo_pagamento -> 'recibo',
laudo -> 'laudo', atestado -> 'atestado' etc) em vez de
hardcoded 'laudo'.
- emitirReciboParaSessao(eventoId, opts) — quick path one-call:
busca template recibo_pagamento global, carrega variaveis,
gera PDF blob, salva no Storage + documents + document_generated,
dispara download.
Migration 20260521000008 substitui no template recibo_pagamento
"Psicologo(a) - CRP {{terapeuta_crp}}" por "{{terapeuta_registro}}"
e atualiza variaveis[]. Universal — funciona com qualquer conselho
(CRP/CRM/CRFa/CREFITO/CRESS/CRN).
DocumentTemplates.service.TEMPLATE_VARIABLES ganha terapeuta_
registro + _tipo + _numero + _uf (terapeuta_crp marcado legacy).
useDocumentGenerate.generateAndSave passa templateTipo no save.
AgendaEventoFinanceiroPanel ganha botao "Emitir recibo" (icon
pi-file-pdf, outlined, full width) que aparece SOMENTE quando
record.status === 'paid'. Toast de sucesso/erro. Loading state.
Fluxo end-to-end: terapeuta marca sessao como paga -> botao
"Emitir recibo" aparece -> click -> PDF baixado + aparece em
/clinic/documents/templates do paciente como tipo 'recibo'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>