Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

R-GO

R-GO kassa - handbok

R-GO är ett kassasystem för butiker: kassan i webbläsaren eller på en kassaterminal, kvittoskrivare, kontrollenhet och kortterminal.

DelFör vem
Användarhandbok för kassörenden som står i kassan
Användarhandbok för butikschefenden som sköter inställningar, varor och rapporter
Systemmanualinstallatör och tekniker
R-GO Fortnoxden som kopplar bokföringen till Fortnox - en fristående tjänst
Teknisk referensutvecklare och integratörer: utskrifts-, display- och journalformat

Handboken skrivs i Markdown i docs/handbok/ och är gjord för att kunna läggas ut som webbsidor på r-go.se. Bilder ligger i bilder/.

Kassören

Den här delen är skriven för dig som står i kassan. Den förklarar vad du ser på skärmen, vilka knappar du trycker för att sälja och ta betalt, hur du gör dagens rapporter och vad du gör när kassan visar ett meddelande eller inte gör som du väntar dig. Du behöver inga tekniska förkunskaper. Hur varor, knappar och kortterminal ställs in beskrivs i butikschefens del.

Knapparnas namn och placering kan skilja sig mellan butiker, eftersom varje butik lägger upp sin egen knappsats. Handboken använder de namn som kassan har från början och säger till där din kassa kan se annorlunda ut.

  1. Komma igång
  2. Sälja
  3. Ta betalt
  4. Retur och tillgodo
  5. Rapporter: X och Z
  6. Meddelanden och fel

Komma igång

Det här kapitlet visar hur du startar kassan och hittar på skärmen. Du får veta vad de olika delarna av skärmen visar, vad kunden ser på sin skärm och hur sifferknapparna och C fungerar. Allt annat i handboken bygger på det som står här.

Starta kassan

Kassan är en sida som visas i en webbläsare eller i en app som visar samma sida. Hur du startar den beror på vilken utrustning butiken har.

På en kassaterminal (CHD6800 eller Casio) startar kassan av sig själv i helskärm när terminalen slås på. Du behöver inte göra något mer än att vänta tills knapparna syns.

På en Windows-dator finns appen R-GO Kassa på skrivbordet och i startmenyn. Den öppnar kassan i helskärm på datorns första skärm. Har butiken en kundskärm finns också R-GO Kunddisplay, som öppnar kundens fönster på den andra skärmen.

På en iPad eller i en vanlig webbläsare öppnar du kassans adress, som butikschefen ger dig. På en iPad har butikschefen oftast lagt kassan som en ikon på hemskärmen, så att den öppnas utan adressfält som en vanlig app.

När sidan har laddats kopplar den upp sig mot kassan. Medan det pågår står det Ansluter … högst upp i displayen, och när kontakten finns står det Ansluten en kort stund innan displayen går över till sitt vanliga läge. Om kontakten bryts står det Frånkopplad - försöker igen…, och sidan försöker själv koppla upp sig igen varje sekund. Trycker du på en knapp när kassan inte är ansluten står det Ej ansluten - knapptryckning ignorerad. Inget av det du tryckte har då hänt, så vänta tills det står Ansluten och tryck igen.

Operatörsdisplayen

Operatörsdisplayen är din del av skärmen: den visar vad som händer i kassan just nu. Den har tre delar som du har nytta av hela tiden.

Högst upp finns en lägesrad. I vanligt läge står det PRIS, vilket betyder att kassan väntar på att du ska slå in ett belopp eller trycka på en vara. Visar kassan ett felmeddelande står det i stället i den här raden, med ett utropstecken först.

Bredvid finns inmatningsfältet, som visar siffrorna du slagit in men ännu inte använt. Står det 0 har du inte slagit in något.

Den stora rutan är kvittorutan. Där växer kvittot fram rad för rad medan du säljer, med delsumman längst ner. När kunden har betalat visas det färdiga kvittot med betalsätt och eventuell växel tills du börjar på nästa köp. Kvittorutan är också den plats där kassan visar sådant du måste agera på: en fråga som kräver Ja eller Nej, kortterminalens texter under ett kortköp och meddelandet om en okänd vara. De rutorna läggs överst i kvittorutan, så att de inte skymmer några knappar.

På många kassor finns också en liten spegling av kundens display och en klocka. Exakt vad som syns var bestäms av butikens skärmlayout.

Kunddisplayen

Kunddisplayen är kundens skärm. Den visar samma kvittorader som du ser, och nederst två rader med stor text som går att läsa på avstånd: när du slår in en vara visas varans namn, antal och belopp, när du trycker Delsumma visas Att betala och beloppet, och efter en kontantbetalning visas Växel och växelbeloppet. När kassan står tom visas bara texten r-go, så att man ser att skärmen är igång, och tappar kundskärmen kontakten med kassan står det Ingen kontakt med kassan.

Kunddisplayen kan bara visa. Den har inga knappar som påverkar kassan, så det gör ingenting om en kund råkar trycka på den. Visas en knapp Helskärm på kundskärmen trycker du på den en gång, så fyller kundbilden hela skärmen.

Att kontrollera: Vilken text som visas på en tom kunddisplay (i dag “r-go”) och hur kundskärmen ser ut i butikens egen uppställning.

Knapparna på skärmen

Knappsatsen består av två slags knappar. Varuknapparna sitter i en stor yta som kan ha flera flikar, till exempel en flik för kaffe och en för bröd. Varje varuknapp säljer en varugrupp eller en bestämd vara och har ofta en egen färg. Funktionsknapparna sitter på fasta platser och gör samma sak oavsett flik: sifferknapparna, C, Delsumma, betalsätten (Kontant, Kort, Swish, Faktura), Ja och Nej, Kvitto, rapporterna och några till.

Färgerna hjälper dig att hitta rätt. Samma funktion har samma färg var den än sitter, så alla betalknappar och alla rapportknappar känns igen på färgen.

Eftersom varje butik lägger upp sin egen knappsats kan en knapp ha ett kortare namn hos er än i handboken. Delsumma kan heta ST, kortavstämning K-Avs och växelkassa Växel. Fråga butikschefen om du inte hittar en knapp.

Att kontrollera: Vilka knappar som finns och vad de heter på butikens egen kassa, eftersom knappsatsen läggs upp per butik.

Tangentbord

Har kassan ett vanligt tangentbord fungerar det också. I grundinställningen säljer F1-F10 varugrupp 1-10, sifferraden och det numeriska tangentbordet slår in siffror, Enter är Kontant, Backsteg är C och + på det numeriska tangentbordet är Delsumma. Y och N svarar Ja och Nej, X och Z tar rapporterna, J skriver ut journalen och K skriver ut kvittot.

Att kontrollera: Att tangentbordets knappar är kvar enligt grundinställningen på butikens kassa.

Siffror, decimaler och C

Belopp, antal och nummer slår du in med sifferknapparna innan du trycker på den knapp som ska använda dem. Siffrorna syns i inmatningsfältet tills de används. Ett belopp får vara högst nio tecken långt.

Hur du slår in kronor och ören beror på hur kassan är inställd, och det syns på knappen bredvid 0. Står det . på den slår du in beloppet som du skriver det: 35 betyder 35 kronor, och 35.50 betyder 35 kronor och 50 öre. Du kan ha högst två siffror efter punkten. Står det 00 på knappen slår du alltid in beloppet i ören: 3500 betyder 35 kronor, och 00-knappen är en genväg för att slippa trycka 0 två gånger.

C rensar det du har slagit in men inte använt. Den tar inte bort rader från kvittot - det gör du med Backa, se Sälja. C avbryter också sådant som kassan väntar på att du ska fortsätta med: ett antal som du har tryckt × för, en markerad kvittorad, registreringen av en okänd vara och en påbörjad journalutskrift. Under ett kortköp med Nets-terminal avbryter C köpet, se Ta betalt. Att trycka C när det inte finns något att rensa gör ingenting.

Sälja

Det här kapitlet handlar om att slå in ett köp: hur en vara hamnar på kvittot, hur du säljer flera av samma, vad som händer när en streckkod är okänd och hur du tar bort en rad du slagit fel. Ett kvitto börjar med den första varan du slår in, så det finns inget särskilt steg för att öppna ett nytt kvitto.

Varugrupper, varor och streckkoder

Kassan känner till varor på två sätt. En varugrupp är en samling varor med samma moms, till exempel “Kaffe” eller “Tidningar”. En vara är en bestämd artikel med eget namn, eget pris och ofta en streckkod. Båda hamnar på kvittot som en rad med namn och belopp.

Med varugruppsknapp. Slå in priset och tryck på varugruppens knapp. Raden läggs på kvittot och inmatningsfältet töms. Har varugruppen ett grundpris kan du trycka på knappen utan att slå in något, så används grundpriset. Har den inget grundpris måste du slå in ett pris först; annars läggs ingen rad in och lägesraden visar varför.

Med streckkodsläsare. Läs av varans streckkod. Finns varan i kassans varuregister läggs den på kvittot direkt med sitt eget namn och pris, utan att du behöver slå in något. Finns den inte, se Okänd vara nedan.

Med varuknapp. En knapp kan också vara kopplad till en bestämd vara, till exempel en kaffe med fast pris. Då trycker du bara på knappen.

Det finns ingen funktion för att slå in ett artikelnummer och söka fram en vara på det. En vara som saknar streckkod och egen knapp säljer du på dess varugrupp.

Att kontrollera: Vilka knappar på butikens kassa som säljer varugrupper och vilka som säljer bestämda varor.

Antal och ×

Säljer du flera av samma vara behöver du inte trycka på knappen flera gånger. Slå in antalet, tryck ×, och slå sedan in varan som vanligt: med pris och varugruppsknapp, med en varuknapp eller med streckkodsläsaren. Kassan lägger då in en rad med antalet och det sammanlagda beloppet.

Ett exempel: tre bullar för 25 kronor styck på varugruppen Bröd slår du in som 3, ×, 25 och Bröd. Kvittot får en rad på 75 kronor, och under den en indragen rad med uträkningen, 3 x 25:00. Samma rad syns i kvittorutan och på kundskärmen.

När du har tryckt × står antalet, till exempel 3x, längst till vänster i inmatningsfältet tills varan är inslagen.

Antalet kan vara 1-99. Antalet gäller bara nästa vara du slår in. Ångrar du dig innan dess trycker du C, så glöms antalet bort. Trycker du × utan att ha slagit in något händer ingenting.

Okänd vara

När du läser en streckkod som inte finns i varuregistret visar kassan rutan OKÄND VARA överst i kvittorutan, med streckkoden under. Kvittot du håller på med ligger kvar under rutan, så du ser fortfarande vad du har slagit in.

Du har två val, och rutan påminner om dem: “Slå in pris och tryck en varugrupp för att lägga upp varan – eller C för att avbryta.”

  1. Slå in varans pris.
  2. Tryck på den varugrupp som varan hör till.

Kassan lägger då upp varan i registret med streckkoden, varugruppens namn och det pris du slog in, och säljer den på samma gång. Nästa gång samma streckkod läses känner kassan igen varan och säljer den direkt. Butikschefen kan sedan ge varan ett riktigt namn i inställningarna.

Trycker du C i stället försvinner rutan och ingenting sparas. Det passar när streckkoden lästes av misstag eller när du hellre säljer varan på en varugrupp utan att lägga upp den.

Vägda varor

Kassan kan i dag inte läsa av en våg. En vara som säljs efter vikt säljer du genom att slå in det pris som vågen eller prislappen visar och trycka på varans varugrupp, precis som vilken annan vara som helst.

Att kontrollera: Att det här är rätt arbetssätt för vägda varor i butiken, och om någon våg ska kopplas in senare.

Rätta och ta bort rader

Har du slagit in fel tar du bort raden med Backa och slår in den rätt igen. Det finns inget sätt att ändra beloppet på en rad som redan ligger på kvittot; du tar bort den och gör om.

Backa kan användas på tre sätt:

  • Senaste raden. Tryck Backa utan att ha slagit in något, så tas den senaste raden bort.
  • En rad längre upp, räknat bakifrån. Slå in ett tal och tryck Backa. 2 tar bort den näst sista raden, 3 raden före den, och så vidare. Du räknar bara de rader som syns på kvittot.
  • En rad du pekar på. Tryck på raden i kvittorutan, så markeras den. Tryck sedan Backa, så tas just den raden bort. Att trycka på en rad tar aldrig bort den av sig själv, så en oavsiktlig tryckning gör ingen skada. C tar bort markeringen.

En rad som tas bort försvinner från kvittot men finns kvar i kassans journal, där det syns att den slogs in och togs bort. Det är så det ska vara: allt som händer i kassan sparas.

Backa går att använda även efter att du tryckt Delsumma. När kunden har betalat går det däremot inte längre att ta bort rader från det kvittot.

Delsumma

Delsumma visar kunden vad det kostar. Kunddisplayen visar Att betala och beloppet. Kvittot påverkas inte, och du kan fortsätta slå in varor efteråt. Du behöver inte trycka Delsumma före betalningen, men det är ett bra sätt att låta kunden se summan innan du tar betalt.

Flikar

Varuknapparna kan vara uppdelade på flera flikar, till exempel en flik per varuslag. Du byter flik genom att trycka på flikens namn ovanför knapparna. Står kassan på högkant visas flikarna i en meny bakom knappen ≡. I vissa layouter finns det inga synliga flikar alls, utan särskilda knappar som byter till en viss flik. Det går också att slå in flikens nummer och trycka Flik; den första fliken har nummer 0. Numret ligger då kvar i inmatningsfältet efteråt, så tryck C innan du slår in nästa pris.

Att byta flik påverkar inte kvittot. Det du har slagit in i inmatningsfältet ligger också kvar.

Kassan kan i dag inte parkera ett kvitto för att ta en annan kund emellan. Ett påbörjat kvitto måste betalas eller tömmas med Backa innan nästa kund kan börja.

Att kontrollera: Om butiken behöver kunna parkera kvitton - funktionen finns inte i den här versionen.

Ta betalt

När alla varor är inslagna tar du betalt. Det här kapitlet går igenom betalsätten, vad som händer på skärmen vid vart och ett och vad du gör när något inte går igenom. Det förklarar också varför kassan ibland väntar en stund efter att du tryckt på en betalknapp, och hur kvittot kommer ut.

Så går en betalning till

Du betalar alltid hela kvittot på en gång med ett betalsätt. Det går inte att dela upp betalningen, till exempel att kunden betalar en del kontant och resten med kort. Har kunden inte nog med ett betalsätt får kunden välja ett annat, eller så tar du bort varor med Backa.

När du trycker på en betalknapp skickar kassan kvittot till kontrollenheten, den låda som enligt lag ska registrera varje kvitto. Först när kontrollenheten har svarat räknas kvittot som betalt. Det tar oftast bara ett ögonblick. Svarar kontrollenheten inte tar kassan inte betalt alls - se Om kontrollenheten inte svarar nedan.

BetalsättKnappSlå in belopp först?Vad kassan gör
KontantKontantJa, det kunden ger dig (valfritt)Räknar ut växeln
KortKortNejStartar köpet på kortterminalen och väntar på svaret
SwishSwishNejRegistrerar betalningen direkt
FakturaFakturaNejAvslutar kvittot som en fakturaförsäljning
TillgodoTillgodo eller streckkodsläsarenSe Retur och tillgodoLöser in ett tillgodokvitto

Kontant och växel

Slå in det belopp kunden ger dig och tryck Kontant. Kassan räknar ut växeln och visar den i kvittorutan, och kunddisplayen visar Växel med beloppet. Om kunden betalar jämnt kan du trycka Kontant direkt utan att slå in något; då blir växeln noll.

Beloppet du slår in måste räcka till hela summan. Är det mindre händer ingenting, och kvittot är fortfarande obetalt. Kontrollera beloppet, tryck C och slå in det igen.

Efter betalningen visar kvittorutan det färdiga kvittot. Raden BETALT (KONTANT) visar vad som betalades, Mottaget vad kunden gav och Växel växeln.

Kort

Tryck Kort. Kassan skickar hela beloppet till kortterminalen, och kunden betalar på terminalen som vanligt. Ett belopp som du slagit in före Kort används inte - det är alltid hela kvittot som dras.

Medan köpet pågår väntar kassan på terminalen och tar inte emot något annat. När köpet är godkänt avslutas kvittot precis som vid kontantbetalning, och kortterminalens egen kvittotext skrivs med på kassakvittot. Om köpet nekas eller avbryts ligger kvittot kvar obetalt, och lägesraden visar “Kortbetalningen misslyckades” följt av orsaken från terminalen. Du kan försöka igen eller låta kunden betala på annat sätt.

Hur det ser ut under köpet beror på vilken terminal butiken har.

Nets. Terminalens egna texter - till exempel att kunden ska sätta i kortet eller slå sin kod - visas i en ruta KORTTERMINAL överst i kvittorutan. Du ser alltså vad kunden ska göra utan att titta på terminalen. Vill du avbryta köpet, till exempel för att kunden ångrar sig, trycker du C på kassan. Terminalen avbryter då köpet och kvittot ligger kvar obetalt.

Worldline. Terminalens texter visas inte i kassan, och köpet kan inte avbrytas från kassan. Följ köpet på terminalens skärm och avbryt det på terminalen om det behövs.

Att kontrollera: Vilken orsak Nets- och Worldline-terminalen anger efter “Kortbetalningen misslyckades” när ett köp nekas eller avbryts.

Har butiken ingen kortterminal inställd går det inte att ta kortbetalt, och Kort-knappen gör ingenting.

Swish

Tryck Swish när kunden har swishat. Kassan registrerar betalningen för hela beloppet direkt. Kassan har ingen egen koppling till Swish och kan inte se om pengarna har kommit in, så det är du som kontrollerar betalningen innan du trycker - till exempel på kundens telefon eller i butikens Swish-app.

Att kontrollera: Hur butiken vill att kassören kontrollerar att en Swish-betalning har kommit in.

Faktura

Tryck Faktura när kunden ska betala mot faktura. Kassan avslutar då kvittot som en fakturaförsäljning, och kvittot visar BETALT (FAKTURA).

Kassan skickar aldrig själv någon faktura. Den lämnar ett underlag som butikens affärssystem tar hand om, och det är där fakturan eventuellt skapas. Det som kunden får med sig från kassan är en följesedel.

Att kontrollera: Hur följesedeln skrivs ut och hur underlaget når affärssystemet i butiken - i den här versionen avslutar Faktura bara kvittot.

Om kontrollenheten inte svarar

Om kontrollenheten inte svarar när du trycker på en betalknapp visas rutan SVAR KRÄVS i kvittorutan med frågan “Kontrollenheten svarar inte - försök igen? (Ja/Nej)”. Lägesraden visar dessutom en kort förklaring med ett utropstecken först. Kassan väntar nu på ditt svar och tar inte emot försäljning eller betalning förrän du har svarat.

  • Tryck Ja för att försöka igen. Ofta räcker det, till exempel om kontrollenheten bara var upptagen. Går det fortfarande inte kommer samma fråga igen.
  • Tryck Nej för att ge upp betalningen. Kvittot är då inte betalt, men raderna ligger kvar så att du kan försöka igen senare.

Har kunden betalat med kort när kontrollenheten inte svarar och du trycker Nej, försöker kassan föra tillbaka pengarna till kundens kort. Går inte heller det är pengarna dragna, och då sparar kassan försäljningen utan att skriva något kvitto. Säg till butikschefen om det händer.

Fungerar kontrollenheten inte efter flera försök får du inte ta betalt i kassan. Kontakta butikschefen. Se också Meddelanden och fel.

Att kontrollera: Vilken text lägesraden visar när kontrollenheten inte svarar, och hur kunden ska hanteras när ett kortköp sparats utan kvitto.

Kvitto och kvittokopia

När betalningen är klar visar kvittorutan det färdiga kvittot, men det skrivs inte ut av sig själv. Vill kunden ha kvittot trycker du Kvitto, så skrivs det ut. Vill kunden inte ha något kvitto fortsätter du bara med nästa kund: så fort du slår in nästa vara eller trycker en rapportknapp sparas det förra kvittot elektroniskt i kassan och försvinner från skärmen. Kvittot finns då kvar i kassans journal, men det går inte längre att skriva ut det med Kvitto-knappen.

Kvitto-knappen gör ingenting om det inte finns något betalt kvitto som väntar.

Kvittokopia. Slå in kvittonumret och tryck Kvitto. Kassan letar upp kvittot i journalen, också om det är från en tidigare dag, och skriver ut en kopia, märkt KOPIA överst och nederst. Kopian skickas till kontrollenheten och får en egen kontrollkod, som står under originalets.

  • Ett kvitto kan bara få en kopia. Försöker du igen svarar kassan “Kvitto … har redan en kopia”.
  • Bara kvitton som kontrollenheten har godkänt kan kopieras.
  • Svarar kontrollenheten inte blir det ingen kopia - försök igen när den svarar.
  • Kopiorna räknas på X- och Z-rapporten, med antal och belopp.

Väntar ett betalt kvitto fortfarande på utskrift skriver Kvitto ut det kvittot - slå in kvittonumret först när det är klart.

Att kontrollera: Om butikens kassa är inställd så att kvittot skrivs ut automatiskt efter varje betalning i stället för med Kvitto-knappen.

Att kontrollera: Vad kassören ska göra om skrivaren inte skriver ut när Kvitto trycks - kassan visar i dag inget fel på skärmen.

Retur och tillgodo

Det här kapitlet handlar om när en kund lämnar tillbaka en vara och om tillgodokvitton, de papper som är värda pengar i butiken. Returer är den del av kassan som ännu inte är färdig, så kapitlet beskriver både vad du kan göra i dag och hur det kommer att fungera.

Returköp mot kvitto

Kassan har i den här versionen ingen returfunktion. Du kan alltså inte slå in en retur i kassan. En rad som redan är betald kan inte heller tas bort med Backa; det fungerar bara på kvittot du håller på med.

Hur returer ska skötas tills funktionen finns bestämmer butikschefen.

Att kontrollera: Hur butiken hanterar returer så länge kassan saknar returfunktion.

När returfunktionen kommer blir en retur ett eget kvitto. Kunden får inte tillbaka pengar i handen, utan returbeloppet blir ett tillgodo som kunden kan handla för.

Tillgodokvitto med QR-kod

Ett tillgodokvitto är ett papper som visar att butiken är skyldig kunden ett belopp. Det är inte ett vanligt kvitto utan en värdehandling: överst står TILLGODOKVITTO, sedan butikens namn, beloppet med stor stil, tillgodots nummer och datum. Längst ner finns en QR-kod och en kod vid manuell inlösen, en sifferkod som består av tillgodots nummer och fyra kontrollsiffror.

Varje tillgodokvitto är signerat av kassan. Det betyder att kassan kan se om koden är äkta, och att ingen kan skriva ut ett eget tillgodo med ett påhittat belopp. Varje tillgodo kan dessutom bara lösas in en gång, så en kopia av ett tillgodo som redan använts är värdelös.

Tillgodokvitton skrivs ut av kassan av sig själv när de behövs. Du behöver aldrig skriva ut ett själv.

Lösa in tillgodo

Ett tillgodo används som betalning för hela kvittot. Slå först in varorna som vanligt.

Med streckkodsläsaren. Läs av QR-koden på tillgodokvittot. Kassan kontrollerar att tillgodot är äkta och inte redan använt, och betalar kvittot med det.

För hand, om QR-koden inte går att läsa:

  1. Slå in tillgodots belopp, så som det står på papperet.
  2. Tryck Tillgodo. Beloppet försvinner från inmatningsfältet och kassan väntar nu på koden.
  3. Slå in hela koden som står under “Kod vid manuell inlösen”, alla siffror i en följd (mellanslaget i koden slår du inte in).
  4. Tryck Tillgodo igen.

Stämmer koden betalas kvittot med tillgodot. Har du slagit fel på koden står det i lägesraden, och kassan står kvar och väntar, så du kan slå in koden igen utan att börja om med beloppet. Beloppet ingår i kontrollen, så går koden inte igenom fast du är säker på den kan det vara beloppet som blev fel: tryck då C och börja om från steg 1. C avbryter och ingenting har hänt.

Att kontrollera: Kassan visar i dag ingen text om att den väntar på koden efter steg 2 - lägesraden står kvar på PRIS.

Knappen Tillgodo finns inte på alla kassor. Saknas den kan tillgodot bara lösas in med streckkodsläsaren.

Om tillgodot är större än köpet används hela tillgodot ändå, och kassan skriver ut ett nytt tillgodokvitto på det som blir över, med nytt nummer. Det gamla tillgodot går inte att använda igen. Ge kunden det nya papperet. Det kan komma ut ur skrivaren innan du tryckt Kvitto för själva köpet.

Om tillgodot är mindre än köpet går det inte att använda i dag, eftersom ett kvitto bara kan betalas med ett betalsätt. Tillgodot är då orört och kan användas vid ett senare köp.

Kassan vägrar också ett tillgodo som redan är inlöst, som butikschefen har makulerat, eller vars kod inte är äkta. När du läser av QR-koden står förklaringen i lägesraden högst upp på skärmen, till exempel att tillgodot redan är inlöst eller att det inte räcker till hela kvittot. Samma förklaringar visas när du slår in koden för hand.

Begränsningar: retur och försäljning på samma kvitto

Retur och försäljning kan aldrig blandas på samma kvitto. Det beror inte på kassan utan på kontrollenheten: den tar inte emot ett kvitto där varor både säljs och lämnas tillbaka. Därför blir en retur, när funktionen finns, alltid ett eget kvitto, och det kunden sedan handlar blir ett nytt kvitto som betalas med tillgodot.

Rapporter: X och Z

Kassan räknar hela tiden ihop det som säljs. Med rapporterna får du ut summorna på papper: X-rapporten när du vill se hur dagen går, och Z-rapporten när dagen ska avslutas. Det här kapitlet förklarar skillnaden mellan dem, hur du registrerar växelkassan, hur du skriver ut journalen och hur kortterminalens rapporter hänger ihop med kassans.

Alla rapporter kräver att inget kvitto pågår. Har du varor inslagna som inte är betalda tar kassan ingen rapport när du trycker på en rapportknapp, och lägesraden visar varför. Betala klart eller ta bort raderna med Backa först. Ett kvitto som är betalt men inte utskrivet är däremot inget hinder: trycker du på en rapportknapp sparas det kvittot elektroniskt och rapporten tas.

Växelkassa

Växelkassan är de pengar som ligger i kassalådan när dagen börjar. Beloppet står på X- och Z-rapporten, så att den som räknar kassan vet vad som ska finnas kvar i lådan utöver dagens försäljning.

Räkna lådan, slå in beloppet och tryck Växelkassa (på knappen kan det stå Växel). Har du räknat fel kan du slå in ett nytt belopp och trycka igen, så länge dagens första köp inte är gjort. Efter första köpet är växelkassan låst och kan inte ändras förrän nästa Z-rapport har tagits. Registrerar du ingen växelkassa står den som noll på rapporterna.

När växelkassan registreras skriver kvittoskrivaren en remsa med beloppet, kassan och tiden, och en rad för signatur. Räknar du om skriver den en ny remsa som också visar vilket belopp som ersattes.

Fast växelkassa. Kassan kan vara inställd på att föra över växelkassan till nästa dag. Den växelkassa som gäller vid Z-rapporten registreras då direkt för nästa period, och en remsa med texten “Överförd från Z” skrivs ut. Stämmer lådan inte med beloppet, till exempel för att pengar har tagits ut, räknar du lådan och slår in det rätta beloppet före dagens första köp.

X-rapport (avläsning)

X-rapporten visar hur det ser ut just nu: hur mycket som sålts sedan förra Z-rapporten, fördelat på betalsätt och moms, hur många kvitton som gjorts och vad växelkassan är. Rubriken på papperet är X-DAGRAPPORT.

Tryck X (eller X-rapport). Rapporten skrivs ut. Den nollställer ingenting, så du kan ta en X-rapport hur många gånger du vill under dagen, till exempel när du byter kassör eller vill stämma av lådan mitt på dagen. Kommer rapporten inte ut frågar kassan inte om ett nytt försök; tryck X igen när skrivaren fungerar.

Har butiken en Nets-terminal tar terminalen samtidigt en egen X-rapport, som skrivs ut efter kassans.

Z-rapport (dagsavslut)

Z-rapporten avslutar dagen. Den visar samma sorts summor som X-rapporten, men nollställer sedan dagens räkning så att nästa dag börjar från noll. Varje Z-rapport får ett eget löpnummer som står på papperet, och rubriken är Z-DAGRAPPORT. Z-rapporten är ett lagkrav och ska tas en gång när butiken stänger, efter dagens sista kvitto.

Tryck Z (eller Z-rapport). Det händer flera saker efter varandra:

  1. Har butiken en Nets-terminal gör den sitt eget dagsavslut först.
  2. Kassans Z-rapport skrivs ut. Först när den har kommit ut på skrivaren stängs dagen.
  3. Kortterminalens rapport skrivs ut efter kassans.
  4. Är bokföringen påslagen skrivs också ett bokföringsverifikat ut, som visar hur dagens försäljning bokförs. Det lämnar du till den som sköter bokföringen om butiken vill ha det på papper.

Kassans Z-rapport tas även om kortterminalen inte svarar. Terminalens dagsavslut får då göras senare, men kassans dag är stängd.

Efter Z-rapporten kan växelkassan för nästa dag registreras. Med fast växelkassa är den redan registrerad, men kan ändras före första köpet.

Svarar skrivaren inte när Z-rapporten ska skrivas ut visar kassan rutan SVAR KRÄVS med frågan “Z-rapport: försök skriva ut igen? (Y/N)”. Dagen är då ännu inte stängd, och kassan väntar på ditt svar. Kontrollera att skrivaren är påslagen, har papper och att luckan är stängd, och tryck Ja; frågan kommer tillbaka så länge utskriften inte går igenom. Trycker du Nej avbryts Z-rapporten och dagen förblir öppen; ta då en ny Z-rapport när skrivaren fungerar. Det avbrutna försöket har redan fått ett löpnummer, så nästa Z-rapport får nästa nummer och ett nummer hoppas över. Det är meningen: luckan visar att ett försök gjordes.

Att kontrollera: Vad som syns om kortterminalens dagsavslut misslyckas - kassan visar i dag inget fel för det på skärmen.

Journalutskrift

Journalen är kassans fullständiga logg över allt som har hänt: varje rad, varje betalning och varje rapport. Den kan skrivas ut när någon, till exempel Skatteverket vid en kontroll, vill se den.

Dagens journal. Tryck Journal utan att slå in något. Journalen sedan förra Z-rapporten skrivs ut.

Äldre dagar. Journalen är uppdelad per Z-rapport, och du väljer vilka dagar som ska skrivas ut med Z-rapporternas löpnummer:

  1. Slå in numret på den första Z-perioden och tryck Journal. Inget skrivs ut än.
  2. Slå in numret på den sista Z-perioden och tryck Journal igen. Journalen för hela intervallet skrivs ut.

Vill du bara ha en period slår du in samma nummer båda gångerna. Medan kassan väntar på det andra numret tar den inte emot försäljning; tryck C om du vill avbryta.

Kortterminalens rapport

Kortterminalen håller sin egen räkning över kortköpen. Med en Nets-terminal tar kassan terminalens X- och Z-rapport automatiskt tillsammans med sina egna, som beskrivs ovan.

Avstämning (på knappen kan det stå K-Avs) gör en kortavstämning på Nets-terminalen: terminalens köp skickas till banken och terminalens räkning nollställs. Terminalens rapport skrivs ut på kassans skrivare. Avstämning går inte att göra mitt i ett kvitto.

Med en Worldline-terminal tar kassan inga rapporter från terminalen. Avstämningen sker då på terminalen själv eller hos banken.

Att kontrollera: Om och när butiken vill att kassören gör Avstämning, eller om den sköts automatiskt av kortsystemet.

Export till Skatteverket

Skatteverket kan begära en export av kassans journal i ett särskilt filformat. Den görs från kassan: se till att inget kvitto pågår, slå in 2027 och tryck Delsumma. Lägesraden visar sedan “SKVFS-export skapad” och var filen hamnade. Det är bara när butikschefen ber om det som du behöver göra detta.

Meddelanden och fel

Det här kapitlet samlar det kassan kan visa när något behöver din uppmärksamhet, och vad du gör i varje fall. Det tar också upp vad det betyder när en knapp inte gör det du väntade dig. Kassan är byggd så att inget fel kan få ett köp att räknas fel. Därför stannar den hellre och väntar på dig än gissar.

Kassan visar meddelanden på två ställen. Rutor som kräver att du gör något läggs överst i kvittorutan. Korta besked och felmeddelanden står i lägesraden högst upp, med ett utropstecken först; de står kvar tills du trycker på nästa knapp.

SVAR KRÄVS

Rutan SVAR KRÄVS betyder att kassan har ställt en fråga och väntar på att du svarar Ja eller Nej. Tills du har svarat tar kassan inte emot försäljning, betalning eller rapporter. Det är alltså ingen hängning, och det hjälper inte att trycka på andra knappar. Läs frågan och svara.

Frågan i rutanVad som har häntJaNej
Kontrollenheten svarar inte - försök igen? (Ja/Nej)Kontrollenheten svarade inte när kunden skulle betalaFörsöker igenBetalningen avbryts; varorna ligger kvar på kvittot
Försök igen? (Y/N)Kassan kunde inte spara i sin journalFörsöker spara igenKassan frågar en gång till, se nedan
Z-rapport: försök skriva ut igen? (Y/N)Z-rapporten kunde inte skrivas utFörsöker skriva ut igenDagen stängs inte

Kontrollenheten svarar inte. Det vanligaste skälet är att kontrollenheten eller dess sladd har lossnat, eller att datorn den sitter i har startats om. Tryck Ja några gånger. Går det inte får du inte ta betalt i kassan; tryck Nej och kontakta butikschefen. Vad som händer med ett kortköp i det läget står i Ta betalt.

Försök igen? (Y/N) betyder att kassan inte kunde skriva i sin journal, till exempel för att disken är full. Tryck Ja. Svarar du Nej kommer samma text en gång till, men nu är frågan en annan: Ja betyder att kassan ställer det som skulle sparas i kö och fortsätter, Nej att det som du just gjorde inte blir av. Det som står i kö sparas först nästa gång kassan sparar något, före det nya. Kontakta butikschefen om frågan kommer tillbaka.

Att kontrollera: Att journalens två frågor verkligen visas med samma text på skärmen, och vad butiken vill att kassören svarar på den andra.

Kortterminalens texter

Med en Nets-terminal visas terminalens egna texter i rutan KORTTERMINAL under ett kortköp, till exempel att kunden ska sätta i kortet, slå sin kod eller att köpet är godkänt. Texterna kommer från terminalen, inte från kassan, så de ser ut som på terminalens skärm. Rutan försvinner när köpet är klart. Under köpet väntar kassan på terminalen; vill du avbryta trycker du C.

Med en Worldline-terminal visas inga texter i kassan. Följ köpet på terminalen.

Om terminalen inte svarar alls när du trycker Kort, kontrollera att den är påslagen och ansluten och försök igen. Går det inte får kunden betala på annat sätt.

Att kontrollera: Vad som syns i kassan när kortterminalen inte går att nå.

Skrivaren svarar inte

Kassan visar inget meddelande när skrivaren inte skriver ut ett kvitto eller en X-rapport. Z-rapporten är ett undantag: där frågar kassan om ett nytt försök, se Rapporter. Märker du att inget papper kommer ut:

  • kontrollera att skrivaren är påslagen, har papper och att luckan är stängd;
  • tryck Kvitto igen om kvittot fortfarande syns i kvittorutan.

Har du redan börjat på nästa köp är det förra kvittot sparat i kassan men går inte att skriva ut från kassan. Det är ändå registrerat, så försäljningen är inte förlorad.

Att kontrollera: Om butiken kan skriva ut ett missat kvitto på annat sätt, och om något meddelande om skrivaren syns på kassan.

Okänd vara

Rutan OKÄND VARA betyder att streckkodsläsaren läste en kod som inte finns i varuregistret. Slå in priset och tryck på varans varugrupp, så läggs varan upp och säljs, eller tryck C för att avbryta. Se Sälja.

Läser streckkodsläsaren ett tillgodokvitto som inte går att använda står förklaringen i lägesraden i stället. Se Retur och tillgodo.

När en knapp inte gör något

Kan kassan inte göra det du bad om står orsaken i lägesraden, med ett utropstecken först. Ingenting har då registrerats. Läs texten, rätta det den säger och tryck igen. De vanligaste orsakerna:

  • En fråga väntar på svar. Titta efter SVAR KRÄVS i kvittorutan och svara Ja eller Nej.
  • Varan saknar pris. Du tryckte på en varugrupp utan att slå in pris, och varugruppen har inget grundpris.
  • Beloppet räcker inte. Du slog in mindre än summan och tryckte Kontant.
  • Ett kvitto pågår. Du tryckte på en rapport eller Avstämning medan varor ligger på kvittot.
  • Växelkassan är låst. Den kan bara registreras före dagens första köp.
  • Journalutskriften väntar. Du har slagit in ett första Z-nummer och tryckt Journal; slå in det sista och tryck Journal igen, eller tryck C.
  • Kvittot är tomt. Du tryckte på en betalknapp eller Delsumma utan att ha slagit in någon vara.

Två lägen ger ingen text:

  • Ett kortköp pågår. Kassan väntar på terminalen.
  • Kassan är inte ansluten. Det står Frånkopplad eller Ej ansluten i lägesraden; vänta tills det står Ansluten och tryck igen.

Hjälper inget av detta, tryck C, börja om med det du skulle göra och kontakta butikschefen om det fortfarande inte går.

Butikschefen

Den här delen är skriven för dig som sköter kassan bakom kulisserna: varor och varugrupper, knappsatsen, momsen, kvittots utseende, kortterminalen, bokföringen och tillgodokvittona. Nästan allt görs i inställningssidan, som du öppnar i en webbläsare på kassadatorn. Du behöver vara van vid datorer, men inte kunna programmera. Där något inte går att göra i inställningssidan står det vilken inställningsfil som gäller, och installation, skrivare och kontrollenhet beskrivs närmare i systemdelen.

  1. Inställningssidan
  2. Varor och varugrupper
  3. Knappar och panel
  4. Moms
  5. Kvitto och logga
  6. Kortterminal
  7. Bokföring och export
  8. Värdehandlingar

Inställningssidan

Inställningssidan (programmet heter web_setup) är där du ändrar hur kassan är uppsatt. Den är ett eget program bredvid kassan och läser och skriver samma inställningsfiler som kassan läser när den startar. Att den är fristående betyder att du kan arbeta i den medan kassan används, utan att påverka ett pågående köp. Baksidan är att de flesta ändringar inte syns i kassan förrän kassan har startats om. Det här kapitlet beskriver hur du når sidan, vad som finns på den och när en ändring slår igenom.

Adress och inloggning

Inställningssidan öppnas i en webbläsare på adressen http://127.0.0.1:8092/. I Windows finns genvägen R-GO Inställningar i startmenyn, som öppnar samma sida.

Sidan har ingen inloggning. Den skyddas i stället av att den bara svarar på kassadatorn själv: adressen 127.0.0.1 betyder “den här datorn”, och från en annan dator i nätet går den inte att nå. Det är därför viktigt att inte ändra det, eftersom vem som helst som når sidan kan ändra priser och knappar.

Att kontrollera: Hur butikschefen når inställningssidan på en CHD6800 eller Casio-kassa, där kassan visas i helskärm.

Flikarna

Sidan är uppdelad i flikar högst upp. Varje flik är en egen sida, så ett fel i den ena påverkar inte de andra. Byter du flik innan du sparat försvinner det du ändrat på den flik du lämnar.

FlikVad du gör därKapitel
MomstabellDe fyra momssatsernaMoms
ProduktgrupperVarugrupper med moms, grundpris och färgVaror och varugrupper
ProdukterVaruregistret med streckkoderVaror och varugrupper
RutnätVaruknapparna och deras flikarKnappar och panel
Fasta knapparFunktionernas färger och de fasta knapparnas funktionKnappar och panel
LoggaLoggan på kvittotKvitto och logga
KontoplanKonton och bokföring vid Z-rapportenBokföring och export
TillgodonUtfärdade tillgodokvittonVärdehandlingar
KortterminalNets, Worldline eller ingenKortterminal

Några inställningar finns inte på sidan och ändras direkt i inställningsfilerna i kassans datakatalog, under config/. Det gäller företagsuppgifterna på kvittot (company_info.json), kassans beteende som antal decimaler vid beloppsinmatning (logic_settings.json) och kontrollenheten (control_unit.json, cleancash.json). Skrivaren och kontrollenhetens anslutning ställs in på skrivarprogrammets egen sida, se systemdelens kapitel om skrivare och kontrollenhet.

Spara, och när ändringen syns i kassan

Varje flik har en egen spara-knapp, och sidan visar ett besked under rubriken när det är sparat (“Sparat.”) eller vad som gick fel (“Fel: …”). Inställningssidan kontrollerar det du skrivit innan den sparar, så en ogiltig ändring sparas inte alls.

Kassan läser de flesta inställningarna bara när den startar. Därför gäller olika regler för olika flikar:

FlikSparasSyns i kassan
Produkternär du trycker Spara produktdirekt
Tillgodondirekt när du makulerardirekt
Logga, bildfilennär du laddar uppdirekt, nästa kvitto
Logga, placeringennär du trycker Spara placeringefter omstart av kassan
Momstabell, Produktgruppernär du trycker sparaefter omstart av kassan
Rutnät, Fasta knappardirekt vid varje ändringefter omstart av kassan
Kontoplan, Kortterminalnär du trycker sparaefter omstart av kassan

Starta om kassan när butiken är stängd eller ingen kund står vid kassan. Ett påbörjat kvitto som inte är betalt finns inte kvar efter en omstart. I Windows körs kassan som tjänsten rgo-web_till; på en kassaterminal startar du om terminalen. Ladda sedan om kassans sida, så att den hämtar den nya knappsatsen.

Att kontrollera: Det enklaste sättet att starta om kassan på varje plattform, och att ett obetalt kvitto verkligen försvinner vid omstart.

Varor och varugrupper

Kassan säljer på två nivåer. En varugrupp (i inställningssidan kallad produktgrupp) är en kategori, till exempel “Kaffe” eller “Tidningar”, och bestämmer momsen för det som säljs på den. En produkt är en enskild vara med eget namn, pris och streckkoder, och hör alltid till en varugrupp. En liten butik klarar sig ofta med bara varugrupper, där kassören slår in priset; en butik med streckkodsläsare lägger också upp sina produkter. Det här kapitlet beskriver båda och hur de hänger ihop.

Varugrupperna

Varugrupperna redigeras under fliken Produktgrupper och sparas i config/extended_product_groups.json. Varje rad i tabellen är en grupp:

KolumnBetydelse
NrGruppens nummer. Det är numret knapparna och tangentbordets F1-F10 pekar på.
NamnDet som står på kvittot och på kunddisplayen när gruppen säljs.
MomsMomssats ur momstabellen, visad som “25 % (1)” - procent och radnummer.
Grundpris (kr)Pris som används när kassören trycker på gruppen utan att slå in något. 0 betyder att kassören alltid måste slå in pris.
TjänstBockas för tjänster. Z-rapporten räknar sålda varor och sålda tjänster var för sig.
Marginal %Följer med till varor som kassören lägger upp direkt i kassan, och används där för att räkna fram inköpspriset.
RabatterbarOm gruppens varor får rabatteras. Kassan har ännu ingen rabattfunktion, så valet sparas för framtiden.
FärgKnappfärgen för gruppen, var dess knapp än placeras.

Lägg till en grupp med + Lägg till grupp, ta bort en med Ta bort på dess rad, och spara med Spara ändringar. Ändringarna gäller efter att kassan startats om.

Tänk på att knapparna pekar på gruppens nummer. Byter du nummer på en grupp, eller tar bort den, slutar dess knappar att sälja något: de syns fortfarande men gör ingenting när kassören trycker. Byt därför hellre namn på en grupp än nummer, och flytta eller ta bort knapparna i rutnätet om du tar bort en grupp.

Utökade varugrupper

Filen heter “utökade” varugrupper för att den bär mer än det kassan behöver för att sälja - marginal, rabatterbarhet och färg ligger i samma fil som namn, moms och grundpris. För dig som butikschef är det samma sak som varugrupperna på fliken Produktgrupper; det finns ingen separat lista att hålla i ordning.

Produkterna

Produktregistret redigeras under fliken Produkter och ligger i databasen products.db. Till skillnad från nästan allt annat i inställningssidan gäller ändringar här direkt, utan att kassan behöver startas om. Nästa gång kassören läser streckkoden används det nya priset.

Formuläret Lägg till / ändra har dessa fält:

FältBetydelse
SKUProduktens egen kod, högst 20 tecken: bokstäver, siffror, punkt, understreck och bindestreck. Finns koden redan uppdateras den produkten; annars skapas en ny.
NamnDet som står på kvittot.
VarugruppGruppen produkten hör till.
Försäljningspris (kr)Priset kassan tar.
Marginal %Produktens marginal. Lämnas fältet tomt används 30 %, inte varugruppens marginal.
Inköpspris (kr)Lämnas tomt så räknas det fram ur försäljningspris och marginal.
EAN-koderEn eller flera streckkoder, åtskilda med kommatecken. Alla leder till samma produkt.
RabatterbarSom för varugrupperna.

Tryck Spara produkt. Rensa tömmer formuläret. I tabellen Registret under formuläret listas alla produkter; Ändra fyller i formuläret med en produkt och Ta bort tar bort den efter en bekräftelse.

Pris, moms och enhet

Pris anges alltid i kronor i inställningssidan, till exempel 35.50. Hur kassören slår in priser i kassan styrs av en annan inställning, antalet decimaler vid beloppsinmatning i config/logic_settings.json: med 2 slår kassören in 35.50, med 0 slår kassören in 3550.

Moms sätts på varugruppen. En produkt får sin varugrupps momssats när den sparas, och behåller den sedan. Kassan sparar också momsen på varje såld rad, så en senare ändring påverkar aldrig redan sålda varor. Se Moms om vad det innebär när en momssats ändras.

Enhet. Kassan säljer allt per styck. Kassören kan sälja flera av samma med ×, upp till 99 åt gången. Det finns ingen styckenhet som kilo eller meter, och ingen våg är inkopplad; varor som säljs efter vikt säljs genom att kassören slår in priset på varugruppen.

Varor som läggs upp i kassan

Läser kassören en streckkod som inte finns i registret kan kassören lägga upp varan direkt i kassan genom att slå in pris och trycka på en varugrupp. Varan får då streckkoden som SKU, varugruppens namn som namn, det inslagna priset och gruppens moms och marginal. Den dyker upp i registret under fliken Produkter, och du bör gå igenom sådana varor med jämna mellanrum och ge dem ett riktigt namn - annars står det bara gruppens namn på kvittot.

Knappar och panel

Kassans skärm består av två slags knappar. Artikelytan är den stora ytan med varuknappar, uppdelad i flikar, där du själv bestämmer vilka knappar som finns och var de sitter. De fasta knapparna sitter runt omkring - sifferknappar, betalknappar, rapporter - på platser som är bestämda av skärmlayouten, men du kan välja vilken funktion varje plats har. Det här kapitlet beskriver båda, och hur färgerna fungerar.

Hur knappar och färger hänger ihop

En knapp gör en sak: säljer en varugrupp eller utför en funktion. Färgen hör till det knappen gör, inte till själva knappen. En varugrupps färg ställs in under Produktgrupper, och en funktions färg under Fasta knappar. Flyttar du en knapp följer färgen med, och byter du vad en plats gör byter den färg.

Knapparnas uppsättning sparas i flera filer som hänger ihop: panel_layout.json (vilka knappar som finns), item_area_grid.json (var på artikelytan de sitter), panel_positions.json (de fasta platserna) och key_bindings.json (vad varje knapp gör). Ett och samma knapp-id förekommer i flera av dem. Ändra dem därför bara i inställningssidan. En fil som har redigerats för hand och inte stämmer med de andra kan göra att kassans panel inte ritas alls, utan något felmeddelande.

Alla ändringar av knappar sparas direkt, men kassan läser dem när den startar. Starta om kassan och ladda om dess sida för att se resultatet.

Artikelytans flikar och knappar

Artikelytan redigeras under fliken Rutnät. Högst upp finns en rad med artikelytans flikar; klicka på en flik för att redigera den. Under den visas flikens rutnät, och till höger en palett med två listor: Produktgrupper och Funktioner.

Rutnätet är 20 rutor brett och kan vara upp till 36 rader högt. I kassan visas så många rader som får plats, och resten nås genom att rulla. På en skärm på högkant lägger kassan om knapparna automatiskt, så du behöver inte göra en egen layout för det.

Lägga till en knapp. Dra en varugrupp eller en funktion från paletten och släpp den på en tom ruta. En varugruppsknapp får gruppens namn som text, en funktionsknapp funktionens korta namn (till exempel ST för Delsumma).

Lägga till en flik. Tryck + Ny flik och skriv flikens namn. Fliken läggs sist. Flikar kan inte byta namn eller tas bort i inställningssidan.

Knappen får sin text när den placeras. Byter du senare namn på en varugrupp står det gamla namnet kvar på knappen i kassan; ta bort knappen och placera den igen för att få det nya namnet.

Att kontrollera: Om butiken behöver kunna byta namn på eller ta bort flikar, och hur det i så fall görs i dag.

Funktionsknappar

Under fliken Fasta knappar finns två tabeller.

Funktionsfärger listar alla funktioner som kan läggas på en knapp, med namn och teknisk beteckning inom parentes, till exempel “Kontant (pay)”. Välj en färg för varje funktion och tryck Spara funktionsfärger. Färgen gäller funktionen var den än sitter, både på de fasta platserna och i rutnätet.

Fasta knappar (pos-e/g/h) listar skärmens fasta platser med id och position. I kolumnen Funktion väljer du vad platsen ska göra, eller (ledig) för att lämna den tom. Ändringen sparas direkt. Platsen flyttas inte - det är bara funktionen på den som byts - och färgen visas i sista kolumnen.

Funktionerna som kan läggas på en knapp är:

FunktionKort namn på knappenVad den gör
DelsummaSTVisar summan för kunden
C (rensa)CRensar inmatningen, avbryter kortköp (Nets)
Kontant, Kort, Swish, FakturasammaBetalsätten
TillgodoTillgodLöser in tillgodokvitto för hand
Ja, NejsammaSvar på kassans frågor
KvittoKvittoSkriver ut kvittot efter betalning
X-rapport, Z-rapportX, ZRapporterna
JournalJournalJournalutskrift
AvstämningK-AvsKortavstämning på Nets-terminalen
VäxelkassaVäxelRegistrerar växelkassan
BackaBackaTar bort en kvittorad
××Antal för nästa vara
Byt flikFlikByter flik på artikelytan
WebbsidaWebbÖppnar en webbsida, till exempel inställningarna

Ändra en knapp som redan ligger ute. I rutnätet dubbelklickar du på knappen: där ändrar du etiketten och knappens värde - varugruppens nummer, flikens nummer, artikelnumret eller webbadressen, det som skiljer två knappar med samma funktion åt. Bland de fasta knapparna står värdet i kolumnen Värde: ett heltal blir ett tal, annan text blir text, * betyder “det som är inslaget” och ett tomt fält tar bort värdet. Ett värde som kassan inte skulle godta sparas inte. Vad knappen gör ändras redan vid nästa knapptryck, utan omstart; en ny etikett eller bild syns när kassasidan laddas om (bakåtknappen på en CHD6800, F5 i en webbläsare).

I samma ruta i rutnätet kan du ge funktionen en egen etikett, en egen färg och en bild. Funktionens etikett går före knappens etikett och varugruppens namn, färgen går före all annan färg (rutans, varugruppens och funktionsfärgen), och bilden ligger under texten. Båda följer det knappen gör, inte rutan den ligger i. Bilder laddas upp i rutan (png, jpg, webp eller svg, högst 1 MB) och sparas i config/button_images/.

Webbsida frågar efter en adress när du lägger ut den, och varje Webb-knapp har sin egen adress. Med http://127.0.0.1:8092/ öppnar den inställningarna på samma maskin. Det är så man når dem på en CHD6800, där kassan fyller hela skärmen. Androids bakåtknapp tar dig tillbaka till kassan; i en vanlig webbläsare är det webbläsarens bakåtknapp.

Ja och Nej måste finnas någonstans på skärmen. Kassan kan när som helst ställa en fråga som bara kan besvaras med dem, och då står den still tills någon svarar. Detsamma gäller Kvitto om kunderna ska kunna få kvitton på papper, och C, som är det enda sättet att avbryta ett kortköp från kassan.

Knappen Tillgodo löser in tillgodokvitton för hand när QR-koden inte går att läsa. Lägg bara ut den om butiken använder tillgodokvitton.

En knapp som säljer en bestämd produkt i stället för en varugrupp kan kassan hantera, men den kan inte läggas upp i inställningssidan i den här versionen.

Flytta och ta bort knappar

Flytta. Dra en placerad knapp i rutnätet och släpp den på en tom ruta. Knappen gör samma sak och har samma färg på sin nya plats.

Ändra storlek. Dra i knappens nedre högra hörn. En knapp kan täcka flera rutor på bredden och höjden.

Ta bort. Klicka på × i knappens övre högra hörn.

Om en knapp inte får plats där du släpper den - rutan är upptagen eller ligger utanför rutnätet - står det “Får inte plats - upptaget eller utanför griden.” och ingenting ändras.

Att kontrollera: Att knappar kan flyttas mellan flikar, eller om de måste tas bort och placeras igen.

Moms

Kassan räknar med fyra momssatser. De står i en fast tabell med fyra rader, och varje varugrupp pekar på en av raderna. Det här kapitlet beskriver hur du ändrar en momssats och vad som händer med det som redan är sålt. I de flesta butiker behöver tabellen aldrig röras: den är från början inställd på de svenska satserna 25, 12, 6 och 0 procent.

Momstabellen

Momstabellen finns under fliken Momstabell och sparas i config/vat_rates.json. Den har alltid exakt fyra rader, med index 1-4, och varje rad har en procentsats.

Antalet är fast av ett skäl: kontrollenheten, Z-rapporten och exporten till Skatteverket har var och en plats för just fyra momssatser. En femte sats skulle inte gå att redovisa, och därför går det inte att lägga till eller ta bort rader.

Varugrupperna pekar på en rad i tabellen, inte på en procentsats. Under Produktgrupper visas momsen som till exempel “25 % (1)” - procentsatsen och radens index.

Ändra momssats

  1. Öppna fliken Momstabell.
  2. Ändra procentsatsen på den rad som ska ändras.
  3. Tryck Spara momstabell.
  4. Starta om kassan när det är dags för den nya satsen att gälla.

Alla varugrupper som pekar på raden får den nya satsen när kassan startas om. Du behöver alltså inte gå igenom varugrupperna en och en. Ska bara vissa grupper få en ny sats ändrar du i stället vilken rad de pekar på, under Produktgrupper.

Produkterna i varuregistret fungerar annorlunda. En produkt får sin varugrupps momssats när den sparas och behåller den. Efter en ändring av momstabellen behöver du därför spara om de produkter som berörs, under fliken Produkter, så att de får den nya satsen.

Att kontrollera: Att en produkt verkligen behåller sin gamla momssats tills den sparas om, och att det räcker att trycka Ändra och Spara produkt.

Ta en Z-rapport innan du startar om kassan med en ny momssats, så att dagen före och dagen efter ändringen hamnar på var sin rapport.

Vad som händer med gamla kvitton

Ingenting. Kassan sparar momssatsen på varje såld rad i journalen i samma ögonblick som raden säljs. Kvitton, rapporter och exporter som rör tiden före ändringen visar därför den moms som gällde då, och en journalutskrift eller Skatteverksexport för en äldre period påverkas inte av att tabellen ändrats.

Redan skapade verifikat påverkas inte heller. Däremot är kontoplanens försäljningskonton kopplade till procentsatsen, så en ny sats behöver egna konton under fliken Kontoplan innan bokföringen kan skapa verifikat för den. Se Bokföring och export.

Att kontrollera: Vad bokföringen gör vid Z-rapporten om en momssats saknar konton i kontoplanen.

Kvitto och logga

Kvittot byggs av kassan efter en fast mall som följer kassaregisterlagen. Det du själv bestämmer är företagsuppgifterna i huvudet, en fritext längst ner och om butikens logga ska stå överst. Det här kapitlet beskriver var uppgifterna ställs in, hur loggan laddas upp och vilka skrivare som kan skriva ut den.

Vad som står på kvittot

Ett kvitto innehåller, uppifrån och ner: loggan om den är påslagen, rubriken KVITTO och kvittonumret, företagets namn, organisationsnummer, adress och telefonnummer, de sålda varorna, summan, momsen uppdelad per momssats (netto, moms och brutto), betalsättet, och vid kontant betalning mottaget belopp och växel. Vid kortbetalning följer kortterminalens egen kvittotext oförändrad. Sist kommer kontrollenhetens tillverkningsnummer, kontrollkoden och butikens fritext.

Kvittots mall går inte att ändra i inställningssidan. Det är med avsikt: de uppgifter som lagen kräver ska alltid finnas med.

Företagsuppgifter

Företagsuppgifterna har ingen flik i inställningssidan. De står i config/company_info.json i kassans datakatalog och ändras för hand, och gäller när kassan startats om. Filen har dessa delar:

DelFältPå kvittot
organizationlegalName, taxID, telephoneFöretagsnamn, organisationsnummer och telefon
legalAddressstreetAddress, postalCode, addressLocalityFöretagets registrerade adress
tradingAddresssamma fältButikens adress, där försäljningen sker
footeren lista med raderFritext längst ner, till exempel “Tack för ditt köp!”
posIdkassans idStår inte på kvittot, men skickas till kontrollenheten

Kvittot visar butikens adress, alltså tradingAddress. Lämnar du ett fält där tomt används motsvarande fält ur legalAddress, så en butik som ligger på företagets registrerade adress behöver bara fylla i den.

Var försiktig med posId. Kontrollenheten är parad med kassans id, och byts id:t ser kontrollenheten en ny kassa. Den har ett begränsat antal platser, och ett id som inte stämmer gör att kontrollenheten vägrar ta emot kvitton. Ändra det bara i samråd med den som installerade kassan.

Organisationsnumret skickas också till kontrollenheten, så det måste stämma med det kontrollenheten är registrerad på.

Att kontrollera: Att kvittot inte behöver datum eller kassabeteckning i huvudet utöver det kassan skriver i dag.

Ladda upp logga

Loggan ställs in under fliken Logga. Själva bilden lagras hos skrivarprogrammet, inte i kassan. Kvittot bär bara en hänvisning till bilden, så samma inställning fungerar oavsett vilken skrivare som skriver ut. En följd är att bilden måste laddas upp igen om skrivarprogrammet flyttas till en annan dator.

  1. Under Bildfil, välj en PNG-fil. Andra bildformat går inte.
  2. Tryck Ladda upp. Sidan säger “Loggan är uppladdad till skrivaren” och visar den lagrade bilden.
  3. Under Placering, bocka i Visa loggan, välj Justering (Vänster, Centrerad eller Höger) och Bredd (% av kvittot), 1-100.
  4. Tryck Spara placering och starta om kassan.

En ny bild ersätter den gamla direkt, utan omstart. Placeringen gäller efter omstart. Är loggan påslagen men ingen bild uppladdad skriver kvittot en platshållarruta där loggan ska sitta; sidan säger då “Ingen logga är lagrad hos skrivaren än”.

Välj en bild med god kontrast. Kvittoskrivare skriver i svartvitt, och färger och gråtoner blir svarta eller vita punkter.

Att kontrollera: Hur en färglogga eller en logga med gråtoner ser ut på butikens skrivare, och vilken bildstorlek som ger bäst resultat.

Vilka skrivare kan skriva loggan

Loggan skrivs ut av de skrivare som får kvittot som en bild. Det är de flesta:

SkrivareLogga
USB-skrivare med ESC/POS (till exempel TH508, SNBC)Ja
Star mC-Print2Ja
NätverksskrivareJa
Skrivare via Windows skrivarköJa
CHD6800:s inbyggda skrivareJa - loggan lagras i skrivarens eget minne och skrivs därifrån
Casio V-R100 och V-R200Ja - loggan lagras i skrivarens eget minne och skrivs därifrån
Worldline-terminalens skrivareNej - tar inte emot bilder

CHD6800 och Casio-kassorna får resten av kvittot som text, men loggan ligger sparad i själva skrivaren, så den kommer med ändå. Bara Worldline-terminalens skrivare kan inte skriva någon logga; där utelämnas den, och kvittot blir i övrigt likadant.

Kortterminal

Kassan kan ta kortbetalt genom en Nets-, Worldline- eller Swedbank Pay-terminal. Swedbank Pay finns ännu inte i inställningssidan och ställs in för hand - se Swedbank Pay. Det här kapitlet beskriver hur du väljer terminal i inställningssidan, vad som ska ställas in för respektive terminal och vad kassören märker av skillnaden. De två terminalerna pratar med kassan på helt olika sätt, och det förklarar varför inställningarna ser så olika ut.

Välja terminal

Kortterminalen ställs in under fliken Kortterminal och sparas i config/card_payment.json. I listan Terminal väljer du ett av tre alternativ:

  • Ingen - kortbetalning avstängd
  • Nets (SOFIE ECR-ITU)
  • Worldline (Samport REST)

Resten av sidan ändrar sig efter valet. Tryck Spara och starta om kassan: förbindelsen med terminalen sätts upp när kassan startar, så en ändring gäller inte förrän då.

Längst ner på sidan, under Vid dagsavslut, beskriver sidan vad den valda terminalen gör när kassans Z-rapport tas. Där finns inget att ställa in; texten talar bara om vad terminalen klarar.

Nets

Med Nets är det kassan som väntar på terminalen. Terminalen ringer upp kassan och håller förbindelsen öppen hela dagen. Därför är adressen du ställer in kassans, inte terminalens.

FältBetydelse
Lyssna påAdress och port som kassan tar emot terminalen på, normalt 0.0.0.0:20002. Adressen måste innehålla en port.
DisplaybreddHur många tecken per rad terminalens texter får i kassans display, 10-80. Terminalen formaterar sina texter efter detta.

Terminalen ställs sedan in, av dig eller av Nets, med kassadatorns IP-adress och samma port. Kassadatorns brandvägg måste släppa in den porten från nätet.

Med Nets får kassören mest hjälp av kassan. Terminalens texter visas i kassans operatörsdisplay under köpet, kassören kan avbryta ett köp med C på kassan, och terminalens kvittotext skrivs ut på kassakvittot. Vid X- och Z-rapporten tar terminalen sina egna rapporter samtidigt, och knappen Avstämning gör en avstämning mot banken. Terminalens rapporter skrivs ut på kassans skrivare.

Worldline

Med Worldline är det tvärtom: terminalen väntar på kassan, och kassan ringer upp den för varje köp. Därför är adressen här terminalens.

FältBetydelse
Terminalens adressBörjar med http:// eller https://, till exempel http://172.16.10.142:8080/api/v2. Lämnas fältet tomt används adressen i config/worldline_keys.json.

Under Terminaler i nätet listar sidan de Worldline-terminaler den har hört. En terminal meddelar sig var 60:e sekund, så det kan ta upp till en minut innan den syns. Tryck Använd bredvid terminalen för att fylla i adressen, och sedan Spara. Det fungerar inte genom alla nät - VLAN, wifi och brandväggar kan stoppa meddelandet - och då skriver du in adressen för hand. Ge terminalen en fast IP-adress i routern, så att den inte byter adress.

Worldline kräver också två nycklar, som du får från Worldline. De läggs för hand i config/worldline_keys.json och visas aldrig i inställningssidan. Filen ska bara kunna läsas av kassans egen användare, eftersom den som har nycklarna kan styra terminalen.

Worldline-kopplingen ger kassören mindre hjälp än Nets i den här versionen. Terminalens texter visas inte i kassan, ett köp kan inte avbrytas från kassan utan bara på terminalen, och terminalens dagsavslut är inte kopplat till kassans Z-rapport. Terminalens kvittotext skrivs däremot med på kassakvittot, precis som med Nets. Terminalens egen skrivare kan däremot användas som kvittoskrivare, se systemdelens kapitel om skrivare.

Att kontrollera: Ett riktigt kortköp, ett nekat köp och ett avbrutet köp mot Worldline-terminalen i butiken - grunden är provad, men inte hela köpflödet.

Ingen terminal

Väljer du Ingen - kortbetalning avstängd fungerar kassan som vanligt för kontant, Swish och faktura. Kort-knappen gör då ingenting, och kassan öppnar ingen port för en terminal. Det är också vad som gäller om config/card_payment.json saknas helt.

Har butiken en fristående kortterminal som inte är kopplad till kassan kan kassören inte registrera kortköpen som kort i kassan. Ta bort Kort-knappen från panelen så att ingen trycker på den i onödan.

Att kontrollera: Hur butiker med fristående kortterminal ska registrera kortköp i kassan.

Bokföring och export

Kassan kan göra ett bokföringsunderlag av varje Z-rapport. Varje gång dagen stängs räknar den ut hur dagens försäljning ska bokföras - vilka konton som ska debiteras och krediteras med vilka belopp - och lämnar det som ett verifikat, både på papper och som en fil som kan läsas in i ett bokföringsprogram. Det här kapitlet beskriver hur du kopplar kassans siffror till din kontoplan, vad som skapas vid varje Z-rapport och vilka filer du får ut.

Bokföringen är ett tillägg till Z-rapporten och kan aldrig hindra den. Är något fel i kontoplanen tas Z-rapporten ändå, och felet syns i underlaget i stället.

Kontoplan

Kontoplanen ställs in under fliken Kontoplan och sparas i config/chart_of_accounts.json. Den gäller efter att kassan startats om.

Bokföring aktiv slår på eller av hela funktionen. Låt den vara avstängd tills kopplingen till kontona stämmer: ett felaktigt verifikat är värre än inget. Verifikationsserie är den serie verifikaten får i bokföringen, till exempel Z.

Sidan har sedan flera avsnitt:

  • Konton är kontoplanens egna konton, med nummer och namn. Alla val längre ner på sidan kan bara peka på konton som finns här, så lägg upp kontona först med + Lägg till konto.
  • Betalmedel anger vilket konto varje betalsätt debiteras: Kontant, Kort, Swish och Faktura. Kortbetalningar bokförs normalt mot ett fordringskonto, till exempel 1580, och inte direkt mot banken, eftersom pengarna kommer från kortinlösaren först några dagar senare.
  • Försäljningskonton per momssats är standardkontona för alla varugrupper. För varje momssats finns fyra konton: netto och moms, var för sig för försäljning (debet) och retur (kredit). Oftast är det samma kontonummer på båda sidor.
  • Kontering per varugrupp låter en enskild varugrupp bokföras på egna konton. Bocka i gruppen för att bryta ut den, och välj sedan konton för de momssatser som visas. En grupp som inte är ibockad följer standarden ovan.
  • Övriga konton är konton för Rabatter, Öresutjämning och Differens.

Tryck Spara kontoplan när du är klar.

Kontot för Differens behöver en förklaring. Om verifikatet av någon anledning inte går jämnt ut - debet och kredit skiljer sig - bokas skillnaden på det kontot, så att verifikatet ändå går att läsa in. Ett belopp på differenskontot betyder att något i kontoplanen behöver ses över.

Tillgodokvitton bokförs på ett eget skuldkonto, normalt 2421. Det kontot finns inte bland betalmedlen på sidan.

Att kontrollera: Hur kontot för tillgodo ställs in, eftersom det inte visas under Betalmedel i inställningssidan.

Förhandsvisning

Längst ner på fliken Kontoplan finns Visa förhandsvisning. Den bygger det verifikat som den senaste Z-rapporten skulle ha gett med den kontoplan som är sparad, utan att skriva någon fil. Går verifikatet inte jämnt ut visas en varning med DIFFERENS och beloppet. Använd förhandsvisningen varje gång du har ändrat i kontoplanen, och innan du slår på Bokföring aktiv första gången.

Verifikat vid varje Z-rapport

När bokföringen är aktiv skapar kassan ett verifikat i samma ögonblick som Z-rapporten tas. Verifikatet får nästa nummer i verifikationsserien. Det hamnar på flera ställen:

  • På papper, utskrivet på kvittoskrivaren direkt efter Z-rapporten.
  • Som SIE-fil i kassans journalkatalog.
  • I skrivarprogrammets exportarkiv, i en egen mapp per verifikat, tillsammans med en PDF av verifikatet och en PDF av Z-rapporten det bygger på.
  • I kassans journal, där verifikatets alla rader sparas. Det är den varaktiga källan om en fil skulle försvinna.

Z-rapporten följer med verifikatet för att den som bokför ska kunna se var siffrorna kommer ifrån utan att leta fram kassarullen.

SIE och PDF

SIE är det svenska standardformatet för att flytta bokföring mellan program. Kassan skriver SIE typ 4, ett verifikat per fil, och filen kan läsas in i de flesta svenska bokföringsprogram. I exportarkivet heter filen bokforing.si och ligger i en mapp med kassans beteckning och verifikatets nummer, i formen <kassa>_voucher_z000009. Mappnamnet börjar med kassans beteckning så att flera kassor kan dela samma skrivarprogram utan att deras verifikat krockar.

PDF-filerna i samma mapp, verifikat.pdf och zrapport.pdf, är för den som vill arkivera underlaget eller skicka det till en redovisare. Ett verifikat som inte ryms på en A4-sida kortas av i PDF:en; SIE-filen är alltid komplett.

Exportarkivet ligger hos skrivarprogrammet, som kan köra på en annan dator än kassan. Säkerhetskopiera arkivet som annat bokföringsmaterial.

Att kontrollera: Var exportarkivet hamnar på butikens installation (skrivarprogrammets exportkatalog), och exakt hur kassans beteckning skrivs i mappnamnet.

Fortnox

Kassan skickar inte själv något till Fortnox, och inställningssidan har ingen Fortnox-flik. Kassans del slutar vid exportarkivet. Överföringen sköts av R-GO Fortnox, en fristående tjänst som läser verifikaten där och skapar dem i kundens Fortnox, med verifikationen och Z-rapporten som PDF-bilagor. Varje leverans startas av någon, och tjänsten håller reda på vad som redan skickats, så att samma Z-rapport aldrig hamnar två gånger.

SIE-filen kan inte läsas in i Fortnox - Fortnox har ingen sådan import. Andra bokföringsprogram brukar kunna det.

Kontoplanen du ställer in här styr också det som hamnar i Fortnox. Två saker måste stämma med kundens Fortnox: kontona ska finnas där (normalt BAS), och verifikationsserien - kassans är normalt Z - ska vara upplagd i Fortnox och markerad som manuell. Hur tjänsten installeras och kopplas till kundens Fortnox står i R-GO Fortnox.

Värdehandlingar

En värdehandling är ett papper som är värt pengar i butiken. Den enda sorten kassan hanterar i dag är tillgodokvittot: beviset på att butiken är skyldig kunden ett belopp, till exempel efter en retur. Tillgodokvittot är inte ett kvitto - det registreras inte i kontrollenheten och har ingen kontrollkod - men det är lika viktigt att hålla ordning på, eftersom varje utestående tillgodo är en skuld. Det här kapitlet beskriver registret över tillgodon, hur du spärrar ett och hur signeringen skyddar mot förfalskning.

Hur tillgodon uppstår

Tillgodon utfärdas bara av kassan, aldrig i inställningssidan. Varje tillgodo får ett eget nummer ur en egen nummerserie, skild från kvittonumren, och sparas i ett register i databasen values.db. Kassan och inställningssidan läser samma register, så en ändring i det ena syns direkt i det andra.

I den här versionen uppstår ett nytt tillgodo när en kund löser in ett tillgodo som är större än köpet: hela det gamla tillgodot förbrukas, och resten skrivs ut som ett nytt tillgodo med nytt nummer, som hänvisar till det gamla. Värdet ändras alltså aldrig på ett papper som redan finns. Tillgodon från returer kommer när kassans returfunktion är klar.

Att kontrollera: Hur butiken utfärdar tillgodon så länge returfunktionen saknas.

Lista tillgodon

Registret visas under fliken Tillgodon. Överst står Utestående: summan av alla tillgodon som ännu inte är inlösta eller makulerade. Det är butikens skuld till kunderna, och beloppet ska stämma med saldot på bokföringens tillgodokonto (normalt 2421).

Tabellen visar normalt bara utestående tillgodon, nyast först. Bocka i Visa även inlösta och makulerade för att se alla.

KolumnBetydelse
NrTillgodots nummer
BeloppVärdet
UtfärdatDatum och tid
Avser kvittoKvittot tillgodot utfärdades på
ErsätterNumret på det tillgodo det ersatte, om det är en rest
StatusGiltig, Inlöst med datum och kvittonummer, eller Makulerad

Står det — (ej från kvitto) i Avser kvitto har tillgodot inte utfärdats av kassan vid ett köp. Det ska inte förekomma i en butik i drift; ta reda på var det kommer ifrån.

Skriv ut igen och makulera

Vid varje giltigt tillgodo finns två knappar.

Skriv ut igen skickar tillgodot till kvittoskrivaren en gång till, till exempel om kunden har tappat bort papperet eller utskriften misslyckades. Det är ofarligt: ett tillgodo kan bara lösas in en gång, så när ett av papperen har använts är det andra värdelöst.

Makulera spärrar tillgodot så att det inte längre kan lösas in. Använd det när ett tillgodo har utfärdats av misstag, eller när kunden har fått pengarna tillbaka på annat sätt. Sidan frågar först, eftersom det inte går att ångra: ett makulerat tillgodo kan aldrig lösas in igen. Kommer kunden senare med papperet säger kassan att tillgodot är makulerat.

Tillgodon skrivs alltid ut direkt och läggs aldrig i en utskriftskö. En kö som skriver ut samma tillgodo senare, eller två gånger, skulle ge kunden två papper med samma värde.

Signering

Varje tillgodokvitto är signerat. Kassan räknar fram en kod ur tillgodots nummer, belopp och datum med en hemlig nyckel som bara kassan har - i en butik med flera kassor huvudkassan, se Flera kassor, och den koden står både i QR-koden och, förkortad, i sifferkoden “Kod vid manuell inlösen” (tillgodots nummer följt av fyra kontrollsiffror). När ett tillgodo läses in räknar kassan fram koden igen och jämför. Den som ändrar beloppet på ett tillgodo, eller skriver ut ett eget, kan inte räkna fram rätt kod.

Signeringen stoppar förfalskning men inte kopiering: en kopia av ett äkta tillgodo har en äkta kod. Det är registret som stoppar kopior, eftersom varje nummer bara kan lösas in en gång.

Den hemliga nyckeln ligger i values.db, samma fil som registret. Det får två följder som du behöver känna till:

  • Säkerhetskopiera values.db lika noga som journalen. Försvinner filen slutar alla utskrivna tillgodon att gå att lösa in, eftersom kassan inte längre kan kontrollera deras kod.
  • Sprid aldrig filen. Den som har nyckeln kan skapa tillgodon som kassan godtar. Kopiera den inte till e-post, delade mappar eller molnlagring, och kryptera säkerhetskopian.

Systemmanual

Systemmanualen är till för den som installerar, ställer in och underhåller R-GO: hur delarna hänger ihop, var filerna ligger, hur skrivare, kortterminaler och kontrollenhet kopplas in, vad som gäller för respektive plattform och hur vanliga fel känns igen. Den förutsätter att du är van vid datorer och nätverk, men inte att du kan programmera.

  1. Översikt och arkitektur
  2. Installation
  3. Datakatalogen och konfigurationsfilerna
  4. Skrivare (receiptprinter)
  5. Kortterminaler
  6. Kontrollenhet
  7. Journal, export och lagkrav
  8. Plattformar
  9. Felsökning

Översikt och arkitektur

R-GO är inte ett enda program utan några små program som samarbetar. Kassan själv, inställningarna och allt som rör hårdvara - skrivare, kontrollenhet, skanner - körs var för sig. Det gör att samma kassa kan stå på en Windows-dator, en Linux-burk, en Mac eller en Android-terminal, och att en skrivare kan sitta på en annan maskin än kassan. Det här kapitlet beskriver delarna och hur de pratar med varandra.

Delarna

web_till är kassan. Den håller kassalogiken - rader, betalningar, rapporter - och den fiskala journalen, och serverar kassans webbsida. Kassören arbetar i en webbläsare eller i en app som visar sidan (R-GO Kassa i Windows, APK:n på CHD6800 och Casio). Sidan pratar med kassan över HTTP och WebSocket, normalt på port 8090 och 8091.

web_setup är inställningssidan för butikschefen: varor, knappar, moms, kvittots utseende, kortterminal och bokföring. Den läser och skriver samma filer som kassan och lyssnar normalt på port 8092, bara lokalt - den har ingen inloggning.

receiptprinter är länken till hårdvaran. Den tar emot kvitton från kassan och skriver ut dem, den gör kontrollenhetens serieport till en WebSocket som kassan kan nå, och den kan vidarebefordra koder från en seriell skanner. Den har en egen inställningssida på /setup. På Casio-kassorna gör Casio-appen samma jobb, eftersom bara Casios egna gränssnitt kommer åt den hårdvaran.

Webbklienterna finns i två utföranden. Den vanliga är skriven för moderna webbläsare. ES5-versionen (index.es5.html) är till för äldre webbvyer - CHD6800 och Casio-kassorna - som inte förstår modern JavaScript och som annars bara visar en tom ram.

  kassör ── webbsida ──HTTP/WS──> web_till ──HTTP──> receiptprinter ──> skrivare
                                     │                    └──────────> CleanCash (serieport)
                                     ├──WS──> CleanCash-bryggan
                                     └──TCP/REST──> kortterminal (Nets/Worldline)
  butikschef ── webbläsare ──> web_setup ──> samma inställningsfiler

En kassatråd

All kassalogik körs på en enda tråd, i tur och ordning. Det är ett medvetet val: varje tangenttryck och varje betalning ska hamna i journalen i exakt den ordning de skedde, och en kassa som gör två saker samtidigt kan inte garantera det. Baksidan är att något långsamt på den tråden - en skrivare som inte svarar, en kortterminal som tänker - får hela kassan att stå still. Därför sker kortköp asynkront: kassan ber terminalen börja och frågar sedan efter resultatet, i stället för att vänta med allt annat stängt.

Tjänster i nätet

Delarna hittar varandra av sig själva när de står i samma nät. Kassan, inställningarna och receiptprinter annonserar sig med mDNS (samma teknik som skrivare och Apple-prylar använder), och receiptprinter talar om vad den klarar - grafik, QR-kod, kniv. En Worldline-terminal annonserar sig med en egen sändning var 60:e sekund. Inställningssidan visar det som hittats, så att en adress kan väljas i stället för att skrivas in. Det är en bekvämlighet: mDNS når inte genom VLAN eller wifi med klientisolering, så manuell adress fungerar alltid. På Android finns bara Worldlines sändning, inte mDNS.

Var datan ligger

Allt kassan behöver ligger i en datakatalog: inställningarna, journalen, databaserna och webbklienterna. Se Datakatalogen och konfigurationsfilerna.

Installation

R-GO består av några små program som kan stå på samma maskin eller spridas ut i butiken. Hur de placeras avgörs av butiken, inte av programmen - samma paket används i alla upplägg. Det här kapitlet hjälper dig att välja upplägg; underkapitlen beskriver vart och ett steg för steg.

Delarna

delgörfinns i paketet som
kassankassalogik, journal, kassans webbsidaweb_till
inställningarnavaror, knappar, moms, kvitto, kortterminal, bokföringweb_setup
skrivartjänstenkvittoskrivare, CleanCash-brygga, seriell skannerreceiptprinter (på Casio: Casio-appen)
kassans fönsterkassan och kunddisplayen som apparrgo-display (Windows), APK:erna på Android
Fortnoxbokföringen till Fortnoxfristående, se R-GO Fortnox

Kassan och inställningarna måste stå på samma maskin: de delar datakatalogen. Allt annat kan stå var som helst i butikens nät.

Tre upplägg

Allt i ett - en maskin gör allt: en Windows-dator med kundskärm och kvittoskrivare, en CHD6800 eller en Casio-kassa. Enklast att installera och felsöka, och det vanliga för en butik med en kassa.

Modulär - delarna sprids ut: skrivaren och kontrollenheten hänger på en liten dator vid disken, kassan visas på en surfplatta eller en tunn klient, kunddisplayen på en egen skärm någon annanstans. Passar när hårdvaran inte står där kassan står.

Flera kassor - två eller fler kassor i samma butik. Varje kassa är en egen installation med egen journal och egen kontrollenhet; vad som kan delas mellan dem, och vad som ännu inte går, står i kapitlet.

Paketen

Allt hämtas från r-go.se/downloads, med en .sha256 bredvid varje fil.

plattformpaket
Windows 10/11windows/R-GO-windows-<datum>.zip - installationsprogram med tjänster och appar
CHD6800android/R-GO-chd6800-<datum>.apk - hela kassan
Casio V-R100/V-R200android/R-GO-casio-kassa-<datum>.apk (hela kassan) eller R-GO-casio-skrivare (bara skrivaren)
Linuxlinux/R-GO-linux-x86_64-<datum>.tar.gz
Macmacos/R-GO-macos-arm64 (Apple Silicon) eller -x86_64 (Intel)
Android, fristående programandroid/R-GO-android-armv7 (Android 4.1+) eller -api10 (Android 2.3+)

Gemensamt för alla: en uppdatering byter program och webbklienter men rör aldrig butikens inställningar, journal eller databaser.

Portar

tjänstportbehöver nås från
kassan, sida och WebSocket8090, 8091kassans fönster; i modulärt upplägg surfplattor och tunna klienter
inställningarna8092bara samma maskin - ingen inloggning
skrivartjänsten8088kassan
CleanCash-bryggan8765 (CHD6800 8766, Casio 8081)kassan
Nets-terminalen ringer in20002kortterminalen
Worldline-terminalens annonsUDP 8000 inkortterminalen
mDNSUDP 5353övriga R-GO-delar

Öppna bara det som faktiskt ska nås från en annan maskin. Allt som lyssnar på 127.0.0.1 nås bara från maskinen själv.

Allt i ett

I det här upplägget gör en maskin allt: kassan, inställningarna, skrivartjänsten och kontrollenhetens brygga körs på samma dator eller terminal, och skrivare, kontrollenhet och kundskärm sitter direkt på den. Inga delar behöver nå varandra över nätet, så allt lyssnar bara på 127.0.0.1 - utom en Nets-terminal, som ringer in till kassan.

Windows-dator

Det här behövs

  • Windows 10 eller 11, 64-bitars, med Microsoft Edge WebView2 Runtime (följer med Windows; installationen varnar om den saknas).
  • En kvittoskrivare installerad i Windows med tillverkarens drivrutin eller “Generic / Text Only”.
  • CleanCash på en serieport (COM).
  • Gärna en andra skärm som kundskärm.

Installera

  1. Hämta windows/R-GO-windows-<datum>.zip, packa upp och dubbelklicka Installera.cmd. Den ber själv om administratörsrätt.
  2. Döp kvittoskrivaren i Windows till Kvittoskrivare (Inställningar → Skrivare → Egenskaper), eller ange dess namn i nästa steg.
  3. Öppna R-GO Skrivarinställningar i startmenyn (lösenord R-go-go, byt det på sidan). Välj Windows skrivarkö och kön, kryssa i “CleanCash är ansluten här”, välj serieporten med “Visa serieportar”, och spara. Tryck Starta om tjänsten och sedan Skriv ut provsida.
  4. Öppna R-GO Inställningar och lägg in företagsuppgifter, moms, varugrupper, knappar och kortterminal.
  5. Starta R-GO Kassa och R-GO Kunddisplay.

Programmen hamnar i C:\Program Files\R-GO, allt butiksspecifikt i C:\ProgramData\R-GO. Tre tjänster startar med Windows: kassan, inställningarna och skrivartjänsten. Kassan visas på första skärmen och kunddisplayen på den andra - vilken som är vilken styrs av ordningen i Windows skärminställningar.

Kortterminal

  • Nets: terminalen ringer in till kassan på port 20002. Kassan måste då lyssna på nätet: ändra "--http", "127.0.0.1:8090" och "--ws", "127.0.0.1:8091" till 0.0.0.0 i C:\ProgramData\R-GO\services.json och öppna port 20002 i brandväggen.
  • Worldline: kassan ringer upp terminalen. Lägg nycklarna i C:\ProgramData\R-GO\config\worldline_keys.json och välj terminalen i inställningarna (den syns där när UDP 8000 är öppen).

CHD6800

CHD6800 är en allt-i-ett-terminal med Android 5.1, inbyggd skrivare och CleanCash på egna serieportar. APK:n kör allt på terminalen.

  1. Stäng av leverantörens kassaapp, som annars håller skrivaren: adb shell pm disable com.chd.ecroandroid
  2. Installera: adb install -r R-GO-chd6800-<datum>.apk
  3. Starta R-GO på terminalen. Vid första start läggs webbklienten och standardinställningarna på SD-kortet (/storage/extsd/rgo).

Skrivaren (/dev/ttymxc4) och CleanCash (/dev/ttymxc3) är inställda i APK:n. Kvittot skrivs som text eftersom serieporten är för långsam för bilder; loggan lagras i skrivarens minne och kommer med ändå. Inställningarna nås på två sätt. På terminalen öppnar knappen Webb (nere till höger) dem, och bakåtknappen tar dig tillbaka till kassan. Från en dator i butiksnätet når du dem på http://<terminalen>:8092 med lösenordet R-go-go; användarnamnet spelar ingen roll. Byt lösenordet i en riktig butik: lägg SHA-256 av det nya i config/web_setup_losen.txt (printf %s 'nytt' | sha256sum). Rutnätsredigeraren fungerar bäst från datorn, eftersom terminalens webbläsare saknar CSS Grid. Kassan lyssnar också på nätet, så att en Nets-terminal kan ringa in.

Knapparna har CHD:s egen form, samma som leverantörens app: 12 × 7 rutor över hela skärmen med varugrupperna till vänster, displayen uppe till höger och siffror och betalsätt nere till höger. Den följer med som standardinställning, så den gäller vid en ny installation; en terminal som redan har inställningar behåller sina knappar. Formen hämtas ur config/layouts/ecro.* och kan ändras i inställningarnas rutnät som vilken layout som helst.

En kundskärm i HDMI-uttaget visar kundsidan av sig själv - priser, summa och 2 × 20-raden - i stället för att spegla kassan. Utan kundskärm händer ingenting.

Casio V-R100 och V-R200

Casio-kassorna (Android 2.3 och 4.2) styr skrivare och serieportar genom Casios egna gränssnitt, så här är det Casio-appen som skriver ut och är brygga för CleanCash.

  1. Installera R-GO-casio-kassa-<datum>.apk. Installera inte även skrivarappen - de delar port 8080.
  2. Starta R-GO kassa. Inställningar och webbklient läggs på den externa lagringen vid första start.

CleanCash ska sitta på COM1. Skrivaren klarar text och logga men inte QR-kod och inte fetstil (rubriker skrivs i dubbel bredd). Kassan på Casio är inte provad på hårdvaran än; störst osäkerhet är webbvyn på Android 2.3.

Linux eller Mac

För en kassa på en Linux-dator eller en Mac finns arkiv med programmen, webbklienterna och standardinställningarna.

tar xzf R-GO-linux-x86_64-<datum>.tar.gz && cd R-GO-linux-x86_64-<datum>
mkdir -p ~/rgo && cp -r config web/* ~/rgo/
bin/receiptprinter --printer-only --http 127.0.0.1:8088 --config ~/rgo/config/receiptprinter.json
bin/web_till  --data-dir ~/rgo --http 127.0.0.1:8090 --ws 127.0.0.1:8091
bin/web_setup --data-dir ~/rgo --http 127.0.0.1:8092

Kör dem som tjänster (systemd på Linux, launchd på Mac) så att de startar med datorn. Kassan öppnas i webbläsaren på http://127.0.0.1:8090/, kunddisplayen på /customer/. Skrivaren och CleanCash ställs in på http://127.0.0.1:8088/setup. På Mac: kör xattr -dr com.apple.quarantine . i katalogen en gång - programmen är inte signerade.

En USB-skrivare på Linux kräver att användaren får skriva till USB-enheten (en udev-regel för skrivarens tillverkar- och produkt-id), och serieporten att användaren är med i gruppen dialout.

Modulär installation

Delarna i R-GO pratar med varandra över HTTP och WebSocket, så de behöver inte stå på samma maskin. I ett modulärt upplägg står varje del där den gör mest nytta: skrivaren och kontrollenheten på en liten dator vid disken, kassan på en server eller en dator i bakrummet, kassörens skärm på en surfplatta, kunddisplayen på en skärm vid utgången.

Priset är fler saker att hålla ordning på: adresser, brandväggar och fler maskiner som måste vara igång. Ge varje maskin en fast adress i routern

  • delarna hittar varandra via adresser i inställningarna, och en adress som byts av routern gör att kassan tappar skrivaren.

Vad som kan flyttas

delkan ståbinds till
kassan (web_till) + inställningarna (web_setup)tillsammans, på valfri maskinkassan 0.0.0.0 när andra ska nå den; inställningarna alltid 127.0.0.1
skrivartjänsten (receiptprinter)där skrivaren och CleanCash sitter0.0.0.0:8088
CleanCash-bryggani skrivartjänsten, där CleanCash sitter0.0.0.0:8765
kassörens skärmsurfplatta, tunn klient, valfri webbläsare-
kunddisplayenvalfri skärm med webbläsare eller rgo-display-
Fortnox-tjänstendär den når exportarkivet-

Kassan och inställningarna kan inte delas upp: de läser och skriver samma datakatalog.

Skrivare och kontrollenhet på en egen maskin

Typfallet: en liten dator (Windows, Linux eller en Raspberry Pi) vid disken med kvittoskrivaren och CleanCash, och kassan någon annanstans.

På skrivarmaskinen installeras bara skrivartjänsten. Den måste lyssna på nätet, inte bara lokalt:

receiptprinter --printer-only --http 0.0.0.0:8088 --config receiptprinter.json

I Windows-paketet: ändra "127.0.0.1:8088" till "0.0.0.0:8088" under receiptprinter i C:\ProgramData\R-GO\services.json och starta om tjänsten. Ställ sedan in skrivaren och CleanCash på http://<skrivarmaskinen>:8088/setup; ändra CleanCash-bryggans WebSocket-adress till 0.0.0.0:8765 och tryck Starta om tjänsten.

På kassans maskin pekas kassan dit, i datakatalogens config/:

  • printer_service.json: "base_url": "http://<skrivarmaskinen>:8088"
  • cleancash.json: "websocketUrl": "ws://<skrivarmaskinen>:8765/ws"

och kassan startas om.

Brandväggen på skrivarmaskinen: öppna 8088 och 8765, och begränsa dem till kassans adress. Varken skrivartjänsten eller CleanCash-bryggan har någon inloggning utöver lösenordet på /setup.

Exportarkivet för bokföringen ligger hos skrivartjänsten (export/ i dess arbetskatalog) - det är där Z-rapportens verifikat hamnar, och dit Fortnox-tjänsten behöver nå.

Kassörens skärm på en surfplatta eller tunn klient

Kassan är en webbsida, så kassörens skärm kan vara vilken enhet som helst med en webbläsare. Kassan måste då lyssna på nätet med båda portarna:

web_till --data-dir <katalog> --http 0.0.0.0:8090 --ws 0.0.0.0:8091

(i Windows-paketet: services.json under web_till). Webbsidan öppnar sin WebSocket mot samma maskin den hämtades från, så det räcker att öppna http://<kassan>:8090/ på surfplattan.

  • iPad: öppna adressen i Safari och lägg till den på hemskärmen - då startar kassan i helskärm utan adressfält.
  • Windows tunn klient: installera bara appen rgo-display och ange kassans adress som host i display\kassa.json.
  • Äldre enheter (Android 5 och äldre webbvyer): använd http://<kassan>:8090/index.es5.html.

Öppna 8090 och 8091 i kassans brandvägg, gärna bara för de enheter som ska vara kassor.

Kunddisplayen på en egen skärm

Kunddisplayen är sidan /customer/ på kassan. Den kan visas på vilken skärm som helst som når kassan: i en webbläsare i helskärm, eller med rgo-display och display\kunddisplay.json där host är kassans adress och path är /customer.

Inställningarna

Inställningssidan har ingen inloggning och lyssnar därför bara på kassans egen maskin. Når du inte den maskinens skärm, använd en SSH-tunnel eller fjärrskrivbord:

ssh -L 8092:127.0.0.1:8092 <kassans maskin>

och öppna http://127.0.0.1:8092/ på din egen dator.

Kortterminal

  • Nets ringer upp kassan: terminalen ställs in med kassans adress och port 20002, och kassans brandvägg släpper in den.
  • Worldline rings upp av kassan: kassan behöver nå terminalen, och för att terminalen ska synas automatiskt i inställningarna måste kassans maskin ta emot UDP 8000 från terminalens nät.

Hitta delarna

R-GO-delarna annonserar sig i nätet (mDNS), och inställningssidan kan visa vad som finns - kassor, skrivartjänster med vad de klarar, nätverksskrivare och Worldline-terminaler. Det når bara det egna nätsegmentet; adresserna går alltid att skriva in för hand.

Flera kassor

Två eller fler kassor i samma butik är i R-GO två eller fler installationer. Varje kassa är ett eget kassaregister i lagens mening: den har sin egen journal, sina egna löpnummer, sina egna X- och Z-rapporter och sin egen registrering i kontrollenheten. Det delas aldrig, och det ska inte delas.

Annat går att dela, och mer kommer att gå att dela. Det här kapitlet beskriver hur flera kassor sätts upp i dag, och vad som fortfarande är per kassa.

Varje kassa för sig

Installera varje kassa som i Allt i ett eller Modulär. Det som skiljer kassorna åt är posId i varje kassas config/company_info.json - kassans beteckning. Samma värde används överallt: mot kontrollenheten (två kassor med samma id är för kontrollenheten samma kassa), på kvitton och rapporter, och i namnet på kassans katalog i exportarkivet. Ge kassorna korta, unika beteckningar, till exempel 1, 2, 3.

Ändra inte posId på en kassa som redan är i drift: kontrollenheten är parad mot id:t, och ett nytt id tar en ny plats av de få den har.

Kontrollenhet

Varje kassa ska vara ansluten till en kontrollenhet. Vi utgår från en dosa per kassa (klass A). En CleanCash kan betjäna flera kassor, men bara ett begränsat antal - hur många beror på dess licens. När kontrollenheten är full svarar den “License exceeded” för nya kassor. Behöver kassorna egna kontrollenheter sitter de på var sin serieport, med var sin brygga.

En kontrollenhet per kassa, på samma dator

Kontrollenheterna behöver inte sitta vid kassorna. En dator kan vara kontrollenhetsserver: alla dosor sitter där, var och en på sin serieport. Det är till för bärbara kassor, till exempel en kortterminal som kör kassan vid bordet. Ingen dosa behöver då kopplas till en enhet som bärs runt, och kassan når sin dosa över nätet. Varje dosa får då en egen brygga, alltså en egen receiptprinter, som lyssnar på en egen port. Varje kassa pekar ut sin brygga i config/cleancash.json.

I Windows-paketet läggs en brygga till som en ny post i C:\ProgramData\R-GO\services.json. Posten får ett eget namn och en egen port:

"receiptprinter-kassa2": {
  "exe": "{bin}\\receiptprinter.exe",
  "args": ["--serial-only", "--serial-port", "COM4", "--ws", "0.0.0.0:8766"]
}

Kör sedan Installera.cmd igen. Varje post i services.json blir en tjänst, här rgo-receiptprinter-kassa2. Tjänsten har en egen logg, logs\receiptprinter-kassa2.log, och tas bort av avinstallationen som de andra. Installationen öppnar också port 8766 i brandväggen för det lokala nätet, eftersom posten lyssnar på 0.0.0.0. Kassa 2 pekar på ws://<datorn>:8766/ws.

En brygga talar med en enda dosa. Låt aldrig två bryggor öppna samma serieport, och låt aldrig två kassor dela en brygga.

Kvittoskrivaren från andra datorer

I Windows-paketet lyssnar kvittoskrivartjänsten som förval bara på den egna datorn (127.0.0.1:8088). Ska andra kassor eller handterminaler skriva ut på den frågar installationen:

Ska kvittoskrivaren nås från andra datorer i butiken (andra kassor, handterminaler)? [j/N]

Svarar du j lyssnar tjänsten på nätet (0.0.0.0:8088). Brandväggen släpper då in porten och mDNS (UDP 5353) från det lokala nätet, och inget annat. Kassorna hittar tjänsten själva på inställningssidan, där den annonseras som _rgo-printer med sin port. Frågan går att hoppa över med install.ps1 -Natverk eller install.ps1 -BaraLokalt.

Brandväggsreglerna heter R-GO <tjänst> <port> och R-GO mDNS. De stäms av vid varje installation mot services.json, så en tjänst du själv har bundit till 0.0.0.0 får också sin regel. Avinstallationen tar bort dem.

Det som kan delas i dag

  • Skrivare. Flera kassor kan skriva till samma skrivartjänst: peka deras printer_service.json mot samma adress. Utskrifterna kommer i den ordning de skickas.
  • Exportarkivet för bokföringen. Arkivet är byggt för att delas: varje kassa skriver i en egen katalog efter sin beteckning (<beteckning>_voucher_z000001/ …). Låt kassorna använda samma skrivartjänst, eller samma delade katalog som export.
  • Varuregistret. Registret (products.db) ligger hos en av kassorna, huvudkassan, och sköts i dess inställningar. De andra kassorna slår upp varor hos huvudkassans inställningstjänst - se nedan.
  • Tillgodo. Registret över tillgodokvitton (values.db) ligger hos huvudkassan, och de andra kassorna utfärdar och löser in där - se nedan.
  • Fortnox. En Fortnox-tjänst kan leverera verifikaten från alla kassornas kataloger, var och en efter sin beteckning.
  • Kortterminal. Varje kassa har normalt sin egen terminal; en Nets-terminal ringer upp en bestämd kassa.

Det som ännu är per kassa

Knappar och inställningar. Varje kassa har sin egen config/. Ska kassorna se likadana ut kopieras filerna mellan dem.

Gemensamt varuregister

Varuregistret är en egen databasfil, products.db, och inställningarna (web_setup) är tjänsten för den. I en butik med flera kassor ligger filen hos en kassa - huvudkassan - och de andra kassorna frågar huvudkassans inställningar när de slår upp en vara. Filen delas inte över en nätverksdelning: databasens låsning är inte pålitlig över nätet, och två kassor som skriver samtidigt kan skada den.

På huvudkassan ska inställningarna lyssna på nätet, så att de andra kassorna når dem. I Windows-paketet: ändra "127.0.0.1:8092" till "0.0.0.0:8092" under web_setup i C:\ProgramData\R-GO\services.json och starta om tjänsten; öppna port 8092 i brandväggen för de andra kassorna. Huvudkassan själv fortsätter läsa sin fil direkt.

Från andra maskiner går det bara att läsa varor. Inställningssidan, prisändringar och allt annat svarar “Inställningarna kan bara ändras på den här datorn” - det finns ingen inloggning, och priser ska inte kunna ändras från vilken dator som helst i butiksnätet. Varor läggs alltså upp och ändras vid huvudkassan.

På de andra kassorna pekas varuregistret dit, i config/logic_settings.json:

"product_lookup": { "endpoint": "http://<huvudkassan>:8092" }

och kassan startas om. En skannad vara slås nu upp hos huvudkassan. Svarar huvudkassan inte säger kassan det (“varuregistret på … svarar inte”) - då går det inte att sälja på streckkod, men varugruppsknapparna fungerar som vanligt.

Tillgodo i flera kassor

Ett tillgodokvitto ska kunna lösas in i vilken kassa som helst i butiken, men bara en gång. Därför finns ett enda register, hos huvudkassan, i samma fil som huvudkassan själv använder (values.db). De andra kassorna utfärdar, kontrollerar och löser in tillgodo hos huvudkassans inställningar, på samma sätt som de slår upp varor.

En tillgodo är pengar, så här räcker det inte att bara kunna nå huvudkassan. De andra kassorna måste visa kassanyckeln, en lång slumpad kod som inställningarna skapar första gången de startar, i huvudkassans config/kassanyckel.txt. Utan rätt nyckel svarar huvudkassan som för allt annat: “Inställningarna kan bara ändras på den här datorn”. Behandla nyckeln som ett lösenord: den ska inte skickas med e-post eller ligga i en delad mapp, och den följer aldrig med i ett installationspaket.

Signeringsnyckeln, den som QR-koderna och kontrollsiffrorna bygger på, lämnar aldrig huvudkassan. När en annan kassa skriver ut ett tillgodo får den koderna från huvudkassan, och när den läser ett tillgodo är det huvudkassan som kontrollerar det.

På huvudkassan behövs inget mer än för varuregistret: inställningarna ska lyssna på nätet. Kassanyckeln finns i config/kassanyckel.txt så fort inställningarna har startat en gång.

På de andra kassorna pekas registret dit, med nyckeln, i config/logic_settings.json:

"value_documents": {
  "endpoint": "http://<huvudkassan>:8092",
  "key": "<innehållet i kassanyckel.txt>"
}

och kassan startas om. Saknas nyckeln vägrar kassan starta och säger varför. Svarar huvudkassan inte när ett tillgodo ska lösas in eller utfärdas visar kassan det (“tillgodoregistret på … svarar inte”), och inget registreras: kunden får betala på annat sätt, eller vänta tills huvudkassan svarar.

Byts nyckeln - radera kassanyckel.txt och starta om inställningarna på huvudkassan, så skapas en ny - måste den nya föras in på alla andra kassor.

Datakatalogen och konfigurationsfilerna

Kassan (web_till), inställningssidan (web_setup) och terminalkassan (interactive) startas med samma datakatalog, --data-dir <katalog>, och läser då exakt samma filer. Sökvägarna räknas ut på ett enda ställe i koden (rust-poc/src/data_paths.rs), så en ny fil syns i alla tre.

Layout

<datakatalog>/
  journal/              fiskal journal, en fil per Z-period
  counters.db           löpnummer (kvitto, Z)
  products.db           produktregistret
  values.db             värdehandlingar (tillgodo) och signeringsnyckeln
  config/*.json         inställningarna, se nedan
  web_client/           kassans webbsidor
  web_client_setup/     inställningssidans webbsidor

Filerna i config/

filinnehålländras i
company_info.jsonföretagets namn, adress, org.nr - står på kvittotför hand
vat_rates.jsonde fyra momssatsernainställningssidan, Moms
logic_settings.jsonkassans beteende (t.ex. decimaler vid beloppsinmatning)för hand
control_unit.jsonvilken kontrollenhet kassan använderför hand
cleancash.jsonanslutning till CleanCashför hand
printer_service.jsonvar receiptprinter kör (base_url), kan vara en annan maskinför hand
receipt_logo.jsonloggans placering (på/av, justering, bredd); bilden ligger hos receiptprinterinställningssidan, Logga
card_payment.jsonkortterminal: none, nets eller worldlineinställningssidan, Kortterminal
worldline_keys.jsonWorldline-terminalens adress och nycklarför hand - se nedan
chart_of_accounts.jsonkontoplan för bokföringsexporteninställningssidan, Konton
extended_product_groups.jsonvarugrupperinställningssidan, Varugrupper
function_concepts.jsonfunktionernas färger på knapparnainställningssidan
panel_layout.json, panel_positions.json, item_area_grid.jsonskärmens panel och artikelytans rutnätinställningssidan, Knappar
key_bindings.json, keymap.json, web_keymap.jsonvad tangenter och knappar görinställningssidan, Knappar

Ljud vid knapptryck

Kassan klickar kort när en knapp trycks och ger en lägre ton när den svarar med ett fel. Det styrs i logic_settings.json:

"key_sound": {"click": true, "error": true, "volume": 0.3}

volume är 0-1; 0 stänger av ljudet helt. Saknas avsnittet är båda ljuden på, med låg volym. Ändringen gäller när kassan startas om och kassasidan laddats om.

Fast växelkassa

Den växelkassa som gäller vid Z-rapporten kan föras över till nästa period, så att den inte behöver slås in varje dag:

"change_fund": {"carry_over": true}

Vid Z-rapporten journalförs samma belopp som växelkassa i den nya perioden, med numret på den Z-rapport det kom från, och en remsa skrivs ut. Beloppet kan ändras före periodens första köp, som en vanlig växelkassa. Saknas avsnittet är det avstängt, och växelkassan registreras för hand varje period.

Föreskrifterna (SKVFS 2021:17, 5 kap. 1 § och 7 kap.) kräver att kassan kan registrera växelkassa och förändringar av den, och att X- och Z-rapporten visar den - inte att den slås in varje dag. Stäm ändå av inställningen med er kontrollant eller revisor.

Panelens och knapparnas filer hänger ihop - ett knapp-id finns i flera av dem. Ändra dem i inställningssidan, inte för hand: en handredigerad fil som inte stämmer gör att panelen tyst inte ritas.

Säkerhet

  • values.db innehåller nyckeln som signerar tillgodokvitton. Den ska aldrig kopieras till git, mejl eller delade kataloger. Säkerhetskopiera den krypterat.
  • worldline_keys.json innehåller terminalens hemliga nyckel. Filen ska bara kunna läsas av kassans användare (chmod 600) och hålls utanför git.
  • Kassan lämnar bara ut de filer i config/ som kassasidan behöver - layouten, knapparna, färgerna och knappbilderna. Nycklar, lösenord och logic_settings.json går inte att hämta via kassans webbadress.
  • Journalen är fiskal och får inte ändras. Säkerhetskopiera hela journal/.

Skrivare (receiptprinter)

Kassan skriver inte själv till skrivaren. Den bygger en kvittolayout och skickar den till receiptprinter, ett eget program som kan köra på samma maskin eller på en annan (config/printer_service.json). receiptprinter gör om layouten till det skrivaren förstår.

kassan ──HTTP──> receiptprinter ──> USB (ESC/POS eller StarPRNT)
                                ──> Windows skrivarkö (RAW)
                                ──> seriellt (CHD6800:s inbyggda)
                                ──> nätverk, TCP 9100
                                ──> Worldline-terminalens skrivare (REST)
                                ──> PDF (A4: verifikationer, export)

Välja skrivare

Valet görs med flaggor när receiptprinter startas. Bara en skrivare per process.

skrivareflaggorskriver
USB, ESC/POS (TH508, SNBC m.fl.)--usb-vendor <id> --usb-product <id> (--usb-list visar)bild
USB, Star mC-Print2samma + --dialect starbild
Nätverksskrivare--net-printer <ip>[:9100] (+ --dialect)bild
CHD6800 (inbyggd)--serial-http --serial-port /dev/ttymxc4text
Worldline-terminalen--worldline <nycklar.json>text och QR
Windows skrivarkö--windows-printer "<kö>" (--windows-printer-list visar)bild

Övriga flaggor: --http :8080 (port som kassan skickar till), --width 576 (punkter; 576 för 80 mm, 384 för 58 mm), --cut/--no-cut, --feed 4, --asset-dir assets (loggan).

Språket ska anges, inte gissas. En Star-skrivare i StarPRNT-läge ignorerar ESC/POS-bilder tyst: den svarar OK och skriver ingenting. Ange därför alltid --dialect star för Star.

Inställningssidan /setup

Startas receiptprinter med --config <fil> står skrivarvalet i filen, och kan ändras på http://<receiptprinter>/setup (lösenord R-go-go, byts på sidan). Sidan hittar Windows skrivarköer, USB-enheter och skrivare i nätet, och skriver ut en provsida. Ändringen gäller från nästa utskrift. Finns filen inte skapas den från flaggorna vid start.

Samma sida ställer in CleanCash (kontrollenheten på en serieport, nåbar för kassan som WebSocket, normalt 127.0.0.1:8765) och en seriell skanner (koderna skickas till kassans /device_event). Serieportarna öppnas vid start; knappen “Starta om tjänsten” avslutar receiptprinter så att Windows-tjänsten (rgo-service) startar den igen. HTTP-adress och kataloger styrs fortfarande av flaggorna.

Windows: skrivarkön

I Windows är skrivarkön förvalet. Skrivaren installeras med sin vanliga drivrutin och receiptprinter lämnar kvittot till kön som ett RAW-jobb - samma bytes som över USB, men utan att drivrutinen behöver bytas mot WinUSB, och skrivaren går fortfarande att använda från andra program. Drivrutinen måste släppa igenom RAW (tillverkarens eller “Generic / Text Only”).

Bild eller text

De flesta skrivare får kvittot som en bild - samma bild oavsett väg, med logga och QR-kod. Två skrivare får text i stället:

  • CHD6800 - bilden blir för långsam över dess seriella port.
  • Worldline-terminalen - den tar inte emot bilder alls.

Med text blir kolumnerna utfyllda med mellanslag, och fet stil och dubbel höjd finns. Loggan kommer ändå med på CHD6800: den lagras i skrivarens eget minne och skrivs därifrån, så den behöver inte skickas som bild. Bara Worldline-terminalen skriver ingen logga.

Worldline-terminalens skrivare

En långsam och begränsad skrivare, men den finns där kortterminalen står.

  • 60 mm, ingen kniv - kvittot rivs av för hand.
  • Text, fet, dubbel höjd, å/ä/ö: fungerar.
  • QR-kod fungerar (tillgodokvitton).
  • Ingen logga och ingen bild - terminalen tolkar bara sitt eget textformat.
  • Ett kvitto tar 2-3 sekunder; terminalen svarar först när det är utskrivet.
  • Nyckelfilen är samma som kassans config/worldline_keys.json.
  • Tecken per rad: --worldline-width-chars (standard 34, uppmätt). Dubbel storlek ryms 16 tecken.
  • Får terminalen ett kortköp startat på själva terminalen svarar den “upptagen” (503) på utskrifter tills köpet avbryts där.

Kassalåda

Kassalådan öppnas via skrivaren. Fungerar i dag med nätverksskrivare (Star). Worldline-terminalen har ingen kassalådeport.

Fler detaljer

Teknisk översikt över alla vägar, status och kända egenheter per skrivare: docs/skrivarvagar.md i källkoden.

Kortterminaler

R-GO kan ta kortbetalt via en Nets-, Worldline- eller Swedbank Pay-terminal. Vilken det är står i config/card_payment.json; utan filen är kortbetalning avstängd. Ändringen gäller efter omstart av kassan.

Terminalerna kopplas till kassan på olika sätt, och det avgör installationen:

Vem ansluterPortBrandvägg
Netsterminalen till kassan20002in till kassan
Worldlinekassan till terminalenterminalens, t.ex. 8080; annons på UDP 8000UDP 8000 in till kassan
Swedbank Paykassan till terminalen11000ingen in till kassan

Allt om respektive terminal - inställning, vad som är provat, fallgropar och felsökning - står i avdelningen Kortterminaler.

Kontrollenhet

En kassa i Sverige måste ha en certifierad kontrollenhet som registrerar varje kvitto. R-GO använder CleanCash. Kassan tar inte betalt utan den: varje kvitto skickas till kontrollenheten innan det räknas som genomfört, och ett kvitto som kontrollenheten inte tagit emot blir inte ett kvitto.

Hur kassan når CleanCash

CleanCash sitter på en serieport, men kassan pratar med den över en WebSocket. Mellan dem står en brygga som gör serieporten till en WebSocket:

  • på en vanlig dator: receiptprinter, inställd på skrivarsidan (/setup, avsnittet Kontrollenhet) - serieport, hastighet och WebSocket-adress, normalt 127.0.0.1:8765;
  • på CHD6800: receiptprinter i APK:n, mot terminalens port /dev/ttymxc3, på 127.0.0.1:8766;
  • på Casio-kassorna: Casio-appen, mot COM1, på 127.0.0.1:8081.

Kassan hittar bryggan genom config/cleancash.json (websocketUrl). Adressen där och bryggans adress måste vara densamma.

Kassan letar efter kontrollenheten en gång, när den startar. Startar kassan före bryggan, eller är bryggan felinställd, går det inte att ta betalt förrän kassan startats om. Därför väntar apparna på CHD6800 och Casio in bryggan innan de startar kassan.

När kontrollenheten frågar

Ibland behöver kontrollenheten ett beslut från kassören. Då visar operatörsdisplayen SVAR KRÄVS och kassan väntar på Ja eller Nej innan något annat kan göras. Det är ingen hängning - kassan väntar på svaret.

Begränsningar

CleanCash tar inte emot ett kvitto som blandar retur och försäljning; en retur görs på ett eget kvitto. Det står inte i dokumentationen och upptäcktes på riktig hårdvara.

En kontrollenhet är parad mot kassans id (posId i config/company_info.json). Byts id:t ser kontrollenheten en ny kassa, och den har ett begränsat antal platser - ändra det inte i onödan.

Simulerad kontrollenhet

För utveckling och prov finns en simulerad kontrollenhet som talar samma språk som bryggan, så att ett helt köp går igenom utan hårdvara. Den får aldrig användas i en butik - kvittona registreras inte någonstans.

Journal, export och lagkrav

Allt som händer i kassan skrivs i en journal. Den är kassans fiskala minne: Skatteverket ska kunna se exakt vad som registrerades, i vilken ordning och när. Därför skrivs journalen bara till, aldrig om, och den ska sparas enligt bokföringslagen.

Journalen

Journalen ligger i datakatalogens journal/, med en fil per Z-period (journal_z000001.ndjson och så vidare). Varje rad är en händelse - en registrerad vara, en betalning, en rapport - med tid och löpnummer. Rätta aldrig i filerna: en ändring går inte att skilja från ett manipulerat kassaregister. Säkerhetskopiera hela katalogen.

En Z-rapport avslutar perioden och nästa händelse hamnar i en ny fil. Journalen kan också skrivas ut från kassan, period för period; utskriften återger händelserna som de står, inte en tolkning av dem.

Export till Skatteverket

Från 1 januari 2027 ska ett kassaregister kunna exportera sitt journalminne som XML enligt Skatteverkets schema (SKVFS 2021:16). R-GO bygger den exporten ur journalen. Underlaget - föreskrifterna och schemat - finns i källkodens docs/skvfs/.

Bokföringsexport

Vid varje Z-rapport kan kassan ta fram en verifikation för bokföringen: försäljning per momssats och betalsätt, konterad enligt kontoplanen som butikschefen ställer in (se Bokföring och export). Verifikationen sparas både som SIE-fil för bokföringsprogrammet och som PDF för pärmen, i en katalog per Z-rapport hos receiptprinter (export/).

Kassans del slutar där. Överföring till Fortnox sköts av en fristående tjänst, R-GO Fortnox, som läser verifikaten i exportarkivet - kassan vet inte om att den finns.

“Faktura” i kassan

Betalsättet faktura fakturerar inte. Kassan lämnar ett underlag och skriver ut en följesedel; själva fakturan görs i ekonomisystemet. Det gör att kassans journal och kundreskontran inte kan komma ur takt med varandra.

Plattformar

R-GO körs på vanliga datorer och på några kassaterminaler. Det här kapitlet samlar det som är speciellt för var och en - ofta saker som bara upptäckts på riktig hårdvara.

Windows-dator

Den vanligaste installationen: en dator med pekskärm eller tangentbord, en kundskärm och en kvittoskrivare. Kassan och kunddisplayen är apparna R-GO Kassa och R-GO Kunddisplay, och skrivaren nås via Windows skrivarkö med sin vanliga drivrutin. Se Installation.

CHD6800

En allt-i-ett-terminal med Android 5.1, inbyggd skrivare och kontrollenhet på egna serieportar.

  • Skrivaren sitter på /dev/ttymxc4 i 38400 baud. Det är för långsamt för kvitton som bilder, så kvittot skrivs som text - loggan lagras i skrivarens eget minne och skrivs därifrån.
  • Kontrollenheten sitter på /dev/ttymxc3.
  • Leverantörens kassaapp (com.chd.ecroandroid) håller skrivaren och måste stängas av före installation.
  • Webbvyn är Chrome 56. Den saknar modern JavaScript och CSS Grid, så kassan visas med ES5-klienten.

Casio V-R100 och V-R200

Casios kassor med Android 2.3 (V-R100) och 4.2 (V-R200). Skrivaren och serieportarna nås bara via Casios egna gränssnitt, så det är Casio-appen som skriver ut och som gör kontrollenhetens port till en WebSocket.

  • Ingen fetstil: skrivaren ignorerar kommandot tyst, så rubriker skrivs i dubbel bredd i stället.
  • Loggan lagras i skrivarens eget minne och skrivs därifrån, på samma sätt som Casios egen kassaapp gör.
  • Ingen QR-kod: skrivaren kan inte rita den.
  • Casios odokumenterade utskriftsväg fungerar inte: Casios egen tjänst äger skrivaren, så appen använder Casios skrivargränssnitt.
  • Den hela kassan på Casio är ny och inte provad på hårdvaran; störst osäkerhet är webbvyn på Android 2.3.

Surfplatta (iPad)

Kassan kan användas från en surfplatta i webbläsaren eller som hemskärmsapp, mot en kassa som kör på en annan maskin i butiken. Kassan måste då lyssna på nätet och inte bara lokalt.

Linux och macOS

Programmen finns för Linux (x86-64) och Mac (Apple Silicon och Intel). USB-skrivare nås direkt utan särskild drivrutin. Mac-versionen är provad på Apple Silicon; Intel-versionen är byggd men inte provad.

Felsökning

De flesta fel i en kassa är inte fel i programmet utan i det som sitter runt omkring: en skrivare med fel språk, en port som någon annan redan tagit, en brandvägg. Här är de som faktiskt inträffat, och hur de känns igen.

Var loggarna finns

plattformloggar
WindowsC:\ProgramData\R-GO\logs\<tjänst>.log; kassans och kunddisplayens fönster: %LOCALAPPDATA%\R-GO\rgo-display.log
CHD6800, Casioadb logcat -s rgo.Till rgo.Supervisor rgo.Install
Linux, macOSprogrammens egna utskrifter

Skrivaren skriver ingenting

Vanligaste orsaken är fel skrivarspråk. En Star-skrivare i StarPRNT-läge tar emot ESC/POS-bilder, svarar att allt gick bra - och skriver ingenting. Välj StarPRNT på skrivarsidan för Star.

I Windows: kontrollera att skrivarkön heter det receiptprinter skriver till (“Kvittoskrivare”, eller namnet på skrivarsidan), och att drivrutinen släpper igenom RAW-utskrift. Skrivarsidans provsida visar snabbt om vägen fungerar.

Kassan tar inte betalt

Det är nästan alltid kontrollenheten. Kassan letar efter den en gång vid start; nådde den inte bryggan då, går det inte att ta betalt förrän kassan startats om. Kontrollera att CleanCash-bryggan är på (skrivarsidan, avsnittet Kontrollenhet), att serieporten stämmer, och att adressen i config/cleancash.json är bryggans. Starta sedan om kassan.

En port svarar, men det är fel program

I Windows kan två program lyssna på samma port utan att någon av dem får ett fel, och bara det ena får anslutningarna. Det har hänt: en nystartad tjänst skrev “lyssnar”, medan en gammal process fortsatte svara. R-GO:s program vägrar därför starta om porten redan svarar - ett sådant fel i loggen betyder att något gammalt fortfarande kör. Samma symptom kan komma av att utvecklingsverktyg (VS Code) vidarebefordrar portar.

Worldline-terminalen svarar “upptagen”

Svarar terminalen 503 på allt, även utskrifter, finns oftast ett köp påbörjat på själva terminalen. Avbryt det på terminalen.

Kassans fönster öppnas inte i Windows

Saknas WebView2 eller går fönstret inte att starta visas en dialogruta med orsaken, och den skrivs till rgo-display.log. Fönstren sparar sina data per användare i %LOCALAPPDATA%\R-GO\webview\.

Tjänster syns inte i nätet

Kassor, skrivare och Worldline-terminaler som inte dyker upp i inställningssidans listor står ofta i ett annat nätsegment, eller så stoppar brandväggen UDP 5353 (mDNS) eller 8000 (Worldline). Adressen kan alltid skrivas in för hand.

Kortterminaler

R-GO kan ta kortbetalt via tre sorters terminaler: Nets, Worldline och Swedbank Pay. Den här avdelningen beskriver varje terminal för sig - hur den kopplas till kassan, hur den ställs in och vad som är provat - och sist Nets-emulatorn, en Android-app som låter kassor som bara kan tala Nets ta betalt via andra lösningar.

Kassan behandlar alla terminaler lika: ett kortköp startas när kassören trycker Kort, och först när terminalen har godkänt köpet räknas betalningen och kontrollenheten tillfrågas. Ett nekat eller avbrutet köp lämnar varorna kvar på kvittot. Går kontrollenheten inte att nå efter ett godkänt köp, makuleras kortköpet i terminalen.

De tre terminalerna i korthet

NetsWorldlineSwedbank Pay
ProtokollSOFIE ECR-ITUSamport RESTnexo Retailer 3.1
FormatbinärtJSONXML
Vem ansluterterminalen till kassan (TCP 20002)kassan till terminalenkassan till terminalen (port 11000)
Terminalens texter i kassanjanejtillval (spegling)
Avbryta från kassan (C)ja-ja
Dagsavslut i terminalenjajafinns inte i protokollet
Kvittotext till kassans skrivarejajaja, färdiga rader
Lägei drift, provadgrund provadinloggning provad

Vilken terminal kassan använder står i config/card_payment.json. Utan filen är kortbetalning avstängd. Ändringar gäller efter omstart av kassan, eftersom förbindelsen sätts upp när kassan startar.

Kapitel

Nets

Med Nets (protokollet SOFIE ECR-ITU) är det kassan som är server. Terminalen ringer upp kassan på TCP-port 20002 och håller förbindelsen öppen hela dagen. Kassan måste därför lyssna på nätet, och terminalen ställs in med kassans adress.

{"provider": "nets", "listen": "0.0.0.0:20002", "display_columns": 20}

Kassadatorns brandvägg måste släppa in port 20002 från terminalen.

Vad kassören märker

Under ett köp skickar terminalen sina skärmtexter till kassan - “SÄTT I/DRA KORT”, “KOD + OK”, “GODKÄNT” - och de visas i operatörsdisplayen. Kassören ser alltså vad kunden gör utan att titta på terminalen, och kan avbryta ett pågående köp med C på kassan. Terminalens kvittotext skrivs ut på kassans skrivare.

Vid kassans Z-rapport kan terminalens egna rapporter och avstämningen mot banken skrivas ut efter kassans.

Provat

Mot en riktig terminal: godkända och nekade köp, avbrott från kassan och terminalens rapporter.

Att känna till

  • Ett nekat köp ser annorlunda ut i protokollet än i specifikationen
    • terminalen skickar mer data än specen säger. Kassan klarar båda.
  • Vissa terminaler frågar efter kassans egenskaper (H60) och väntar på svar innan de går vidare; andra frågar aldrig. Kassan svarar när den får frågan.
  • Displaybredden (display_columns) styr hur terminalen formaterar sina texter.

Worldline

Med Worldline (Samport REST) är det terminalen som är server och kassan som ringer upp den. Kassan behöver terminalens adress och två nycklar från Worldline.

{"provider": "worldline", "terminal": "http://172.16.10.142:8080/api/v2"}

Nycklarna läggs för hand i config/worldline_keys.json, som bara kassans användare ska kunna läsa. De visas aldrig i inställningssidan, lämnas aldrig ut av kassan och följer aldrig med i paketen.

Hitta terminalen

Terminalen skickar ut sin adress i nätet var 60:e sekund, och inställningssidan visar den med en knapp som fyller i adressen. Det kräver att UDP-port 8000 är öppen in till maskinen och att terminal och kassa står i samma nät. Ge ändå terminalen en fast adress i routern.

Köpet

Köpen sker asynkront: kassan ber terminalen starta ett köp och frågar sedan efter resultatet. Om terminalen startas om mitt i ett köp letar kassan upp köpet efter dess eget id hellre än att gissa, och säger rakt ut om utfallet är okänt.

Svarar terminalen “upptagen” (503) på allt finns ofta ett köp påbörjat på själva terminalen - avbryt det där.

Skrivaren

Terminalens inbyggda skrivare kan användas som kassans kvittoskrivare - se Skrivare. Den skriver text och QR-kod, men ingen logga och ingen grafik, och den saknar avskärare.

Provat

Mot en riktig Axium-terminal: anslutning, nycklar, annonsen i nätet och utskrift. Ett riktigt kortköp, dagsavslut och avbrott från kassan återstår.

Swedbank Pay

Swedbank Pays PAX-terminaler (till exempel A920Pro) talar nexo Retailer 3.1, en ISO-standard med XML över HTTP. Terminalen är server: den lyssnar på port 11000 och kassan skickar sina meddelanden dit med POST /EPASSaleToPOI/3.1.

Rekommenderat läge: “bara klient”. Kassan ringer upp terminalen och terminalen ringer aldrig tillbaka. Det är det driftsäkraste: en enda förbindelse, ingen port in till kassan och ingen kassaadress att ställa in i terminalen. Kassören följer köpet på terminalen, och kan avbryta det med C på kassan.

Som tillval kan kassan spegla terminalen - terminalens skärmtexter i kassans display. Då lyssnar kassan också ("listen"), och terminalens adminmeny ställs in med kassans adress och port. Det är en förbindelse till som kan gå fel - välj det bara om butiken verkligen vill ha det.

Inställning

Ställs in på kortterminalfliken i inställningssidan, eller för hand i config/card_payment.json:

{"provider": "swedbankpay", "terminal": "http://172.16.10.185:11000", "poi_id": "FHD1"}
FältBetydelse
terminalTerminalens adress och port. Ge terminalen en fast adress i routern.
poi_idTerminalens ID hos Swedbank Pay - se nedan. Måste vara rätt.
sale_idKassans namn mot terminalen. Förval RGO1.
listenBara för speglingen, t.ex. "0.0.0.0:11000". Utelämnas i “bara klient”.

Inställningssidans kortterminalflik har Swedbank Pay, med en sökning som föreslår terminaler i nätet.

Hitta adressen

Terminalens inställningsskärm för kassakopplingen visar IP-adress och port, och en QR-kod som innehåller samma sak:

{"terminalIP":"172.16.10.185","terminalPort":"11000"}

Står det “Ingen IP-adress funnen” är terminalen inte ansluten till något nät - koppla den till wifi först.

POIID - terminalens ID

poi_id är inte ett fritt namn. Det tilldelas av Swedbank Pay och väljer terminalens inställningar hos dem - fråga supporten vilket ID terminalen har.

Terminalen byter till det ID kassan loggar in med: den svarar “New Poi ID detected, updating parameters”, rapporterar sig till Swedbank Pay under det nya ID:t och byter om det godkänns. Är ID:t okänt för Swedbank Pay nekas rapporten (“invalid POIId: not found”) och terminalen visar “felaktig konfiguration” - också efter omstart och ny parameterhämtning. Det rättas genom att kassan loggar in med det rätta ID:t; inget behöver göras på terminalen.

Köpet

  1. Kassan loggar in på terminalen vid första köpet.
  2. Ett köp skickas som PaymentRequest. Beloppet anges som decimaltal med punkt (1.00), inte i ören.
  3. Godkänt: kassan sparar terminalens transaktions-id och skriver kundkvittots färdiga rader på sin egen skrivare.
  4. Nekat: terminalen svarar “Failure” både för ett nekat kort och för ett tekniskt fel. Kassan skiljer dem åt med svarskoden i kvittot och säger “kortköpet nekades” eller “gick inte igenom”.
  5. Tappas svaret frågar kassan terminalen efter utfallet (TransactionStatusRequest) i stället för att gissa.

Makulering (om kontrollenheten inte svarar efter ett godkänt köp) görs med ReversalRequest och går bara på det senaste köpet. Terminalen svarar “upptagen” en kort stund efter varje köp; kassan väntar och försöker igen.

Dagligt underhåll

Swedbank Pay vill att terminalen är utloggad med underhåll tillåtet minst en timme per dygn, så att den kan hämta uppdateringar när ingen kund väntar. Kassan gör det själv: efter Z-rapporten loggar den ut terminalen med underhåll tillåtet, och loggar in igen vid nästa köp.

Inget dagsavslut

Protokollet saknar dagsavslut helt - ingen X-, Z- eller batchrapport. Kassans Z-rapport bygger på sin egen journal, och terminalens totaler stäms av i Swedbank Pays egna rapporter. Terminalen vill i stället vara utloggad med underhåll tillåtet en stund varje dag, för uppdateringar.

Fallgropar

  • Kompakt XML. Med radbrytningar och indrag stänger terminalen anslutningen utan att svara. Kassan skickar alltid allt på en rad.
  • POIID måste finnas i varje meddelande, annars stängs anslutningen.
  • Terminalens egna inställningar stänger av kassakopplingen. Medan någon är inne i terminalens meny svarar den “Busy - Maintenance in progress”.
  • Elementordningen i XML:en följer schemat och får inte ändras.

Känt problem: terminalen slutar ta emot kassan

Status: orsaken hittad 2026-10-26 - terminalen hade laddat ur. En A920Pro är en batteriterminal. När batteriet tar slut, eller nästan slut, slutar den svara kassan fast den kan se ut att vara på. Ladda terminalen, starta om den vid behov, och kassan når den igen.

Rutin i butiken (förslag, inte bestämd): terminalen har en fast plats i en laddvagga när den inte bärs runt, så att den alltid står på laddning mellan köpen och efter stängning.

Vad som syns. Kassan säger “kortterminalen svarar inte” vid Kort, fast terminalen ser normal ut och har nät. Inget köp går igenom från kassan.

Vad vi har sett (testterminal A920Pro, POIID FHD1, 2026-10-24 21.20):

  • Terminalen lyssnar fortfarande på port 11000 - det syns i dess egen nätverkstabell (adb shell cat /proc/net/tcp).
  • Men ingen kommer in: anslutningar från två olika maskiner (en dator och CHD6800-kassan, som var den kassa terminalen var inställd på) avbryts innan betalappen ser dem - inget hamnar i appens logg.
  • Terminalen själv når både internet och kassan, och adb över nätet (port 5555) fungerar.
  • Dagen innan gick det att ansluta, så länge terminalens kassaadress pekade på den maskin som anslöt. Felet kom efter att kassaadressen ändrats till CHD6800.
  • Strax innan hade terminalen ett underhållspass som inte nådde Swedbank Pays system (“failed to connect to tms.externaltest.payex.com”).

Vad det visade sig vara. Batteriet. Det vi först misstänkte - att terminalen bara släpper in den kassa den är inställd på, att underhållspasset lämnat den i ett halvt läge, eller wifi-nätet - behövde inte förklara något.

Kontrollera så här:

  1. Kan kassans maskin nå porten? Från en dator: curl http://<terminalen>:11000/ ska ge 404 (det är ett gott tecken - terminalen svarar). Inget svar alls = felet ovan.
  2. Lyssnar terminalen? adb shell cat /proc/net/tcp - port 11000 är 2AF8 i listan.
  3. Vad säger betalappen? adb logcat | grep SwedbankPay - leta efter underhåll, nätverksfel och vilket fönster som visas (Displaying fragment ...).

Åtgärd, i tur och ordning:

  1. Kontrollera batteriet och sätt terminalen på laddning. Det var orsaken 2026-10-26.
  2. Starta om terminalen.
  3. Hjälper inte det: spara terminalens adminmeny igen, med rätt kassaadress - eller utan kassaadress i läget “bara klient” - och starta om betalappen.

Om ett köp pågick när felet kom: kontrollera på terminalen om det gick igenom innan kunden går - kassan kan inte fråga terminalen när den inte kommer fram.

Felsökning

Testterminalerna går att nå med adb över nätet (adb connect <terminalen>:5555, efter adb tcpip 5555 via USB). Betalappen (com.optomany.AxeptPro) skriver varje meddelande den tar emot och skickar i loggen:

adb logcat | grep "SwedbankPay"

Där syns också terminalens kontakt med Swedbank Pays system (TMS), och det är där orsaken till ett “felaktig konfiguration” brukar stå.

Provat

Mot en riktig A920Pro (testterminal): inloggning, byte av POIID till det Swedbank Pay tilldelat, och felbilden vid fel POIID och vid öppen meny. Ett riktigt kortköp, nekat köp och makulering återstår.

Nets-emulatorn

Nets-emulatorn är en Android-app som låtsas vara en Nets-terminal. Den är till för kassor som bara kan tala Nets protokoll (SOFIE ECR-ITU) - ofta äldre kassor med en serieport - men som ska ta betalt via något annat: en betalapp i en telefon, eller en annan leverantörs terminal.

  kassa  --Nets ECR-ITU-->  [ Android-enhet                    ]
  (seriellt, TCP           [  Nets-emulatorn                   ]
   eller Bluetooth)        [     |                             ]
                           [  betalningslösning (t.ex. Softpay) ]

Kassan tror att den pratar med en Nets-terminal. Emulatorn tar emot beloppet, låter betalningslösningen sköta kortet, och svarar kassan med resultatet och kvittotexten i Nets format - samma meddelanden som en riktig Nets-terminal skickar.

Emulatorn är ett eget projekt (nets-emulator) och ingen del av R-GO kassa. R-GO kassa talar själv med Nets-, Worldline- och Swedbank Pay-terminaler och behöver den inte.

Anslutning till kassan

Tre sätt, valda i appens inställningar:

SerielltUSB-OTG-kabel till kassans RS232-port
TCPöver nätet, som en Nets-terminal
BluetoothSPP

Betalningslösningar

Läge
Softpay (betalning i telefonen)byggd, både via molnet och genom att växla app i telefonen
Worldline Axium (Samport)skisserad: appen körs på själva Axium-terminalen och talar med den lokalt
Swedbank Pay PAX (nexo)skisserad: samma meddelanden som R-GO kassa nu använder

Arbetet med R-GO kassans koppling till Worldline och Swedbank Pay är därmed också grunden för emulatorns: protokollet mot terminalen är detsamma, bara åt andra hållet sett från kassan.

Provat

Mot riktig hårdvara: Nets-länken över serieport (fel i länklagret hittades och rättades så), svar på kassans fråga om egenskaper (H62) och X-rapport. Appen har körts på en Samsung S25.

Installation

Appen byggs med Gradle och installeras med adb; den behöver behörighet att visa notiser för att kunna köra i bakgrunden. Se android/TESTING.md i projektet.

R-GO Fortnox

R-GO Fortnox är en fristående tjänst som för över bokföringsverifikat till kundens Fortnox. Den är inte en del av kassan: den läser färdiga verifikat - en SIE-fil och tillhörande PDF:er - ur ett exportarkiv och skapar dem i Fortnox, med PDF:erna som bilagor. Vilket system som skrev filerna spelar ingen roll. R-GO kassa är ett av källsystemen; andra av FHD:s lösningar, som System-900/FHDcore, kan lämna verifikat på samma sätt.

Att tjänsten står för sig själv är ett medvetet val. Kopplingen till Fortnox godkänns en gång per Fortnox-företag och kräver nycklar och tokens som ska förvaras säkert - det hör inte hemma i varje kassa. Och kassans fiskala delar - journalen, kontrollenheten - påverkas aldrig av något som händer mot Fortnox.

Vad tjänsten gör - och inte gör

Tjänsten skapar verifikat. Varje leverans startas av någon, och tjänsten håller en egen leveransjournal så att samma verifikat aldrig skickas två gånger - Fortnox kan nämligen varken ändra eller ta bort ett verifikat, så en dubblett går inte att städa bort i efterhand.

Den tar aldrig bort något i Fortnox, rör inte kundregister, artiklar eller fakturor, och ändrar inte ett verifikat som redan skickats.

Två program

programgör
fortnox-setupkopplar ett Fortnox-företag: godkännande, nycklar och förnyelse
fortnox-deliverkontrollerar ett verifikat och skickar det

Tjänsten finns för Windows, Linux och Mac under r-go.se/downloads/fortnox.

  1. Installera och koppla en kund

Installera och koppla en kund

Det här kapitlet går igenom hur tjänsten installeras och hur den kopplas till en kunds Fortnox, från behörigheterna i Fortnox utvecklarportal till det första levererade verifikatet. Räkna med 20-30 minuter första gången. Du behöver inte kunna programmera, men du behöver tillgång till kundens Fortnox och till maskinen där tjänsten körs.

Installera tjänsten

Tjänsten finns för Windows, Linux och Mac under r-go.se/downloads/fortnox. Packa upp arkivet där tjänsten ska bo, till exempel C:\R-GO\fortnox eller ~/fortnox. Programmen arbetar relativt den katalogen:

filvad
secrets/keys.jsonintegrationens nycklar - lämnas ut av FHD per installation
secrets/tokens.jsonkundens koppling, skrivs av fortnox-setup
data/deliveries.dbleveransjournalen, skyddet mot dubbletter

Lägg nycklarna från FHD i secrets/keys.json (paketet har en exempelfil som visar formatet). Katalogen secrets/ ska bara kunna läsas av den som kör programmen: den som har nycklarna och kundens koppling kommer åt kundens bokföring. På Mac är programmen inte signerade; kör xattr -dr com.apple.quarantine . i katalogen en gång.

Tjänsten behöver komma åt källsystemets exportarkiv - för R-GO kassa receiptprinterns export/ - antingen på samma maskin eller via en delad katalog.

Räkna med 20-30 minuter första gången.


Innan du börjar

Tre saker måste finnas på plats hos kunden:

Bokföring-licens i Fortnox-abonnemangetutan den nekas verifikaten även om kopplingen godkänns
Ett räkenskapsår upplagtverifikatet måste höra till ett år
En kontoplan med de konton kassans kontoplan pekar pånormalt BAS, som följer med räkenskapsåret

Och du behöver kunna logga in i kundens Fortnox med en användare som får godkänna integrationer.


Steg 1: Behörigheter i utvecklarportalen

Görs en gång för hela integrationen, inte per kund. Hoppa över det här steget om det redan är gjort.

Logga in på https://developer.fortnox.se, öppna integrationen r-go och gå till Behörigheter.

Fyra rutor ska vara ikryssade:

BehörighetVarför
Bokföringskapa verifikat - det här är kärnan
Företagsinformationläsa kundens namn och org.nr, för att bekräfta rätt företag
Inboxladda upp PDF-bilagor
Koppla filerfästa bilagorna på verifikatet

Lämna resten tom. Portalen säger det själv: “Begär därför endast behörigheter som behövs” - varje behörighet kan ställa licenskrav på kunden.

Kryssa INTE i “Ta bort verifikat”. Tjänsten tar aldrig bort något, och behörigheten skulle bara öka vad ett misstag kan ställa till med.

“Arkivplats” är inte samma sak som “Inbox”. Det tog oss ett extra försök: arkivplats gäller filarkivet, inbox är den brevlåda en bilaga går igenom. Du behöver inbox.

Efter publicering kräver nya behörigheter en ny förfrågan till Fortnox, så det är värt att få rätt från början.


Steg 2: Godkänn kopplingen för kunden

På maskinen där tjänsten körs:

fortnox-setup connect "Kundens Namn AB" --scope "bookkeeping companyinformation inbox connectfile"

Programmet skriver ut en adress och väntar.

  1. Öppna adressen i en webbläsare på samma maskin. Den pekar på localhost, så en webbläsare på en annan dator når den inte.
  2. Logga in som kunden och godkänn. Dialogen säger “r-go vill få tillgång till…”.
  3. Programmet svarar Klart och sparar nycklarna.

Namnet du anger är ditt eget - det används bara för att hålla isär kunder i tjänsten. Välj något du känner igen, gärna företagsnamnet.

Om det inte fungerar

invalid_scope - An unsupported scope was requested Behörigheten är inte ikryssad för integrationen. Gå tillbaka till steg 1. Felet ser ut som ett stavfel men är det nästan aldrig.

kunde inte lyssna på port 8099 En tidigare körning väntar fortfarande. Stäng den och försök igen.

Inget händer när du godkänt Webbläsaren körs troligen på en annan dator än tjänsten.


Steg 3: Verifikationsserie i Fortnox

Kassans kontoplan använder normalt serie Z, som inte finns i Fortnox standarduppsättning. Lägg upp den i kundens Fortnox:

Bokföring → Inställningar → Verifikationsserier, ny serie:

KodZ
BeskrivningKassarapport
ManuellJa

Manuell måste vara Ja. En serie som inte är manuell avvisar varje verifikat utifrån, med felet “Verifikationsserien är inte manuell”. “Manuell” betyder här att verifikat kommer från ett annat system - till skillnad från de serier Fortnox fyller själv, som kundfakturor och lön.

Använder kunden en annan serie ändrar du i stället kassans kontoplan, under fliken Kontoplan i kassans inställningssida.


Steg 4: Provlevera ett verifikat

Ta fram ett verifikat i källsystemet. I R-GO kassa görs det med en Z-rapport, som skapar en katalog i exportarkivet:

kassa-1_voucher_z000001/
  bokforing.si      <- verifikatet
  verifikat.pdf     <- bokföringsordern
  zrapport.pdf      <- Z-rapporten den byggdes av

Titta först, skicka sedan:

fortnox-deliver check "Kundens Namn AB" .../kassa-1_voucher_z000001/bokforing.si

Den visar konton, belopp och om verifikatet balanserar - utan att skicka något. Ser det rätt ut:

fortnox-deliver send "Kundens Namn AB" .../bokforing.si --with-pdf

Svaret ska bli Levererat som Z1. följt av bilagorna.

Kontrollera i Fortnox: Bokföring → Verifikationer, välj rätt räkenskapsår och serie Z.


Det viktigaste att förstå

Ett verifikat kan inte tas bort. Fortnox har ingen sådan funktion i API:et, och ingen i webbgränssnittet heller för ett bokfört verifikat. Ett verifikat som skickats av misstag ligger kvar och måste rättas med ett motverifikat.

Därför finns en leveransjournal (data/deliveries.db) som håller reda på vad som skickats. Skickar du samma Z-rapport igen svarar tjänsten:

Redan levererat som Z1 - ingenting skickades.

Journalen måste följa med. Flyttar du tjänsten till en annan maskin, eller återställer från säkerhetskopia, måste data/ följa med. En borttappad journal betyder att allt kan skickas igen - och dubbletterna går inte att städa bort.


Underhåll

Förnya innan 45 dagar. Kopplingen håller i 45 dagar och förnyas automatiskt varje gång tjänsten används. En kund som bokför kvartalsvis hinner tappa sin koppling mellan körningarna - då får du göra om steg 2.

Kontrollera läget med:

fortnox-setup list

Står det token utgången - kör refresh:

fortnox-setup refresh "Kundens Namn AB"

Felmeddelanden du kan möta

MeddelandeVad som är fel
Har inte behörighet för scope (2000663)behörigheten saknas - steg 1, och kunden måste godkänna om
Verifikationsserien är inte manuell (2001940)serien är inte markerad Manuell - steg 3
inget räkenskapsår i Fortnox täcker ...räkenskapsåret saknas, eller verifikatet har ett datum utanför det
Fältet VoucherNumber är endast läsbartska inte hända - Fortnox sätter numret, tjänsten skickar det aldrig
OKLART - kontrollera i Fortnoxett tidigare försök avbröts mitt i. Titta i Fortnox innan du försöker igen

Det sista är värt att ta på allvar. Tjänsten antecknar att den ska skicka innan den gör det, så ett avbrott mitt i lämnar ett frågetecken i stället för en tyst dubblett. Finns verifikatet i Fortnox är det klart; finns det inte kan du skicka igen.


Rätta en felaktig bilaga

Verifikat går inte att ta bort, men bilagor gör det: DELETE /3/voucherfileconnections/{FileId}. Har fel PDF hamnat på ett verifikat kan kopplingen tas bort och rätt fil fästas i stället.

Det finns inget kommando för det än - säg till om det behövs.


Vad tjänsten aldrig gör

  • Tar inte bort något i Fortnox
  • Rör inte kundregister, artiklar eller fakturor
  • Ändrar inte ett verifikat som redan skickats
  • Skickar inget automatiskt - varje leverans startas av någon

Tjänsten är också fristående från kassan. Den läser filer ur exportarkivet och bryr sig inte om vilket system som skrev dem.

Teknisk referens

Den tekniska referensen är till för utvecklare och integratörer: den som ska skriva en egen skrivartjänst, en egen operatörs- eller kunddisplay, eller ett program som läser kassans journal. Den beskriver dataformaten som de faktiskt ser ut i koden - fältnamn och typnamn står exakt som i källkoden, och där koden har en egenhet eller ett fält som inte används står det uttryckligen.

Referensen förutsätter att du har läst Översikt och arkitektur i systemmanualen: kassan (web_till) äger all logik, skrivartjänsten (receiptprinter) och displayerna är tunna mottagare som bara visar det de får.

  1. Utskriftsformatet - kvittolayouten (ReceiptLayout) som kassan skickar till skrivartjänsten, och skrivartjänstens HTTP-gränssnitt.
  2. Displayformatet - tillståndet kassan skickar till operatörsdisplayen och kunddisplayen, och meddelandena som kommer tillbaka.
  3. Journalminnet - journalens design, filformat och samtliga händelsetyper.

Utskriftsformatet

Kassan ritar aldrig själv. Allt som ska ut på papper - kvitto, X- och Z-rapport, journalutskrift, kortterminalens rapport, verifikation och tillgodokvitto - byggs först som en kvittolayout, typen ReceiptLayout, och skickas som JSON till skrivartjänsten receiptprinter. Det är skrivartjänsten som vet vilken skrivare som sitter i andra änden och gör om layouten till en rasterbild, till ESC/POS-text, till Worldline-terminalens textformat eller till en PDF.

Det här skiljer på två frågor som annars blandas ihop: vad som står på kvittot (kassans sak, och en del av det fiskala underlaget) och hur det ser ut på just den här skrivaren (skrivartjänstens sak). En egen skrivartjänst behöver alltså bara förstå formatet nedan; den behöver inte veta något om moms, kontrollenheter eller kvittonummer.

Typen finns i två exemplar som hålls lika för hand: rust-poc/src/receipt_layout/mod.rs på kassans sida och rust-poc/receiptprinter/src/receipt_layout_types.rs på mottagarens. Skrivartjänsten är en fristående crate som inte beror på kassan, så det är trådformatet - inte en delad Rust-typ - som är kontraktet. Ett test på kassans sida (serializes_to_designmd_documented_shape) låser formatet.

Kvittolayouten

ReceiptLayout
├── receipt_width    "flexible"
├── rows[]           text | image | qr
├── document_number  kvittonummer, 0 = inget dokument
└── footer[]         fria fotrader
fälttypbetydelse
receipt_widthsträngBreddläge. Bara "flexible" finns, och ingen renderare i receiptprinter läser fältet - bredden bestäms helt av skrivartjänstens konfiguration.
rowslista av raderKvittots innehåll uppifrån och ned. Varje rad har fältet type: "text", "image" eller "qr".
document_numberheltalKvittonumret layouten hör till (samma nummer som receipt_number i journalens PAYMENT). 0 betyder att layouten inte hör till något numrerat dokument - X/Z-rapporter, journalutskrifter och verifikationer sätter 0. Får saknas (blir 0). Receiptprinter läser det inte.
footerlista av strängarFria fotrader som skrivs ut under rows, var och en som en vänsterställd rad i stilen normal. Kommer från company_info.json. Utelämnas när den är tom; bara kvittot sätter den.

Belopp är redan formaterade strängar när de kommer hit ("35:00"), inte heltal i öre. Layouten är en presentation, inte data att räkna på.

Textrad ("type": "text")

En textrad har en av två former. En kolumn: columns har ett enda element och align säger var det hamnar. Flera kolumner: tabs_percent och alignments har ett element per kolumn. Typen tvingar inte fram den ena eller andra formen; det är en konvention som alla layoutbyggare i kassan följer. Det som avgör hur raden tolkas är om tabs_percent är tom eller inte.

fälttypbetydelse
stylesträngRadens stil, se tabellen nedan. Okända namn ritas som normal.
columnslista av strängarTexten, en sträng per kolumn.
align"left", "right", "center"Justering i enkolumnsformen. Utelämnas när den inte är satt; saknas den i enkolumnsform blir den left. Ignoreras när tabs_percent har värden.
tabs_percentlista av talVarje kolumns startposition i procent av den utskrivbara bredden. Utelämnas när den är tom.
alignmentslista av "left"/"right"/"center"Varje kolumns justering, parallell med columns. Saknade element blir left. Utelämnas när den är tom.
column_styleslista av sträng eller nullStil per kolumn, parallell med columns. null, ett saknat element eller en tom lista betyder “radens style”. Utelämnas när den är tom.
row_idheltalevent_id för den LINE_ADDED raden visar. Sätts bara av layouten för ett pågående kvitto (displayen, se Displayformatet); alla utskrivna layouter saknar det. Båda renderarna i receiptprinter ignorerar fältet.

Stilnamnen, som de tolkas av de olika renderarna:

stylerasterbild (print_layout.rs)ESC/POS-text (escpos_text.rs)Worldline (samport_printer.rs)PDF (voucher_pdf.rs)
normal24 pt, normal viktinga stilkoderinga stilkodernormal
header30 pt, fetfet (ESC E), normal storlekfetfet, större
bold_total24 pt, fetfet (ESC E)fetfet
dbl_heightdubbel höjdGS ! dubbel höjd, samma bredddubbel (höjd och bredd)dubbel höjd
dbl_widthdubbel breddGS ! dubbel bredddubbeldubbel bredd (Tz 200)
dbl_sizedubbel höjd och breddGS ! dubbel höjd och bredddubbeldubbel höjd och bredd

Worldline-terminalens skrivare har bara ett “dubbelt” läge, och det gör tecknen både högre och bredare, så alla tre dbl_* blir samma sak där.

Kassans layoutbyggare använder i dag normal, header, bold_total och dbl_size som radstil (dbl_size för rubriken KVITTO), och dbl_width som kolumnstil för beloppet på kvittots SUBTOTAL-rad.

Bildrad ("type": "image")

fälttypbetydelse
sourcesträngLogiskt namn på en bild som finns lagrad hos skrivartjänsten (se /asset/:id nedan), till exempel "logo". Aldrig bildens bytes.
align"left"/"right"/"center"Var bilden placeras.
width_percenttalBildens bredd i procent av den utskrivbara bredden. Höjden följer bildens proportioner.

En bild som inte finns lagrad, eller inte går att avkoda, ritas som en platshållarruta i rasterläget - aldrig ett avbrott, eftersom ett kvitto är ett lagstadgat dokument och inte får falla på en logga. I textläge (CHD6800) skrivs "[BILD: <source>]", utom när source är "logo" och en logga har laddats upp: då skrivs den ur skrivarens NV-minne med FS p. Worldline-terminalen hoppar över bildrader helt, och PDF:en gör det också.

QR-rad ("type": "qr")

fälttypbetydelse
datasträngDet som ska kodas. Används för tillgodokvittot.
align"left"/"right"/"center"Placering.
width_percenttalKodens sida i procent av den utskrivbara bredden (koden är kvadratisk).

Raden bär data, inte en bild: skrivaren vet sin egen punktbredd och kan rita modulerna skarpt, där en skalad bitmapp kan bli oläsbar. I rasterläget ritas koden in i bilden; går den inte att koda blir det en platshållarruta. I ESC/POS-textläget skickas Epsons QR-kommando med fast modulstorlek 6 (width_percent används inte) - koden säger själv att sekvensen inte är verifierad på en CHD6800. Worldline skriver QR med sitt eget kommando och centrerar bara när align är "center". PDF:en hoppar över QR-rader.

Kolumner och procenttabbar

tabs_percent anger var varje kolumn börjar, i procent av den utskrivbara bredden - inte hur bred den är. En rad med "tabs_percent": [0.0, 85.0] och "alignments": ["left", "right"] har första kolumnen från vänsterkanten och andra kolumnen från 85 %. Kvittots momsrader använder [5.0, 85.0] för att dra in moms och brutto en bit.

I rasterläget (layout_text_row_pixels) går kolumn i från sin tabb till nästa kolumns tabb, och den sista kolumnen till högerkanten. En vänsterställd kolumn börjar vid sin tabb, en högerställd slutar vid sitt spanns slut och en centrerad centreras i spannet. En kolumn som inte får plats klipps aldrig: nästa kolumn knuffas åt höger (minst ett mellanslag), och en högerställd text som är för lång växer åt vänster. Blir bilden bredare än pappret skalas hela bilden ned till skrivarens bredd före rastreringen. Alla kolumner på en rad delar samma baslinje, och radhöjden är den högsta av kolumnernas stilar.

I textläget (CHD6800 och Worldline, render_text_row) används procentsatserna inte alls - att listan inte är tom väljer bara flerkolumnsvägen. Skälet är skrivarnas fasta teckenrutnät och att CHD6800:ns skrivare inte förstår några positioneringskommandon. I stället fördelas en rads tecken så här:

  1. Kolumnerna behandlas från höger. Den sista kolumnen - normalt beloppet - får hela sin bredd först och kortas aldrig.
  2. Mellan två kolumner reserveras ett mellanslag.
  3. Det som blir över går till kolumnerna till vänster. Den första kolumnen - normalt en benämning - kortas av om det inte räcker.
  4. Allt överskott hamnar som utfyllnad i första kolumnen, så den sista kolumnen ligger mot högerkanten.

En enkolumnsrad kortas till radens bredd och placeras med inledande mellanslag enligt align. Bredden är 30 tecken på CHD6800 (DEFAULT_WIDTH_CHARS, uppmätt på riktig hårdvara) och 34 på Worldline-terminalen (flaggan --worldline-width-chars). En kolumn i dbl_width/dbl_size räknas som två tecken per tecken på CHD6800; på Worldline räknas alla dbl_* dubbelt, och en rad med någon dubbel kolumn får två teckens marginal eftersom terminalens dubbla tecken är något mer än dubbelt så breda. Text kodas som CP437 på CHD6800 och som latin-1 på Worldline (där ESC-tecken tas bort så att texten inte kan ge kommandon); tecken som saknas i CP437 blir ?.

En egen skrivartjänst som skriver text bör följa samma prioritering: beloppet får aldrig kortas, benämningen får det.

Hur kassan skickar

Kassan läser skrivartjänstens adress ur config/printer_service.json (printer_service.base_url, till exempel http://127.0.0.1:8080) och skickar med blockerande HTTP och 20 sekunders timeout (printer_http_sink.rs). Ordningen efter ett köp eller en rapport är:

  1. POST /print_layout med layouten.
  2. Om svaret är 2xx: POST /feed_cut med {"feed": 3, "cut": true} (RECEIPT_FEED_LINES).

Matning och kniv är avsiktligt ett eget anrop. /print_layout hör ihop med vad ett dokument innehåller; när en utskriftsomgång är slut är en annan fråga, och en anropare som vill skriva flera dokument i rad ska kunna klippa en gång på slutet.

Hur ett misslyckat anrop hanteras beror på dokumentet:

  • X- och Z-rapporter och journalutskrifter skrivs ut av kassan själv, genom dess PrintSink (receipt_sink.rs). web_till och interactive sätter dess layoutskrivare till receiptprinter (till::layout_printer_via_http), som gör de två anropen ovan. Utskriften räknas som lyckad när /print_layout svarat 2xx; en misslyckad /feed_cut efteråt loggas bara. Utfallet journalförs i X_REPORT_PRINT_ATTEMPT, Z_REPORT_PRINT_ATTEMPT och JOURNAL_PRINT_ATTEMPT (se Journalminnet). För Z-rapporten är utskriften en spärr: svarar skrivaren inte stängs inte perioden, utan kassan frågar om ett nytt försök och väntar på Ja (försök igen) eller Nej (avbryt; perioden förblir öppen).
  • Kvitton, kortterminalens rapport, verifikationen och övriga dokument är “skjut och glöm” i web_till: misslyckas utskriften loggas det, men ingenting i kassan rullas tillbaka och operatören får ingen fråga.

Efter en Z-rapport skickas också verifikationen (/print_layout), SIE-filen (/export/...) och verifikationen och Z-rapporten som PDF (/render_pdf med arkivhuvuden), i den ordningen.

Skrivartjänstens HTTP-gränssnitt

Receiptprinter lyssnar som standard på port 8080 (--http :8080). Det finns två servrar med olika uppsättning vägar: den vanliga (http_server.rs, för USB-, nätverks-, Windows- och Worldline-skrivare) och den seriella (serial_http_server.rs, för CHD6800:ns inbyggda skrivare, startas med --serial-http).

vägvanligseriellkroppsvar
POST /print_layoutjajaReceiptLayoutPrintResponse
POST /feed_cutjaja{"feed": n, "cut": bool}PrintResponse
POST /printja-PNG/JPEG, se nedanPrintResponse
POST /render_pdfja-ReceiptLayoutPDF-bytes
POST /open_drawerja-ingenPrintResponse
GET /statusja--status-JSON
GET /ja--HTML-sida som beskriver API:t
POST/GET/DELETE /asset/:idjajase nedanAssetResponse / PNG
POST/GET /export/:voucher/:name, GET /export/:voucher, GET /exportjajase nedanse nedan

Den vanliga servern har också /setup-vägarna för inställningssidan; de är inte en del av utskriftsformatet och beskrivs inte här.

Svaret PrintResponse

{"success": true, "message": "printed successfully"}
väglyckat messageHTTP-status
/print_layout, /print"printed successfully"200
/feed_cut"fed/cut successfully"200
/open_drawer"drawer opened"200

Ogiltig JSON ger 400 med {"success": false, "message": "invalid JSON: ..."}. Ett fel från skrivaren ger 500 med felet i message. Kassan tittar bara på statuskoden.

POST /print_layout

Kroppen är en ReceiptLayout. Vad som händer beror på skrivaren:

  • Rasterskrivare (USB, nätverk, Windows-kö): layouten ritas som en gråskalebild i skrivarens bredd (--width, standard 576 punkter), med det inbäddade typsnittet DejaVu Sans Mono, ditheras med Floyd-Steinberg och skickas som ESC/POS- eller StarPRNT-raster. Tjänsten matar och klipper aldrig själv efter en /print_layout; det gör anroparen med ett eget /feed_cut, som kassan alltid skickar efteråt. Flaggorna --cut och --feed gäller bara /print.
  • CHD6800 (seriell server): layouten blir ESC/POS-text enligt textläget ovan, inleds med ESC @ och val av teckentabell PC437 och avslutas med tre radmatningar. Ingen kniv.
  • Worldline-terminalen (--worldline): layouten blir Samports textformat och skickas till terminalens POST /Prints. Bildrader hoppas över; QR skrivs med terminalens eget kommando. Avslutas med tre tomma rader så att kvittot kan rivas av.

POST /feed_cut

{"feed": 3, "cut": true}. Båda fälten kan saknas och är då 0 och false; en tom kropp är en giltig no-op. Worldline-terminalen har ingen kniv och ignorerar cut (matar minst en rad).

POST /print

Den äldre vägen: kassan renderar själv och skickar en färdig bild. Antingen multipart med fältet file, eller JSON:

{"type": "png", "data": "<base64>", "cut": false, "feed": 2}

type måste finnas men används bara som etikett - bildformatet avläses ur själva bytesen. cut och feed är valfria och ersätter tjänstens standardvärden för just det jobbet. Worldline-terminalen vägrar med ett fel, eftersom den inte tar grafik.

POST /render_pdf

Samma ReceiptLayout som /print_layout, men svaret är en PDF (Content-Type: application/pdf) i stället för en utskrift. Ingen skrivare berörs, så anropet kan inte blockeras av en pågående utskrift. Remsan ritas centrerad och inramad på ett A4-ark, 80 mm bred, som text med inbäddat typsnitt. Bild- och QR-rader hoppas över; fotraderna kommer med.

Svarshuvuden:

huvudvärde
X-Pdf-Overflowedtrue om remsan inte fick plats på en sida och kapades nedtill, annars false. Uppdelning i spalter och sidor finns inte ännu.
X-Pdf-Archivedskipped när inga arkivhuvuden skickades, true när filen arkiverades, annars error: ....

Skickar anroparen både X-Export-Voucher och X-Export-Name sparas PDF:en också i exportarkivet, i katalogen för den verifikationen. Kassan använder namnen verifikat.pdf och zrapport.pdf. Ett misslyckat arkiv fäller aldrig svaret.

POST /open_drawer

Ingen kropp. Fungerar bara mot nätverksskrivare och Windows-kö (StarPRNT:s lådkommando); för USB och Worldline svarar tjänsten 500 med ett fel som säger det. Kassan anropar inte vägen i dag.

GET /status

{
  "healthy": true,
  "printer": "usb",
  "printer_connected": true,
  "usb_connected": true,
  "usb_vendor": "0519",
  "usb_product": "000b",
  "serial_connected": true,
  "serial_port": "/dev/ttyACM0",
  "ws_addr": ":8765",
  "width": 576,
  "asset_dir": "/opt/rgo/assets",
  "uptime_seconds": 512.3
}

Statuskoden är 200 när healthy är sant, annars 503, så att en övervakning kan nöja sig med koden. healthy avgörs bara av den valda skrivaren och är samma värde som printer_connected. printer säger vilken skrivare som valts och hur den kontrolleras, i samma ordning som tjänsten väljer skrivare:

printerkontroll
"worldline"TCP-anslutning till Worldline-terminalens adress lyckas (inom 0,5 s).
"windows"Windows-kön med det inställda namnet finns.
"network"TCP-anslutning till nätverksskrivaren lyckas (port 9100 om ingen anges, inom 0,5 s).
"usb"USB-skrivaren med inställt vendor/product-id finns.

usb_connected och serial_connected redovisas fortfarande för sig, men påverkar inte healthy; en installation utan seriell port eller med en annan skrivare än USB kan alltså vara frisk. Kontrollen säger att skrivaren går att nå, inte att den har papper.

/asset/:id - loggan

POST /asset/logo med {"type": "png", "data": "<base64>"} lagrar en bild under namnet logo. type får utelämnas, men anges den måste den vara png. Svaret:

{"success": true, "message": "stored logo", "width": 576, "height": 168}

GET /asset/:id returnerar PNG:en, DELETE /asset/:id tar bort den (404 om den inte fanns). På den seriella servern rastreras loggan också in i skrivarens NV-minne vid uppladdning, så att varje kvitto bara behöver skicka fyra byte för att skriva den. Det är namnet här som en bildrads source pekar på.

/export - arkivet för bokföringsfiler

Kroppen är själva filen, utan JSON eller base64 (en SIE-fil är CP437-bytes, inte UTF-8-text).

  • POST /export/:voucher/:name sparar filen. Svar: {"success": true, "message": "stored <voucher>/<name>", "path": "..."}.
  • GET /export/:voucher/:name hämtar den (application/pdf för .pdf, annars application/octet-stream).
  • GET /export/:voucher listar katalogen: {"voucher": "...", "sie": ..., "attachments": ..., "other": ...}.
  • GET /export listar alla verifikationer: {"vouchers": [...]}.

Kassan namnger katalogen <kassabeteckning>_voucher_<serie><nummer>, till exempel kassa-1_voucher_z000011, och filerna bokforing.si, verifikat.pdf och zrapport.pdf.

Exempel: ett kvitto

Så här ser kroppen till POST /print_layout ut för ett kontantköp av två likadana varor med streckkod, med logga och fottext. Raderna är de som build_receipt_layout_with_logo (receipt_layout/kvitto.rs) bygger, i samma ordning. Två slag av samma vara slås ihop till en rad med en detaljrad under; i journalen ligger de kvar som två LINE_ADDED.

{
  "receipt_width": "flexible",
  "rows": [
    {"type": "image", "source": "logo", "align": "center", "width_percent": 60.0},
    {"type": "text", "style": "dbl_size", "columns": ["KVITTO"], "align": "center"},
    {"type": "text", "style": "normal", "columns": ["Kvitto nr 42"], "align": "center"},
    {"type": "text", "style": "header", "columns": ["Exempelbutiken AB"], "align": "center"},
    {"type": "text", "style": "normal", "columns": ["Org.nr", "556000-0000"],
     "tabs_percent": [0.0, 50.0], "alignments": ["left", "left"]},
    {"type": "text", "style": "normal", "columns": ["Exempelgatan 1"], "align": "center"},
    {"type": "text", "style": "normal", "columns": ["123 45 Exempelstad"], "align": "center"},
    {"type": "text", "style": "normal", "columns": ["Kaffe", "70:00"],
     "tabs_percent": [0.0, 85.0], "alignments": ["left", "right"]},
    {"type": "text", "style": "normal", "columns": ["  2 x 35:00"], "align": "left"},
    {"type": "text", "style": "normal", "columns": ["  7300000000000"], "align": "left"},
    {"type": "text", "style": "bold_total", "columns": ["SUBTOTAL", "70:00"],
     "tabs_percent": [0.0, 85.0], "alignments": ["left", "right"],
     "column_styles": [null, "dbl_width"]},
    {"type": "text", "style": "normal", "columns": ["12% netto", "62:50"],
     "tabs_percent": [0.0, 85.0], "alignments": ["left", "right"]},
    {"type": "text", "style": "normal", "columns": ["moms", "7:50"],
     "tabs_percent": [5.0, 85.0], "alignments": ["left", "right"]},
    {"type": "text", "style": "normal", "columns": ["brutto", "70:00"],
     "tabs_percent": [5.0, 85.0], "alignments": ["left", "right"]},
    {"type": "text", "style": "bold_total", "columns": ["BETALT (KONTANT)", "70:00"],
     "tabs_percent": [0.0, 85.0], "alignments": ["left", "right"]},
    {"type": "text", "style": "normal", "columns": ["Mottaget", "100:00"],
     "tabs_percent": [0.0, 85.0], "alignments": ["left", "right"]},
    {"type": "text", "style": "normal", "columns": ["Växel", "30:00"],
     "tabs_percent": [0.0, 85.0], "alignments": ["left", "right"]},
    {"type": "text", "style": "normal", "columns": ["Kontrollenhet", "EXEMPEL00000000001"],
     "tabs_percent": [0.0, 85.0], "alignments": ["left", "right"]},
    {"type": "text", "style": "normal", "columns": ["Kontrollkod:"], "align": "left"},
    {"type": "text", "style": "normal", "columns": ["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"], "align": "left"},
    {"type": "text", "style": "normal", "columns": [";BBBBBBBBBBBBBBBBBBBBBBBBBB"], "align": "left"}
  ],
  "document_number": 42,
  "footer": ["Tack för ditt köp!", "Öppet vardagar 10-18"]
}

Några saker att lägga märke till:

  • Tomma fält utelämnas: en enkolumnsrad har varken tabs_percent eller alignments, en flerkolumnsrad har inget align.
  • Kontrollkoden delas vid semikolonet; andra halvan börjar med ;.
  • Mottaget/Växel finns bara för kontant med angivet belopp.
  • Vid kortköp läggs kortterminalens egna kvittorader in som enkolumnsrader mellan betalraderna och kontrollkoden.

Svaret vid lyckad utskrift, och därefter kassans matning:

POST /print_layout  ->  200 {"success": true, "message": "printed successfully"}
POST /feed_cut      {"feed": 3, "cut": true}
                    ->  200 {"success": true, "message": "fed/cut successfully"}

Och ett fel från skrivaren:

{"success": false, "message": "open USB printer: ..."}

med status 500.

Andra dokument i samma format

Det finns inget separat format för rapporter eller verifikationer - alla är ReceiptLayout:

dokumentbyggs avanmärkning
kvittoreceipt_layout/kvitto.rsdocument_number = kvittonumret, footer från company_info.json
X/Z-rapportreceipt_layout/rapport.rs (report_data_to_receipt_layout)document_number 0, ingen fottext
journalutskriftreceipt_layout/journal.rsvarje journalrad pretty-printad som JSON, en enkolumnsrad per textrad
kortterminalens rapportreceipt_layout/kortterminal.rs
verifikationreceipt_layout/verifikation.rsskrivs ut och skickas till /render_pdf
tillgodokvittoreceipt_layout/vardehandling.rsinnehåller en QR-rad

Verifikationens PDF är alltså inte en egen A4-layout utan samma remsa som skrivs ut, ritad på ett A4-ark. Det håller papper och arkiv lika.

Kassan har också en egen, stilblind textrenderare (receipt_sink::render_receipt_layout_as_text, 35 tecken bred) som skriver kvitton och rapporter till kassans standardutdata - för rapporterna bara när ingen skrivartjänst är inställd. Den följer tabs_percent bokstavligt och struntar i stilar; den är inte en del av skrivartjänsten.

Displayformatet

Displayerna är speglar. All logik - vad en tangent betyder, vad som står på kvittot, vilken dialog som väntar - finns i kassan (Till, driven av web_till). En display får ett färdigt tillstånd och ritar det; den skickar tillbaka händelser (en tangent trycktes ned, en rad klickades) och väntar på nästa tillstånd. Den räknar aldrig själv, och den behöver inte veta varför ett tillstånd ser ut som det gör.

Samma tillstånd bär båda displayerna: operatörsdisplayens kvittovy och kunddisplayens två rader ligger i samma meddelande. De byggs ur samma Till i samma ögonblick, så de kan inte komma ur takt.

Transport

web_till har två portar:

port (standard)flaggaprotokollanvänds av
127.0.0.1:8090--httpHTTPstatiska filer, GET /state, POST /key_press m.fl.
127.0.0.1:8091--wsWebSocketoperatörsklienten web_client/app.js

GET /server_info.json svarar med den faktiska WebSocket-porten och kassans decimalinställning, så att en klient inte behöver gissa porten:

{"ws_port": 8091, "decimal_places": 0}

Kassan annonseras också på mDNS som _rgo-kassa._tcp.local. med ws_port och version i TXT-posten.

WebSocket är huvudvägen. Varje ansluten flik registreras, och efter varje tillståndsändrande kommando sänds det nya tillståndet till alla anslutna flikar, inte bara den som skickade kommandot - en streckkod som läses in via HTTP syns därmed i alla öppna fönster. Vid anslutning skickas aktuellt tillstånd direkt till den nya fliken.

HTTP-pollning finns för klienter som inte kan hålla en WebSocket: ES5-klienten web_client/app.es5.js (gamla Android-WebViews på V-R100 och CHD6800) pollar GET /state var 2:a sekund och skickar tangenter med POST /key_press, och kundfönstret web_client_customer/customer.js pollar GET /state en gång i sekunden och skickar aldrig något.

Kuvertet

Varje WebSocket-meddelande, i båda riktningar, är ett kuvert:

{"destination": "operator_display", "type": "state", "payload": { ... }}
fältbetydelse
destinationAlltid "operator_display" i dag. Finns för att en ny mottagare ska kunna bli ett nytt värde i stället för ett nytt protokoll. Servern läser inte fältet i inkommande meddelanden; klienten app.js kastar meddelanden med annan destination.
typeMeddelandets slag, se nedan.
payloadInnehållet.

Från kassan kommer två typer: state och terminal_display. Från klienten tas tre emot: key_press, select_tab och select_line. Ett meddelande av annan typ, eller som inte är giltig JSON, ignoreras.

GET /state och POST /key_press svarar med exakt samma state-kuvert som WebSocket-vägen skickar.

Tillståndet (type: "state")

Byggs av snapshot_to_json (web_till/json.rs) ur Till::display_snapshot och Till::customer_display_snapshot.

fälttypbetydelse
buffersträngDet som är inslaget på sifferbordet. "0" när inget är inslaget. Med decimaler påslagna kan den innehålla ett , ("35,5"). Det är inslagna tecken, inte ett tolkat belopp.
modesträngVad kassan väntar på: "price", "awaiting_confirmation", "registering_product" eller "awaiting_credit_checksum".
promptsträng eller nullFärdig svensk text att visa. Satt för awaiting_confirmation och awaiting_credit_checksum, annars null.
barcodesträng eller nullDen lästa streckkoden när mode är registering_product, annars null.
terminal_displaysträng eller nullKortterminalens aktuella text (Nets), eller null. Se nedan.
cart_lineslistaDet pågående kvittots rader: {"group_name": sträng, "amount_minor": heltal}. group_name är varugruppens namn, eller artikelns namn vid streckkodsförsäljning. Belopp i öre.
subtotal_minorheltalKvittots summa i öre.
vat_minorheltalKvittots moms i öre, summerad över momssatserna.
receipt_display_lineslista av DisplayLineKvittot som rader och kolumner, se nedan. Tom lista när inget är inslaget.
customer_displayobjektKunddisplayens två rader: {"row1": [DisplayColumn], "row2": [DisplayColumn]}.
selected_line_event_idheltal eller nullRaden som är markerad (dess row_id), så att alla flikar markerar samma rad.
active_tab_indexheltalVilken flik i varupanelen som är vald.
last_errorsträng eller nullEtt engångsmeddelande som hör till just den händelse som gav svaret. Se nedan.

Ordningen på nycklarna i JSON är inte garanterad.

mode och prompt

mode slår ihop flera interna väntelägen till ett enda awaiting_confirmation, eftersom en display bara behöver visa en Ja/Nej-fråga, inte veta vilken. Kassan väljer i samma ordning som den själv tolkar nästa Ja/Nej, så frågan som visas är alltid den som besvaras:

lägeprompt
Z-rapportens utskrift misslyckades"Z-rapport: försök skriva ut igen? (Y/N)"
kontrollenheten svarade inte"Kontrollenheten svarar inte - försök igen? (Ja/Nej)"
journalen kunde inte skrivas"Försök igen? (Y/N)"
kassans interna utskrift väntar på svar"Skriv kvitto? (Y/N)"

registering_product betyder att en streckkod lästes som inte finns i varuregistret: operatören slår ett pris och en varugrupp, och varan läggs upp och säljs i samma tryck. awaiting_credit_checksum betyder att ett tillgodobelopp har slagits in och kassan väntar på kontrollsumman från tillgodokvittot; prompt innehåller då texten "Tillgodo <kr>,<öre> - ange checksumman, tryck TILLGODO".

receipt_display_lines och DisplayLine

Raderna är samma ReceiptLayout som ett kvitto skrivs ut från (se Utskriftsformatet), omräknade till kolumner med position. Under ett pågående köp används den förenklade layouten build_receipt_layout_in_progress: en rad per inslagen rad plus en SUBTOTAL-rad. Efter betalningen, så länge kvittot ligger kvar i “slussen” i väntan på att skrivas ut eller avslutas, visas i stället hela det betalda kvittot (build_receipt_layout, utan logga) - med betalsätt, växel och kontrollkod, exakt som på papperet.

fälttypbetydelse
columnslista av DisplayColumnRadens kolumner.
row_idheltal eller nullevent_id för radens LINE_ADDED i journalen. Sätts bara på varurader i ett pågående köp; null för SUBTOTAL och för alla rader i ett betalt kvitto. Det är värdet klienten skickar i select_line.
stylesträngRadens stil med samma namn som på kvittot: normal, header, bold_total, dbl_height, dbl_width, dbl_size. Kolumnstilar (column_styles) följer inte med.

En bildrad blir en kolumn med texten "[BILD: <source>]" och en QR-rad blir "[QR]"; inga sådana rader förekommer i displaylayouterna i dag.

DisplayColumn

{"text": "35:00", "percent": 85.0, "align": "right"}
fälttypbetydelse
textsträngDet som ska stå. Belopp är formaterade som på kvittot ("35:00").
percenttalKolumnens position i procent av radens bredd.
align"left", "right", "center"Justering.

percent betyder olika saker beroende på align, och det är den vanligaste källan till fel i en egen klient:

alignpercent ärkolumnens högerkant
leftvänsterkanten-
rightkolumnens början; texten slutar där nästa kolumn börjar, eller vid 100 % för sista kolumnennästa kolumns percent, annars 100
centermittpunkten - en centrerad rad över hela bredden har percent 50-

För en flerkolumnsrad kommer percent direkt från kvittoradens tabs_percent, och align från alignments. För en enkolumnsrad är percent 0 för vänster och höger och 50 för centrerat. Kolumnerna ska placeras mot displayens faktiska bredd (operatörsklienten gör det med absolut positionerade element i procent), inte paddas till ett antal tecken - skärmens ruta är bredare än kvittots 35 tecken.

Kunddisplayen: row1 och row2

Kunddisplayen är tänkt som en fysisk display med 2 rader om 20 tecken, utan grafik. Den visar bara den senaste händelsen av tre slag, inte hela kvittot:

senaste händelserow1row2
ingenting ännu (sedan kassan startade)[][]
en rad slogs invarans namn, vänster, percent 0antal (vänster, percent 0) och radens belopp (höger, percent 50)
SUBTOTAL trycktes"Att betala", vänsteråterstående belopp, höger
betalningen klar"Växel", vänsterväxeln, höger ("0:00" för allt utom kontant med angivet belopp)

Kunddisplayens tillstånd journalförs inte och återskapas inte efter en omstart; det är en markör för “vad visas nu”, inget annat.

Begränsningarna:

  • 20 tecken per rad. Kassan kortar inte texten. Både webbfönstret (customer.js, layoutRow) och den fysiska displayen i Casio-appen (CaiosCustomerDisplay.layoutRow) lägger ut kolumnerna på 20 teckenpositioner och klipper varje kolumn vid sin plats - ett långt varunamn blir alltså avklippt.
  • Ingen grafik och inga stilar. DisplayColumn har ingen stil.
  • I row2 för en inslagen rad börjar antalet vid percent 0 och beloppet vid percent 50. Klienterna räknar en kolumns slut som nästa kolumns percent, så antalet får radens vänstra halva (10 tecken) och beloppet den högra, högerställt mot kanten. Både customer.js och Casio-appens layoutRow lägger alltså ut raden likadant. Ett belopp längre än 10 tecken klipps.
  • Antalet i row2 är det verkliga antalet (multiplikatorn som slogs in), trots att en kommentar i koden fortfarande säger att det alltid är 1.

Casio-appens skrivartjänst (android-casio-receipt-print) tar emot exakt den här formen på POST /display ({"row1": [...], "row2": [...]}, eller två strängar), men web_till skickar inte dit i dag.

terminal_display och meddelandet terminal_display

Under ett kortköp mot Nets visar kortterminalen uppmaningar (“Sätt i kort”, “Ange PIN”). De skickas inte genom Till, som står blockerad i kortbetalningen hela tiden, utan direkt från terminalens läsartråd som ett eget meddelande till alla WebSocket-klienter:

{"destination": "operator_display", "type": "terminal_display", "payload": {"text": "Ange PIN"}}

"text": null betyder att köpet är slut och texten ska bort. Samma text läggs också i fältet terminal_display i state, så att en pollande klient ser den. Eftersom state byggs av den blockerade kassatråden kan det fältet vara inaktuellt null under köpet; app.js låter därför state bara fylla i en terminaltext, aldrig ta bort den - bara terminal_display-meddelandets null tar bort den. Worldline-terminalen skickar inga sådana texter.

last_error

last_error hör till den enskilda händelsen, inte till kassans tillstånd. Det sätts bara i svaret på händelsen som orsakade det och är null i nästa svar. GET /state har alltid null.

För key_press bär det tre slags meddelanden, i den här prioritetsordningen:

  1. Ett fel från kassan själv (Till::handle), när tangenten inte kunde utföras - till exempel "Inget att betala - registrera minst en rad först", ett nekat kortköp eller en okänd varugrupp. Felet loggas också.
  2. Kontrollenhetens fel vid en betalning.
  3. Utfallet av SKVFS-exporten ("SKVFS-export skapad: <sökväg>" eller "SKVFS-export misslyckades: ...").

Texterna är skrivna för kassören och är på svenska. Kortterminalens och bokföringens fel vid en rapport når inte last_error; de loggas bara. För select_tab, select_line och device_event blir varje fel last_error.

Meddelanden från klienten

key_press

{"destination": "operator_display", "type": "key_press",
 "payload": {"scancode": 101, "event_type": "make", "caps_lock": false}}
{"destination": "operator_display", "type": "key_press",
 "payload": {"scancode": 101, "event_type": "break", "caps_lock": false}}
fälttypbetydelse
scancodeheltalTangentens kod. Klienten har redan översatt en knapp eller en fysisk tangent till en kod via config/panel_layout.json och config/web_keymap.json; kassan gör ingen tangentmappning, bara tolkning av koden.
event_type"make" eller "break"Nedtryckning respektive uppsläppning. Obligatoriskt. Saknas det eller har ett annat värde kastas meddelandet - kassan gissar inte, eftersom en felgissning tyst skulle förstöra spårningen av Shift/Ctrl/Cmd.
caps_lockboolOm Caps Lock var på. Valfritt, standard false.

Varje tangent är två meddelanden. Kassan gör ingenting på make utom att minnas vilka modifierare som var nedtryckta just då; funktionen utförs på break, med modifierarna från tangentens egen make. En knapp på skärmen skickar make och break direkt efter varandra.

Svaret är ett state-kuvert till alla anslutna flikar. Undantag: när ett kortköp mot Nets pågår och make för C (CLEAR) kommer, avbryts köpet i terminalen i stället, och meddelandet går aldrig till kassan. Över WebSocket skickas då inget tillstånd; över HTTP blir svaret {"cancelled": true}.

select_tab

{"destination": "operator_display", "type": "select_tab", "payload": {"tab_index": 5}}

Ett direkt klick på en flik i varupanelen. Till skillnad från att slå flikens nummer och trycka på fliktangenten rör det inte det inslagna beloppet.

select_line

{"destination": "operator_display", "type": "select_line", "payload": {"row_id": 7}}

Markerar en rad i kvittovyn (row_id från receipt_display_lines). Markeringen tar inte bort raden - det gör BACKA, som då tar bort den markerade raden. Ett felaktigt tryck på en pekskärm ska aldrig kunna makulera en rad, och en makulering ska alltid journalföras.

HTTP-motsvarigheterna

HTTP-vägarna tar inte kuvertet, bara innehållet i payload, och svarar med ett state-kuvert (som också sänds till alla WebSocket-flikar):

vägkropp
POST /key_press{"scancode": 101, "event_type": "break", "caps_lock": false}
POST /select_tab{"tab_index": 5}
POST /select_line{"row_id": 7}
POST /device_event{"device_type": "scanner", "value": "7300000000000"}
GET /state-

Saknade fält ger 400 med {"error": "..."}. Om kassatråden inte svarar blir det 500 med {"error": "till thread unavailable"}.

POST /device_event är vägen för seriella inmatningsenheter - streckkodsläsare, magnetkortsläsare, RFID - som receiptprinter vidarebefordrar. device_type används bara i felmeddelanden; alla enheter behandlas lika. Värdet tolkas först som en tillgodo-QR-kod (om kassan har en signeringsnyckel), annars som en streckkod: finns varan säljs den, annars går kassan till registering_product.

Statiska filer: / serverar operatörsklienten, /customer/ kundfönstret, /gl/ ett experimentellt WebGL-skal, och /config/... filerna i kassans konfigurationskatalog (till exempel panel_layout.json).

Exempel

Två rader är inslagna och operatören har tryckt SUBTOTAL:

{
  "destination": "operator_display",
  "type": "state",
  "payload": {
    "buffer": "0",
    "mode": "price",
    "prompt": null,
    "barcode": null,
    "terminal_display": null,
    "cart_lines": [
      {"group_name": "Kaffe", "amount_minor": 3500},
      {"group_name": "Bullar", "amount_minor": 1250}
    ],
    "subtotal_minor": 4750,
    "vat_minor": 950,
    "receipt_display_lines": [
      {"columns": [{"text": "Kaffe", "percent": 0.0, "align": "left"},
                   {"text": "35:00", "percent": 85.0, "align": "right"}],
       "row_id": 7, "style": "normal"},
      {"columns": [{"text": "Bullar", "percent": 0.0, "align": "left"},
                   {"text": "12:50", "percent": 85.0, "align": "right"}],
       "row_id": 8, "style": "normal"},
      {"columns": [{"text": "SUBTOTAL", "percent": 0.0, "align": "left"},
                   {"text": "47:50", "percent": 85.0, "align": "right"}],
       "row_id": null, "style": "bold_total"}
    ],
    "customer_display": {
      "row1": [{"text": "Att betala", "percent": 0.0, "align": "left"}],
      "row2": [{"text": "47:50", "percent": 0.0, "align": "right"}]
    },
    "selected_line_event_id": null,
    "active_tab_index": 0,
    "last_error": null
  }
}

(Momsen förutsätter 25 % på båda raderna: 700 + 250 öre.)

Direkt efter att raden “Kaffe” slogs in med multiplikatorn 2 såg kunddisplayen ut så här:

"customer_display": {
  "row1": [{"text": "Kaffe", "percent": 0.0, "align": "left"}],
  "row2": [{"text": "2", "percent": 0.0, "align": "left"},
           {"text": "70:00", "percent": 50.0, "align": "right"}]
}

vilket på 2x20 blir:

Kaffe
2              70:00

Journalminnet

Journalen är kassans fiskala minne. Varje sak som händer i kassan och som har betydelse i efterhand - en inslagen vara, en makulerad rad, en betalning, kontrollenhetens svar, en rapport - skrivs som en rad i journalen i samma ögonblick som den händer. Det är journalen, inte kassans minne eller databaser, som är sanningen om vad som registrerats: X- och Z-rapporternas siffror återskapas ur den vid omstart, och exporten till Skatteverket byggs ur den.

Därför gäller tre principer:

  • Bara tillägg. En rad skrivs aldrig om och tas aldrig bort. Ett misstag rättas med en ny händelse som pekar på den gamla (LINE_CORRECTED), inte genom att den gamla ändras. En ändrad fil går inte att skilja från ett manipulerat kassaregister.
  • Händelsen som den skedde, inte en tolkning. Två slag av samma vara är två LINE_ADDED, även om kvittot visar dem som en rad med antal 2. Kvittots sammanslagning är ren presentation.
  • Först journalen, sedan verkligheten. För de händelser som styr kassans tillstånd skrivs journalraden först, och kassan ändrar sitt tillstånd först när skrivningen lyckats.

Filformat

Journalen ligger i datakatalogens journal/. Det är NDJSON: en JSON-objekt per rad, avslutad med radbrytning, i UTF-8.

Det finns en fil per Z-period:

journal/journal_z000001.ndjson
journal/journal_z000002.ndjson
...

Namnet är journal_z följt av periodnumret med sex siffror (period_file_name). Själva Z_REPORT-händelsen är den sista som skrivs i en fil. Därefter fortsätter journalen i filen med Z-rapportens eget löpnummer (z_report_sequence_number) plus ett. Normalt är det samma sak som nästa fil i ordningen: fil N innehåller perioden som avslutas av Z-rapport nummer N, och nästa händelse hamnar i fil N+1.

Skillnaden syns efter ett avbrutet Z-försök (se Z_REPORT_PRINT_ATTEMPT). Det tar ett Z-nummer utan att stänga perioden, så nästa Z-rapport stänger fil N med nummer N+1, och journalen fortsätter i fil N+2. Filnumreringen får alltså samma lucka som Z-numren, och fil N+1 skapas aldrig. Alla läsare (omstarten, journalutskriften och SKVFS-exporten) hoppar över en fil som saknas. När kassan startar öppnar den filen för next_z_report_number i counters.db och fortsätter skriva i den.

Not för äldre journaler: Kassor före 2026-10-20 räknade alltid upp filnumret med ett efter en Z_REPORT. I sådana journaler följer filnumret inte Z-numret efter ett avbrutet Z-försök, och en period som löpte över en omstart kan vara delad på två filer. En läsare ska därför gå på händelserna, inte förutsätta att fil N slutar med Z-rapport N.

I samma katalog lägger kassan även SIE-filer och PDF-kopior av verifikationer (voucher_z000011.si, voucher_z000011.pdf) och SKVFS-exporter (skvfs_export_<tid>.xml). Läsarna tittar bara på filer som matchar journal_z*.ndjson.

Gemensamma fält

Varje rad är ett platt JSON-objekt. Tre fält finns alltid, först:

fälttypbetydelse
event_idheltalLöpnummer inom perioden. Börjar på 1 i varje ny fil. Sätts av journalen, aldrig av anroparen, och först när händelsen faktiskt accepterats.
event_typesträngHändelsetypen, till exempel "LINE_ADDED".
timestampsträngLokal tid utan tidszon, sekundprecision: "2026-10-06T16:59:26". Sätts vid själva skrivningen, inte när försöket påbörjades.

Resten av fälten är händelsens egna och ligger på samma nivå. Deras ordning är inte fast - de byggs ur en HashMap - så en läsare får aldrig förlita sig på fältordning. Belopp är heltal i öre (fält som slutar på _minor), momssatser är bråk (0.25, inte 25).

Det finns inget gemensamt kvittonummerfält. Händelser som hör till ett visst kvitto bär receipt_number, document_number eller hänger ihop genom ordningen i filen - se varje händelsetyp.

Ordning och perioder

En läsare ska läsa filerna i periodordning och raderna i filordning. Ordningen i filen är den ordning händelserna skrevs; event_id stiger normalt med den. Ett kvitto är inte en egen händelse utan ett förlopp:

LINE_ADDED            en rad slogs in           (event_id 7)
LINE_ADDED                                      (event_id 8)
LINE_CORRECTED        rad 7 makulerades
PAYMENT               betalning, receipt_number 35
CONTROL_UNIT_VERIFICATION   kontrollenhetens svar för 35
RECEIPT_LAYOUT        kvittot som det ser ut, document_number 35
RECEIPT_DISTRIBUTION  papper eller elektroniskt

Alla LINE_ADDED sedan förra PAYMENT hör till kvittot som den PAYMENT stänger. RECEIPT_DISTRIBUTION skrivs när kvittot lämnar “slussen” - när operatören trycker KVITTO (papper) eller går vidare till nästa kund (elektroniskt) - och kan därför komma en stund senare. Den saknar kvittonummer och gäller det senast betalda kvittot.

En dagsavslutning ser ut så här:

CARD_TERMINAL_REPORT     kortterminalens egen Z (om terminal finns)
Z_REPORT_PRINT_ATTEMPT   ett eller flera utskriftsförsök
Z_REPORT                 sista raden i filen
--- ny fil ---
BOOKKEEPING_VOUCHER      första raden i nästa period (om bokföring är på)

Verifikationen för Z-rapport N hamnar alltså som event_id 1 i fil N+1, eftersom den byggs efter att Z_REPORT redan rullat över journalen.

Kön (se nästa avsnitt) gör att ordningen i filen och event_id alltid följs åt: en köad händelse skrivs före allt som kommer efter den.

Hur inget går förlorat

Skrivningen är enkel: för varje händelse öppnas periodfilen i tilläggsläge, raden skrivs med en avslutande radbrytning, och filen tvingas ut till disken (sync_data) innan den stängs. Först när det lyckats räknas skrivningen som gjord. En journalrad som ett strömavbrott kan ta tillbaka är inte en fiskal registrering.

Utöver det skyddar ordningen och beslutsträdet i journal.rs:

  1. Försök skriva. Finns köade händelser (se punkt 3) skrivs de först, äldst först. Därefter skrivs den nya händelsen. Lyckas det får händelsen sitt event_id och sin tid, och räknas som inträffad. Går kön inte att skriva skrivs inte heller den nya händelsen; den går då samma väg som ett misslyckat försök.
  2. Misslyckas det frågar kassan operatören “Försök igen?”. Ja gör om försöket, så länge det behövs.
  3. Nej leder till frågan om händelsen ska köas. Ja lägger den i en kö i minnet (högst 10, MAX_QUEUE_SIZE), ger den ett event_id och låter kassan fortsätta som om den skrivits. Nej ångrar hela handlingen: raden slås inte in, betalningen sker inte, kvittonumret lämnas tillbaka. Är kön full stoppar kassan (HardStop).

Kön finns bara i minnet. Den töms vid nästa skrivning: varje gång journalen ska skriva något - ett nytt record() eller ett “försök igen” (retry()) - skrivs först alla köade händelser, i event_id-ordning. Filen innehåller därför händelserna i event_id-ordning utan luckor, och ingenting nytt hamnar i filen före en äldre köad händelse. Det som fortfarande kan gå förlorat är en kö som aldrig hann skrivas: stängs kassan medan händelser ligger i kön försvinner de, och deras event_id blir en lucka i slutet av filen.

Not för äldre journaler: Före 2026-10-20 skrevs kön aldrig ut. En köad händelse försvann när kassan stängdes, och händelser som skrevs efter den fick högre event_id. Journaler från den tiden kan alltså ha luckor i event_id mitt i en fil.

Detta gäller de styrande händelserna, där kassans tillstånd ändras först efter en lyckad skrivning: LINE_ADDED, LINE_CORRECTED, PAYMENT, PRODUCT_CREATED, X_REPORT, Z_REPORT, JOURNAL_PRINT_ATTEMPT och CHANGE_FUND_REGISTERED. Övriga händelser är observerande: de skrivs med ett enkelt försök, och skrivs inte alls om journalen redan väntar på ett beslut om en annan händelse.

Kontrollenheten är den andra spärren. PAYMENT skrivs innan kontrollenheten tillfrågas, men kvittot byggs, journalförs (RECEIPT_LAYOUT) och skrivs ut först när kontrollenheten svarat ja. Svarar den inte får operatören försöka igen; varje försök blir en egen CONTROL_UNIT_VERIFICATION. Ger operatören upp lämnas kvittonumret tillbaka och inget kvitto skapas - men PAYMENT ligger kvar i journalen, eftersom journalen bara växer. En läsare som vill veta om en betalning blev ett kvitto måste titta efter en CONTROL_UNIT_VERIFICATION med "success": true för samma receipt_number.

När kassan startar läser den igenom den aktuella periodfilen (rebuild_period_state_from_journal) och räknar som kassan gör under drift. Raderna (LINE_ADDED, med LINE_CORRECTED tillämpade) samlas tills ett kvitto godkänts: en PAYMENT följd av en CONTROL_UNIT_VERIFICATION för samma receipt_number med "success": true. Först då läggs kvittot till periodens momsackumulatorer, antal kvitton, sålda varor och tjänster och försäljningen per betalsätt (method). Ett kortköp som varken kunde verifieras eller återföras (felet börjar med "card charge could not be voided", se CONTROL_UNIT_VERIFICATION) räknas också, eftersom pengarna är dragna. Ett avvisat kvitto räknas inte; dess rader står kvar som ett öppet kvitto och räknas med den betalning som till slut godkänns. Innehåller filen ingen CONTROL_UNIT_VERIFICATION alls (journaler från innan händelsen fanns) räknas varje PAYMENT som ett kvitto.

Växelkassan återställs ur den senaste CHANGE_FUND_REGISTERED i filen. En rad som inte går att tolka - till exempel en halvskriven sista rad efter ett strömavbrott - hoppas över, och numreringen fortsätter efter det högsta event_id som finns i filen.

Läsarna

läsareläserhur
X/Z-rapport (till.rs, report.rs)indirektRapporterna räknar ur kassans ackumulatorer i minnet, som byggs upp ur journalen vid start (se ovan). Grand total kommer ur counters.db.
Journalutskrift (receipt_layout/journal.rs)alla händelser i perioderna från-tillVarje rad pretty-printas som JSON med två blankstegs indrag, direkt ur råtexten så att fältordningen bevaras, en utskriftsrad per textrad. Inget tolkas, ingenting märks om. Trasiga rader hoppas över.
SKVFS-export (skvfs_xml_export.rs)period 1 till aktuellBygger kvitton ur LINE_ADDED (+ äldre DISCOUNT_APPLIED) fram till PAYMENT, med LINE_CORRECTED tillämpade på samma sätt som vid omstarten (en borttagen rad försvinner, new_amount_minor ersätter radens belopp). Kompletterar med CONTROL_UNIT_VERIFICATION och RECEIPT_DISTRIBUTION, tar med X_REPORT/Z_REPORT och hämtar kontrollenhetens tillverkningsnummer ur den senaste CONTROL_UNIT_IDENTITY. Allt annat exporteras inte, enligt SKVFS 2021:16 3 kap. 3 §. Startas med koden 2027 + SUBTOTAL utanför ett kvitto.
Kontoplanens förhandsvisning (web_setup/konton.rs)senaste Z_REPORTBygger om rapportdata ur sales_by_group_and_rate för att visa hur kontona skulle bli.
Bokföring-Verifikationen byggs ur Z-rapportens data i minnet och journalförs som BOOKKEEPING_VOUCHER; den läses inte tillbaka ur journalen. R-GO Fortnox läser exportarkivet, inte journalen.

Händelsetyperna

JournalEventType i journal.rs har 18 typer. 16 av dem skrivs av kassan; RECEIPT_OPENED och RECEIPT_CLOSED finns i typen men skrivs aldrig. Dessutom förekommer tre typer i äldre journaler från Python-versionen, se sist.

händelseskrivs närstyrande
LINE_ADDEDen rad slås inja
LINE_CORRECTEDen rad makulerasja
PAYMENTett kvitto betalasja
CONTROL_UNIT_VERIFICATIONkontrollenheten svarar på en betalningnej
RECEIPT_LAYOUTett kvitto godkänts av kontrollenhetennej
RECEIPT_DISTRIBUTIONkvittot lämnar slussennej
X_REPORTX-rapport tasja
X_REPORT_PRINT_ATTEMPTefter X-rapportennej
Z_REPORTZ-rapport tas, rullar över periodenja
Z_REPORT_PRINT_ATTEMPTvarje utskriftsförsök av Z-rapportennej
JOURNAL_PRINT_ATTEMPTjournalutskriftja
CONTROL_UNIT_IDENTITYkassan startarnej
BOOKKEEPING_VOUCHERefter Z-rapporten, om bokföring är pånej
CARD_TERMINAL_REPORTkortterminalens X/Z/avstämningnej
PRODUCT_CREATEDen okänd streckkod läggs upp som varaja
CHANGE_FUND_REGISTEREDväxelkassan registrerasja
RECEIPT_OPENEDaldrig-
RECEIPT_CLOSEDaldrig-

Exemplen nedan är riktiga rader ur testjournaler, med namn, organisationsnummer, serienummer, kontrollkoder och terminal-id utbytta mot platshållare. Exemplen för RECEIPT_LAYOUT och *_PRINT_ATTEMPT är dessutom omskrivna till layoutens nuvarande form.

LINE_ADDED

En rad slogs in - antingen ett belopp på en varugruppstangent eller en vara från varuregistret via streckkod. En tryckning, en händelse.

fälttypbetydelse
product_group_numberheltalVarugruppen.
product_group_namesträngVarugruppens namn vid en gruppförsäljning; vid streckkodsförsäljning artikelns namn (fältnamnet är historiskt).
amount_minorheltalRadens totalbelopp i öre (antal × styckpris).
quantityheltalAntal. Finns bara när det inte är 1; saknas det är antalet 1.
unit_price_minorheltalStyckpris i öre. Finns bara tillsammans med quantity; saknas det är styckpriset lika med amount_minor.
vat_ratetalMomssatsen vid försäljningen, som bråk. Sparas så att en senare ändring av varugruppen inte ändrar historiken.
is_serviceboolOm gruppen räknas som tjänst (för X/Z:s antal varor och tjänster).
skusträngArtikelns identitet. Bara vid streckkodsförsäljning.
barcodesträngArtikelns första registrerade streckkod. Bara vid streckkodsförsäljning, och bara om artikeln har en.

Radens event_id är radens identitet: det är vad LINE_CORRECTED pekar på och vad displayen kallar row_id.

{"event_id":7,"event_type":"LINE_ADDED","timestamp":"2026-10-06T16:59:26","product_group_number":2,"product_group_name":"Grupp 2","vat_rate":0.25,"is_service":false,"amount_minor":12400}
{"event_id":83,"event_type":"LINE_ADDED","timestamp":"2026-10-13T10:25:25","unit_price_minor":4500,"product_group_number":6,"product_group_name":"Grupp 6","vat_rate":0.25,"is_service":false,"amount_minor":18000,"quantity":4}
{"event_id":135,"event_type":"LINE_ADDED","timestamp":"2026-09-29T17:31:39","amount_minor":20000,"product_group_number":1,"product_group_name":"Grupp 1","is_service":false,"sku":"1234567890999","vat_rate":0.25,"barcode":"1234567890999"}

LINE_CORRECTED

En tidigare inslagen rad på det pågående kvittot ändras eller tas bort. Den ursprungliga LINE_ADDED står kvar; det här är ett tillägg om den.

fälttypbetydelse
corrects_event_idheltalevent_id för den LINE_ADDED som rättas, i samma period.
removedbooltrue: raden är makulerad.
new_amount_minorheltalNytt belopp i öre för raden.

Händelsen har antingen removed eller new_amount_minor. I praktiken skrivs bara makuleringar: BACKA tar bort den markerade raden, eller den n:e raden bakifrån. Funktionen som skriver new_amount_minor (Till::correct_line) finns, och både omstartsåterskapandet och SKVFS-exporten läser fältet, men den anropas inte från något tangentflöde i dag. Makulering är bara möjlig innan betalningen påbörjats.

{"event_id":143,"event_type":"LINE_CORRECTED","timestamp":"2026-10-19T17:15:48","removed":true,"corrects_event_id":140}

PAYMENT

Kvittot betalas och får sitt kvittonummer. Stänger kvittot: alla LINE_ADDED sedan förra PAYMENT hör hit. Ett kvitto betalas alltid med ett betalsätt och en PAYMENT - delbetalning finns inte, bland annat för att SKVFS-exporten och periodåterskapandet antar en PAYMENT per kvitto.

fälttypbetydelse
methodsträngBetalsättets fasta kod: CASH, CARD, SWISH, INVOICE eller CREDIT (tillgodo). Översätts aldrig; visningsnamnet (KONTANT osv.) står bara på kvittot.
amount_minorheltalBetalt belopp i öre (kvittots återstående belopp).
tendered_minorheltal eller nullMottaget belopp vid kontant när operatören slagit in det; annars null. Alla andra betalsätt har null.
receipt_numberheltalKvittonumret (löpnummer ur counters.db, taget innan händelsen skrivs).

Vid kortbetalning har kortterminalen redan dragit pengarna när PAYMENT skrivs; kortets uppgifter journalförs inte som egna fält utan finns som textrader i RECEIPT_LAYOUT. INVOICE fakturerar inte - kassan lämnar ett underlag och skriver en följesedel.

Se avsnittet om kontrollenheten ovan: en PAYMENT som aldrig fick ett godkännande ligger kvar, och dess kvittonummer kan återanvändas av nästa betalning.

{"event_id":8,"event_type":"PAYMENT","timestamp":"2026-10-06T16:59:28","tendered_minor":null,"amount_minor":12400,"method":"CASH","receipt_number":35}
{"event_id":66,"event_type":"PAYMENT","timestamp":"2026-10-13T10:23:07","receipt_number":5,"amount_minor":56900,"method":"SWISH","tendered_minor":null}

CONTROL_UNIT_VERIFICATION

Kontrollenhetens (CleanCash) svar på en betalning. En per försök - blir det omförsök finns flera för samma kvitto, och det är den sista som gäller.

fälttypbetydelse
receipt_numberheltalKvittot det gäller.
successboolOm kontrollenheten godkände kvittot.
control_unit_idsträngDet id kontrollenheten själv skickar i svaret, om något; ofta tom sträng. Bara vid success: true.
control_codesträngKontrollkoden som skrivs på kvittot (59 tecken från en riktig CleanCash: 32 + ; + 26). Bara vid success: true.
errorsträngFelet. Bara vid success: false.

Ett specialfall: om operatören ger upp efter ett kortköp och kortköpet inte går att återkalla i terminalen, skrivs en extra CONTROL_UNIT_VERIFICATION med success: false och felet "card charge could not be voided after control unit rejection: ...". Försäljningen räknas då som gjord men inget kvitto skapas. Omstarten känner igen felet och räknar försäljningen på samma sätt.

{"event_id":9,"event_type":"CONTROL_UNIT_VERIFICATION","timestamp":"2026-10-06T16:59:28","success":true,"receipt_number":35,"control_code":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;BBBBBBBBBBBBBBBBBBBBBBBBBB","control_unit_id":""}
{"event_id":21,"event_type":"CONTROL_UNIT_VERIFICATION","timestamp":"2026-09-03T18:59:41","success":false,"error":"RH NAK: 003","receipt_number":15}

RECEIPT_LAYOUT

Kvittot som det ser ut - samma layout som skickas till skrivaren, inklusive loggans bildrad. Skrivs direkt efter ett godkännande från kontrollenheten, innan kvittot hamnar i slussen. Gör att journalen innehåller vad kunden faktiskt fick, inte bara siffrorna bakom.

fälttypbetydelse
receipt_widthsträng"flexible".
rowslistaKvittots rader, se nedan.
document_numberheltalKvittonumret, samma som PAYMENT:s receipt_number.
footerlista av strängarKvittots fotrader. Saknas när kvittot inte har några.

Fälten är layoutens egen JSON-form, exakt samma som kroppen till POST /print_layout i utskriftsformatet, bara utplattad bland händelsens övriga fält. Allt som står där gäller också här: tomma fält utelämnas (en enkolumnsrad har varken tabs_percent eller alignments, en flerkolumnsrad saknar align), och column_styles och footer följer med. En kolumnstil som det dubbelt breda beloppet på SUBTOTAL syns alltså i journalen. row_id sätts aldrig på ett utskrivet kvitto och förekommer därför inte.

{"event_id":94,"event_type":"RECEIPT_LAYOUT","timestamp":"2026-10-14T16:09:53","receipt_width":"flexible","document_number":9,"rows":[{"type":"image","source":"logo","align":"center","width_percent":60.0},{"type":"text","style":"dbl_size","columns":["KVITTO"],"align":"center"},{"type":"text","style":"normal","columns":["Kvitto nr 9"],"align":"center"},{"type":"text","style":"normal","columns":["Grupp 6","12:00"],"tabs_percent":[0.0,85.0],"alignments":["left","right"]},{"type":"text","style":"bold_total","columns":["SUBTOTAL","12:00"],"tabs_percent":[0.0,85.0],"alignments":["left","right"],"column_styles":[null,"dbl_width"]}],"footer":["Tack för ditt köp!"]}

(Förkortad: en riktig rad har alla kvittots rader, med företagsuppgifter, moms, betalning och kontrollkod.)

Not för äldre journaler: Före 2026-10-20 byggdes journalens form för hand. Där har varje textrad alltid align, tabs_percent och alignments (align är null i flerkolumnsform och tomma listor skrivs som []), medan column_styles, row_id och footer saknas. En läsare som ska klara båda formerna kan behandla null, [] och ett saknat fält som samma sak.

RECEIPT_DISTRIBUTION

Hur det betalda kvittot lämnade slussen. Lagen kräver att ett kvitto skapas, inte att det skrivs ut.

fälttypbetydelse
statussträng"PAPER" - operatören tryckte KVITTO (eller kassan är inställd på att alltid skriva ut). "ELECTRONIC" - operatören gick vidare utan att begära papper.
destinationsträngBara vid ELECTRONIC: vart kvittot gick. I dag alltid "grön papperskorg", en mottagare som tar emot men inte sparar.

Händelsen saknar kvittonummer och gäller det senast betalda kvittot. PAPER betyder att utskrift valdes; om skrivaren sedan lyckades journalförs inte. Ett kvitto som ligger i slussen när kassan stängs får ingen RECEIPT_DISTRIBUTION.

{"event_id":11,"event_type":"RECEIPT_DISTRIBUTION","timestamp":"2026-10-06T16:59:31","status":"PAPER"}
{"event_id":6,"event_type":"RECEIPT_DISTRIBUTION","timestamp":"2026-10-05T12:32:50","destination":"grön papperskorg","status":"ELECTRONIC"}

X_REPORT och Z_REPORT

Rapportens siffror, med samma fält för X och Z. Typen avgör vilken det är. X_REPORT ändrar ingenting; Z_REPORT avslutar perioden, och att den skrivs är det som rullar över journalen till nästa fil. Fälten motsvarar SKVFS 2014:9 7 kap. 2 § (bokstäverna a-v), plus sales_by_group_and_rate för bokföringen.

fälttypbetydelse
company_namesträngFöretagets namn (a).
organisation_numbersträngOrganisationsnummer med bindestreck (a).
produced_atsträngNär rapporten togs fram, samma form som timestamp (b).
register_designationsträngKassabeteckning (d).
total_sales_minorheltalPeriodens försäljning (e).
total_sales_by_main_group_minorobjektPer huvudgrupp (f). Huvudgrupper finns inte - alltid {}.
vat_by_ratelistaMoms per sats (g): {"vat_rate": tal, "vat_minor": heltal, "net_minor": heltal}.
sales_by_group_and_ratelistaPer varugrupp och momssats: {"group_number", "vat_rate", "debit_gross_minor", "debit_vat_minor", "credit_gross_minor", "credit_vat_minor"}. Inget SKVFS-fält; behövs för att kunna återskapa en verifikation ur journalen. Kreditsidan är alltid 0 eftersom returer inte finns.
change_fund_minorheltalVäxelkassa (h); 0 om ingen registrerats.
items_sold_countheltalAntal sålda varor (i) - summa av antal, inte antal rader.
services_sold_countheltalAntal sålda tjänster (j).
receipt_countheltalAntal kvitton (k).
drawer_openings_countheltalLådöppningar (l). Alltid 0.
receipt_copies_count, receipt_copies_total_minorheltalKvittokopior (m). Alltid 0.
training_mode_receipts_count, training_mode_total_minorheltalÖvningsläge (n). Alltid 0.
sales_by_payment_method_minorobjektPer betalsätt (o), nyckel = method-kod: {"CASH": 66600}.
return_count, return_total_minorheltalReturer (p). Alltid 0.
discount_total_minorheltalRabatter (q). Alltid 0.
other_reduction_count, other_reduction_total_minorheltalÖvriga minskningar (r). Alltid 0.
unfinished_sale_count, unfinished_sale_total_minorheltalOavslutade försäljningar (s). Alltid 0.
grand_total_sales_minorheltalGrand total försäljning (t), ur counters.db plus periodens.
grand_total_returns_minorheltalGrand total retur (u).
grand_total_net_minorheltalGrand total netto (v).
z_report_sequence_numberheltal eller nullZ-rapportens löpnummer; null på X.
control_unit_serial_numbersträngKontrollenhetens tillverkningsnummer; tom på X.
control_unit_modelsträngKontrollenhetens modell; tom på X.
control_unit_versionsträngKontrollenhetens version; tom på X.

Fält som anges “alltid 0” finns för att formatet ska vara komplett; kassan har ännu ingen funktion som räknar dem.

{"event_id":18,"event_type":"Z_REPORT","timestamp":"2026-10-06T16:49:30","total_sales_by_main_group_minor":{},"register_designation":"Kassa 1","control_unit_version":"1.1","other_reduction_count":0,"grand_total_sales_minor":1155310,"produced_at":"2026-10-06T16:49:30","training_mode_total_minor":0,"receipt_count":2,"z_report_sequence_number":11,"services_sold_count":0,"drawer_openings_count":0,"control_unit_serial_number":"EXEMPEL00000000001","other_reduction_total_minor":0,"sales_by_payment_method_minor":{"CASH":66600},"discount_total_minor":0,"receipt_copies_total_minor":0,"unfinished_sale_count":0,"training_mode_receipts_count":0,"change_fund_minor":0,"return_count":0,"organisation_number":"556000-0000","receipt_copies_count":0,"total_sales_minor":66600,"unfinished_sale_total_minor":0,"vat_by_rate":[{"vat_rate":0.25,"vat_minor":13320,"net_minor":53280}],"grand_total_returns_minor":0,"items_sold_count":3,"sales_by_group_and_rate":[{"group_number":2,"vat_rate":0.25,"debit_gross_minor":11100,"debit_vat_minor":2220,"credit_gross_minor":0,"credit_vat_minor":0},{"group_number":4,"vat_rate":0.25,"debit_gross_minor":55500,"debit_vat_minor":11100,"credit_gross_minor":0,"credit_vat_minor":0}],"control_unit_model":"Exempelmodell","grand_total_net_minor":1155310,"return_total_minor":0,"company_name":"Exempelbutiken AB"}

En X_REPORT har samma fält med "z_report_sequence_number":null och tomma kontrollenhetsfält.

X_REPORT_PRINT_ATTEMPT

Skrivs efter X_REPORT, med rapporten som den ritades. X-rapporten har ingen omförsöksdialog: ett försök, utfallet journalförs.

fälttypbetydelse
receipt_width, rows, document_numberRapportens layout, i samma form som RECEIPT_LAYOUT. document_number är 0.
successboolOm utskriftsförsöket lyckades.

Rapporter och journalutskrifter skrivs ut genom kassans PrintSink (receipt_sink.rs). När en skrivartjänst är inställd (config/printer_service.json) sätter både web_till och interactive dess layoutskrivare till receiptprinter (till::layout_printer_via_http): layouten skickas med POST /print_layout och avslutas med POST /feed_cut. success speglar alltså den riktiga utskriften: true när receiptprinter svarat 2xx på /print_layout. En misslyckad matning efteråt loggas men ändrar inte utfallet. Utan inställd skrivartjänst skriver PrintSink texten till kassans standardutdata, och då lyckas försöket nästan alltid. Samma sak gäller Z_REPORT_PRINT_ATTEMPT och JOURNAL_PRINT_ATTEMPT.

Not för äldre journaler: Före 2026-10-20 gällde success alltid den interna textutskriften till standardutdata, och den riktiga utskriften till receiptprinter gjordes efteråt utan att journalföras. I sådana journaler säger success: true alltså inget om papperet.

{"event_id":6,"event_type":"X_REPORT_PRINT_ATTEMPT","timestamp":"2026-10-06T16:52:12","receipt_width":"flexible","document_number":0,"success":true,"rows":[{"type":"text","style":"header","columns":["X-DAGRAPPORT"],"align":"center"}]}

(Förkortad.)

Z_REPORT_PRINT_ATTEMPT

Ett per utskriftsförsök av Z-rapporten. Z-rapporten måste skrivas ut innan Z_REPORT journalförs. Svarar skrivaren inte frågar kassan “Z-rapport: försök skriva ut igen?” och väntar på Ja eller Nej; varje försök journalförs. Ger operatören upp (Nej) skrivs ingen Z_REPORT och perioden förblir öppen - men Z-numret är redan taget och lämnas inte tillbaka, så löpnumret får en lucka, och därmed också journalfilernas numrering (se Filformat). Det är avsiktligt: luckan är spåret av ett övergivet försök.

fälttypbetydelse
receipt_width, rows, document_numberRapportens layout, i samma form som RECEIPT_LAYOUT. document_number är 0.
z_report_numberheltalZ-numret försöket gäller.
successboolOm försöket lyckades (se X_REPORT_PRINT_ATTEMPT om vad som räknas).

Om just den här loggningen inte kan skrivas överges den tyst, så att journalen är fri för den Z_REPORT som måste skrivas.

{"event_id":17,"event_type":"Z_REPORT_PRINT_ATTEMPT","timestamp":"2026-10-06T16:49:30","z_report_number":11,"document_number":0,"receipt_width":"flexible","success":true,"rows":[{"type":"text","style":"header","columns":["Z-DAGRAPPORT"],"align":"center"},{"type":"text","style":"normal","columns":["Löpnummer","11"],"tabs_percent":[0.0,50.0],"alignments":["left","left"]}]}

(Förkortad.)

JOURNAL_PRINT_ATTEMPT

Att journalen skrevs ut. Bara faktumet loggas, inte innehållet - det finns ju redan i journalen. Utskriften görs utan siffror för den aktuella perioden, eller med två Z-nummer för ett intervall.

fälttypbetydelse
from_zheltalFörsta perioden.
to_zheltalSista perioden (högst den aktuella).
successboolOm utskriften lyckades (se X_REPORT_PRINT_ATTEMPT om vad som räknas).

Händelsen är styrande: kan den inte skrivas får operatören samma omförsöksdialog som för en betalning, eftersom en journalutskrift i sig är ett spår av att journalen lästes.

{"event_id":3,"event_type":"JOURNAL_PRINT_ATTEMPT","timestamp":"2026-09-03T15:19:03","from_z":1,"to_z":3,"success":true}

CONTROL_UNIT_IDENTITY

Kontrollenhetens identitet, frågad vid varje start av kassan (CCSP IQ/IR), lyckad eller inte. SKVFS-exporten tar tillverkningsnumret ur den senaste lyckade, och vägrar exportera om ingen finns.

fälttypbetydelse
successboolOm enheten svarade.
manufacturing_idsträngTillverkningsnummer. Bara vid success: true.
protocol_versionsträngCCSP-protokollversion. Bara vid success: true.
firmware_versionsträngFirmware. Bara vid success: true.
errorsträngFelet. Bara vid success: false.
{"event_id":17,"event_type":"CONTROL_UNIT_IDENTITY","timestamp":"2026-10-06T17:01:02","success":true,"manufacturing_id":"EXEMPEL00000000001","firmware_version":"R1.07 L1","protocol_version":"2"}
{"event_id":96,"event_type":"CONTROL_UNIT_IDENTITY","timestamp":"2026-10-19T16:55:30","success":false,"error":"connect ws://127.0.0.1:8765/ws: Connection refused (os error 111)"}

BOOKKEEPING_VOUCHER

Verifikationen för bokföringen, byggd ur en Z-rapport. Själva verifikationen journalförs, inte bara filnamnet - filer kan tas bort, journalen finns kvar. Skrivs bara när kontoplanen är påslagen, och hamnar först i nästa periods fil.

fälttypbetydelse
successbooltrue om verifikationen byggdes och SIE-filen skrevs.
seriessträngVerifikationsserie från kontoplanen, t.ex. "Z".
numberheltalVerifikationsnummer = Z-rapportens löpnummer.
datesträngYYYYMMDD, ur rapportens produced_at.
textsträng"Dagsrapport Z<nr>, <kassabeteckning>", med (DIFFERENS) om den inte balanserade.
imbalance_minorheltalDebet minus kredit innan differensraden lades till; 0 om den balanserade av sig själv.
sie_filesträngSIE-filens namn i journalkatalogen, t.ex. "voucher_z000011.si".
lineslistaKonteringsraderna: {"account": sträng, "debit_minor": heltal, "credit_minor": heltal, "text": sträng}.
errorsträngFinns när något gick fel.

Två former: kunde verifikationen inte byggas alls (t.ex. ett fel i kontoplanen) innehåller händelsen bara "success": false och error. Byggdes den men SIE-filen kunde inte skrivas finns alla fält, med "success": false och error. Z-rapporten fälls aldrig av ett fel här.

{"event_id":1,"event_type":"BOOKKEEPING_VOUCHER","timestamp":"2026-10-06T16:49:30","date":"20261006","series":"Z","imbalance_minor":0,"lines":[{"account":"1910","debit_minor":66600,"credit_minor":0,"text":"Försäljning KONTANT"},{"account":"2611","debit_minor":0,"credit_minor":13320,"text":"Utgående moms 25 %"},{"account":"3001","debit_minor":0,"credit_minor":53280,"text":"Försäljning 25 %"}],"text":"Dagsrapport Z11, Kassa 1","number":11,"sie_file":"voucher_z000011.si","success":true}

CARD_TERMINAL_REPORT

En rapport som körts i kortterminalen: dess X, dess Z eller en avstämning mot banken. Terminalens siffror sparas separat från kassans så att de kan jämföras. Kassans X kör terminalens X först, kassans Z kör terminalens Z först (innan något fiskalt börjar), och avstämningen har en egen tangent. En kassa utan kortterminal journalför ingenting här.

fälttypbetydelse
kindsträng"X", "Z" eller "RECONCILIATION".
successboolOm terminalen levererade rapporten.
sitesträngTerminalens butiks-id. Vid success: true.
sessionsträngTerminalens period/session. Vid success: true.
terminal_timestampsträngTerminalens egen tid, som terminalen skickar den (YYYYMMDDHHMMSS i exemplen). Vid success: true.
issuerslistaPer kortutgivare: {"issuer_id": sträng, "transaction_count": heltal, "total_minor": heltal, "cash_minor": heltal, "deposit_minor": heltal}. cash_minor och deposit_minor ingår redan i total_minor.
print_lineslista av strängarTerminalens egen utskrift, rad för rad, oförändrad.
infosträngFritext från värden. Bara när terminalen skickade någon.
errorsträngFelet. Bara vid success: false.
{"event_id":273,"event_type":"CARD_TERMINAL_REPORT","timestamp":"2026-10-02T17:30:42","kind":"RECONCILIATION","site":"000000","terminal_timestamp":"20261002173041","issuers":[{"issuer_id":"05","transaction_count":0,"total_minor":0,"cash_minor":0,"deposit_minor":0},{"issuer_id":"41","transaction_count":9,"total_minor":118700,"cash_minor":0,"deposit_minor":0}],"success":true,"print_lines":["TERM: 00000000-000000","2026-10-02 17:30","VALUTA: SEK","AVST. PERIOD: 439","","DAGSAVSLUT","","STANDARD               9","BELOPP=          1187,00"],"session":"439"}
{"event_id":4,"event_type":"CARD_TERMINAL_REPORT","timestamp":"2026-10-06T16:52:12","error":"kortterminalen är inte ansluten","success":false,"kind":"X"}

(Den första raden är förkortad: en utgivare och terminalens sista utskriftsrader är borttagna.)

PRODUCT_CREATED

En okänd streckkod lästes in och operatören lade upp den som vara (pris och varugrupp). Varuregistret i SQLite får ändras; journalen är beviset på att en vara skapades och hur den såg ut då. Skrivs omedelbart före den LINE_ADDED som säljer varan.

fälttypbetydelse
skusträngArtikelns identitet - den lästa koden.
barcodesträngDen lästa streckkoden.
product_group_numberheltalVarugruppen.
namesträngVarans namn, ärvt från varugruppen.
sale_price_minorheltalFörsäljningspris i öre.
purchase_price_minorheltalInköpspris i öre, räknat ur gruppens marginal.
margin_percenttalMarginal i procent.
vat_ratetalMomssats som bråk.
discountableboolOm varan får rabatteras.

Bara uppläggning från kassan skrivs. Varor som skapas, ändras eller tas bort i inställningsprogrammet (web_setup, produkter.rs) skriver ingen journalhändelse alls - trots att kommentaren vid ProductCreated i journal.rs säger att varje ändring i artikelregistret ska journalföras.

{"event_id":134,"event_type":"PRODUCT_CREATED","timestamp":"2026-09-29T17:31:39","purchase_price_minor":15385,"barcode":"1234567890999","sku":"1234567890999","margin_percent":30.0,"sale_price_minor":20000,"vat_rate":0.25,"discountable":true,"name":"Grupp 1","product_group_number":1}

CHANGE_FUND_REGISTERED

Växelkassan för perioden. Får registreras om fritt fram till periodens första köp, sedan är den låst tills nästa Z-rapport.

fälttypbetydelse
change_fund_minorheltalVäxelkassan i öre.
replaced_minorheltalDet tidigare registrerade beloppet, när en registrering ersätter en annan i samma period.

Händelsen är styrande: kassan sätter växelkassan i minnet först när händelsen skrivits. Misslyckas skrivningen får operatören samma omförsöksdialog som för en betalning, och lyckas ett senare “försök igen” (eller köas händelsen) registreras beloppet då. Vid omstart återställs växelkassan ur den senaste CHANGE_FUND_REGISTERED i periodens fil.

{"event_id":2,"event_type":"CHANGE_FUND_REGISTERED","timestamp":"2026-10-06T16:51:51","change_fund_minor":111100}
{"event_id":3,"event_type":"CHANGE_FUND_REGISTERED","timestamp":"2026-10-06T16:52:08","replaced_minor":111100,"change_fund_minor":123400}

RECEIPT_OPENED och RECEIPT_CLOSED

Finns i JournalEventType men skrivs aldrig. Ett kvittos början och slut framgår av LINE_ADDED och PAYMENT.

Äldre typer: DISCOUNT_APPLIED, X_REPORT_LAYOUT, Z_REPORT_LAYOUT

Journaler från den tidigare Python-versionen (ecrlogik/journal.py) kan innehålla tre typer som Rust-kassan inte skriver. De syns bland annat i testjournaler/.

  • DISCOUNT_APPLIED - en procentrabatt på en rad: corrects_event_id (radens LINE_ADDED), percent, discount_minor. SKVFS-exporten läser den fortfarande och lägger rabatten på raden. Rabatt finns inte i Rust-kassan.
  • X_REPORT_LAYOUT, Z_REPORT_LAYOUT - rapportens layout (receipt_width, rows), ersatta av layouten i *_PRINT_ATTEMPT.

Dessa journaler skrevs också med blanksteg efter : och ,; läsare ska inte förutsätta kompakt JSON.

Värt att veta för en läsare

  • Värdehandlingar journalförs inte som egna händelser. Utfärdade och inlösta tillgodokvitton finns i values.db. I journalen syns en inlösen bara som PAYMENT med "method": "CREDIT".
  • Kunddisplayen och displaytillståndet journalförs inte.
  • Omstart läser den öppna periodens fil. Momsackumulatorerna, antalen, försäljningen per betalsätt och växelkassan återskapas ur den nyaste journalfilen om den inte är stängd med en Z_REPORT, annars ur filen för next_z_report_number (journal::open_period_number). Efter ett avbrutet Z-försök har next_z_report_number redan gått förbi den öppna periodens fil; då fortsätter kassan i den öppna filen.
  • Ett öppet kvitto kommer tillbaka vid omstart. LINE_ADDED efter det senaste godkända kvittot, med LINE_CORRECTED tillämpade, läggs tillbaka på kvittot med sina event_id. Raderna står alltså kvar i kassan och kommer med på nästa PAYMENT - samma kvitto som omstarten och SKVFS-exporten bygger ur journalen. Före 2026-10-21 försvann raderna ur kassan men räknades ändå in i nästa betalda kvitto vid omstart.
  • Elektroniska kvitton i SKVFS-exporten. Exporten markerar ett kvitto som elektroniskt (ElektronisktKassakvitto) när RECEIPT_DISTRIBUTION har status "ELECTRONIC", eller ett värde som börjar på elektron i äldre journaler.