{
  "id": "geracao-de-documentos-docx-e-variaveis",
  "title": "Geração de documentos DOCX e variáveis",
  "description": "Arquitetura da geração DOCX, validação de templates e catálogo canônico de variáveis.",
  "type": "integration-contract",
  "status": "defined",
  "visibility": "public",
  "tags": [
    "sge/documentos",
    "sge/templates",
    "sge/integracoes"
  ],
  "related": [
    "migration-13-document-templates",
    "migration-14-template-versions",
    "migration-16-generated-documents",
    "helper-numbertowordshelper"
  ],
  "sourceRefs": [],
  "authors": [],
  "updated": null,
  "diagram": null,
  "body": "## Decisão técnica\n\nCada upload validado de um DOCX diferente cria uma versão do template lógico. O catálogo de variáveis é fixo no código; cada arquivo usa as variáveis necessárias. A geração usa a versão validada mais recente e registra a versão exata em `generated_documents`, sem criar uma versão nova por documento. Se uma correção substituir um arquivo já usado, o anterior permanece; versões nunca usadas podem ser excluídas fisicamente.\n\nO arquivo DOCX versionado será processado localmente com `PhpOffice\\PhpWord\\TemplateProcessor`. A dependência `phpoffice/phpword` deverá ser direta no `composer.json`; a imagem de execução precisa das extensões `zip`, `xml`, `dom`, `mbstring` e `intl`. `brick/math` também será dependência direta porque o código de moeda o utiliza, ainda que Laravel já o instale transitivamente.\n\nO marcador canônico é `${NOME_DA_VARIAVEL}`: letras maiúsculas, números e `_`, sem espaços, barras, acentos ou chaves duplas. Somente essa sintaxe será aceita nos templates cadastrados.\n\n## Componentes\n\n| Componente | Responsabilidade |\n| --- | --- |\n| `TemplateVariableCatalog` | Define nomes permitidos, tipo, sensibilidade, origem e formatação. |\n| `TemplateInspector` | Lê o DOCX como ZIP/XML e encontra variáveis inclusive em tabelas, cabeçalhos e rodapés. |\n| `TemplateValidator` | Rejeita variável desconhecida, obrigatória ausente, arquivo inválido e conteúdo inseguro. |\n| `DocumentSnapshotBuilder` | Carrega FKs e snapshots do estágio e produz um contexto imutável. |\n| `DocumentVariableResolver` | Resolve somente as variáveis declaradas pela versão do template. |\n| `RemunerationParagraphFormatter` | Produz o texto completo de `${PARAGRAFO_REMUNERACAO}`. |\n| `DocxDocumentGenerator` | Aplica valores no template, verifica sobras e salva em arquivo temporário privado. |\n| `GenerateInternshipDocument` | Autoriza, bloqueia concorrência, registra snapshot/status e entrega o arquivo. |\n\nHelpers continuam restritos a formatação pura (`CurrencyHelper`, `NumberToWordsHelper`, datas e documentos). Regra jurídica, consulta ao banco, autorização e persistência pertencem aos serviços/Actions acima.\n\n## Fluxo de geração\n\n1. o Setor escolhe um template lógico e a versão validada mais recente compatível com o campus e o tipo documental;\n2. a Policy valida o vínculo ativo e o estágio;\n3. a Action adquire lock por estágio, versão e token idempotente;\n4. o builder carrega o contexto histórico, sem usar cadastro atual no lugar de snapshot já congelado;\n5. o resolver produz somente as variáveis declaradas no schema da versão;\n6. o gerador preenche uma cópia privada e temporária do DOCX;\n7. uma inspeção final rejeita qualquer `${...}` restante;\n8. após geração bem-sucedida, `generated_documents` registra template, hash, nome de saída e snapshot dos valores;\n9. o arquivo é transmitido ao usuário autorizado e apagado em `finally`;\n10. nova emissão cria novo registro; um retry com o mesmo token não duplica a geração.\n\nGeração unitária será síncrona para permitir download imediato sem armazenamento definitivo. Lotes futuros poderão usar Job, mas o resultado permanecerá em armazenamento temporário privado com prazo curto e limpeza automática. DOCX/PDF final e documento assinado não são acervo do SGE.\n\n## Validação e segurança do upload\n\n- aceitar apenas `.docx` OOXML; rejeitar `.docm`, OLE e executáveis embutidos;\n- validar MIME, assinatura ZIP, tamanho total, quantidade e tamanho descompactado das entradas;\n- rejeitar relacionamentos externos, links de template remoto e macros;\n- calcular SHA-256 e impedir duplicata acidental dentro do mesmo template;\n- extrair variáveis de corpo, tabelas, cabeçalhos, rodapés, notas e caixas de texto suportadas;\n- rejeitar variáveis fora do catálogo e variáveis obrigatórias do schema que não estejam no arquivo;\n- registrar relatório de validação e impedir ativação enquanto houver erro;\n- gerar com dados fictícios, renderizar e exigir confirmação visual do Setor antes da ativação;\n- nunca incluir o comprovante de emancipação, tokens, senhas, logs ou metadados internos no contexto documental.\n\n## Catálogo de variáveis\n\nCada versão declara quais itens abaixo são obrigatórios ou opcionais. Uma variável conhecida não se torna automaticamente disponível em todo template: o tipo de documento e a Policy limitam o contexto.\n\n### Documento e instituição\n\n| Variável | Origem/formato |\n| --- | --- |\n| `${DOCUMENTO_NUMERO}` | identificador público da geração, quando aplicável. |\n| `${DOCUMENTO_DATA_EMISSAO}` | data da geração em `dd/mm/aaaa`. |\n| `${DOCUMENTO_DATA_EMISSAO_EXTENSO}` | data por extenso em `pt_BR`. |\n| `${DOCUMENTO_TITULO}` | nome lógico aprovado da versão. |\n| `${CAMPUS_NOME}` | snapshot do campus. |\n| `${CAMPUS_CNPJ}` | CNPJ formatado. |\n| `${CAMPUS_EMAIL}` / `${CAMPUS_TELEFONE}` | contatos institucionais. |\n| `${CAMPUS_ENDERECO}` | endereço composto. |\n| `${CAMPUS_LOGRADOURO}` / `${CAMPUS_NUMERO}` / `${CAMPUS_BAIRRO}` | partes do endereço. |\n| `${CAMPUS_CIDADE}` / `${CAMPUS_UF}` / `${CAMPUS_CEP}` | localidade formatada. |\n| `${CAMPUS_REPRESENTANTE_NOME}` | pessoa representante no snapshot da geração. |\n| `${CAMPUS_REPRESENTANTE_CARGO}` | cargo institucional no vínculo/snapshot. |\n| `${CAMPUS_RESPONSAVEL_ESTAGIOS_NOME}` | signatário institucional configurado para o documento. |\n| `${CAMPUS_RESPONSAVEL_ESTAGIOS_CARGO}` | cargo exibido do signatário. |\n| `${SEGURO_SEGURADORA}` / `${SEGURO_APOLICE}` | configuração institucional vigente, congelada na geração. |\n\n### Discente, curso e responsável\n\n| Variável | Origem/formato |\n| --- | --- |\n| `${ALUNO_NOME}` | `student_snapshot.name`. |\n| `${ALUNO_EMAIL}` / `${ALUNO_TELEFONE}` | contatos do snapshot. |\n| `${ALUNO_MATRICULA}` | matrícula do vínculo discente. |\n| `${ALUNO_PERIODO}` | ano/semestre declarado e validado. |\n| `${ALUNO_NASCIMENTO}` | `dd/mm/aaaa`. |\n| `${ALUNO_CPF}` / `${ALUNO_RG}` | documentos formatados. |\n| `${ALUNO_RG_ORGAO}` / `${ALUNO_RG_DATA_EMISSAO}` | emissor e data. |\n| `${ALUNO_ENDERECO}` | endereço completo de `internships.student_address_id`, quando houver; a cidade é resolvida por `city_id`. |\n| `${ALUNO_LOGRADOURO}` / `${ALUNO_NUMERO}` / `${ALUNO_BAIRRO}` | partes do endereço. |\n| `${ALUNO_CIDADE}` / `${ALUNO_UF}` / `${ALUNO_CEP}` | localidade formatada. |\n| `${CURSO_NOME}` | curso do estágio. |\n| `${RESPONSAVEL_NOME}` / `${RESPONSAVEL_CPF}` | somente para menor não emancipado. |\n| `${RESPONSAVEL_PARENTESCO}` / `${RESPONSAVEL_EMAIL}` | dados do responsável legal. |\n| `${BLOCO_RESPONSAVEL_LEGAL}` | bloco completo ou vazio; emancipação validada não expõe comprovante. |\n\n### Parte concedente\n\n| Variável | Origem/formato |\n| --- | --- |\n| `${CONCEDENTE_NOME}` | `granting_party_snapshot.name`. |\n| `${CONCEDENTE_DOCUMENTO}` | CPF/CNPJ formatado conforme o tipo. |\n| `${CONCEDENTE_EMAIL}` / `${CONCEDENTE_TELEFONE}` | contatos do snapshot. |\n| `${CONCEDENTE_AREA_ATUACAO}` | área de atuação. |\n| `${CONCEDENTE_ENDERECO}` | endereço completo de `internships.workplace_address_id`, preservado na formalização; a concedente atual não substitui essa referência histórica. |\n| `${CONCEDENTE_LOGRADOURO}` / `${CONCEDENTE_NUMERO}` / `${CONCEDENTE_BAIRRO}` | partes do endereço. |\n| `${CONCEDENTE_CIDADE}` / `${CONCEDENTE_UF}` / `${CONCEDENTE_CEP}` | localidade formatada. |\n| `${CONCEDENTE_REPRESENTANTE_NOME}` | representante legal. |\n| `${CONCEDENTE_REPRESENTANTE_CARGO}` | cargo do representante. |\n| `${CONCEDENTE_CONSELHO_PROFISSIONAL}` | vazio quando não houver. |\n| `${CONCEDENTE_REGISTRO_CONSELHO}` | vazio quando não houver. |\n| `${CONCEDENTE_PROCESSO_CREDENCIAMENTO}` | obrigatório apenas no modelo que o exigir. |\n\n### Orientação e supervisão\n\n| Variável | Origem/formato |\n| --- | --- |\n| `${ORIENTADOR_NOME}` / `${ORIENTADOR_EMAIL}` | snapshot do vínculo orientador. |\n| `${ORIENTADOR_MATRICULA}` | matrícula institucional, se exigida. |\n| `${SUPERVISOR_NOME}` | `supervisor_snapshot.name`. |\n| `${SUPERVISOR_EMAIL}` / `${SUPERVISOR_TELEFONE}` | contatos do snapshot. |\n| `${SUPERVISOR_CARGO}` | cargo/função na concedente. |\n| `${SUPERVISOR_QUALIFICACAO}` | qualificação declarada e aprovada. |\n| `${SUPERVISOR_FORMACAO}` / `${SUPERVISOR_EXPERIENCIA}` | opcionais conforme o documento. |\n\n### Estágio, jornada e remuneração\n\n| Variável | Origem/formato |\n| --- | --- |\n| `${ESTAGIO_TIPO}` | nome do tipo congelado. |\n| `${ESTAGIO_SETOR}` | setor/área de realização. |\n| `${ESTAGIO_ATIVIDADES}` | texto do plano de atividades. |\n| `${ESTAGIO_DATA_INICIO}` | `dd/mm/aaaa`. |\n| `${ESTAGIO_DATA_TERMINO_PREVISTA}` | resultado vigente do cálculo. |\n| `${ESTAGIO_CARGA_TOTAL}` / `${ESTAGIO_CARGA_TOTAL_EXTENSO}` | horas exigidas. |\n| `${ESTAGIO_CARGA_DIARIA_MAXIMA}` / `${ESTAGIO_CARGA_DIARIA_MAXIMA_EXTENSO}` | maior jornada diária da vigência usada. |\n| `${ESTAGIO_CARGA_SEMANAL}` / `${ESTAGIO_CARGA_SEMANAL_EXTENSO}` | soma semanal da vigência usada. |\n| `${ESTAGIO_JORNADA_DESCRICAO}` | descrição por dia da semana, pronta para bloco textual. |\n| `${ESTAGIO_REMUNERADO}` | `Sim` ou `Não`; usar apenas quando o modelo realmente pedir. |\n| `${ESTAGIO_BOLSA_VALOR}` / `${ESTAGIO_BOLSA_EXTENSO}` | moeda BRL e valor por extenso. |\n| `${ESTAGIO_AUXILIO_TRANSPORTE_VALOR}` / `${ESTAGIO_AUXILIO_TRANSPORTE_EXTENSO}` | moeda BRL e valor por extenso. |\n| `${PARAGRAFO_REMUNERACAO}` | §1º completo e descritivo; substitui definitivamente `ESPECIAL`. |\n| `${ESTAGIO_PROTOCOLO_SIGAA}` | protocolo, quando já existir e o documento permitir. |\n\n### Aditivo e rescisão\n\n| Variável | Origem/formato |\n| --- | --- |\n| `${ADITIVO_NUMERO}` | sequência do aditivo dentro do estágio. |\n| `${ADITIVO_VIGENCIA_INICIO}` | data em que a alteração passa a valer. |\n| `${ADITIVO_DESCRICAO_ALTERACAO}` | texto produzido a partir das mudanças aprovadas. |\n| `${RESCISAO_DATA_EFETIVA}` | data aprovada no pedido de cancelamento. |\n| `${RESCISAO_JUSTIFICATIVA}` | motivo aprovado, sem texto fixo no template. |\n| `${RESCISAO_SOLICITANTE_NOME}` | pessoa/parte que solicitou, quando exigido. |\n\n### Atestado de orientação e notas\n\n| Variável | Origem/formato |\n| --- | --- |\n| `${ESTAGIO_NOTA_SUPERVISOR}` | nota aprovada na escala de seu peso. |\n| `${ESTAGIO_NOTA_RELATORIO}` / `${ESTAGIO_NOTA_APRESENTACAO}` | contribuições lançadas pelo orientador. |\n| `${ESTAGIO_NOTA_FINAL}` | soma consolidada de 0 a 10. |\n| `${ESTAGIO_PERIODO}` | início e término formatados em uma expressão. |\n| `${ATESTADO_CARGA_ORIENTACAO}` | somente se existir regra institucional própria. |\n\n## Parágrafo de remuneração\n\nNão existe variável `${ESPECIAL}`. `${PARAGRAFO_REMUNERACAO}` recebe o parágrafo completo e é resolvida por regra de domínio:\n\n- não remunerado: texto institucional informando ausência de bolsa e auxílio-transporte;\n- remunerado: texto institucional com bolsa e auxílio-transporte, cada valor em BRL e por extenso;\n- ausência de auxílio: usar o texto aprovado para zero/ausência, sem produzir `R$ 0,00` por acidente;\n- valores são `decimal`/`BigDecimal`, nunca `float`;\n- o texto efetivamente usado entra no snapshot da geração.\n\nO texto jurídico deve ser aprovado uma vez pela instituição e coberto por teste de snapshot. O discente não edita o parágrafo.\n\n## Dados obrigatórios por template\n\nA versão armazena `required_variables` e `optional_variables`. Na geração, valor vazio em variável obrigatória interrompe o processo e informa os campos faltantes. Variável opcional vazia vira string vazia ou bloco omitido conforme o contrato. Blocos compostos devem ser preferidos quando remover apenas um valor deixaria rótulos, pontuação ou linhas vazias no documento.\n\n## Testes de aceitação\n\n- template válido e inválido, variável desconhecida e marcador remanescente;\n- marcador dividido em múltiplos runs do Word, em tabela, cabeçalho e rodapé;\n- acentos, quebras de linha, `&`, `<`, `>` e texto longo;\n- maior, menor com responsável e menor emancipado sem exposição da prova;\n- remunerado, não remunerado e auxílio ausente;\n- TCE padrão, credenciamento, SEDUC, EMATER, aditivo, rescisão e atestado;\n- falha antes/depois da criação do temporário com limpeza garantida;\n- duas requisições concorrentes e retry idempotente;\n- renderização visual de todas as páginas antes de disponibilizar cada versão.\n\n## Referências\n\n- [Migration 13 — document_templates](doc:migration-13-document-templates)\n- [Migration 14 — template_versions](doc:migration-14-template-versions)\n- [Migration 16 — generated_documents](doc:migration-16-generated-documents)\n- [Helper — NumberToWordsHelper](doc:helper-numbertowordshelper)",
  "sections": [
    {
      "id": "decisao-tecnica",
      "level": 2,
      "title": "Decisão técnica",
      "text": "Cada upload validado de um DOCX diferente cria uma versão do template lógico. O catálogo de variáveis é fixo no código; cada arquivo usa as variáveis necessárias. A geração usa a versão validada mais recente e registra a versão exata em `generated_documents`, sem criar uma versão nova por documento. Se uma correção substituir um arquivo já usado, o anterior permanece; versões nunca usadas podem ser excluídas fisicamente.  O arquivo DOCX versionado será processado localmente com `PhpOffice\\PhpWord\\TemplateProcessor`. A dependência `phpoffice/phpword` deverá ser direta no `composer.json`; a imagem de execução precisa das extensões `zip`, `xml`, `dom`, `mbstring` e `intl`. `brick/math` também será dependência direta porque o código de moeda o utiliza, ainda que Laravel já o instale transitivamente.  O marcador canônico é `${NOME_DA_VARIAVEL}`: letras maiúsculas, números e `_`, sem espaços, barras, acentos ou chaves duplas. Somente essa sintaxe será aceita nos templates cadastrados.",
      "line": 1
    },
    {
      "id": "componentes",
      "level": 2,
      "title": "Componentes",
      "text": "| Componente | Responsabilidade | | --- | --- | | `TemplateVariableCatalog` | Define nomes permitidos, tipo, sensibilidade, origem e formatação. | | `TemplateInspector` | Lê o DOCX como ZIP/XML e encontra variáveis inclusive em tabelas, cabeçalhos e rodapés. | | `TemplateValidator` | Rejeita variável desconhecida, obrigatória ausente, arquivo inválido e conteúdo inseguro. | | `DocumentSnapshotBuilder` | Carrega FKs e snapshots do estágio e produz um contexto imutável. | | `DocumentVariableResolver` | Resolve somente as variáveis declaradas pela versão do template. | | `RemunerationParagraphFormatter` | Produz o texto completo de `${PARAGRAFO_REMUNERACAO}`. | | `DocxDocumentGenerator` | Aplica valores no template, verifica sobras e salva em arquivo temporário privado. | | `GenerateInternshipDocument` | Autoriza, bloqueia concorrência, registra snapshot/status e entrega o arquivo. |  Helpers continuam restritos a formatação pura (`CurrencyHelper`, `NumberToWordsHelper`, datas e documentos). Regra jurídica, consulta ao banco, autorização e persistência pertencem aos serviços/Actions acima.",
      "line": 9
    },
    {
      "id": "fluxo-de-geracao",
      "level": 2,
      "title": "Fluxo de geração",
      "text": "1. o Setor escolhe um template lógico e a versão validada mais recente compatível com o campus e o tipo documental; 2. a Policy valida o vínculo ativo e o estágio; 3. a Action adquire lock por estágio, versão e token idempotente; 4. o builder carrega o contexto histórico, sem usar cadastro atual no lugar de snapshot já congelado; 5. o resolver produz somente as variáveis declaradas no schema da versão; 6. o gerador preenche uma cópia privada e temporária do DOCX; 7. uma inspeção final rejeita qualquer `${...}` restante; 8. após geração bem-sucedida, `generated_documents` registra template, hash, nome de saída e snapshot dos valores; 9. o arquivo é transmitido ao usuário autorizado e apagado em `finally`; 10. nova emissão cria novo registro; um retry com o mesmo token não duplica a geração.  Geração unitária será síncrona para permitir download imediato sem armazenamento definitivo. Lotes futuros poderão usar Job, mas o resultado permanecerá em armazenamento temporário privado com prazo curto e limpeza automática. DOCX/PDF final e documento assinado não são acervo do SGE.",
      "line": 24
    },
    {
      "id": "validacao-e-seguranca-do-upload",
      "level": 2,
      "title": "Validação e segurança do upload",
      "text": "- aceitar apenas `.docx` OOXML; rejeitar `.docm`, OLE e executáveis embutidos; - validar MIME, assinatura ZIP, tamanho total, quantidade e tamanho descompactado das entradas; - rejeitar relacionamentos externos, links de template remoto e macros; - calcular SHA-256 e impedir duplicata acidental dentro do mesmo template; - extrair variáveis de corpo, tabelas, cabeçalhos, rodapés, notas e caixas de texto suportadas; - rejeitar variáveis fora do catálogo e variáveis obrigatórias do schema que não estejam no arquivo; - registrar relatório de validação e impedir ativação enquanto houver erro; - gerar com dados fictícios, renderizar e exigir confirmação visual do Setor antes da ativação; - nunca incluir o comprovante de emancipação, tokens, senhas, logs ou metadados internos no contexto documental.",
      "line": 39
    },
    {
      "id": "catalogo-de-variaveis",
      "level": 2,
      "title": "Catálogo de variáveis",
      "text": "Cada versão declara quais itens abaixo são obrigatórios ou opcionais. Uma variável conhecida não se torna automaticamente disponível em todo template: o tipo de documento e a Policy limitam o contexto.",
      "line": 51
    },
    {
      "id": "documento-e-instituicao",
      "level": 3,
      "title": "Documento e instituição",
      "text": "| Variável | Origem/formato | | --- | --- | | `${DOCUMENTO_NUMERO}` | identificador público da geração, quando aplicável. | | `${DOCUMENTO_DATA_EMISSAO}` | data da geração em `dd/mm/aaaa`. | | `${DOCUMENTO_DATA_EMISSAO_EXTENSO}` | data por extenso em `pt_BR`. | | `${DOCUMENTO_TITULO}` | nome lógico aprovado da versão. | | `${CAMPUS_NOME}` | snapshot do campus. | | `${CAMPUS_CNPJ}` | CNPJ formatado. | | `${CAMPUS_EMAIL}` / `${CAMPUS_TELEFONE}` | contatos institucionais. | | `${CAMPUS_ENDERECO}` | endereço composto. | | `${CAMPUS_LOGRADOURO}` / `${CAMPUS_NUMERO}` / `${CAMPUS_BAIRRO}` | partes do endereço. | | `${CAMPUS_CIDADE}` / `${CAMPUS_UF}` / `${CAMPUS_CEP}` | localidade formatada. | | `${CAMPUS_REPRESENTANTE_NOME}` | pessoa representante no snapshot da geração. | | `${CAMPUS_REPRESENTANTE_CARGO}` | cargo institucional no vínculo/snapshot. | | `${CAMPUS_RESPONSAVEL_ESTAGIOS_NOME}` | signatário institucional configurado para o documento. | | `${CAMPUS_RESPONSAVEL_ESTAGIOS_CARGO}` | cargo exibido do signatário. | | `${SEGURO_SEGURADORA}` / `${SEGURO_APOLICE}` | configuração institucional vigente, congelada na geração. |",
      "line": 55
    },
    {
      "id": "discente-curso-e-responsavel",
      "level": 3,
      "title": "Discente, curso e responsável",
      "text": "| Variável | Origem/formato | | --- | --- | | `${ALUNO_NOME}` | `student_snapshot.name`. | | `${ALUNO_EMAIL}` / `${ALUNO_TELEFONE}` | contatos do snapshot. | | `${ALUNO_MATRICULA}` | matrícula do vínculo discente. | | `${ALUNO_PERIODO}` | ano/semestre declarado e validado. | | `${ALUNO_NASCIMENTO}` | `dd/mm/aaaa`. | | `${ALUNO_CPF}` / `${ALUNO_RG}` | documentos formatados. | | `${ALUNO_RG_ORGAO}` / `${ALUNO_RG_DATA_EMISSAO}` | emissor e data. | | `${ALUNO_ENDERECO}` | endereço completo de `internships.student_address_id`, quando houver; a cidade é resolvida por `city_id`. | | `${ALUNO_LOGRADOURO}` / `${ALUNO_NUMERO}` / `${ALUNO_BAIRRO}` | partes do endereço. | | `${ALUNO_CIDADE}` / `${ALUNO_UF}` / `${ALUNO_CEP}` | localidade formatada. | | `${CURSO_NOME}` | curso do estágio. | | `${RESPONSAVEL_NOME}` / `${RESPONSAVEL_CPF}` | somente para menor não emancipado. | | `${RESPONSAVEL_PARENTESCO}` / `${RESPONSAVEL_EMAIL}` | dados do responsável legal. | | `${BLOCO_RESPONSAVEL_LEGAL}` | bloco completo ou vazio; emancipação validada não expõe comprovante. |",
      "line": 75
    },
    {
      "id": "parte-concedente",
      "level": 3,
      "title": "Parte concedente",
      "text": "| Variável | Origem/formato | | --- | --- | | `${CONCEDENTE_NOME}` | `granting_party_snapshot.name`. | | `${CONCEDENTE_DOCUMENTO}` | CPF/CNPJ formatado conforme o tipo. | | `${CONCEDENTE_EMAIL}` / `${CONCEDENTE_TELEFONE}` | contatos do snapshot. | | `${CONCEDENTE_AREA_ATUACAO}` | área de atuação. | | `${CONCEDENTE_ENDERECO}` | endereço completo de `internships.workplace_address_id`, preservado na formalização; a concedente atual não substitui essa referência histórica. | | `${CONCEDENTE_LOGRADOURO}` / `${CONCEDENTE_NUMERO}` / `${CONCEDENTE_BAIRRO}` | partes do endereço. | | `${CONCEDENTE_CIDADE}` / `${CONCEDENTE_UF}` / `${CONCEDENTE_CEP}` | localidade formatada. | | `${CONCEDENTE_REPRESENTANTE_NOME}` | representante legal. | | `${CONCEDENTE_REPRESENTANTE_CARGO}` | cargo do representante. | | `${CONCEDENTE_CONSELHO_PROFISSIONAL}` | vazio quando não houver. | | `${CONCEDENTE_REGISTRO_CONSELHO}` | vazio quando não houver. | | `${CONCEDENTE_PROCESSO_CREDENCIAMENTO}` | obrigatório apenas no modelo que o exigir. |",
      "line": 94
    },
    {
      "id": "orientacao-e-supervisao",
      "level": 3,
      "title": "Orientação e supervisão",
      "text": "| Variável | Origem/formato | | --- | --- | | `${ORIENTADOR_NOME}` / `${ORIENTADOR_EMAIL}` | snapshot do vínculo orientador. | | `${ORIENTADOR_MATRICULA}` | matrícula institucional, se exigida. | | `${SUPERVISOR_NOME}` | `supervisor_snapshot.name`. | | `${SUPERVISOR_EMAIL}` / `${SUPERVISOR_TELEFONE}` | contatos do snapshot. | | `${SUPERVISOR_CARGO}` | cargo/função na concedente. | | `${SUPERVISOR_QUALIFICACAO}` | qualificação declarada e aprovada. | | `${SUPERVISOR_FORMACAO}` / `${SUPERVISOR_EXPERIENCIA}` | opcionais conforme o documento. |",
      "line": 111
    },
    {
      "id": "estagio-jornada-e-remuneracao",
      "level": 3,
      "title": "Estágio, jornada e remuneração",
      "text": "| Variável | Origem/formato | | --- | --- | | `${ESTAGIO_TIPO}` | nome do tipo congelado. | | `${ESTAGIO_SETOR}` | setor/área de realização. | | `${ESTAGIO_ATIVIDADES}` | texto do plano de atividades. | | `${ESTAGIO_DATA_INICIO}` | `dd/mm/aaaa`. | | `${ESTAGIO_DATA_TERMINO_PREVISTA}` | resultado vigente do cálculo. | | `${ESTAGIO_CARGA_TOTAL}` / `${ESTAGIO_CARGA_TOTAL_EXTENSO}` | horas exigidas. | | `${ESTAGIO_CARGA_DIARIA_MAXIMA}` / `${ESTAGIO_CARGA_DIARIA_MAXIMA_EXTENSO}` | maior jornada diária da vigência usada. | | `${ESTAGIO_CARGA_SEMANAL}` / `${ESTAGIO_CARGA_SEMANAL_EXTENSO}` | soma semanal da vigência usada. | | `${ESTAGIO_JORNADA_DESCRICAO}` | descrição por dia da semana, pronta para bloco textual. | | `${ESTAGIO_REMUNERADO}` | `Sim` ou `Não`; usar apenas quando o modelo realmente pedir. | | `${ESTAGIO_BOLSA_VALOR}` / `${ESTAGIO_BOLSA_EXTENSO}` | moeda BRL e valor por extenso. | | `${ESTAGIO_AUXILIO_TRANSPORTE_VALOR}` / `${ESTAGIO_AUXILIO_TRANSPORTE_EXTENSO}` | moeda BRL e valor por extenso. | | `${PARAGRAFO_REMUNERACAO}` | §1º completo e descritivo; substitui definitivamente `ESPECIAL`. | | `${ESTAGIO_PROTOCOLO_SIGAA}` | protocolo, quando já existir e o documento permitir. |",
      "line": 123
    },
    {
      "id": "aditivo-e-rescisao",
      "level": 3,
      "title": "Aditivo e rescisão",
      "text": "| Variável | Origem/formato | | --- | --- | | `${ADITIVO_NUMERO}` | sequência do aditivo dentro do estágio. | | `${ADITIVO_VIGENCIA_INICIO}` | data em que a alteração passa a valer. | | `${ADITIVO_DESCRICAO_ALTERACAO}` | texto produzido a partir das mudanças aprovadas. | | `${RESCISAO_DATA_EFETIVA}` | data aprovada no pedido de cancelamento. | | `${RESCISAO_JUSTIFICATIVA}` | motivo aprovado, sem texto fixo no template. | | `${RESCISAO_SOLICITANTE_NOME}` | pessoa/parte que solicitou, quando exigido. |",
      "line": 142
    },
    {
      "id": "atestado-de-orientacao-e-notas",
      "level": 3,
      "title": "Atestado de orientação e notas",
      "text": "| Variável | Origem/formato | | --- | --- | | `${ESTAGIO_NOTA_SUPERVISOR}` | nota aprovada na escala de seu peso. | | `${ESTAGIO_NOTA_RELATORIO}` / `${ESTAGIO_NOTA_APRESENTACAO}` | contribuições lançadas pelo orientador. | | `${ESTAGIO_NOTA_FINAL}` | soma consolidada de 0 a 10. | | `${ESTAGIO_PERIODO}` | início e término formatados em uma expressão. | | `${ATESTADO_CARGA_ORIENTACAO}` | somente se existir regra institucional própria. |",
      "line": 153
    },
    {
      "id": "paragrafo-de-remuneracao",
      "level": 2,
      "title": "Parágrafo de remuneração",
      "text": "Não existe variável `${ESPECIAL}`. `${PARAGRAFO_REMUNERACAO}` recebe o parágrafo completo e é resolvida por regra de domínio:  - não remunerado: texto institucional informando ausência de bolsa e auxílio-transporte; - remunerado: texto institucional com bolsa e auxílio-transporte, cada valor em BRL e por extenso; - ausência de auxílio: usar o texto aprovado para zero/ausência, sem produzir `R$ 0,00` por acidente; - valores são `decimal`/`BigDecimal`, nunca `float`; - o texto efetivamente usado entra no snapshot da geração.  O texto jurídico deve ser aprovado uma vez pela instituição e coberto por teste de snapshot. O discente não edita o parágrafo.",
      "line": 163
    },
    {
      "id": "dados-obrigatorios-por-template",
      "level": 2,
      "title": "Dados obrigatórios por template",
      "text": "A versão armazena `required_variables` e `optional_variables`. Na geração, valor vazio em variável obrigatória interrompe o processo e informa os campos faltantes. Variável opcional vazia vira string vazia ou bloco omitido conforme o contrato. Blocos compostos devem ser preferidos quando remover apenas um valor deixaria rótulos, pontuação ou linhas vazias no documento.",
      "line": 175
    },
    {
      "id": "testes-de-aceitacao",
      "level": 2,
      "title": "Testes de aceitação",
      "text": "- template válido e inválido, variável desconhecida e marcador remanescente; - marcador dividido em múltiplos runs do Word, em tabela, cabeçalho e rodapé; - acentos, quebras de linha, `&`, `<`, `>` e texto longo; - maior, menor com responsável e menor emancipado sem exposição da prova; - remunerado, não remunerado e auxílio ausente; - TCE padrão, credenciamento, SEDUC, EMATER, aditivo, rescisão e atestado; - falha antes/depois da criação do temporário com limpeza garantida; - duas requisições concorrentes e retry idempotente; - renderização visual de todas as páginas antes de disponibilizar cada versão.",
      "line": 179
    },
    {
      "id": "referencias",
      "level": 2,
      "title": "Referências",
      "text": "- [Migration 13 — document_templates](doc:migration-13-document-templates) - [Migration 14 — template_versions](doc:migration-14-template-versions) - [Migration 16 — generated_documents](doc:migration-16-generated-documents) - [Helper — NumberToWordsHelper](doc:helper-numbertowordshelper)",
      "line": 191
    }
  ],
  "sourcePath": "content/geracao-de-documentos-docx-e-variaveis.md",
  "visuals": [],
  "apiVersion": 1
}
