-
Notifications
You must be signed in to change notification settings - Fork 96
Modelos Simples
Tradicionalmente os modelos do Siga-Doc são desenvolvidos utilizando HTML e a linguagem FreeMarker. Embora esta seja uma opção viável e muito flexível, em muitos casos o desenvolvimento dos modelos se torna demasiado complexo.
Surgiu então a necessidade de simplificar os modelos, na esperança de que os próprios usuários, ou pessoas com menos conhecimento de programação, também fossem capazes de produzir modelos. Pelo menos os mais simples.
Em vez de HTML, os modelos simples utilizam Markdown, que é uma linguagem de marcação muito mais simples e concisa, e que é convertida facilmente em HTML. Markdown é utilizado por muitas empresas, como a Wikipedia e o GitHub, que precisam gerar documentos padronizados, sem dar espaço para muitas "invenções", mas mantendo as principais capacidades de formatação que o HTML oferece. Além do link acima, uma lista de comandos e as formatações produzidas pode ser vista aqui.
Em vez do FreeMarker foi desenvolvida uma nova ferramenta de processamento de modelos chamada JModel. O Jmodel tem por objetivo facilitar ao máximo o trabalho de marcar onde entram os campos que devem compor a "entrevista".
O modelo mais simples de todos é composto de um único parágrafo de texto no qual existe a inserção de um campo para perguntar, por exemplo, o nome de uma pessoa. Este modelo pode ser visto abaixo:
Olá, {nome}!
Se, na entrevista, for fornecido o nome "Renato" o documento resultante terá um único parágrafo, que será assim:
Olá Renato!
Claro que é possível criar mais parágrafos, e para isso basta pular uma linha no texto. Também se pode introduzir quantos campos quiser. Só com esse conhecimento, já seria possível criar um modelo bem básico, algo do tipo:
Eu, {nome}, portador do CPF número {cpf}, venho pedir {pedido}.
Alego ao meu favor que {alegacao}.
Uma coisa importante a respeito dos campos é que o nome que é utilizado deve sempre começar com uma letra minúscula e ser composto por letras não acentuadas, números e o caracter sublinhado (_). Este nome é o identificador de uma variável, por isso tem que respeitar estas limitações.
O mais comum é utilizar campos que permitem a informação de uma linha de texto. No entanto, em muitos casos queremos que o campo aceite apenas um CPF, uma data, ou algum outro tipo de dado específico.
Uma tabela com todos os tipos de campos suportados pelo sistema pode ser vista abaixo:
Tipo | Prefixo | Descrição |
---|---|---|
texto | Campo de texto padrão | |
selecao | Campo de seleção em lista | |
memo | memo | Campo de texto de múltiplas linhas |
data | dt | Campo de texto para entrada de data |
hora | hm | Campo de texto para entrada de hora |
numero | num | Campo de texto para entrada de número inteiro |
valor | val | Campo de texto para entrada de valor monetário |
checkbox | chk | Campo do tipo "checkbox" do HTML |
radio | rad | Campo do tipo "radio" do HTML |
editor | Campo de edição de HTML | |
cpf | cpf | Campo de texto para entrada de CPF |
cnpj | cnpj | Campo de texto para entrada de CNPJ |
pessoa | pessoa | Campo de seleção de pessoa |
lotacao | lotacao | Campo de seleção de lotação |
cossignatario | Campo para seleção de cossignatário (será automaticamente incluído na lista de cossignatários do documento) | |
funcao | funcao | Campo para seleção de função gratificada |
oculto | Campo do tipo "hidden" do HTML |
O nome da variável pode ser utilizado para inferir o tipo. Por exemplo, se o nome for "cpf" ou "cpf_servidor" ou "cpfServidor" será automaticamente atribuído o tipo "cpf". Isto acontece porque, como pode ser visto na tabela acima, para alguns tipos de campo existe um "prefixo". O tipo também pode ser especificado diretamente, através do parâmetro "tipo". No exemplo abaixo, todos os campos serão do tipo CPF:
{cpf}
{cpf_servidor}
{cpfServidor}
{codigo kind='cpf'}
Existe um tipo de campo chamado "selecao" que contem uma lista de opções dentre as quais o usuário
deve escolher apenas uma. A lista de opções deve ser informada no parâmetro options
e precisa estar
separada por ";", como pode ser visto no exemplo abaixo:
País: {pais options='Brasil;Argentina'}
Quando o tipo não é informado e nenhum prefixo é reconhecido, se for informado o parâmetro "options" será assumido o tipo "selecao", caso o contrário, será assumido o tipo "texto"
No exemplo abaixo, o campo {cpf}
será automaticamente reconhecido e permitirá apenas a entrada
de um número válido. E o campo {pedido options='férias;licença médica'}
apresentará apenas estas
duas opções para o usuário selecionar. Além disso, o campo {alegacao kind='memo'}
permitirá que o
usuário digite um texto de várias linhas.
Eu, {nome}, portador do CPF número {cpf}, venho pedir {pedido options='férias;licença médica'}.
Alego ao meu favor que {alegacao kind='memo'}.
O título de um campo na entrevista pode ser especificado através do parâmetro title
:
Servidor: {nome title='Nome do Servidor'}
O número de linhas e colunas de um campo do tipo memo
pode ser espeficicado conforme o exemplo abaixo:
{memo columns=80 lines=3}
Por padrão o preenchimento dos campos é opcional, mas se for obrigatório, basta incluir o parâmetro required=true
:
Nome: {nome required=true}
Caso deseje informar um valor default para o campo, isso pode ser obtido conforme o exemplo abaixo:
País: {pais default='Brasil'}
Quando precisamos que trechos do modelo sejam apresentados, ou não, dependendo do preenchimento de algum campo anterior, podemos utilizar o comando IF. No exemplo abaixo, a Unidade Federativa será perguntada apenas se a esfera for "Estadual". Se a esfera for "Federal", nenhuma pergunta posterior será feita:
Esfera: {esfera options='Federal;Estadual' refresh='esf'}
{if esfera=='Estadual' depend='esf'}
Estado: {uf options='RJ;SP'}
{/if}
Este exemplo introduz uma série de novidades. Vamos estudá-las uma a uma.
Temos dois novos parâmetros que são o refresh
e o depend
. Eles são utilizados para indicar
ao sistema que quando é feita uma alteração no campo que tem o parâmetro refresh
o comando
que tem o depend
deve ser atualizado. E, para isso, é importante que o valor informado para o
refresh
seja o mesmo que foi informado para o depend
, no exemplo acima foi utilizado o valor
'esf'
, que são as 3 primeiras letras de "esfera". Em vez disso, poderia ser qualquer outra coisa como,
por exemplo, 'esfera-alterada'
.
Se não utilizarmos o refresh
e o depend
a entrevista não será automaticamente alterada para
apresentar o campo "Estado" quando o usuário selecionar a esfera "Estadual". Neste caso, seria necessário
dar um OK na edição do documento e depois voltar a editá-lo para que o campo de "Estado" fosse apresentado.
O comando refresh
sempre aceita um único valor. Já o depend
pode receber uma lista de valores
separados por ponto-e-vírgula para indicar que qualquer alteração em um dos campos marcados com refresh
causará a atualização do comando. Por exemplo, poderíamos ter um comando assim:
{if pais=='Brasil' && esfera=='Estadual' depend='pais;esf'}
.
O comando {if esfera=='Estadual' depend='esf'}
marca o início do trecho que é opcional, e o comando
{/if}
marca o final. Tudo que está entre estes dois comando será suprimido caso a expressão
esfera=='Estadual'
não seja verdadeira.
No exemplo acima estamos comparando o valor da variável esfera
com a constante 'Estadual'
. Observe
que o último está entre aspas simples. Isso é necessário para que o valor da constante não se confunda
com o nome de outra variável.
Estamos usando o operador de igualdade, ==
, mas muitos outros operadores poderiam ser utilizados como,
por exemplo, o de desigualdade: !=
. Todas as expressões
do FreeMarker estão disponível para uso e, inclusive, podem conter operadores lógicos como "e" (&&
),
"ou" (||
) e "não" (!
).
Em algumas situações é necessário repetir um trecho do documento ou da entrevista diversas vezes, por exemplo, se
desejarmos colher o nome de várias pessoas. Uma maneira comum de fazer isso é perguntando primeiro quantas pessoas
são e depois usando o comando for
para repetir várias vezes o trecho do documento que contém o campo que
pergunta o nome. Um exemplo deste tipo de modelo pode ser visto abaixo:
Número de Pessoas: {num options='1;2;3;4;5' refresh='num'}
{for num depend='num'}
Nome: {nome}
{/for}
A primeira coisa que percebemos no exemplo acima é que precisamos usar a mesma lógica de refresh
e depend
que usamos no caso do if
. Ela é necessária para que os campos sejam criados dinamicamente na entrevista,
conforme o usuário escolhe o número de pessoas.
O comando for
recebe como parâmetro uma variável que deve conter um número inteiro. O trecho entre o for
e o /for
será repetido o número de vezes indicado por esse parâmetro.
Os campos que estiverem dentro de um for
terão seus nomes acrescidos de um sufixo que varia de 1 até o
número final da repetição. Por exemplo, se o usuário selecionar o número 3, em um {for 3}
os 3 campos de nome
gerados ganhariam o nomes nome1
, nome2
e nome3
.
Se houver a necessidade de utilizar esse contador em alguma expressão do FreeMarker, ou simplesmente imprimi-lo
no documento final, o contador fica disponível na variável automática _index
.
Por exemplo, se desejarmos incluir o número do contador no título do campo que aparece na entrevista, podemos fazer assim:
{nome title='Nome '+_index}
Até agora vimos como se faz para criar o texto do documento e não consideramos outros aspectos como brasão, cabeçalho, assinatura, rodapé, etc.
Existem alguns estilos pré-definidos para os documentos e para inserirmos nosso texto dentro de um deles
utilizaremos o comando set
. O que este comando faz é atribuir valores para algumas variáveis que controlarão
a seleção do estilo e alguns parâmetros para configurar detalhes de formatação.
Existem algumas variáveis que são padrão do JModel e é fácil identificá-las pois os nomes são em inglês e elas
são escritas em letras todas maiúsculas. A principal variável que precisa ser definida se chama STYLE
e é
utilizada para escolher o estilo do documento. A tabela completa pode ser vista abaixo:
Variável | Objetivo |
---|---|
STYLE | Define o estilo do documento e aceita as seguintes opções, todas entre aspas simples: memorando, assentamentoFuncional, requerimento, processo, provimento, portaria, oficio e solicitacao. Se nenhum valor for informado será criado um documento do estilo default apenas com brasão centralizado e assinatura. |
PAGE_SIZE | Define o formato da página, o valor default é 'A4' |
PAGE_ORIENTATION | Define a orientação da página que por padrão é 'portrait' mas pode também ser 'landscape' |
MARGIN_LEFT | Margem esquerda que por padrão é '3cm' |
MARGIN_RIGHT | Margem direita que por padrão é '2cm' |
MARGIN_TOP | Margem superior que por padrão é '1cm' |
MARGIN_BOTTOM | Margem inferior que por padrão é '2cm' |
Também existem parâmetros complementares que são específicos do Siga-Doc e podem ser vistos na tabela abaixo:
Variável | Objetivo |
---|---|
_fecho | Indica o fecho de um memorando, requerimento ou ofício, o valor default é 'Atenciosamente,' para memorando e requerimento |
_tamanhoLetra | Permite aumentar ou diminuir o tamanho do fonte, as opções são Pequena, Normal e Grande, o valor default é 'Normal' |
_tipo | Sobrescreve o tipo do documento que é apresentado logo antes do número |
_formatarOrgao | Apresenta o nome do órgão junto aos dados da assinatura |
_ementa | Texto da ementa, apenas para provimento |
_titulo | Título, apenas para provimento |
_subtitulo | Subtítulo, apenas para provimento |
_dispoeSobre | Texto informado sobre o que dispõe a portaria |
_abertura | Texto de abertura da portaria |
_tipoAutoridade | Tipo de autoridade do ofício |
_genero | Gênero da autoridade do ofício |
_vocativo | Vocativo da autoridade do ofício |
_enderecamentoDest | Endereçamento do destinatário do ofício |
_nomeDest | Nome do destinatário do ofício |
_cargoDest | Cargo do destinatário do ofício |
_orgaoDest | Órgão destinatário do ofício |
_enderecoDest | Endereço do destinatário do ofício |
_assunto | Assunto da solicitação |
_exibeAssinatura | Indica se o estilo default deve exibir assinatura, o default é true |
_orgaoCabecalho | Indica se o estilo default deve apresentar o nome do órgão no cabeçalho, o valor default e true |
_numeracaoCentralizada | Indica se a numeração do estilo default deve ser centralizada, o valor default é false |
_dataAntesDaAssinatura | Indica se a data deve ser exibida logo antes da assinatura no estilo default, o valor default é false |
_incluirMioloDJE | Indica se o "miolo" do documento deve ser exportado para o Diário no estilo default, o valor default é false |
_omitirCodigo | Indica se o código do documento deve ser omitido no estilo default, o valor default é false |
_omitirData | Indica se a data do documento deve ser omitido no estilo default, o valor default é false |
_topoPrimeiraPagina | Texto a ser incluído no topo da primeira página do documento no estilo default |
_incluirAssinaturaBIE | Indica se a assinatura deve ser incluída no Boletim Interno no estilo default, o valor default é true |
_exibeClassificacaoDocumental | Indica se o código da classificação documental deve ser incluída no documento no estilo default, o valor default é true |
_exibeRodapeEnderecamento | Indica se o rodapé de endereçamento deve ser incluída no documento no estilo default, o valor default é false |
Um memorando bem simples poderia ser gerado da seguinte forma:
{set STYLE='memorando' _fecho='Cordialmente,'}
Eu, {nome}, estou de acordo.
É comum acrescentarmos trechos de código FreeMarker que são executados em determinados momentos do ciclo de vida
de um documento. Por exemplo, podemos querer iniciar um procedimento de Workflow quando o documento é assinado,
ou validar o preenchimento de algum perfil antes da assinatura. Para isso existe o comando hook
. No exemplo
abaixo, temos o hook
sendo utilizado exatamente para esse fim:
{hook 'BEFORE_SIGN'}
[#if !doc.getResponsaveisPorPapel("gestor")??]
${exbl.appException("Não é permitido assinar este documento antes de definir uma pessoa ou lotação com o papel de Gestor para representar o proponente da solicitação de deslocamento")}
[/#if]
{/hook}
{hook 'AFTER_SIGN'}
[#assign criado = func.criarWorkflow('TRF2: Solicitação de Deslocamento', doc, cadastrante, titular, lotaCadastrante, lotaTitular) /]
{/hook}
As etapas do ciclo de vida que são interceptadas pelo hook
são as seguintes:
Identificador | Etapa |
---|---|
BEFORE_SAVE | Imediatamente antes de gravar o documento |
AFTER_DRAFT | Quando o documento em elaboração é finalizado |
BEFORE_SIGN | Imediatamente antes de gravar a assinatura |
AFTER_SIGN | Imediatamente depois de gravar a assinatura |
Se desejarmos agrupar alguns campos da entrevista, ou se quisermos acrescentar um aviso ao usuário que vai minutar
o documento, podemos utilizar o comando group
:
{group title='Identificação' warning='Seus dados serão mantidos em sigilo'}
Nome: {nome}
CPF: {cpf}
{/group}
Por padrão cada campo ocupará uma linha inteira na página de entrevista. Muitas vezes este tamanho todo é desnecessário.
Para criar campos menores, podemos utilizar o parâmetro col
. Para o sistema, uma linha da entrevista contém o
equivalente a 12 colunas. Sendo assim, poderíamos criar 2 campos, cada um com a largura de 6 colunas para que eles
dividam a linha meio-a-meio:
Nome: {nome col=6}
CPF: {cpf col=6}
Outras opções podem ser exploradas, por exemplo, o nome poderia ocupar 2/3 da linha e o CPF o terço restante:
Nome: {nome col=8}
CPF: {cpf col=4}
Existem duas maneiras para inserir Modelos Simples no Siga-Doc.
A primeira consiste em selecionar a opção "FreeMarker" e incluir o modelo diretamente. O Siga-Doc faz uma
avaliação do modelo e concluirá que se trata de um modelo simples desde que ele não encontre nenhuma das
macros @entrevista
, @documento
, @descricao
, @markdown
ou @dadosComplementares
.
Por outro lado, pode ser interessante misturar o Modelo Simples com outras definições feitas diretamente em
FreeMarker, do jeito antigo. A segunda opção, portanto, consiste em incluir o Modelo Simples entre as
pseudo macros [@markdown]
e [/@markdown]
. Dizemos que são pseudo macros porque elas não
são processadas pelo FreeMarker com as macros comuns, elas são detectadas pelo Siga-Doc e o conteúdo é
convertido em FreeMarker e Markdown pelo JModel. Um exemplo de uso desta segunda opção seria:
[@entrevista]
[@campo var="nome" /]
[/@entrevista]
[@markdown]
Olá {print nome}!
[/@markdown]
Em determinadas situações pode ser necessário criar algum tipo de diagramação não suportada pelo Markdown.
De maneira geral, isso provavelmente significa que estamos querendo criar um documento digital como se ele fosse um daqueles antigos formulários para serem preenchidos a mão. Por favor, não façam isso. A estética desses documento é coisa de outra época. Mesmo assim, ainda existem pessoas que acreditam que é assim que fica bonito. Fazer documentos digitais com caixinhas como se eles fossem ser preenchidos manualmente dificulta, complica e é muito contraproducente.
Se, mesmo assim, for detectada a necessidade de usar algum tipo de diagramação não suportada pelo Markdown, a boa notícia é que código HTML pode ser escrito junto com o Markdown, sem problema algum:
<p style="color: red">Olá, {nome}</p>
Por outro lado, pode ser necessário usar IFs ou FORs ou expressões mais complexa. Neste caso, é possível aplicar código FreeMarker diretamente no Modelo Simples, conforme pode ser visto abaixo:
País: {pais options='Brasil;Argentina'}
[#if pais=='Brasil']
Ótimo lugar para se morar!
[/#if]