Pular para o conteúdo

Linguagem dos modelos

Esta página é para quem quer ir além dos modelos prontos e escrever o próprio layout da comanda ou de um complemento. Não é preciso saber programar, mas é preciso atenção: um detalhe fora do lugar pode impedir a impressão. Trabalhe sempre numa cópia do modelo, acompanhe a pré-visualização e faça um Imprimir teste antes de colocar em uso (veja Modelos de comanda).

Um modelo tem duas camadas, misturadas no mesmo texto:

  1. Os dados, sempre entre chaves duplas: {{ empresa.nome }}, {{ pesagem.total | moeda }}. Essa camada escreve os dados da comanda, decide o que aparece (condições) e repete linhas (repetições).
  2. O layout, com marcações parecidas com as de uma página de internet: <p> para parágrafos, <table> para tabelas, <hr/> para linhas separadoras e assim por diante. Essa camada diz como cada coisa é arrumada no papel.

Primeiro o sistema troca tudo o que está entre chaves pelos dados da comanda; depois monta o resultado na largura do papel, em texto de largura fixa, como a impressora térmica imprime. Por exemplo, este modelo:

<p bold text-center>{{ empresa.nome }}</p>
<p>Comanda N.{{ pesagem.numero }}</p>

vira, numa comanda de número 5 do “Restaurante Sabor”:

Restaurante Sabor
Comanda N.5

com o nome em negrito e centralizado na linha.

Uma variável é escrita entre {{ e }} e é trocada pelo valor correspondente da comanda. Os nomes são sempre em letras minúsculas, sem acento, com as palavras separadas por _ e os grupos separados por ponto: empresa.endereco_completo, pesagem.peso_aferido, configuracao_comanda.mensagem_rodape.

<p>{{ empresa.nome }}</p>
<p>{{ empresa.cidade }} / {{ empresa.estado }}</p>
<p>Peso: {{ pesagem.peso_aferido | numero 3 }} kg</p>

Se você errar o nome de uma variável, não aparece erro: o lugar dela fica em branco. Quando um dado sumir da pré-visualização, confira a grafia.

Variáveis disponíveis nos modelos de comanda e nos complementos:

Variável O que contém
empresa.nome Nome (fantasia) da empresa.
empresa.endereco Logradouro, sem número.
empresa.endereco_numero Número do endereço (opcional).
empresa.bairro Bairro.
empresa.cidade Cidade.
empresa.estado Sigla do estado (UF).
empresa.cep CEP.
empresa.telefone Telefone fixo.
empresa.celular Telefone celular.
empresa.email E-mail de contato.
empresa.site Endereço do site.
empresa.contato_empresa “Telefone / Celular” (só os preenchidos).
empresa.possui_algum_contato Verdadeiro quando telefone ou celular estão preenchidos.
empresa.endereco_completo “Endereço, Número - Bairro” (o número só aparece quando preenchido).
frase.descricao Texto da frase.
frase.autor Autor da frase (opcional).
configuracao_comanda.exibir_frases Imprime a frase do dia quando houver.
configuracao_comanda.quantidade_linhas_em_branco Linhas em branco para anotações: 0 a 20.
configuracao_comanda.mensagem_rodape Mensagem impressa no rodapé (vazia = sem rodapé).
configuracao_comanda.produtos_adicionais_comanda Lista. Produtos adicionais listados na comanda para marcação manual.
configuracao_comanda.produtos_adicionais_comanda[].ordem Posição na lista (ordem crescente).
configuracao_comanda.produtos_adicionais_comanda[].descricao Nome do produto.
configuracao_comanda.produtos_adicionais_comanda[].valor_unitario Preço unitário (nulo = não impresso).
configuracao_comanda.imprimir_codigo_barras Imprime o código de barras na comanda.
configuracao_comanda.template_codigo Modelo de 12 caracteres do código de barras: letras I, C, T, P, Q e dígitos.
pesagem.numero Número sequencial da comanda.
pesagem.codigo Código do produto (usado pelo “I” do código de barras).
pesagem.data Data e hora da pesagem.
pesagem.descricao Descrição do preço/produto pesado.
pesagem.modalidade Forma de cobrança.
pesagem.valor_unitario Valor do quilo (por quilo) ou da unidade (fixo) aplicado.
pesagem.peso_aferido Peso lido na balança (kg).
pesagem.quantidade Quantidade cobrada: kg (por quilo, já com a política à vontade) ou unidades (preço fixo).
pesagem.total Valor cobrado (valor unitário × quantidade, já truncado/arredondado pelo app).
preco.titulo Nome do preço (ex.: “Refeição”).
preco.modalidade Forma de cobrança do preço.
preco.padrao Preço padrão da balança (usado quando nenhum outro é escolhido).
preco.utilizar_politica_avontade Aplica a política “à vontade”: a cobrança fica limitada ao valor do à vontade.
preco.valor_vigente Valor do quilo (ou valor fixo) vigente agora.
preco.valor_avontade Valor “à vontade” vigente agora (0 quando não se aplica).
preco_atual Valor do quilo vigente (preço do dia/horário); sem preço usa o valor unitário da pesagem.
total Peso aferido × valor do quilo vigente (sem truncamento). O valor cobrado é pesagem.total.
exibir_frase Verdadeiro quando a configuração exibe frases e há uma frase com texto.
exibir_mensagem_rodape Verdadeiro quando há mensagem de rodapé configurada.
linhas_em_branco[] [1..N] para repetir linhas em branco: {{ for linha in linhas_em_branco }}. N limitado a 0–20.
codigo_barras Conteúdo do código de barras (12 caracteres) montado pelo modelo do código; nulo quando desativado ou quando o template do código é inválido.
comanda_livre Comanda livre (em branco): quantidade, peso aferido e total zerados.
gratis Houve peso aferido, mas o valor cobrado é zero.
modalidade_por_quilo Verdadeiro quando a pesagem é cobrada por quilo (e não por valor fixo).
produtos_adicionais Lista. Produtos adicionais, na ordem cadastrada.
produtos_adicionais[].ordem Posição na lista (ordem crescente).
produtos_adicionais[].descricao Nome do produto.
produtos_adicionais[].valor_unitario Preço unitário (nulo = não impresso).
produtos_adicionais_agrupados_por_dois Lista. Produtos adicionais em grupos de 2; o último grupo é completado com itens vazios.
produtos_adicionais_agrupados_por_dois[][].descricao Nome do produto (nulo no item vazio).
produtos_adicionais_agrupados_por_dois[][].valor_unitario Preço unitário (nulo quando não informado ou no item vazio).
produtos_adicionais_agrupados_por_tres Lista. Produtos adicionais em grupos de 3; o último grupo é completado com itens vazios.
produtos_adicionais_agrupados_por_tres[][].descricao Nome do produto (nulo no item vazio).
produtos_adicionais_agrupados_por_tres[][].valor_unitario Preço unitário (nulo quando não informado ou no item vazio).

Algumas dicas sobre elas:

  • pesagem.total é o valor cobrado, já com a política à vontade e o arredondamento configurado. É o valor que você normalmente quer imprimir.
  • Na política à vontade, pesagem.descricao já traz o título do à vontade (por exemplo “Refeição à vontade”), pesagem.quantidade é 1 e pesagem.valor_unitario é o valor do à vontade. Para mostrar o peso real do prato, use pesagem.peso_aferido.
  • Na comanda em branco (comanda livre), valores e peso vêm zerados; use comanda_livre para esconder esses campos.

Para que números, dinheiro e datas saiam no formato brasileiro, passe o valor por uma função com a barra vertical |:

Função O que faz
moeda {{ pesagem.total | moeda }} → “R$ 12,34”.
numero {{ pesagem.peso_aferido | numero 3 }} → “0,450”.
formatar Formata datas e números no padrão brasileiro: {{ pesagem.data | formatar "dd/MM/yyyy" }} → “27/09/2026”, {{ pesagem.total | formatar "C2" }} → “R$ 12,34”.
bruto Escreve o valor sem escapar HTML (permite gerar tags a partir de dados).

Exemplos prontos:

Você escreve Sai no papel
{{ pesagem.total | moeda }} R$ 26,95
{{ pesagem.peso_aferido | numero 3 }} 0,450
{{ pesagem.quantidade | numero 0 }} 1
{{ pesagem.data | formatar "dd/MM/yyyy HH:mm" }} 27/09/2026 12:48
{{ pesagem.data | formatar "dd/MM/yy" }} 27/09/26
{{ pesagem.data | formatar "HH:mm" }} 12:48
{{ pesagem.data | formatar "dddd" }} domingo
{{ preco_atual | formatar "C2" }} R$ 59,90

Sem função, uma data sai completa, como 27/09/2026 12:48:30, e um número sai com vírgula decimal, mas sem casas fixas. Prefira sempre formatar.

Use {{ if ... }} e {{ end }} para imprimir um trecho só em certas situações. {{ else }} define o que sai no caso contrário, e {{ else if ... }} encadeia mais casos:

{{ if empresa.site }}
<p text-center>{{ empresa.site }}</p>
{{ end }}
<p>Total: {{ if gratis }}Grátis{{ else }}{{ pesagem.total | moeda }}{{ end }}</p>
{{ if pesagem.peso_aferido > 1 }}
<p>Prato caprichado!</p>
{{ else if pesagem.peso_aferido > 0.5 }}
<p>Bom apetite!</p>
{{ end }}
  • O ! inverte a condição: {{ if !comanda_livre }} imprime tudo, menos na comanda em branco.
  • Para comparar, use >, <, >=, <=, == (igual) e != (diferente). Em números, use ponto como separador decimal dentro das chaves: 0.5, e não 0,5.
  • Contam como “falso” as opções desligadas e os dados vazios: sem valor, texto em branco ou lista sem itens. Por isso {{ if empresa.site }} só imprime quando o site está preenchido.
  • Números sempre contam como verdadeiro, até o zero. Para testar um valor, compare: {{ if pesagem.total > 0 }}.
  • Todo {{ if }} precisa do seu {{ end }}.

Use {{ for ... in ... }} e {{ end }} para repetir um trecho para cada item de uma lista:

{{ for item in produtos_adicionais }}
<p>( ) {{ item.descricao }} {{ if item.valor_unitario }}{{ item.valor_unitario | moeda }}{{ end }}</p>
{{ end }}

A lista linhas_em_branco existe só para repetir linhas vazias a quantidade de vezes configurada nas configurações gerais:

{{ for linha in linhas_em_branco }}
<p>______________________________</p>
{{ end }}

Dentro da repetição, for.index dá a posição (começando em 0), for.first é verdadeiro no primeiro item e for.last no último.

Trechos entre {{# e }} são anotações suas e não são impressos:

{{# Cabeçalho com o nome e o endereço }}

Os dados são impressos exatamente como foram cadastrados: um nome como “Bar & Grill” sai correto, sem atrapalhar o layout. Se um dado contiver, de propósito, marcações de layout que devem ser obedecidas, use a função bruto. Isso é raro e só é necessário em modelos avançados.

A linguagem dos dados segue o padrão Scriban, e as funções prontas dele também funcionam, como {{ empresa.nome | string.upcase }} para imprimir o nome em maiúsculas.

Tudo o que é impresso precisa estar dentro de um bloco. Texto solto, fora de um bloco, não é impresso.

Marcação O que faz
<p>texto</p> Parágrafo. O texto quebra nas palavras quando não cabe na linha.
<table>, <tr>, <td> Tabela: <table> abre a tabela, cada <tr> é uma linha e cada <td> é uma célula.
<br/> Linha em branco. Dentro de um parágrafo, quebra a linha.
<hr/> Linha separadora, com traços de ponta a ponta.
<logo/> Logo da empresa, cadastrado em Empresa. Sem logo, não imprime nada.
<bar-code>...</bar-code> Código de barras nativo da impressora.

Marcações que não estão nesta lista (como <div>) são ignoradas, mas o texto dentro delas continua valendo.

  • Espaços repetidos, tabulações e quebras de linha do texto do modelo viram um único espaço. Para quebrar a linha dentro de um parágrafo, use <br/>: <p>Rua das Flores, 120<br/>Centro</p>.
  • Para manter espaços ou impedir que duas palavras se separem, use &nbsp;: <p>&nbsp;&nbsp;Recuo de dois espaços</p>.
  • Letras acentuadas funcionam normalmente. Emojis não existem na impressora e saem como ?.

O atributo font-size define o tamanho da letra do bloco inteiro. O tamanho muda quantos caracteres cabem por linha:

Atributo Letra Papel de 80 mm Papel de 58 mm
font-size="small" Pequena 64 caracteres 42 caracteres
font-size="normal" Normal (padrão) 48 caracteres 32 caracteres
font-size="large" Grande: dobro da largura e da altura 24 caracteres 16 caracteres
<p font-size="large" bold text-center>{{ empresa.nome }}</p>
<p font-size="small">Letra pequena, para textos longos.</p>

Na letra grande cabe só metade dos caracteres: um nome comprido quebra em duas linhas.

Acrescente o atributo ao bloco (<p>, <table>, <hr/>, <br/>); ele vale para o bloco inteiro:

Atributo Efeito
bold Negrito.
underline Sublinhado, inclusive nos espaços da linha.
italic Aparece só na pré-visualização: as impressoras térmicas não imprimem itálico.
<p bold underline>TOTAL: {{ pesagem.total | moeda }}</p>
Atributo Efeito
text-left À esquerda (o padrão do texto).
text-center Centralizado (o padrão do logo e do código de barras).
text-right À direita.
text-justified Preenche a linha inteira, partindo palavras se preciso.
text-top, text-middle, text-bottom Alinhamento vertical dentro de uma célula de altura fixa.

Também vale a forma align="center" (ou left, right), e valign="top" (ou middle, bottom) para o vertical. O alinhamento pode ser posto no <p>, na <table>, na <tr> ou na <td>. Na tabela, a linha herda o alinhamento da tabela e a célula herda o da linha; o mais específico vence:

<table no-border text-right>
<tr>
<td text-left>Refeição</td>
<td>{{ pesagem.total | moeda }}</td>
</tr>
</table>

As tabelas são o jeito de pôr informações lado a lado na mesma linha.

  • As colunas são definidas pela primeira linha (<tr>). As outras linhas devem ter a mesma quantidade de células.
  • Não existe mesclagem de células.
  • A largura de cada coluna é dada pelo atributo width nas células da primeira linha:
Valor de width Largura da coluna
width="10" Exatamente 10 caracteres.
width="auto" Do tamanho do maior texto da coluna.
width="*" Divide o espaço que sobra (é o padrão).
width="2*" Recebe o dobro do espaço que sobra de uma coluna *.
  • A altura de uma linha pode ser fixada com height na <tr>: height="3" dá 3 linhas de altura. O padrão, auto, cresce conforme o texto.
  • Se as colunas não couberem no papel, elas são reduzidas aos poucos; o texto quebra dentro da célula.

Exemplo: descrição ocupando o espaço livre e valor à direita, do tamanho do texto:

<table no-border>
<tr>
<td>{{ pesagem.descricao }}</td>
<td width="auto" text-right>{{ pesagem.total | moeda }}</td>
</tr>
</table>

As tabelas nascem com todas as bordas, desenhadas com |, - e +. Os parágrafos nascem sem bordas. Para mudar, use estes atributos na <table> (ou no <p>):

Atributo Bordas
all-borders Todas.
no-border Nenhuma.
inside-borders Só as internas, entre linhas e colunas.
inside-horizontal-border Só as linhas horizontais internas.
inside-vertical-border Só as divisões verticais internas.
outside-borders Só o contorno.
top-border, bottom-border, left-border, right-border Uma borda externa.
header-border Uma caixa em volta da primeira linha (o cabeçalho).
white-space-border Bordas de espaço em branco (margem de um caractere).
white-space-vertical-border Separa as colunas com espaço, sem linhas.

Os atributos são aplicados na ordem em que aparecem, então a ordem importa. Por exemplo, <table inside-borders top-border bottom-border> tem as bordas internas e as linhas de cima e de baixo; já em <table bottom-border inside-borders> a linha de baixo é desfeita pelo inside-borders que vem depois.

Para trocar os caracteres das bordas:

Atributo O que troca
border="*" Todos os caracteres de borda.
edge="=" As arestas (esquerda, topo, direita e base).
corner="+" Os cantos.
border-left, border-top, border-right, border-bottom Uma aresta.
border-top-left, border-top-right, border-bottom-right, border-bottom-left Um canto.
pad-value="." O caractere que preenche o espaço vazio da célula.

O pad-value é ótimo para listas de preço com pontilhado:

<table no-border>
<tr>
<td pad-value=".">{{ pesagem.descricao }}</td>
<td width="auto" text-right>{{ pesagem.total | moeda }}</td>
</tr>
</table>
Refeição................................R$ 26,95

<hr/> desenha uma linha de traços na largura do papel. Use pad-value para outro caractere:

<hr/>
<hr pad-value="="/>
<hr pad-value="*"/>

<logo/> imprime o logo cadastrado em Empresa, centralizado. Atributos opcionais:

  • align="left", align="center" ou align="right": posição na linha.
  • width e height: tamanho em pontos da impressora (o papel de 80 mm tem cerca de 576 pontos de largura; o de 58 mm, 384). Informando só um dos dois, a proporção da imagem é mantida. O logo nunca passa da largura do papel.
<logo align="center" width="300"/>

<bar-code> imprime um código de barras com os números abaixo das barras. O normal é usar o código montado nas configurações gerais, só quando a opção estiver ligada:

{{ if configuracao_comanda.imprimir_codigo_barras }}
<bar-code>{{ codigo_barras }}</bar-code>
{{ end }}
  • O tipo é o escolhido nas configurações gerais. Para forçar outro, use type="ean13" ou type="code128".
  • No EAN-13 são 12 números; a impressora calcula o 13º.
  • height="80" define a altura, em pontos (de 1 a 255); width="3" define a espessura das barras (de 2 a 6).
  • Se o conteúdo ficar vazio, nada é impresso.
Sintoma Causa provável
Erro “Linha X, coluna Y” logo após escrever um {{ if }} ou {{ for }} Falta o {{ end }} correspondente, ou há chaves abertas sem fechar.
Um dado não aparece Nome da variável escrito errado (não dá erro, só fica em branco).
Um texto não aparece Texto solto, fora de <p> ou <td>.
A tabela ficou com bordas que você não queria Tabelas nascem com todas as bordas: acrescente no-border.
Uma condição com número nunca falha Números sempre contam como verdadeiro: compare, como em > 0.
O itálico não sai no papel A impressora térmica não tem itálico.
Letras trocadas por “?” Emoji ou caractere que a impressora não tem.

Este modelo imprime o logo, o cabeçalho da empresa, o número e a data, o prato com peso e valor, os produtos adicionais, as linhas para anotação, a frase, o rodapé e o código de barras. Copie, cole num modelo novo e adapte.

{{# Cabeçalho }}
<logo/>
<p bold font-size="large" text-center>{{ empresa.nome }}</p>
<p text-center>{{ empresa.endereco_completo }}<br/>{{ empresa.cidade }} / {{ empresa.estado }}</p>
{{ if empresa.possui_algum_contato }}
<p text-center>{{ empresa.contato_empresa }}</p>
{{ end }}
<hr/>
{{# Número e data }}
<table no-border>
<tr>
<td>Comanda N.{{ pesagem.numero }}</td>
<td width="auto" text-right>{{ pesagem.data | formatar "dd/MM/yyyy HH:mm" }}</td>
</tr>
</table>
<hr/>
{{# Prato }}
{{ if comanda_livre }}
<p>Comanda livre</p>
{{ else }}
<p bold>{{ pesagem.descricao }}</p>
{{ if modalidade_por_quilo }}
<p>{{ pesagem.quantidade | numero 3 }} kg x {{ pesagem.valor_unitario | moeda }}/kg</p>
{{ end }}
<p bold font-size="large" text-right>{{ if gratis }}Grátis{{ else }}{{ pesagem.total | moeda }}{{ end }}</p>
{{ end }}
{{# Produtos adicionais e linhas para anotação }}
<table inside-horizontal-border top-border bottom-border>
<tr>
<td>Adicionais</td>
<td width="12" text-right>Valor</td>
</tr>
{{ for item in produtos_adicionais }}
<tr>
<td>{{ item.descricao }}</td>
<td text-right>{{ if item.valor_unitario }}{{ item.valor_unitario | moeda }}{{ end }}</td>
</tr>
{{ end }}
{{ for linha in linhas_em_branco }}
<tr>
<td></td>
<td></td>
</tr>
{{ end }}
</table>
{{# Frase, rodapé e código de barras }}
{{ if exibir_frase }}
<br/>
<p font-size="small" text-center>"{{ frase.descricao }}"</p>
<p font-size="small" bold text-center>{{ frase.autor }}</p>
{{ end }}
{{ if exibir_mensagem_rodape }}
<br/>
<p text-center>{{ configuracao_comanda.mensagem_rodape }}</p>
{{ end }}
{{ if configuracao_comanda.imprimir_codigo_barras }}
<br/>
<bar-code>{{ codigo_barras }}</bar-code>
{{ end }}
<br/>