Plantillas HTML
Las plantillas HTML usan una sintaxis sin lógica de estilo Mustache con marcadores de posición {{variable}}. Se renderizan en el cliente dentro de la aplicación POS, lo que significa que funcionan sin conexión: no se necesita conexión con el servidor para mostrar o imprimir un recibo.
Este es el motor recomendado para la mayoría de los usuarios.
Sintaxis
Variables
Inserte datos usando llaves dobles:
<h1>{{store.name}}</h1>
<p>Order #{{order.number}}</p>
<p>Total: {{totals.total_display}}</p>
Use variantes _display para valores de moneda ya formateados (p. ej., $12.50 en lugar de 12.5). Consulte la referencia de datos de recibos para ver todos los campos disponibles.
Secciones (bucles y condicionales)
Use {{#section}}...{{/section}} para recorrer matrices o mostrar contenido de forma condicional:
{{#lines}}
<div class="line-item">
<span>{{name}} × {{qty}}</span>
<span>{{line_total_display}}</span>
</div>
{{/lines}}
Secciones invertidas
Utilice {{^section}}...{{/section}} para mostrar contenido cuando un valor esté vacío o sea falso:
{{#customer.id}}
<p>Customer: {{customer.name}}</p>
{{/customer.id}}
{{^customer.id}}
<p>Guest checkout</p>
{{/customer.id}}
Etiquetas localizadas
Utilice {{i18n.key}} para las etiquetas traducibles que se adaptan al idioma de la tienda:
<th>{{i18n.subtotal}}</th>
<td>{{totals.subtotal_display}}</td>
Patrones comunes
Encabezado de la tienda
El array store.address_lines está preformateado para recibos; recórralo en lugar de unir campos de dirección individuales.
<div style="text-align: center;">
{{#store.logo}}<img src="{{store.logo}}" alt="{{store.name}}" style="max-width: 200px;" />{{/store.logo}}
<h1 style="margin: 8px 0;">{{store.name}}</h1>
{{#store.address_lines}}<div>{{.}}</div>{{/store.address_lines}}
{{#store.phone}}<div>{{store.phone}}</div>{{/store.phone}}
{{#store.tax_ids}}<div>{{#label}}{{label}} {{/label}}{{value}}</div>{{/store.tax_ids}}
</div>
Partidas con descuentos
El campo discounts de una partida es el importe del descuento como número positivo, o 0 cuando no hay descuento. Mustache trata 0 como falso, por lo que {{#discounts}}...{{/discounts}} es la condición de protección adecuada.
{{#lines}}
<div class="line-item" style="display: flex; justify-content: space-between;">
<div>
<div>{{name}} × {{qty}}</div>
{{#discounts}}
<div style="font-size: 0.9em; color: #6b7280;">
<s>{{unit_subtotal_display}}</s> {{unit_price_display}}
</div>
{{/discounts}}
</div>
<div>{{line_total_display}}</div>
</div>
{{/lines}}
Resumen de impuestos
{{#tax_summary}}
<div class="tax-line">
<span>{{label}} ({{rate}}%)</span>
<span>{{tax_amount_display}}</span>
</div>
{{/tax_summary}}
Datos de pago
{{#payments}}
<div class="payment" style="display: flex; justify-content: space-between;">
<span>{{method_title}}</span>
<span>{{amount_display}}</span>
</div>
{{#tendered}}
<div style="display: flex; justify-content: space-between;">
<span>{{i18n.tendered}}</span><span>{{tendered_display}}</span>
</div>
<div style="display: flex; justify-content: space-between;">
<span>{{i18n.change}}</span><span>{{change_display}}</span>
</div>
{{/tendered}}
{{/payments}}
Códigos de barras y códigos QR
Utilice el <barcode> elemento — la misma sintaxis que plantillas térmicas. El valor va dentro del elemento; la simbología se establece en el type atributo. El renderizador sustituye cada elemento por un SVG en línea.
<!-- Code 128 barcode of the order number -->
<barcode type="code128" height="40">{{order.number}}</barcode>
<!-- QR code -->
<barcode type="qrcode" scale="3">{{order.payment_url}}</barcode>
<!-- EAN-13 -->
<barcode type="ean13">{{order.number}}</barcode>
El atributo type debe establecerse literalmente en la plantilla; no puede provenir de un marcador de posición. Un type de qr o qrcode se renderiza como código QR tanto en plantillas HTML como térmicas.
Si el tipo de código de barras seleccionado no puede codificar el valor (por ejemplo, datos EAN-13 no numéricos o con una longitud incorrecta), la vista previa muestra un bloque Barcode error o QR code error con el valor original, para que pueda corregir el valor o cambiar a un tipo compatible.
Se admiten todas las simbologías de bwip-js: code128, qrcode, ean13, ean8, upca, pdf417, datamatrix y muchas más.
Estilo
Las plantillas sin lógica se sanean mediante la función de WordPress wp_kses_post antes del renderizado, lo que elimina <style>, <head>, y etiquetas de nivel de documento. Utilice estilos en línea en cada elemento:
<div style="font-family: monospace; font-size: 12px; max-width: 300px; margin: 0 auto;">
<div style="text-align: center; margin-bottom: 16px;">
<strong style="font-size: 16px;">{{store.name}}</strong>
</div>
<div style="display: flex; justify-content: space-between; font-weight: 700; border-top: 1px solid black; padding-top: 8px;">
<span>{{i18n.total}}</span>
<span>{{totals.total_display}}</span>
</div>
</div>
La misma restricción se aplica a <script>, <link>, y otras etiquetas que no son de contenido: se eliminan, por lo que no se debe depender de CSS o JavaScript externos.
Los recibos suelen imprimirse en impresoras térmicas o láser en blanco y negro. Diseñe con esto en mente: use grosor de fuente, espacios en blanco, contraste tipográfico y líneas horizontales para la jerarquía en lugar de rellenos de color. Los fondos de color y el texto gris desaparecen en la impresión en blanco y negro o se imprimen como medios tonos poco definidos.
Haga clic en Usar plantilla en la tarjeta Recibo estrecho de la galería: es un diseño monoespaciado de 72mm de ancho que se imprime correctamente mediante la impresión del navegador, en impresoras térmicas compatibles con HTML (dispositivos Sunmi/Imin WebView) y en papel estándar. No es para impresoras térmicas ESC/POS sin procesar; use las plantillas XML de Recibo térmico simple para esas impresoras.
Buenas prácticas
- Use los campos
_displaypara todos los valores de moneda; gestionan automáticamente el formato según la configuración regional - Use etiquetas
{{i18n.*}}en lugar de codificar texto de forma fija, para que las plantillas funcionen en varios idiomas - Utilice secciones para condicionales — envuelva los campos opcionales en
{{#field}}...{{/field}}para que se oculten cuando estén vacíos - Comience con una plantilla de galería en lugar de crearla desde cero
- Pruebe con la vista previa en el editor de plantillas antes de activarla