{"id":29,"date":"2026-05-18T20:00:00","date_gmt":"2026-05-18T18:00:00","guid":{"rendered":"https:\/\/airex.se\/blogg\/kassaapparat-nar-lagen-ritar-produkten\/"},"modified":"2026-05-18T20:00:00","modified_gmt":"2026-05-18T18:00:00","slug":"kassaapparat-nar-lagen-ritar-produkten","status":"publish","type":"post","link":"https:\/\/airex.se\/blogg\/kassaapparat-nar-lagen-ritar-produkten\/","title":{"rendered":"Kassaapparaten: n\u00e4r lagen ritar produkten"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Ett kassasystem ser ut som en webbshop med f\u00e4rre sidor. Det \u00e4r det inte. En webbshop f\u00e5r misslyckas \u2014 kunden f\u00f6rs\u00f6ker igen. En kassa har en m\u00e4nniska framf\u00f6r sig med en kortterminal i handen och en k\u00f6 bakom sig, och den f\u00e5r inte tveka.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Det h\u00e4r handlar om <a href=\"https:\/\/kassaapparat.se\/\">kassaapparat.se<\/a>, och om att det sv\u00e5raste inte var tekniken.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Lagen ritar produkten<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I Sverige finns en gr\u00e4ns som avg\u00f6r allt: den som s\u00e4ljer mot kontant betalning f\u00f6r mer \u00e4n fyra prisbasbelopp om \u00e5ret m\u00e5ste ha ett <strong>certifierat kassaregister med typgodk\u00e4nd kontrollenhet<\/strong>. Under gr\u00e4nsen \u2014 och f\u00f6r m\u00e5nga ideella f\u00f6reningar \u2014 g\u00e4ller inte kravet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Den gr\u00e4nsen \u00e4r inte en detalj i kravlistan. Den <em>\u00e4r<\/em> produktstrategin.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ovanf\u00f6r den finns en mur av certifiering, h\u00e5rdvara och myndighetskrav som kostar pengar att ta sig igenom. Under den finns f\u00f6reningar och sm\u00e5 verksamheter som beh\u00f6ver exakt samma funktioner \u2014 s\u00e4lja, kvittera, st\u00e4mma av dagen \u2014 men inget av regelverket. Det \u00e4r ett ovanligt tydligt l\u00e4ge: en fri niv\u00e5 under gr\u00e4nsen kostar mig n\u00e4stan ingenting att erbjuda, och en betald niv\u00e5 ovanf\u00f6r den har ett sj\u00e4lvklart existensber\u00e4ttigande, eftersom den l\u00f6ser n\u00e5got kunden \u00e4nd\u00e5 \u00e4r tvungen att l\u00f6sa.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bygger man i ett reglerat omr\u00e5de \u00e4r regelverket f\u00e4rdplanen. Det tog mig l\u00e4ngre tid att inse \u00e4n det borde.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">&#8221;Helt gratis&#8221; var charmigt och l\u00e5ste allt<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00f6rsta versionen av landningssidan sa att allt var gratis. Det k\u00e4ndes gener\u00f6st och det st\u00e4mde \u2014 systemet hade en enda anv\u00e4ndare, en cateringverksamhet som st\u00e5r mig n\u00e4ra.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Problemet med ett offentligt l\u00f6fte om gratis \u00e4r att det cementeras i samma sekund det f\u00e5r sin f\u00f6rsta riktiga anv\u00e4ndare. G\u00e5r det att ta tillbaka? Formellt ja. I praktiken blir det ett svek mot dem som kom in p\u00e5 det l\u00f6ftet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Det var allts\u00e5 sista chansen att positionera om, och beslutet blev tre niv\u00e5er i st\u00e4llet f\u00f6r en: en fri niv\u00e5 med <strong>h\u00e5rda kvoter<\/strong> \u2014 en f\u00f6rs\u00e4ljningsplats, ett begr\u00e4nsat antal produkter och anv\u00e4ndare, tre m\u00e5naders rapporthistorik \u2014 och tv\u00e5 betalda ovanf\u00f6r.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Kvoter i st\u00e4llet f\u00f6r &#8221;obegr\u00e4nsat gratis&#8221; \u00e4r inte sn\u00e5lhet. Det \u00e4r det som g\u00f6r att en verksamhet som borde betala inte kan bo kvar p\u00e5 fribiljetten, och det \u00e4r den enda anledningen till att fribiljetten kan forts\u00e4tta finnas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Priserna l\u00e4mnades f\u00f6rst tomma. Att gissa ett pris och skriva ut det \u00e4r v\u00e4rre \u00e4n att skriva att det kommer \u2014 tomrummet gav n\u00e5gra veckor att lyssna. N\u00e4r de v\u00e4l sattes blev de <em>l\u00e5gt<\/em>, av ett enda sk\u00e4l: det \u00e4r betydligt l\u00e4ttare att h\u00f6ja ett pris \u00e4n att s\u00e4nka det.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">L\u00f6ften utan kod bakom sig<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Och h\u00e4r gjorde jag felet som \u00e4r v\u00e4rt hela det h\u00e4r inl\u00e4gget.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Kvoterna stod p\u00e5 landningssidan. De fanns inte i koden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En bes\u00f6kare kunde allts\u00e5 l\u00e4sa att gratisniv\u00e5n rymmer femtio produkter, registrera sig, l\u00e4gga in femhundra, och ingenting hade h\u00e4nt. Marknadsf\u00f6ringen hade skrivit checkar som systemet inte kunde l\u00f6sa in, och det \u00e4r exakt s\u00e5 f\u00f6rtroende raseras \u2014 inte genom att man lovar f\u00f6r mycket, utan genom att l\u00f6ftet och verkligheten aldrig kopplades ihop.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">R\u00e4ttningen var att flytta ner planerna i databasen: en kolumn p\u00e5 f\u00f6retaget, en modul med kvoterna, och kontroller i de anrop som skapar resurser. F\u00f6rs\u00f6ker man passera gr\u00e4nsen svarar servern med en tydlig statuskod och texten om att uppgradera \u2014 i sj\u00e4lva gr\u00e4nssnittet, inte i finstilt text.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Samtidigt fick den enda befintliga anv\u00e4ndaren en flagga som undantar dem fr\u00e5n kvoterna. Den som var med fr\u00e5n b\u00f6rjan ska inte straffas av att villkoren \u00e4ndrades.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Buggen som bara finns i fleranv\u00e4ndarsystem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">En s\u00e4kerhetsgenomg\u00e5ng hittade tre allvarliga fynd. Det mest l\u00e4rorika handlade om identitet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Systemet \u00e4r fleranv\u00e4ndarbaserat: samma person kan finnas i flera f\u00f6retag. Det var l\u00f6st genom en rad per f\u00f6retag \u2014 vilket \u00e4r en fullt rimlig modell, \u00e4nda tills man kommer till l\u00f6senord.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ett l\u00f6senordsbyte uppdaterade n\u00e4mligen <em>en<\/em> rad. De andra beh\u00f6ll det gamla l\u00f6senordet. Allts\u00e5: en anv\u00e4ndare som blivit av med sitt konto, eller som bytt l\u00f6senord efter en misst\u00e4nkt l\u00e4cka, kunde fortfarande logga in \u2014 i ett annat f\u00f6retag, med den gamla uppgiften. Ingen del av fl\u00f6det var uppenbart fel. Felet l\u00e5g i att identiteten fanns i flera exemplar medan alla trodde att den fanns i ett.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Fixen var en gemensam funktion som s\u00e4tter l\u00f6senordet p\u00e5 <em>samtliga<\/em> rader med samma e-postadress, anropad fr\u00e5n alla fyra st\u00e4llen d\u00e4r ett l\u00f6senord kan \u00e4ndras. Plus deterministisk sortering vid inloggning, s\u00e5 att det inte beror p\u00e5 databasens hum\u00f6r vilken rad som r\u00e5kar v\u00e4ljas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L\u00e4xan: <strong>n\u00e4r samma person kan finnas flera g\u00e5nger i din datamodell har du en identitetsmodell, vare sig du best\u00e4mt dig f\u00f6r det eller inte.<\/strong> Best\u00e4mmer man sig inte blir svaret olika p\u00e5 olika st\u00e4llen i koden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Det som verkligen tog tid<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Inte kassavyn. Inte lagerhanteringen. Inte kunddisplayen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Det som tog tid var allt runtomkring som g\u00f6r att n\u00e5gon v\u00e5gar anv\u00e4nda det: integritetspolicy, ett personuppgiftsbitr\u00e4desavtal att signera, en statussida att peka p\u00e5 n\u00e4r n\u00e5got strular, en hj\u00e4lpsida som faktiskt svarar p\u00e5 fr\u00e5gor, och en supportadress som inte \u00e4r ett svart h\u00e5l.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ingen av de sakerna syns i produkten. Alla saknas omedelbart om de inte finns \u2014 och en f\u00f6rening som ska hantera medlemmars betalningar kommer att fr\u00e5ga efter dem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Vad jag skulle gjort annorlunda<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Best\u00e4mt aff\u00e4rsmodellen f\u00f6re landningssidan.<\/strong> Att skriva &#8221;gratis&#8221; innan man vet vad det ska kosta \u00e4r att fatta beslutet \u00e4nd\u00e5 \u2014 bara utan att t\u00e4nka efter f\u00f6rst.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Aldrig publicerat en gr\u00e4ns som inte gick att \u00f6vertr\u00e4da.<\/strong> Kvoter p\u00e5 en s\u00e4ljsida utan kod bakom \u00e4r inte marknadsf\u00f6ring, det \u00e4r en l\u00f6gn med f\u00f6rdr\u00f6jd verkan.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>L\u00e4st regelverket f\u00f6rst.<\/strong> Gr\u00e4nsen p\u00e5 fyra prisbasbelopp hade gett hela produktstrukturen p\u00e5 en eftermiddag, i st\u00e4llet f\u00f6r efter ett halv\u00e5r av gissningar om vad folk kunde t\u00e4nkas vilja betala f\u00f6r.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Att bygga systemet gick fort. Att f\u00f6rst\u00e5 vad det skulle vara tog mycket l\u00e4ngre tid \u2014 och den delen kan ingen agent g\u00f6ra \u00e5t mig.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Ett kassasystem ser ut som en webbshop med f\u00e4rre sidor. Det sv\u00e5raste var inte tekniken utan gr\u00e4nsen p\u00e5 fyra prisbasbelopp \u2014 och att landningssidan lovade kvoter som koden inte kunde h\u00e5lla.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-29","post","type-post","status-publish","format-standard","hentry","category-bygget"],"_links":{"self":[{"href":"https:\/\/airex.se\/blogg\/wp-json\/wp\/v2\/posts\/29","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/airex.se\/blogg\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/airex.se\/blogg\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/airex.se\/blogg\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/airex.se\/blogg\/wp-json\/wp\/v2\/comments?post=29"}],"version-history":[{"count":0,"href":"https:\/\/airex.se\/blogg\/wp-json\/wp\/v2\/posts\/29\/revisions"}],"wp:attachment":[{"href":"https:\/\/airex.se\/blogg\/wp-json\/wp\/v2\/media?parent=29"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/airex.se\/blogg\/wp-json\/wp\/v2\/categories?post=29"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/airex.se\/blogg\/wp-json\/wp\/v2\/tags?post=29"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}