Skip to main content

Receipt Layout

Layout

Receipt-Slovakia

For printing a fiscal transaction, the data has to be formatted, which is done using the HTML templating engine PUG (former JADE). Language details can be found on pugjs.org.

For Slovakian fiscal printers the item description and additional text lines may be formatted freely, but referring amounts are printed in a format that's predetermined by the printer.

The following rules occur for bbox eKasa fiscal receipts:

  • All lines up to 48 characters
  • Barcodes may be printed on the footer
  • Paper is cut after print completion

You can start http://localhost:5618/peri/pugedit for layout configuration, it works as a WYSIWYG editor.

Besides fiscal.pug, different non-fiscal layout files can be provided in directory /EFR/rn/def/cfg, the exclusively lowercase file name is derived from the NF or DT tag:

NF="Login" => "login.pug"`

Transaction Time

The fiscal printer itself has a clock. Date and time printed on the receipt are printer time.

PUG Editor

Workflow:

  • Start http://localhost:5618/peri/pugedit with a browser
  • [Open] e.g. file /EFR/rn/def/cfg/fiscal.pug
  • Copy your sample transaction data into the textbox at the left side
  • The right side box shows the transaction data transformed to HTML
  • Modifications in PUG code (center box) are shown immediately
  • When finished [download] e.g. as fiscal.pug and copy it to /EFR/rn/def/cfg/

The EFR now transforms every transaction into HTML and renders it to the line printer. By their nature, fiscal printers provide only very limited formatting functionality.

At the moment, the editor implementation is fairly basic, but it is going to be evolved as base technique for transaction rendering and print layout.

Layout Example

//- fiscal.pug - Layout for Fiscal Transactions
-
function fStr(str) { return str || str === 0 ? str.toString().replace(/\r/g, '') : '' }
function fDec(dec) { return fStr(dec).replace(/\./, ',') }
function fAmt(Amt) { return fDec(Amt && Amt.toFixed ? Amt.toFixed(2) : Amt) }
function fPrc(Prc) { return fDec((Prc+'%').replace(/%%$/, '%')) }
function fD(D) { return D.substr(8, 2) + '-' + D.substr(5, 2) + '-' + D.substr(2, 2) }
function fTime(D) { return D.substr(11, 8).replace(/^0/, '') }

mixin pos(p)
if p.Qty && p.Pri
.DscTxt= fDec(p.Qty) + ' ' + fStr(p.QtyU) + ' x ' + fAmt(p.Pri)
if p.TaxG
.Dsc= fStr(p.Dsc)
.TaxG= fStr(p.TaxG)
else
.Dsc2= fStr(p.Dsc)
if p.Amt
.Amt= fAmt(p.Amt)
else
.Amt= fStr(p.LAmt)

mixin tot(t)
hr
.Tot
.Dsc2 TOTAL
.Amt= fAmt(t)
hr

mixin pay(p)
if p.Amt
.DscTxt= fStr(p.Dsc)
.Amt= fAmt(p.Amt)
else
.DscTxt= ' ' + fStr(p.Dsc)
.Amt= fStr(p.LAmt)

mixin tax(t)
.DscTax
.Prc= fPrc(t.Prc)
.Net= fAmt(t.Net)
.TAmt= fAmt(t.TAmt)
.TaxG= fStr(t.TaxG)
.Amt= fAmt(t.Amt)

mixin head(h)
if h
br
each v, k in h
if '_' !== k
.Txt= v._ ? fStr(v.value) : fStr(v)

mixin foot(f)
if f
br
each v, k in f
if '_' !== k
.TxtCenter= v._ ? fStr(v.value) : fStr(v)

html
head
title= ESR.DT||ESR.NF||'Receipt'
style(type='text/css').
body {
font-family: Consolas, 'Courier New';
width: 46ch;
background-color: white;
}
.Txt { white-space: pre; }
.TxtCenter {
white-space: pre;
text-align: center;
}
.Net, .TAmt, .TaxG, .Amt { text-align: right; }
.Pos, .Mod, .Lin, .Tot, .Pay, .Tax, .ItemHead {
display: grid;
grid-template-columns: 37ch 1ch 8ch;
}
.Dsc { grid-column: 1; }
.Dsc2, .DscTxt { grid-column: 1 / span 2; }
.DscTxt { white-space: pre; }
.TaxG { grid-column: 2; }
.Amt { grid-column: 3; }
.DscTax {
width: 90%;
display: grid;
grid-template-columns: 4fr 10fr 10fr;
}
.Print { display: none; }
@media fiscal {
.Disp, .Tax, .Tot { display: none; }
.Print { display: block; }
}
body

//- Header
+head(ESR.Head)

//- Itemheader
hr
.Lin.Disp
.Dsc Item
.TaxG %
.Amt Amt
.Disp
hr

//- required, do not change
each p in ESR.PosA||[]
div(class=p._)
+pos(p)
+tot(ESR.T)
each p in ESR.PayA||[]
div(class=p._)
+pay(p)
if ESR.TaxA
br
each t in ESR.TaxA
div(class=t._)
+tax(t)

//- Footer
.Print
br
+foot(ESR.Foot)
hr
.TxtCenter= 'Terminal: ' + fStr(ESR.TL) + '/' + fStr(ESR.TT) + ' ' + fStr(ESR.DT || ESR.NF || 'Receipt') + ': ' + fStr(ESR.TN)
.TxtCenter= fD(ESR.D) + ' ' + fTime(ESR.D)

Restrictions

The fiscal printer allows only layout of header and footer lines and item text, amounts are formatted by the printer.
Although transaction data usually is provided with UTF-8 encoding, not all characters can be printed. e.g. printing of the Euro symbol is not allowed.

Barcode

To add a barcode to a fiscal or non-fiscal layout enter:

div
img(data-barcode="type=ean13" data-value="123456789012" style="width:30ch;height:3ch")

The data-barcode attribute defines barcode parameters, data-value the content. Style (local or CSS) is used for dimensioning.

data-barcode – Varos FT5000

TypeCharacter set (as regular expression)
upc-a[0-9]{11,12}
upc-e0[0-9]{5,11}
ean13[0-9]{12,13}
ean8[0-9]{7,8}
code39[0-9A-Z $%*+-./]{1,34}
itf[0-9]{2,62}
codabar[0-9A-Da-d$+-.&/:]{1,47}
code93[\u0000-\u007f^{&omid}]{1,59}
code128[\u0000-\u007f^{&omid}]{1,98} (default)
ean128[0-9]{12,13}

data-barcode - Bbox eKasa

TypeCharacter set (as regular expression)
ean13[0-9]{12,13}
ean8[0-9]{7,8}
code39[0-9A-Z $%*+-./]{1,34}
code128[\u0000-\u007f^{&omid}]{1,98}
code128c[0-9]{1,98} (default)

Optional further parameters

ParameterFT5000bboxDescription
posNACenterCenter
w230 (default)Module width in pixels, overrides style width
h753 (default)Barcode height in pixels, overrides style height
hri22 (default)Human readable interface: 0=no, 1=above, 2=below, 3=above and below
hri_f0NAHRI font: 0=Font A, 1=Font B

Example of a very small barcode (code128):

div
img(data-barcode="w=1;h=30" data-value="This is a test")

data-value

The data-value can be set programmatically:

div
- var x = ESR.TL + ("0" + ESR.TT).slice(-2) + ("00000" + ESR.TN).slice(-6)
img(data-value=x style="width:30ch;height:3ch")

Example Response

As long as the printer is not set to fiscal mode (by an official representative), the printout will be marked "NEFISKÁLNY DOKLAD”.

XML Response

Varos FT5000
<TraC SQ="7256">
<Result RC="OK"/>
<Fis D="2022-02-02" FN="O-CCDCF2062A354F269CF2062A35E-TEST" DN="22020200006" OKP="4fe6d770-0c165912-20d0830c-a5765304-18de6c29"/>
</TraC>
Bbox eKasa
<TraC SQ="140">
<Result RC="OK"/>
<Fis D="2019-06-15T15:30:57" FN="O-CCDCF2062A354F269CF2062A35E-TEST" DN="00095" OKP="4fe6d770-0c165912-20d0830c-a5765304-18de6c29"/>
</TraC>

JSON Response

Varos FT5000 Response

{"TraC":
{"SQ":8946,
"Result":{"RC":"OK"},
"Fis{
"D":"2022-02-02",
"DN":"22020200010",
"FN":"O-26F765BF14C44806B765BF14C4C-TEST",
"OKP":"3ca3d7c0-2393cdc4-efa31573-7a68188a-0d7a885d"
}
}

Bbox eKasa Response

{
"TraC":{"SQ":144,
"Result":{"RC":"OK"},
"Fis":{
"D":"2019-06-15T15:55:00",
"FN":"O-4CEE5F91A07F4E51AE5F91A07FD-TEST",
"DN":"00098",
"OKP":"fb1afece-c55788c9-423aa65e-11e5a6e1-adf9bb0c"
}
}
}