Preskoči na sadržaj
XPay.ba

Status, uživo iz sistema

Pitamo
sistem.

Prva provjera je poslana. Odgovor obično stigne za manje od sekunde.

Verzije

Šta je dodano,
promijenjeno i popravljeno.

Isti tekst koji stoji u repozitoriju, pa se ne može razići od onoga što je pušteno.

0.76.59

23. septembar 2026.

Trenutna

Ispravljeno

  • Spora gradnja slika više ne guta provjere. Provjera na GitHubu je imala jedan red za cijeli posao, a taj red drži i najsporiji korak u njemu: gradnja kontejnerskih slika zna trajati dvadeset pet minuta. Dok ona traje, svaki novi commit čeka, a red pušta samo jedan na čekanju, pa svaki sljedeći push otkaže onaj prije sebe. Tri commita zaredom su tako otkazana a da nisu ni provjerena. Sada svaki posao ima svoj red: provjera čeka provjeru, slike čekaju slike, i dokaz koji ništa ne propušta ne može zaustaviti provjeru koja propušta sve.

0.76.58

23. septembar 2026.

Novo

  • xpay.rs poslužuje isti sajt, sa svojim certifikatom i preusmjerenjem sa HTTP-a. Srbija još nije otvorena za posao, pa je to zasad sajt i ništa više.

Ispravljeno

  • Adresa na kojoj se sajt otvori više ne odlučuje da li radi. Skripte sajta zovu API na adresi koja se ugradi pri buildu, bez obzira ko je stranicu poslužio, pa svako ime na kojem sajt odgovara mora biti dozvoljeno. Nije bilo: posjetilac koji ukuca www ispred imena imao je status stranicu i formu za probu koje ne rade, a greška se vidjela samo u konzoli pretraživača. Popravljeno za www i za dodatne domene, koje se sada čitaju iz XPAY_ALT_DOMAINS pa ih ponovno pokretanje instalacije ne briše.

0.76.57

23. septembar 2026.

Novo

  • Srbija na sajtu, u budućem vremenu. Naslovna, stranica za ugostiteljstvo i cijene kažu da XPay stiže u Srbiju i pozivaju prve lokale da se jave. Namjerno nije sadašnje vrijeme: dinar, računi od osamnaest cifara, PIB, stope od 20 i 10 posto i kod koji čitaju aplikacije banaka u Srbiji su napravljeni, ali lokala u Srbiji još nema, a tvrdnju koju posjetilac iz Beograda provjeri i ne nađe ne vrijedi napisati.
  • Cijene za Srbiju u dinarima, isti planovi i isti iznosi: Flex uz 3 RSD po transakciji, Start 2.900, Business 5.900, Pro 11.900 RSD mjesečno, i ugostiteljski paket 2.900 RSD po poslovnici. Stoje uz tabelu a ne u njoj, dok se tržište ne otvori.
  • Fiskalizacija se sada objašnjava po zemlji, jer nije ista stvar. U BiH zakon dolazi do avgusta 2027 i XPay već vodi evidenciju koju nabraja. U Srbiji je fiskalizacija na snazi i XPay nije sistem koji je zadovoljava: lokal zadrži uređaj koji ima, a XPay stoji pored njega isto kao pored kase u Bosni. To piše otvoreno, jer ko to mora da zaključuje, zaključiće ono što mu odgovara.
  • Stranici za banke dodano šta Srbija znači njima: IPS QR kod Narodne banke Srbije je javno objavljen, za razliku od profila za BiH. Profil koji banka u BiH potvrdi nije jednokratan posao nego podešavanje u sistemu koji radi u dvije zemlje.

0.76.56

23. septembar 2026.

Novo

  • Link koji radi i nakon što je plaćen. Račun je jedno plaćanje: izda se, plati i gotov je. Link je ono drugo što firmi treba, a nije imala: jedna adresa koja i dalje radi. Upisnina na stranici škole, donacija, „platite ovdje" u podnožju fakture, kartica koju majstor ostavi. Svako otvaranje diže svoj račun sa svojom referencom, pa četrdeset ljudi koji plate jedan link budu četrdeset priliva koje uparivanje razlikuje, a ne jedan na koji se gleda ručno.
  • Fiksni ili otvoreni. Kod fiksnog je iznos izjava firme, ne prijedlog: šta god platilac pošalje, ignoriše se, jer bi inače svaki odštampani link bio formular koji svako popuni sam sebi. Kod otvorenog platilac upisuje iznos, unutar granica koje je firma postavila; bez granica je zatipkanih 7480 umjesto 74,80 nalog za sedam hiljada, a čovjek to sazna tek u svojoj banci.
  • Iznos se ne može mijenjati na postojećem linku, namjerno. Link koji je već odštampan, poslan ili zalijepljen na izlog je obećanje koliko košta. Nova cijena je novi link.
  • Račun se može poslati na telefon. Kupcu koji nije u prostoriji ode poruka s iznosom i adresom stranice koju taj račun već ima, pa plati iz svoje bankarske aplikacije. Ništa novo se ne izdaje, pa je račun poslan dvaput i dalje jedan račun.
  • Kanal za poruke, bez imena provajdera u kodu. Pošta ima SMTP koji svi govore; SMS nema ništa slično, pa je gateway opisan u postavkama: adresa, jedno zaglavlje s kredencijalom i kako taj gateway zove svoja tri polja. Promjena provajdera je promjena postavki, ne izdanje. Podrazumijevano je isključen i tada odbija i kaže zašto, jer poruka koja tiho nestane je gore od poruke koja nije poslana.
  • Broj telefona se čita onako kako ga ljudi pišu, svih šest načina, a fiksni se odbija: gateway bi ga uzeo i naplatio, a niko ga ne bi pročitao.

Sigurnost

  • Šezdeset četiri napada na svakoj gradnji. Nova provjera vrti prave pokušaje zloupotrebe protiv žive aplikacije i svaka prolazi samo kad je napad odbijen: rute bez kredencijala, tokeni koji nisu ono što tvrde, kredencijal jedne firme nad tuđim računom, poseg iznad svoje uloge, ulaz koji treba pročitati kao kod, šta nikad ne smije nazad, gdje platforma odbija da bude uperena, opterećenje koje nije upotreba, i pogađanje na vratima.
  • Prvi nalaz istog dana: jedan NUL bajt u parametru stizao je do upita i vraćao grešku servera. Sada se odbija uredno, s imenom polja.
  • Ovo nije nezavisan pen test i nigdje se tako ne predstavlja. Ko je pisao pravila, pisao je i napade, pa ne može naći slučaj kojeg se niko nije sjetio. To piše i u dokumentu za banke, odmah do popisa.

Za programere

  • Platforma sada pita u kojoj je državi firma umjesto da pretpostavlja: novac, sat, jezik, QR dijalekt, oblik broja računa, poreski broj, stope PDV-a i odnos prema zakonu o fiskalizaciji na jednom mjestu. BA je podrazumijevano i ponaša se tačno kao do sada; država bez napisanog profila se odbija po imenu umjesto da tiho dobije bosanska pravila.
  • docs/en/MARKETS.md kaže šta od svega pripada kojem tržištu i šta namjerno nedostaje.
  • scripts/pentest.mjs u CI-ju, poslije pregledača, jer namjerno prazni korpu prijava za svoju adresu.

0.76.55

23. septembar 2026.

Ispravljeno

  • Odsječen odgovor više ne prolazi kao lista. Provjera oblika je prihvatala odgovor u kojem je valjan makar jedan red, pa bi prenos prekinut na pola bio upisan kao uža lista Cloudflareovih raspona; posjetioci izvan tog užeg dijela bi opet svi računali kao jedna adresa. Uz to je i sam neuspjeh curl-a bio progutan, pa se prekinut prenos nije ni primjećivao. Sada se čita izlazni status, i traži se najmanje deset IPv4 i pet IPv6 raspona: dovoljno ispod onoga što Cloudflare objavljuje da povlačenje jednog raspona ne bude kvar, i dovoljno iznad onoga što ostane od odsječenog odgovora.

0.76.54

23. septembar 2026.

Ispravljeno

  • Lista Cloudflare raspona se više ne zakucava. Server prepoznaje pravu adresu gosta po tome što veza dolazi s nekog od Cloudflareovih raspona, a ta lista je bila prepisana jednom i ostala takva. Kad Cloudflare doda novi raspon, posjetioci koji stignu kroz njega bi svi računali kao jedna adresa, ograničavanje zahtjeva bi za njih prestalo vrijediti, a u dnevnik bi se umjesto čovjeka upisivao Cloudflare. Ništa ne bi prijavilo grešku. Instalacija sada listu povuče s Cloudflarea, a zakucana ostaje kao rezerva ako mreže nema, pa mašina bez interneta dobije ono što bi i inače imala.
  • doctor.sh sada tu listu poredi s Cloudflareovom i imenuje šta fali, pa je zastarjelost nešto što se vidi umjesto da se sumnja.
  • Pri pisanju te provjere nađena je greška koja bi je učinila beskorisnom: Cloudflareov odgovor ne završava prelomom reda, pa se zadnji IPv4 i prvi IPv6 raspon spoje u jedan red i oba ispadnu. Provjera bi svaki put javljala da su dva raspona zastarjela, a nisu. Sada se svaka lista čita zasebno; provjereno na serveru, javlja aktuelnih 22.
Prikaži još 339 starijih verzija

0.76.53

23. septembar 2026.

Promijenjeno

  • Stranica, konzola i bankarska aplikacija idu kroz Cloudflare. IP servera više ne stoji javno u DNS-u, saobraćaj prolazi kroz rubnu mrežu, i telefon na slaboj vezi dobija HTTP/3.
  • Pošta i cPanel ostaju van toga, namjerno. Cloudflare ne proxya SMTP ni FTP, a cPanelove servise drži na portovima koje dijelom i ne proxya, pa bi ih narandžasti oblak ili oborio ili im tiho prekinuo obnovu certifikata. Skripta za podešavanje sada odbija da upali proxy na tim imenima čak i kad joj se izričito kaže, zajedno s hostom za bankarske sisteme: tamo nginx traži klijentski certifikat, a kroz proxy koji prekida TLS taj certifikat nikad ne bi stigao.
  • Provjereno da adresa gosta i dalje stiže. U dnevniku servera su stvarne adrese posjetilaca, 41 različita u zadnjih 300 zahtjeva, a ne šačica Cloudflareovih. Ograničavanje zahtjeva i revizijski dnevnik i dalje znače ono što su značili.

0.76.52

23. septembar 2026.

Ispravljeno

  • Skripta za Cloudflare je odbijenicu prijavljivala kao nedostatak plana. Kada token nema pravo na neko podešavanje, Cloudflare vrati 403; skripta je to gutala i pisala "nije dostupno na ovom planu", što čovjeka šalje na stranicu za naplatu zbog kvačice koju je zaboravio. Sada razlikuje odbijeno od nepostojećeg, na kraju nabroji šta je odbijeno i kaže koje pravo dodati.
  • Zone ID se više ne mora držati u fajlu: token koji smije čitati zonu nađe je po imenu.
  • --skip-dns odradi podešavanja i pravila keša, a zapise ostavi sive. To je redoslijed koji se i koristi: dok se ne zna da je SSL na "Full (strict)", paljenje narandžastog oblaka može napraviti beskonačni redirect, jer bi Cloudflare origin zvao preko HTTP-a a nginx ga vraćao na HTTPS.
  • Popravljeno i čitanje --hosts, koje je bez te zastavice čitalo putanju do node-a umjesto imena.

0.76.51

23. septembar 2026.

Promijenjeno

  • Adresa gosta preživi Cloudflare. Ako se domena jednom pusti kroz Cloudflare, svaki zahtjev bi inače na server stizao s adrese Cloudflareovog rubnog servera. Ograničavanje zahtjeva na javnim rutama gosta ide po adresi, a i revizijski dnevnik je bilježi: oboje bi tiho prestalo nešto značiti, i cijela zemlja bi dijelila jednu kantu. Nginx sada uzima pravu adresu iz Cloudflareovog zaglavlja, ali vjeruje samo vezama koje stvarno dolaze s njegovih raspona, pa je posjetilac koji dođe direktno ne može falsifikovati.
  • Postavljeno je i na serveru i u deploy/install.sh, pa ga ima i sljedeća mašina. Ne mijenja ništa dok se Cloudflare ne uključi.

Za programere

  • scripts/cloudflare-setup.mjs podesi zonu preko Cloudflare API-ja: proxy na zapisima koje mu se kaže (nikad na mail imenima), SSL "Full (strict)", Always Use HTTPS, HSTS na šest mjeseci bez preloada, HTTP/3, i dva pravila keša - /v1/* se ne kešira nikad, a slike jela i statika se keširaju na rubu.
  • Bez argumenata samo ispiše šta bi promijenio; mijenja tek uz --apply, i pokretanje dvaput ne uradi ništa drugi put.
  • Token čita iz Claudflare_data.txt (van gita) ili iz CLOUDFLARE_API_TOKEN, nikad ga ne ispisuje. Treba token uskog opsega samo za zonu xpay.ba: Zone:Read, DNS:Edit, Zone Settings:Edit, Cache Rules:Edit.

0.76.50

23. septembar 2026.

Popravljeno

  • Pečat koji čuva svaku zapečaćenu tajnu sada ima imenovanu dužinu. Enkripcija u mirovanju je AES-256-GCM, a uz šifrat stoji pečat koji dokazuje da ga niko nije dirao. Pečat je oduvijek bio šesnaest bajtova, ali dužina nije bila napisana, a node bez toga prihvata i pečat od četiri bajta. Ko bi imao bazu i mogao pisati u nju mogao je odsjeći pečat i time spustiti posao krivotvorenja sa dva na sto dvadeset osmu na dva na trideset drugu, a ponovljeni pokušaji s kratkim pečatom otkrivaju i sam ključ za provjeru. Sada je dužina napisana na obje strane, pa se pečat koji nije te dužine odbija prije nego što se uopšte izračuna. Ništa što je do sada zapečaćeno nije promijenjeno niti se drugačije čita.

Za programere

  • crypto.service.ts: authTagLength na createCipheriv i createDecipheriv. Našao ga je korak koji od 0.76.49 čita izvorni kod pri svakoj gradnji, pravilo javascript.node-crypto.security.gcm-no-tag-length, prvi put kad se vrtio.

0.76.49

23. septembar 2026.

Novo

  • Fiskalni spool kao izvor računa. Kasa u BiH ne štampa sama fiskalni račun: to radi drajver proizvođača uređaja, a kasa mu ostavi fajl u folder. Taj folder postoji u svakom lokalu, bez obzira na to koju kasu ima i bez ičega od proizvođača kase. Konektor ga sada prati i za račun koji je uređaj zabilježio kao međuzbir ili kao plaćanje virmanom traži kod.
  • Samo čitanje, i to provjereno u kodu. Adapter neće ni startovati ako bi njegov izlaz završio unutar foldera koji prati. XPay ne štampa, ne fiskalizira i ne upisuje ništa u tok fiskalnog uređaja.
  • Račun plaćen gotovinom ili karticom se preskače. Taj je već naplaćen, pa bi kod uz njega bio poziv da se plati dvaput.
  • Broj računa s uređaja postaje broj naloga, kad ga drajver vrati, pa lokal i gost gledaju isti broj.
  • Na stranici konektora stoji "Prati fiskalni spool", a kad pretraga nađe fiskalni folder, dugme uz njega sada nudi taj adapter umjesto običnog praćenja foldera, koje bi pisalo u drajverov folder.

Format više nije pretpostavka

  • Komandni dijalekt (.inp) provjeren je red po red uz F-Link ME uputstvo Mikroelektronike, uz SC-Link dokumentaciju od ranije: servisno polje 6,1,2, "Ok" i "Er", prodaja s poljem rabata, T bez parametara kao zatvaranje za gotovinu, i J linija kojom drajver vraća broj računa.
  • Zbog tog polja rabata konektor nikad ne sabira stavke da dobije ukupno: uzima samo iznos koji fajl sam navede, a račun bez navedenog iznosa preskače.
  • XML dijalekt (Tring) čita se po nazivima elemenata, jer se sami nazivi ne objavljuju: traži "ukupno" prije "iznos", da se jedna stavka ne zamijeni s cijelim računom.
  • Fajl koji konektor ne razumije kopira se u zaseban folder i u dnevnik se upiše gdje je kopija. Ništa se nigdje ne šalje. Taj jedan fajl je sve što treba da se dijalekt dopiše kako treba, pa lokal ne mora čekati da neko unaprijed pogodi format njegovog drajvera.

0.76.48

23. septembar 2026.

Novo

  • Izvorni kod se pregleda pri svakoj gradnji. Do sada su se čitale zavisnosti koje se isporučuju, historija zbog tajni i stablo zbog poznatih propusta i pogrešno postavljenih fajlova za isporuku. Sam kod nije čitao niko. Sada ga čitaju otvorena Semgrep pravila, ista ona koja traže oblike koji postanu propust: nepouzdan ulaz u upit, u naredbu, u putanju. Prijavljuje se a ne obara gradnju, kao i puni pregled zavisnosti: pravilo koje odjednom počne prijavljivati obrazac star nekoliko mjeseci vrijedi pročitati prije nego što zaustavi popravku naplate.
  • CodeQL se ne vrti i pisali smo zašto. Traži GitHub Advanced Security na privatnom repozitoriju. Semgrep čita iste oblike bez toga, pa upitnik za banku sada kaže šta se stvarno radi umjesto šta je planirano.

Za programere

  • Korak Patterns that become vulnerabilities, over the source u poslu security, nad apps/*/src, packages i scripts, paketi pravila p/javascript, p/typescript i p/owasp-top-ten.
  • BANK_SECURITY_THREAT_MODEL.md i STATUS.md više ne nose red koji čeka Advanced Security.

0.76.47

23. septembar 2026.

Popravljeno

  • Povrat kroz banku se upisuje jednom, koliko god puta se potvrdi. Svaki korak zahtjeva se prije upisa pročita i provjeri, a između ta dva trenutka drugi poziv može uraditi isto. Dva poziva u istom času, dvoklik ili klijent koji ponavlja spor prvi pokušaj, prolazila su oba i oba su upisivala povrat u knjige firme: banka vrati pet, a knjige kažu deset. Sada korak upiše samo onaj poziv koji je zatekao zahtjev u stanju u kojem ga je pročitao, dovršenje se zauzme prije nego što se novac pomjeri, a drugi poziv dobije jasan odgovor da se zahtjev već pomjerio.
  • Vraćanje na spisak osoblja vraća i drugi faktor. Osoba izuzeta od koda s telefona, pa skinuta sa spiska, vraćala se i dalje izuzeta. Niko ko nekoga dodaje ne očekuje da dodaje osobu koja se prijavljuje samom lozinkom, pa se sada pri vraćanju pravilo uključuje.
  • Izvoz cijelog stanara ne puca na datum koji to nije. ?to=2026-13-01 ima oblik dana a nije dan; umjesto uredne greške izlazila je greška servera. Sada se odbija istim riječima kojima to rade i ostali datirani izvozi.
  • Prijava preko identiteta banke podnosi dolazak dvaput. Osvježena stranica ili ponovljeni povratak od pružaoca identiteta znali su završiti greškom servera. Sada je potrošena prijava jednostavno nepoznata prijava, a karta za sesiju se troši tačno jednom.
  • Iz izvoza ne izlazi ništa što se zove ključ. Pravilo je imenovalo oblike (apiKey, privateKey), pa su hmacKey i signingKey prolazili. Sada je dovoljno da se polje zove ključem, potpisom ili hmac-om; javni certifikat zadržan bez potrebe košta jedno pitanje, a izvezen ključ za potpisivanje košta kredencijal.
  • Opis rute za izvoz kaže šta ruta radi: bez raspona su datirani fajlovi posljednja godina, ili od dolaska banke ako je to manje, a duža historija ide kao jedan arhiv po godini.

Za programere

  • bank-refunds.service.ts: svaki prelazak stanja je sada uslovni upis (updateMany s pročitanim stanjem u uslovu) i vraća 409 already_moved kad ne pogodi nijedan red; complete zauzme dovršenje stampanjem completedAt prije poziva payments.refund i vrati zauzeće ako upis povrata ne uspije, tako da ponovni pokušaj koji ruta obećava i dalje radi.
  • bank-sso.service.ts: jednokratnost prijave i karte nosi brisanje (deleteMany s provjerom broja), a ne čitanje prije brisanja.
  • bank-tenant-export.ts: SECRET_LOOKING hvata riječ umjesto oblika.
  • smoke-bank.mjs ima provjeru koja dvije potvrde istog povrata šalje istovremeno i traži jedan upisan povrat, jedan COMPLETED i jedan odbijen poziv. Bankarski smoke: 245 prošlo, 0 palo.

0.76.46

23. septembar 2026.

Novo

  • Kartica "Vaše uobičajeno" na prvom ekranu gosta. Telefonu koji je kod vas već naručivao piše tačno ona narudžba koju kod vas pravi, s cijenama od danas. Naruči isto je pošalje odmah, Izmijeni je otvori u korpi da gost doda, oduzme ili promijeni količinu.
  • Bira se prava narudžba, ne mješavina omiljenih stavki. Ako je istu napravio više puta, piše "Ovo naručujete najčešće"; ako se nijedna ne ponavlja, nudi se zadnja i tako i piše. Gost prepozna "dvije kafe i baklava" jer je to stvarno naručio; korpa složena od stavki koje najčešće uzima bila bi kombinacija koju niko nije jeo.
  • Gleda se zadnjih četrdeset narudžbi u toj poslovnici, pa navika od prije dvije godine ne nadglasa ono što gost pije sada, a uobičajeno iz druge poslovnice se ne nudi kuhinji koja to nikad nije spremala.

Detalji koji se vide tek kad zatreba

  • Ako je nešto iz te narudžbe rasprodano, kartica se i dalje vidi, ta stavka je precrtana, i ostaje samo Izmijeni. Dugme koje bi server ionako odbio ne treba ni nuditi, pogotovo u bučnoj sali.
  • Ako je jelo iz te narudžbe obrisano iz menija, kartice nema uopšte.
  • Slanje ide istim putem kao svaka druga narudžba: cijene se čitaju iznova u tom trenutku, rasprodano se odbija, a dvostruki dodir se veže na isti pokušaj i ne pravi dvije runde.

Za programere

  • GET /v1/t/:slug/usual uz X-Guest-Key, vraća lines (id, količina, opcije, napomena), times i basis. Cijene i nazivi se ne vraćaju: telefon ih crta iz menija koji već drži, pa kartica ne može pokazati cijenu s kojom se ostatak ekrana ne slaže.
  • Izbor runde je usualOrder() u apps/api/src/modules/orders/usual.ts: iste stavke, iste opcije i iste količine su ista runda bez obzira na redoslijed; napomena ne razdvaja naviku; neriješiva runda (obrisano jelo, opcije bez ids) nije kandidat.

0.76.45

23. septembar 2026.

Novo

  • "Vaša 3. posjeta" na ekranu gosta. Telefon koji prvi put otvori račun kod vas dobije slučajan broj i sam ga čuva. Kad isti telefon opet skenira kod za stolom, gost vidi malu oznaku koliko je puta bio, a lokal taj račun broji kao povratnu posjetu.
  • Stopa povratnih gostiju u izvještaju po stolovima, iznad tabele, uz broj računa na kojima se to uopšte moglo vidjeti. Pokazuje se tek od dvadeset takvih računa naviše: prije toga jedan gost pomjeri broj za trideset posto, a to nije podatak nego šum.

Kako se broji

  • Posjeta se upiše tek kad se račun zatvori i plati. Skeniranje menija nije posjeta, otvoren račun nije posjeta, a sto koji je otišao bez plaćanja se ne broji.
  • Telefon koji ne dozvoljava čuvanje podataka izgleda kao prvi put svaki put. Takvi računi se ne broje ni u jednu stranu, pa zato uz stopu i piše na koliko računa se moglo vidjeti: stopa koja pada zato što gosti koriste privatni prozor bila bi podatak o pretraživačima, a ne o lokalu.
  • Ako se za istim stolom desilo da je jedan gost i domaćin i gost, broji se jedna posjeta po telefonu, ne po sjedenju.

Šta taj broj nije

    Za programere

    • VenueGuest (migracija 20261109000000_venue_guest) i visitNumber na SessionGuest (20261110000000_session_guest_visit_number). Broj posjete se upisuje na sjedenje u trenutku kad gost sjedne, jer brojač poslije toga raste i izvještaj za mart bi inače čitao kao veče puno stalnih gostiju.
    • POST /v1/t/:slug/session prima X-Guest-Key i vraća venueKey telefonu koji ga nema, uz visit. GET /v1/t/:slug/visit je čitanje bez upisa, za pozdrav prije nego što se išta naruči.
    • GET /v1/analytics/tables nosi i guests: { known, returning, rate }.

    0.76.44

    23. septembar 2026.

    Novo

    • Banka čiji ljudi izlaze na internet kroz jednu adresu više ne udara u zid. Prijava na bankarsku aplikaciju dopuštala je dvadeset pokušaja u minuti po adresi, što je tačno za ljude koji rade sa svojih računara, a pretijesno za banku čije cijelo osoblje dijeli jedan izlaz. Sada je to BANK_SIGN_IN_PER_MINUTE, s istom podrazumijevanom vrijednošću.

    Popravljeno

    • Browser provjera koja se nije mogla oporaviti. Pomoćna funkcija za prijavu čekala je minutu i jednu sekundu kad limiter kaže "previše pokušaja", a sam test traje najviše minutu: test je umirao u toj pauzi, nasumično, i blokirao izlazak na produkciju. Sada prvo pomjeri vlastiti sat pa čeka u koracima, a CI diže limit tako da do toga ionako ne dolazi.

    0.76.43

    23. septembar 2026.

    Novo

    • Rezervacija, stranica gostove rezervacije i stranica za plaćanje sada govore jezikom gosta. Meni je to radio od ranije, ostale stranice su govorile jezikom lokala: turista koji rezerviše sto sa svog telefona, ili plaća račun iz webshopa koji prodaje vani, dobijao je bosanski. Jezik se sada čita iz samog zahtjeva, prije nego što se išta iscrta, pa stranica nikada ne trepne iz jednog jezika u drugi.
    • Telefon iz Zagreba, Beograda ili Podgorice dobije bosanski. Telefon koji ne govori nijedan naš jezik dobije engleski, jer je to bolja od dvije moguće pretpostavke. Kada zahtjev ne kaže ništa, ostaje jezik lokala.
    • Dugme za jezik na svakoj od tih stranica, dvije oznake u uglu preko slike. Izbor se pamti godinu dana i vrijedi na svim gostinjskim stranicama: ko ispravi našu pretpostavku u meniju, ne mora je ispravljati ponovo kod rezervacije.
    • Naslov u kartici pretraživača i ono što se otvori kad se link proslijedi prate istog čitaoca. To je prvo što vidi onaj kome je link poslan, a često nije onaj ko ga je dobio od lokala.

    Za programere

    • parseAcceptLanguage() i guestLocale() u apps/dashboard/src/i18n/accept-language.ts, iznad postojećeg negotiateLocale(). Izbor gosta živi u kolačiću xpay-guest-locale i u localStorage, pa ga čitaju i stranice iscrtane na serveru i meni.
    • GET /v1/payments/checkout/:token nosi i locale, jezik trgovca, kao rezervu kada pretraživač ne traži ništa.
    • Račun na /r/:token ostaje u jeziku dokumenta. To nije pretpostavka o čitaocu nego svojstvo samog računa.

    0.76.42

    22. septembar 2026.

    Novo

    • Drugi faktor se može isključiti za jednu osobu. Bankarsko osoblje se prijavljuje lozinkom i kodom, i prva prijava upisuje telefon; to ostaje pravilo. Operater sada može izuzeti pojedinu osobu, i tada njena lozinka odmah otvara sesiju. Napravljeno je za probni nalog, jer je pri testiranju kucanje koda svakih trideset sekundi naporno.
    • Ništa u tome nije tiho. Isključivanje zaboravi telefon koji je ta osoba imala, pa sljedeća prijava stvarno bude samo lozinka. I izuzetak i svaka prijava koju je omogućio stoje na revizijskom lancu. Operaterov ekran pokazuje ko je izuzet. Izvještaj o spremnosti okruženja imenuje svakog izuzetog: ispod produkcije kao napomenu, a u produkcijskom okruženju kao grešku, jer produkcija ne trpi nijedan izuzetak.
    • Vraćanje je jedan klik: kad se drugi faktor opet uključi, ta osoba pri sljedećoj prijavi ponovo upisuje telefon.

    Za programere

    • BankMembership.mfaRequired (migracija 20261108000000_bank_membership_mfa_required, podrazumijevano true za sve postojeće redove). PATCH /v1/admin/banks/:id/members/:memberId prima mfaRequired; odgovor kaže i da li je telefon zaboravljen. POST /v1/bank-auth/login za izuzetu osobu vraća par tokena umjesto koraka, a na lancu stoji bank.auth.password_ok s step: "none".
    • Scenario staff_second_factor u izvještaju o spremnosti; scripts/smoke-bank.mjs prolazi kroz sve: izuzimanje, prijavu bez koda, izvještaj koji to imenuje, vraćanje pravila i oba zapisa na lancu.

    0.76.41

    22. septembar 2026.

    Ispravljeno

    • Status stranica je danas pola dana kazivala staru verziju. Nije bila u krivu: ona ispisuje popis verzija iz izdanja koje zaista radi, a na server je izlazilo samo ono što prethodno prođe punu provjeru na GitHubu. Provjeru je svaki novi commit prekidao, pa kad se radi u dvije linije odjednom nijedna nije stizala do kraja i ništa nije izlazilo: server je ostao jedanaest verzija iza. Provjera se sada prekida samo na pull requestu, a svaki commit na glavnoj grani ide do kraja i može biti pušten.

    0.76.40

    22. septembar 2026.

    Ispravljeno

    • XPay Light je bio napola taman. Kartice u konzoli crtale su se iz stare tamne palete, pa su na kremastoj podlozi bile skoro crne; sada svaka tema crta svoje kartice. Isto je popravljeno za najdublju podlogu i pritisnuto stanje dugmeta.
    • Prelazak mišem preko reda se vidi u svakoj temi. Bio je napisan kao bijela boja na 5 posto, što na svijetloj podlozi ne postoji; sada je to jedna vrijednost koju svaka tema postavi po sebi (57 mjesta u konzoli).
    • Naš logo na svijetloj temi više nije blijed: postoji verzija za svijetlu podlogu i tema bira koju vidite, prije prvog iscrtavanja.
    • Meni gosta preuzme novu temu odmah. Stranica se kešira pet minuta, pa je vlasnik koji promijeni temu i odmah otvori svoj meni vidio staru; stranica sada ispravi podlogu iz živog odgovora.

    0.76.39

    22. septembar 2026.

    Novo

    • Scenario demonstracije. U prvoj sobi sjede četiri osobe koje ne žele isto: sponzor pita zašto je ovo važno, šef platnog prometa da li radi, CIO koliko će koštati njegov tim, a neko iz rizika čeka jednu tvrdnju koju može oboriti. Napisan je red kojim se svima odgovara bez čekanja: gost plaća na telefonu, pa pregled banke, pa jedno plaćanje s kraja na kraj i red za sravnjivanje, pa njihovi sistemi i portal, pa portfolio i izvještaj za upravu, pa pitanja rizika.
    • I ono što se u toj sobi nikad ne kaže: da neko već koristi ovo u produkciji, da je išta certificirano ili testirano probojem, bilo koji broj o dostupnosti ili propusnosti koji niko nije izmjerio, i bilo šta o drugoj banci. Obećanje bez dokaza kupi sastanak, a izgubi posao tri sedmice kasnije kad procurement zatraži dokaz.

    Za programere

    • docs/en/bank-platform/BANK_DEMO_SCRIPT.md; indeks pokazuje na njega, a svaki ekran koji scenario imenuje postoji i radi na demo banci iz seeda.

    0.76.38

    22. septembar 2026.

    Popravljeno

    • Red u tabeli za provjeru dobavljača. Stavka 29 stajala je prije stavke 28. Tabela u kojoj brojevi nisu po redu pojede povjerenje u ono što u njoj piše.
    • Putevi do susjednih dokumenata u bankarskim dokumentima sada su jednaki svuda (../08-bank-partner-api.md, ../06-deployment.md), pa onaj ko ih čita s diska zaista dođe do fajla.

    0.76.37

    22. septembar 2026.

    Novo

    • Izaberite kako vaš XPay izgleda. Konzola → Postavke → Izgled. Pet tema: XPay Dark (kao do sada), XPay Light (topla svijetla podloga), XPay Green (tamno zelena s cyan dugmadima), XPay Red (topla crna s crvenom) i XPay Blue (tamno plava s azurnom). Svaka kartica je naslikana u svojoj temi, klik je odmah pokaže na cijelom ekranu, a Sačuvaj je primijeni.
    • Tema važi za cijeli vaš lokal, i samo za vaš. Konzola, kasa, ekran sale, kuhinja, šank, zidni ekran, meni koji gost otvori skeniranjem, stranica za rezervacije i stranica na kojoj kupac plaća račun iz webshopa. Uređaji preuzmu novu temu čim se osvježe. Drugim lokalima se ništa ne mijenja.
    • Naljepnica za sto se štampa u boji vaše teme, a sam QR ostaje crn na bijelom: skener nema temu, a naljepnica koju kamera ne čita ne vrijedi ništa.
    • Ako ste postavili svoju boju, ona i dalje daje naglasak na gostinjskim stranicama: tema daje podlogu, vaša boja dugmad. Teme nisu vezane za paket.

    Promijenjeno

    • Status stranica više ne javlja "degraded" kad mail server odgovori sporo, nego tek preko 30 sekundi. Kašnjenje se i dalje mjeri i piše u detalju.

    Za programere

    • Merchant.theme (migracija 20261107000000_merchant_theme), lista imena u packages/shared/src/themes.ts, uz themeOf() koji svaku nepoznatu vrijednost vraća na podrazumijevanu. PATCH /v1/merchant {theme}; vrijednost putuje u GET /v1/merchant, GET /v1/t/:slug, GET /v1/reserve/:slug, /status/:token, POST /v1/terminals/pair i GET /v1/payments/checkout/:token.
    • CSS: :root[data-xpay-theme=...] u packages/design-tokens/src/tokens.css i #xpay-guest[data-xpay-theme=...] u guest.css; boja lokala se sada piše kao #xpay-guest[data-brand='1'] da nadjača temu samo za naglasak. Skripta u <head> vrati zapamćenu temu prije prvog iscrtavanja.

    0.76.36

    22. septembar 2026.

    Novo

    • Indeks bankarske dokumentacije. Predati banci dvadeset dokumenata odjednom znači da niko neće pročitati nijedan. Sada na jednom mjestu piše šta pročitati za dvadeset minuta, a šta ako ste onaj ko ocjenjuje proizvod, ko radi integraciju, ko gleda sigurnost, ko kupuje ili ko vodi infrastrukturu. Na kraju stoji i ono što nijedan od njih neće reći: da neko drugi ovo već koristi u produkciji.

    Popravljeno

    • Browser provjera specifikacije je pala u CI-ju, i to s pravom: svaka provjera se prijavljuje, a prijava banke dozvoljava dvadeset pokušaja u minuti s jedne adrese. Deveta prijava je prevršila mjeru. Provjera je sada dio postojećeg prolaza koji je ionako prijavljen, a pomoćna funkcija za prijavu sačeka minutu i pokuša ponovo kad ekran kaže da je pokušaja bilo previše, umjesto da padne na poruci koja je tačna.

    Za programere

    • docs/en/bank-platform/README.md, i 08-bank-partner-api.md sada pokazuje na njega s prvog ekrana.
    • Provjera portala i specifikacije živi u apps/bank/e2e/demo.e2e.ts, u prolazu CIO-a; studio.e2e.ts je obrisan. Osam browser tokova prolazi.

    0.76.35

    22. septembar 2026.

    Novo

    • U portalu za developere stoji dugme koje preuzima specifikaciju onog dijela API-ja koji je bankin, kao fajl koji generator odmah čita. Do sada je adresa postojala, ali ju je inženjer morao znati napamet; sada je na istom ekranu gdje su i adrese, zaglavlja i uzorak izvoda.

    Za programere

    • apps/bank/e2e/studio.e2e.ts: nova browser provjera koja se prijavi, otvori portal, klikne preuzimanje i onda otvori preuzeti fajl: naslov nosi ime banke, svaka putanja u njemu je bankina, i konzolinih putanja nema. Devet browser tokova prolazi.

    0.76.34

    22. septembar 2026.

    Novo

    • Četiri sedmice, napisane. Evaluacija banke obično stane na istom mjestu: svi su vidjeli demonstraciju, niko ne zna šta je sljedeći korak. Sada je napisan: šta se dešava koje sedmice, ko šta radi na obje strane, šta banka treba da obezbijedi, i šta se na kraju svake sedmice ima u ruci. Prva sedmica je sandbox, druga su bankini sistemi i izvještaj o spremnosti, treća je pravi lokal i pravo plaćanje, četvrta je paket za odluku.
    • Upitnik unaprijed odgovoren. Sto pitanja koja banke ionako šalju, s odgovorom i s putokazom na dokaz: arhitektura, zaštita podataka, sigurnost, rad, integracija, komercijala. Gdje je odgovor "još ne", tako i piše. Gdje odgovor zavisi od instalacije, piše ko ga popunjava, umjesto da se pogađa umjesto operatera.
    • Gdje sve ovo radi. Tri načina: kod nas, na zasebnoj instalaciji koju vodimo mi, ili unutar banke. Za svaki piše šta banka daje, šta je isto u sva tri, i, za instalaciju unutar banke, tabela onoga što bankin tim traži a u repozitoriju ne postoji: Helm, vlastiti registar slika, ažuriranje bez interneta, objektno skladište za slike, više API procesa, vanjski čuvar ključeva, otpremanje logova. Svako od toga je stavka u ugovoru, a ne iznenađenje u trećem mjesecu.
    • Dva reda u tabeli stanja bila su zastarjela i ispravljena su: dvofazna prijava za operatera i konzolu je gotova od 0.76.20, a paket za provjeru dobavljača postoji od 0.76.18 i popunjen je od 0.76.31. Tabela koja za gotovo kaže "planirano" pojede povjerenje u sve ostalo u njoj.

    Za programere

    • docs/en/bank-platform/BANK_EVALUATION_GUIDE.md, BANK_QUESTIONNAIRE.md i BANK_DEPLOYMENT_MODES.md; VENDOR_ASSURANCE.md sada pokazuje na njih. U tabeli stanja je ostala jedna planirana stavka i ona traži šemu koja ne postoji (IPS potvrda).

    0.76.33

    22. septembar 2026.

    Novo

    • Specifikacija onog dijela API-ja koji je bankin. Inženjer banke na jednoj adresi dobije OpenAPI dokument iz kojeg se generiše klijent u bilo kojem jeziku. Dokument se pravi iz aplikacije koja radi, pa je to što ona odgovara danas, a ne što je neki dokument jednom rekao.
    • U njemu je samo ono što banka zove: bankini pozivi, prijava njenih ljudi, adresa na koju stižu obavijesti o prilivu i stranice koje ugrađuje. Konzola, operater i gost nisu unutra. Naslov nosi ime banke koja je pitala, a adresa servera je ova instalacija, pa generisani klijent ne traži nikakvo dodatno podešavanje.
    • Puni /docs i dalje je ugašen u produkciji. On je mapa cijele površine i tu ostaje kako jeste; ovo je dio koji je bankin, iza bankine sesije.

    Za programere

    • GET /v1/bank/openapi.json za integracijsku ulogu i sistemski ključ. Pravila su čista funkcija u apps/api/src/modules/bank/bank-openapi.ts (BANK_PATH_PREFIXES, bankSurface) s devet testova: svaka bankina putanja ostaje, konzola i operater i gost nestaju, putanja koja samo počinje istim slovima se ne zamijeni s bankinom, šeme ostaju cijele da generator može razriješiti svaku referencu, a dokument koji je dobijen ostaje nepromijenjen.
    • scripts/smoke-bank.mjs traži specifikaciju kao inženjer, provjeri naslov i da je svaka putanja bankina, i da analitičara odbije.

    0.76.32

    22. septembar 2026.

    Novo

    • Alat koji mjeri, a ne tvrdnja. Banka u tehničkoj provjeri pita koliko sistem podnosi. Broj je osobina mašine, baze i mreže, a ne repozitorija, pa u dokumentaciji nema nijednog. Umjesto toga tu je alat koji mjeri instalaciju koja se kupuje: izdavanje naloga za plaćanje, primanje potpisane obavijesti o prilivu, projekciju iz koje banka čita, i same bankarske ekrane. Za svaki korak izvještava koliko poziva u sekundi, p50, p95 i p99, najsporiji poziv, i koliko ih je odbijeno i zašto.
    • Odbijanje s razlogom je dio odgovora. Ograničenje broja poziva koje radi svoj posao nije kvar, i alat kaže koje je od to dvoje bilo.
    • Ne laska razvojnom steku. Pokrenut protiv lokalnog servera, alat sam kaže da mjeri Postgres preveden u WebAssembly na jednom laptopu i da to o serveru ne govori ništa.
    • Dvadeset deveta stavka u paketu za provjeru dobavljača je kapacitet: šta u platformi utiče na njega (bankarski ekrani nikad ne sjede na putu pisanja, obavijesti su idempotentne po identifikatoru poruke, ograničenja su po kredencijalu i adresi, izvozi su omeđeni), šta rezultat ne dokazuje, i prazna tabela rezultata koja ostaje prazna dok neko ne izmjeri.

    Za programere

    • node scripts/load-bank.mjs --url <adresa> --payments 500 --concurrency 16 --key <systems key> --json rezultat.json. Namjerno nije u CI-ju: broj sa zajedničkog build servera mjeri taj server. Prvi put napravi jedan dovod i ispiše dvije zastavice kojima se isti dovod koristi ponovo, jer se tajna dovoda pokazuje jednom i ovaj alat nema izuzetak od tog pravila.
    • docs/en/bank-platform/BANK_CAPACITY.md objašnjava kako se rezultat čita (p95, ne prosjek; odbijanja prije latencije; projekcija je svoj broj) i šta raditi ako brojevi nisu dovoljni, uključujući ono što u repozitoriju ne postoji: više API procesa nad istom bazom, replike za analitiku, red ispred prijema obavijesti.

    0.76.31

    22. septembar 2026.

    Novo

    • Sve što banka ima kod nas, u jednom fajlu. Nova adresa za izvoz daje arhivu s konfiguracijom kakva jeste (banka, njen paket i moduli, okruženja sa sposobnostima i dovodima, kredencijali po vrsti i otisku a nikad po vrijednosti, ljudi s ulogama, poslovanja povezana s bankom i šta je koje dozvolilo, politike dokumenata, domene, brendiranje), s datiranim zapisima (plaćanja, revizijski lanac, slučajevi, incidenti i red izmjena), s popisom koji uz svaki fajl nosi veličinu i SHA-256, i s bilješkom koja kaže kako se to provjeri, kako se lanac verifikuje i šta namjerno nije unutra. Godina po arhivi, kao i svaki drugi datirani izvoz; duža historija dolazi kao jedna arhiva po godini, a konfiguracija je cijela u svakoj.
    • Izlaz se ne naplaćuje i ne traži razgovor. Adresa nije iza licence za modul. Put van nije funkcija koja se prodaje.
    • Nijedna tajna ne izlazi. Kredencijal je u arhivi po vrsti i otisku, s jasnom porukom umjesto vrijednosti. Test to provjerava tako što u cijeloj arhivi traži tajne koje je sam napravio.
    • Paket za provjeru dobavljača više nije spisak rupa. Napisani su: dijagram konteksta (ko s kim priča i gdje su granice), registar podobrađivača (šta softver uopšte traži od onoga ko ga vodi, i predložak koji se popunjava po instalaciji), kontinuitet i oporavak (šta se čuva i koliko često, put nazad korak po korak, i prazna tabela vježbe koja ostaje prazna dok se vježba ne uradi), odgovor na incident, upravljanje ranjivostima s procesom za test proboja, predložak nivoa usluge i plan izlaska. Od dvadeset osam stavki koje procurement pita, otvorena je ostala jedna, i to komercijalna.
    • Ono što nije izmjereno i dalje tako piše. Nema izmišljenog vremena oporavka, nema procenta dostupnosti, nema tvrdnje da je neko izvana provjerio. Gdje broj nije mjeren, stoji kako se mjeri i gdje se upisuje.

    Popravljeno

    • Revizijski lanac se sada čita u stranicama, i kod provjere i kod izvoza. Lanac raste svaki dan dok instalacija radi; tražiti ga cijelog odjednom bio je skok u memoriji koji je svakim danom gori, a na razvojnoj bazi je rušio zahtjev otprilike jednom u deset puta. Redovi, redoslijed i ograničenje su isti.

    Za programere

    • GET /v1/bank/exports/tenant.zip?from&to za izvršne, revizijske i compliance uloge; cijeli izvoz je stavka na lancu (bank.export, meta tenant) s rasponom, brojem fajlova, bajtima i svakim fajlom koji je ograničenje redova skratilo. Pravila su čiste funkcije u apps/api/src/modules/bank/bank-tenant-export.ts s deset testova, a scripts/smoke-bank.mjs otvara arhivu, poredi svaki kontrolni zbir s bajtovima i provjerava izolaciju i uloge.
    • docs/en/bank-platform/ je dobio BANK_CONTEXT_DIAGRAM.md, BANK_SUB_PROCESSORS.md, BANK_CONTINUITY.md, BANK_INCIDENT_RESPONSE.md, BANK_VULNERABILITY_MANAGEMENT.md, BANK_SERVICE_LEVELS.md i BANK_EXIT_PLAN.md; VENDOR_ASSURANCE.md pokazuje gdje je koji odgovor.
    • Razvojni stek: API, migracije i seed dobijaju istu veličinu heapa koju je build već dobio. Bez toga V8 ubije proces usred rada ("Check failed: index < size()"), što izgleda kao greška u kodu a nije.

    0.76.30

    22. septembar 2026.

    Novo

    • Banka koja svoje ljude vodi u Active Directoryju sada ih tako i prijavljuje. U verziji 0.74.3 pisalo je da SAML dolazi onog dana kad ga banka zatraži i s bibliotekom koja provjerava potpis; došao je. Prijava ide preko ADFS-a ili Entra ID-a, na istoj politici i kroz ista vrata kao i do sada: osoba izabere prijavu preko banke, ode kod svog providera i vrati se prijavljena.
    • Šta okruženje kaže. Da je provider SAML i gdje se ide na prijavu, a po potrebi i ko je provider (tada potvrda od nekog drugog ne prolazi, makar bila ispravno potpisana), mora li i odgovor biti potpisan, koliko satovi smiju biti razmaknuti, i pod kojim imenima taj provider nosi e-mail, ime i grupe. Ako ne kaže ništa od toga, čitaju se imena s kojima ADFS i Entra ID dolaze iz kutije.
    • Certifikat providera je kredencijal kao i svaki drugi. Prihvata se PEM, goli sadržaj koji se kopira s ekrana providera, ili cijeli metadata dokument koji administrator izveze, jer tražiti od administratora da zna razliku znači poziv podršci na dan pilota. Ako provider usred zamjene certifikata objavi dva, čitaju se oba, da dan zamjene ne bude ispad.
    • Šta banka uveze kod sebe. Adresa s metapodacima objavljuje ovu stranu: ko smo i gdje se potvrda šalje. Administrator to uveze i prijava radi. Adresa je bankina vlastita, pa ista potvrda poslana na adresu druge banke ne prolazi.
    • Uloga i dalje dolazi sa servera. Ko je već vezan za taj identitet ulazi kakav jeste, ko je poznat po e-mailu se veže, a ko je nov dobije ulogu koju mapiranje daje njegovoj grupi ili podrazumijevanu, ako je banka tako podesila. Mapiranje je bankino i na serveru; iz preglednika uloga ne dolazi nikad. Odbijanje uvijek ima razlog koji ekran zna reći.
    • Na lancu. Identitet, član kojeg je politika napravila i sesija, svaki put, uz ime providera preko kojeg je osoba ušla.
    • U portalu za programere stoji primjer politike i za SAML, s adresama ove instalacije i imenima kredencijala, pored onog za OpenID Connect.

    Za programere

    • GET /v1/bank-auth/sso/saml/:bank/metadata objavljuje metapodatke ove strane, POST /v1/bank-auth/sso/saml/:bank/acs prima potvrdu. Identitet ove strane je {API_BASE_URL}/v1/bank-auth/sso/saml/<oznaka>, a adresa za potvrdu ista ta i /acs. Zahtjev ide preglednikom preko preusmjerenja, potvrda se vraća POST-om.
    • Prijava u toku veže se za potvrdu preko RelayState: mora biti prijava koju je ovaj server započeo, za ovu banku, nepotrošena i neistekla. Potpis, primaoca, publiku i vremenski prozor provjerava @node-saml/node-saml; izdavaoca provjerava XPay, jer biblioteka to radi samo za odjavu, a banka koja imenuje svoj federacijski servis očekuje da potvrda od nekog drugog bude odbijena i kad je certifikat poznat. Kanonizacija XML-a i provjera potpisa ostaju bibliotekine, namjerno.
    • Politika, certifikati, čitanje tvrdnji i izdavalac su čiste funkcije u apps/api/src/modules/bank/bank-sso-saml.ts, sa četrnaest testova. scripts/smoke-bank.mjs igra providera: napravi ključ, potpiše pravu potvrdu i prijavi se njome, pa provjeri da ista osoba zadrži ulogu i da pogrešan ključ, pogrešna publika, pogrešan izdavalac, potvrda bez RelayState i potrošen RelayState budu odbijeni.
    • Izvještaj o spremnosti okruženja provjerava i SAML politiku: da kredencijal postoji i da u njemu ima bar jedan certifikat.

    0.76.29

    22. septembar 2026.

    Novo

    • Admin, Problemi. Jedna stranica koja pokazuje svaki lokal kod kojeg nešto ne radi, najglasnije prvo: istekla licenca, poslovnica bez bankovnog računa, veza s bankom koja ne radi ili ćuti duže od dvanaest sati, uplate koje nisu uparene, kodovi koji vise duže od šest sati, webhook koji pada ili je ugašen, konektor koji se ne javlja pola sata, štampač koji prijavljuje grešku, fiskalni dokument koji je Porezna odbila, poslovnica kojoj fiskalna oznaka nikad nije postavljena, dan koji nije zaključen, lokal koji je otvoren a nikad korišten, i lokal koji je utihnuo. Uz svaki problem piše šta znači, šta uraditi, koliko ih je i od kada.
    • Klik na lokal otvara njegov dosije: svi problemi u cijelosti, paket i stanje, kontakt mail i telefon (odmah pozivni), i zadnjih trideset stvari koje su se tamo desile iz revizijskog dnevnika. To je odgovor na drugo pitanje svakog poziva, "a šta se dešavalo".
    • Brojači na vrhu: koliko lokala ne može raditi, koliko škripi, koliko je za znati i koliko ih je uredno. Stranica se sama osvježava svakih minut.

    Za programere

    • GET /v1/admin/health (?only=problems) i GET /v1/admin/merchants/:id/health, oboje samo za operatera. Pravila su čista funkcija u apps/api/src/modules/admin/merchant-health.ts s dvanaest testova; pragovi su jedan blok na vrhu tog fajla. Novi problem traži kod ondje i tri riječi u katalogu (admin.health.problem, .fix, .amount), što check-i18n provjerava.
    • Runbook: docs/en/01-operator-runbook.md, sekcija "Who has a problem".

    0.76.28

    22. septembar 2026.

    Ispravljeno

    • Grafikon prometa i pločica "naplaćeno" razilazili su se za svaki povrat na zaokruženom ili manje plaćenom računu. Gost zaokruži 48,00 na 50,00, lokal mu vrati 2,00: pločica je to odbila (kao i fajl za knjigovođu), a kriva ispod nje nije, pa su dva broja pod istim natpisom bila različita. Kriva sada odbija povrate na sva tri stanja koja ulaze u promet, isto kao pločica. Račun vraćen u cijelosti se, kao i prije, ne odbija dvaput.

    Za programere

    • GET /v1/analytics/timeseries: noga povrata sada je vezana za PAID, UNDERPAID, OVERPAID (lista COUNTED_IN_TAKINGS iz refund-period.ts), ne samo za PAID.
    • Smoke: smoke-ordering sam napravi zaokružen račun s djelimičnim povratom prije poređenja krive i pločice, pa ovo hvata CI. Tri provjere koje su mjerile ukupno stanje umjesto razlike (printeri konektora, podsjetnici, lista najvećih dužnika) sada mjere razliku, pa lokalna baza koja se nikad ne prazni više ne obara ispravan kod.

    0.76.27

    22. septembar 2026.

    Za programere

    • dev-up je prestao da gradi API na laptopu. Kod API-ja je prerastao zadanu veličinu hrpe koju node daje tsc-u, pa je build padao sa "JavaScript heap out of memory" i izlazom 134, što izgleda kao pad kompajlera i šalje čovjeka da traži grešku u kodu koje nema. Skripta sada gradi sa podignutom hrpom, kao što se i typecheck odavno pokreće ručno. Na CI-ju ništa se ne mijenja: tamo mašina ima memorije i bez toga.

    0.76.26

    22. septembar 2026.

    Novo

    • Karantin za brojeve zatvorenih firmi. Svaka firma nosi četverocifreni broj koji ulazi u svaki poziv na broj koji ikad odštampa, a ima ih 9000. Zatvaranje firme sada upisuje i dan zatvaranja, pa broj firme koja nikad nije izdala nijedno plaćanje ide u karantin i vraća se u opticaj nakon 90 dana: ništa s tim brojem nije nikad odštampano ni poslano, pa ništa ne može ni stići. Firma koja je izdala makar jedno plaćanje zadržava svoj broj zauvijek, jer zakašnjela uplata ne smije sletjeti na tuđi račun. Tako se prostor brojeva vraća od napuštenih prijava i probnih naloga, a ne od onih koji su radili.
    • Pregled operatera kaže koliko ih čeka. Pločica "Brojevi firmi" uz zauzeto i slobodno sada broji i koliko brojeva čeka karantin i koliko se vraća pri sljedećoj prijavi.
    • Stranica za probni nalog prvo pita. Ako su probni nalozi zatvoreni zbog popunjenosti prostora brojeva, posjetilac to vidi odmah, a ne nakon što ispuni cijeli formular.

    Za programere

    • Merchant.closedAt i Merchant.retiredMerchantNo (migracija 20261106000000_merchant_number_quarantine, aditivna). PATCH /v1/admin/merchants/:id/status upisuje i briše closedAt; otpuštanje broja premješta red iznad opsega formata (100000+), upisuje stari broj u retiredMerchantNo, poništava licencni ključ izdat na taj broj (ključ je jedinstven i potpisan nad brojem, planom i danom isteka, pa bi se inače sudario sa sljedećim vlasnikom broja) i piše merchant.number_recycled na lanac. Radi prije svake dodjele i svaki dan u 4.
    • Provjere: sedam provjera u merchant-number.test.ts i jedna u scripts/smoke.mjs.

    0.76.25

    22. septembar 2026.

    Ispravljeno

    • Stranica za rezervaciju kad lokal ne prima rezervacije. Do sada je davala golo "404 This page could not be found", pa je gostu koji je link dobio s Instagrama lokala izgledalo da je stranica lokala pokvarena. Sada otvara stranicu tog lokala, s njegovom slikom, logom i bojama, i kaže da se sto ovdje dogovara telefonom, s dugmetom za poziv kad lokal ima upisan broj. Link i dalje ne prima zahtjeve dok se rezervacije ne uključe.
    • Pogrešan link (nepotpuna adresa, lokal promijenio naziv) kaže da link ne vodi nigdje, umjesto 404 ekrana.
    • Stranica rezervacije s nepoznatim kodom kaže da rezervaciju ne nalazimo i šta da gost uradi, umjesto 404 ekrana.

    Za programere

    • GET /v1/reserve/:slug i dalje vraća 404, ali s razlogom: reason: 'reservations_off' (uz venue: naziv, jezik, telefon, logo, paleta, naslovna slika) ili reason: 'unknown_venue'. GET /v1/reserve/status/:token nosi reason: 'unknown_reservation'.

    0.76.24

    22. septembar 2026.

    Promijenjeno

    • Naslovna slika ide od ivice do ivice. Fotografija s menija (ili boja lokala) više nije kartica s okvirom nego cijeli vrh ekrana, s logom lokala u uglu i imenom preko nje. Na telefonu je to cijela širina ekrana, na računaru cijela širina prozora.
    • Kategorije odmah ispod slike. Red kružića s nazivom i slikom kategorije stoji prije pozdrava i svega ostalog, pa gost koji je došao na kafu ne skrola kroz jela da bi našao piće. Jedan dodir i tu je.
    • Tri jela u redu na velikom ekranu. Na telefonu je jedno jelo po redu kao i do sada, na tabletu dva, na računaru tri; kategorije su dvije u redu na telefonu i tri na širem ekranu. Ekran se razlaže po širini prozora, od malog telefona (360 px) do monitora, bez horizontalnog skrolanja.
    • Miš dobija odgovor. Kartica se malo podigne kad pređete preko nje; na dodir ostaje kako je bilo.
    • Korpa, račun i plaćanje ostaju u širini telefona i na monitoru: spisak od dvije stavke razvučen preko cijelog ekrana ne pomaže nikome.

    Za programere

    • Gostinjska podloga ima .g-shell (širina ekrana) i .g-bleed-inner (mjera sadržaja); #xpay-guest[data-wide] odlučuje koja je koja, a postavlja ga sama stranica prema ekranu na kojem je gost. Naslovna slika je .g-hero[data-full].

    0.76.23

    22. septembar 2026.

    Popravljeno

    • Skener tajni u CI-ju prijavio je dvije lažne uzbune iz prethodnog izdanja. Prva je fiksna so kojom se lozinka razvlači u ključ: ona nije tajna nego razdvajač namjene, pa je sada imenovana konstanta koja to i kaže. Druga je bio primjer u runbooku koji je izgledao kao upisan ključ; sada se ključ u primjeru generiše, a gdje se upisuje piše u rečenici. Nijedna prava tajna nije bila u kodu ni u dokumentaciji.

    0.76.22

    22. septembar 2026.

    Novo

    • Stolovi: rezervisan sto. Sto koji rezervacija drži (pola sata prije termina) na ekranu sale stoji kao Rezervisan, s vremenom, imenom i brojem osoba, i ima dugme Otvori sto. Konobar ili šanker tako pušta naljepnicu s mjesta na kojem ionako radi, bez otvaranja knjige rezervacija. Sto na kojem je račun već otvoren ostaje kako je bio: otvoren račun je preča informacija za salu.

    0.76.21

    22. septembar 2026.

    Novo

    • Rotacija ključa za enkripciju. Svaka zapečaćena vrijednost sada nosi oznaku ključa kojim je zapečaćena, a instalacija može čitati sa više ključeva dok piše jednim. Stari ključ ide u ENCRYPTION_KEYS_OLD, novi u ENCRYPTION_KEY, i nakon restarta operater u Administraciji pokrene prepakivanje: kredencijali integracija banaka, tajne webhookova, tajne i konfiguracije izvora izvoda i tajne telefona za prijavu u dva koraka prelaze na novi ključ. Postupak se može ponoviti; vrijednost koju nijedan ključ na instalaciji ne otvara se prebroji i ostavi, ne obriše. Do sada je promjena ključa značila gubitak svih pohranjenih tajni, pa se u praksi nije ni radila.

    Za programere

    • Omot šifrata je v2.<id ključa>.<iv>.<tag>.<šifrat>; stari v1. se i dalje čita. GET /v1/admin/encryption vraća trenutni ključ, sve ključeve kojima se čita i broj redova po vrsti (telefoni, webhookovi, izvori, kredencijali banaka) na trenutnom ključu, na starom i nečitljivih; POST /v1/admin/encryption/rewrap prepakuje i piše platform.encryption_rewrapped na revizijski lanac. Oboje samo super admin.
    • Provjere: crypto.service.test.ts i jedna provjera u scripts/smoke.mjs.

    0.76.20

    22. septembar 2026.

    Novo

    • Prijava u dva koraka. U Postavkama (firma) i pod Moj nalog (operater) nova kartica: uz lozinku, upisanu ponovo, telefon se upisuje aplikacijom za kodove (QR ili ključ ručno), kod se potvrdi, i deset kodova za oporavak se prikaže jednom. Uključena, prijava poslije lozinke traži kod s telefona ili kod za oporavak; sama lozinka ne otvara ništa. Pogrešan kod se broji u zaključavanje kao pogrešna lozinka. Isključivanje traži lozinku i kod i odjavljuje sve prijave.
    • Operater zaboravlja izgubljeni telefon. Za dan kad nema ni telefona ni kodova za oporavak: operater briše telefon s naloga, sve prijave te osobe prestaju, a zapis je na revizijskom lancu. Niko drugi to ne može.
    • Nalog je jedan: ko je telefon upisao u banci, ima ga i u konzoli.

    Za programere

    • POST /v1/auth/login vraća { step: "verify", stepToken } za nalog s telefonom; POST /v1/auth/mfa/verify sa stepToken i kodom vraća isto što i prijava. GET /v1/auth/mfa, POST /v1/auth/mfa/enrol (lozinka), /confirm (kod, vraća kodove za oporavak), /disable (lozinka i kod), POST /v1/auth/mfa/reset (super admin, e-mail). Revizija: auth.password_ok, auth.login s factor, auth.mfa_enrolled, auth.mfa_disabled, auth.mfa_reset.
    • Provjere: tri provjere u scripts/smoke-bank.mjs na vlasniku Želje, koji na kraju ostaje samo s lozinkom.

    0.76.19

    22. septembar 2026.

    Novo

    • Rezervacija može imenovati sto. U knjizi rezervacija uz potvrdu (ili poslije, u koloni Sto) izaberete sto koji rezervacija drži. Pola sata prije termina naljepnica tog stola gostu kaže "Sto je rezervisan od 17:00" i ne prima narudžbe: ko sjedne u 16:40 ne može otvoriti račun na stolu koji samo što nije zauzet. Kad termin prođe (17:01), meni radi sam od sebe, ko god skenirao. Ako gosti dođu ranije, Otvori sto u knjizi odmah pušta naljepnicu; rezervacija ostaje. Stranica na telefonu sama primijeti i otvaranje i sat, bez osvježavanja.
    • QR kod i kod za sajt. Uz link stranice za rezervacije sada su i QR (PNG za vrata i šank, SVG za štampu) i gotov red HTML-a za sajt lokala: skeniranje ili klik otvaraju stranicu za rezervaciju.

    Za programere

    • Reservation.terminalId i seatedAt, migracija 20261105020000_reservation_table. POST /v1/reservations i .../confirm primaju terminalId; POST /v1/reservations/:id/table {terminalId|null}, POST /v1/reservations/:id/seat. Odgovor knjige nosi terminalId, table, seatedAt, holding, holdMinutes.
    • GET /v1/t/:slug vraća reserved: {at, from} | null; POST /v1/t/:slug/session i /orders odbijaju s 409 conflict, reason: table_reserved, dok sto drži rezervacija (pravilo u reservation-hold.ts: 30 minuta prije termina do termina, dok lokal ne otvori sto).
    • GET /v1/reserve/:slug/qr.png|qr.svg, javno, keširano.

    0.76.18

    22. septembar 2026.

    Novo

    • Vendor assurance pack. docs/en/bank-platform/VENDOR_ASSURANCE.md odgovara na pitanja koja nabavka banke postavlja dobavljaču: arhitektura, tok podataka, sigurnost, RBAC, izolacija, klasifikacija, privatnost, podobrađivači, rezidencija, enkripcija, ključevi, sigurnost API-ja, SDLC, ovisnosti, SBOM, backup i restore, RTO/RPO, BCP/DR, incidenti, ranjivosti, penetracioni test, revizija, promjene i izdanja, SLA, izlazni plan, izvoz podataka, escrow. Svaka stavka nosi oznaku PLANNED, IMPLEMENTED ili TESTED i putanju do dokaza u repozitoriju; ništa nije INDEPENDENTLY VERIFIED ni PRODUCTION-PROVEN, jer vanjske revizije nema i nijedna banka ne radi u produkciji. Što nema dokaza, piše PLANNED.

    0.76.17

    22. septembar 2026.

    Novo

    • Moduli u ugovoru. Operater u konzoli, Banke, Ljudi i ugovor, bira module koje ugovor daje: Kontrolni centar je osnova svakog ugovora, a Integracije, Građani i zahtjevi, Korporativno te Portfolio i izvještaji banka kupuje ili ne. Nema brojanja transakcija, nema kvote i nema cijene: banka se ne naplaćuje po transakciji.
    • Ruta bez modula odgovara imenom modula. Ono što ugovor ne daje odbija se prije nego što ruta krene, i za ljude banke i za njene sisteme, i za ugrađene stranice iza bankinog tokena; osnova i kupljeni moduli rade dalje. Banka čiji ugovor još nije upisan ne gubi ništa.
    • Licenca u aplikaciji za banke. Navigacija pokazuje samo ono što ugovor daje; kartica Licenca u Podešavanjima ispisuje module, period i stanje ugovora (nije upisan, još nije počeo, važi, istekao), nivo podrške, način instalacije i čije je ime na ekranima. Istekao ugovor se kaže, ne gasi ništa sam od sebe.

    Za programere

    • PUT /v1/admin/banks/:id/entitlement prima modules samo iz control_center, integration_factory, retail, corporate, intelligence (nepoznat je invalid_request); odgovor i GET /v1/bank-auth/me nose licensed i state. Ruta modula kojeg nema odgovara permission_denied s module_not_licensed i imenom modula (@BankModule na kontrolerima, provjera u BankRolesGuard, moduli na principalu iz ugovora pri svakom pozivu). Seed upisuje oba demo ugovora sa svim modulima.
    • Provjere: bank-entitlement.test.ts, nav.test.ts, dvije provjere u scripts/smoke-bank.mjs (smoke vraća puni ugovor na kraju, pa tokovi iza njega nalaze sve module).

    0.76.16

    22. septembar 2026.

    Promijenjeno

    • Rezervacija stola izgleda kao meni. Javna stranica za rezervaciju, i stranica na kojoj gost prati odgovor, više nisu bijeli obrazac. Otvaraju se na najboljoj fotografiji s menija (ili u boji lokala kad slika nema), s logom lokala u uglu, imenom preko cijele širine i jednim dugmetom u boji lokala: isto pismo i isti ton kao stranica koju gost skenira za stolom. Broj osoba se bira jednim dodirom (1 do 6, ili više uz brojač), polja nemaju okvire, a stranica prati tamni režim telefona. Logo i boje prate paket, kao na meniju.
    • Odgovor gostu. Potvrđena rezervacija nudi "Dodaj u kalendar" (.ics fajl s vremenom, adresom i porukom lokala) i "Nazovite" s brojem lokala; otkazivanje traži potvrdu. Dan u sedmici je ispisan na bosanskom.
    • Kartica u pregledniku i podijeljeni link (Instagram, WhatsApp) nose ime i logo lokala, ne XPay.

    Ispravljeno

    • Tanke linije na gostinjskim ekranima bile su crne umjesto blijede: konzolino pravilo za boju okvira nadjačavalo je svaku klasu. Sada je u osnovnom sloju, pa klase rade.

    Za programere

    • GET /v1/reserve/:slug i GET /v1/reserve/status/:token vraćaju logoUrl i palette (po paketu, kao /v1/t/:slug) i coverUrl (prva slika s menija po redoslijedu kategorija).
    • Gostinjska podloga (pismo, paleta, #xpay-guest) je izdvojena u components/guest/ground.tsx; dijele je meni i rezervacije.

    0.76.15

    22. septembar 2026.

    Novo

    • Osjetljive poslovnice. U Postavkama, pod Uvid za banku, firma označava poslovnicu čiju djelatnost banka ne treba čitati u detalje iako vrsta posla to ne kaže: apoteka pod trgovinom, advokat pod uslugama. Označena, banka o njoj vidi samo činjenice o plaćanju (iznos, stanje, vrijeme), nikad sažetak ni stavke, ni u detalju, ni u listi, ni uz stavku izvoda. Oznaka djeluje odmah na svaku banku koja firmu čita; snimak konteksta uzet dok je oznaka uključena i sam kaže da je osjetljiv, a oznaka nikad ne proširuje ono što je snimak rekao. Usluge i freelanceri su osjetljivi i bez oznake, kao i do sada.
    • Vidljivost konteksta u banci. Nova kartica u Podešavanjima aplikacije za banke: matrica po ulogama (bez razloga, s razlogom, osjetljivo bez i s razlogom), plafon i ono što se stvarno čita. Administrator predlaže suženje za jednu ulogu, drugi odobrava, kao svaka promjena; nivo iznad plafona odbija se po imenu prije nego što uđe u red. Vraćanje na plafon je dozvoljeno, iznad plafona nikad. Suženje je na lancu revizije.

    Za programere

    • PATCH /v1/locations/:id prima sensitive; GET /v1/locations ga vraća. Kolona locations.sensitive (migracija 20261105000000_location_sensitive, aditivna). Kad se oznaka promijeni, redovi svake banke u bank_payment_views za tu poslovnicu odmah prate.
    • GET /v1/bank/visibility vraća po ulozi ceiling, narrowing i effective. Red čekanja, predmet PRIVACY, prima i { role, general?, generalWithPurpose?, sensitiveWithPurpose? }; proširenje je invalid_request s razlogom widening; odobrenje piše bank.visibility_narrowed. Uskladišten nivo iznad plafona čita se kao plafon.
    • Provjere: bank-visibility.test.ts, payment-context.test.ts, dvije provjere u scripts/smoke-bank.mjs.

    0.76.14

    22. septembar 2026.

    Novo

    • Rezervacije. Konzola, Rezervacije: uključite po poslovnici i dobijete link (xpay.ba/rezervacija/vaš-naziv) za sajt, društvene mreže ili naljepnicu na vratima. Gost upiše datum, vrijeme, broj osoba, ime i telefon (e-mail po želji) i dobije svoju stranicu na kojoj vidi odgovor; zahtjev stiže u konzolu i mailom na adresu firme. Vi potvrdite ili odbijete, s porukom gostu ako hoćete; gost s e-mailom dobije odgovor i poštom. I gost i lokal mogu otkazati prije sata. Rezervacija telefonom ili na šanku se upiše i odmah je potvrđena. Ko sjedi gdje ostaje stvar sale te večeri: rezervacija se ne veže za sto ni za račun.

    Za programere

    • Javno: GET /v1/reserve/:slug, POST /v1/reserve/:slug, GET /v1/reserve/status/:token, POST /v1/reserve/status/:token/cancel (ograničeno po IP-u). Lokal: GET/POST /v1/reservations, POST /v1/reservations/:id/confirm|decline|cancel. Location.reservationsEnabled, model Reservation, migracija 20261104040000_reservations; događaji reservation.* na realtime kanalu.

    0.76.13

    22. septembar 2026.

    Novo

    • Izvještaj za upravu. Kartica na Pregledu u aplikaciji za banke, za direktore, analitičare i administratore: izbor mjeseca (zadnji puni mjesec je zadan; tekući do danas; dvije godine unazad), glavne brojke uz prethodni mjesec i dugme Preuzmi PDF. Paket na papiru: plaćanja i naplaćeno po načinu, potvrde banke i ručne, vrijeme do potvrde; firme povezane, aktivne, koje dijele, nove veze i pristanci, po segmentu, najveći promet; sravnjivanje (otvoreni, riješeni, odbačeni, otvoreni sada, sati do rješenja, udio automatski sravnjenih, prilivi po ishodu); potraživanja korporativnih klijenata (upisano, naplaćeno, otvoreno, kasni, preplaćeno, dani do naplate, računi kroz XPay); incidenti po ozbiljnosti i otvoreni na kraju. Ime i boja banke na vrhu, kad je banka postavila boju kojoj se može vjerovati.
    • Samo izmjereno. Izvještaj ne sadrži procjene, prognoze ni povrat ulaganja; ono što nije izmjereno nije na njemu, i to piše na dnu svake kopije. Svaki preuzeti fajl je na lancu revizije kao izvoz, s mjesecom.
    • Faza 7 zatvorena. Portfolio menadžera odnosa sa signalima i CRM linkom, Radar prilika s pravilima na ekranu i prekidačem banke, i mjesečni izvještaj za upravu: sve prolazi u smoke testu banke pri svakom prolazu CI-ja.

    Za programere

    • GET /v1/bank/reports/board?month= vraća month (granice i prethodni mjesec), bank, payments, business, reconciliation, corporate, incidents; GET /v1/bank/reports/board.pdf?month= vraća application/pdf sa zaglavljem X-Report-Month i upisuje bank.export (cilj board-report). Uloge: sistemi banke, direktor, analitičar, administratori. Mjesec koji nije počeo, dalji od 24 mjeseca ili pogrešno pisan je invalid_request.
    • Brojke dolaze iz BankAnalyticsService (isti pozivi kao ekrani), pa papir i ekran ne mogu reći različito.
    • Provjere: bank-board-report.test.ts, jedna provjera u scripts/smoke-bank.mjs.

    0.76.12

    22. septembar 2026.

    Novo

    • 0,350 kg na kasi. Mesnica, pijaca ili delikatesa prodaje po kilogramu, a kasa na ekranu je do sada prodavala samo cijele komade. Dodir na artikal čija jedinica nije komad (kg, g, l, dl, m) pita količinu s vage, u hiljaditim dijelovima; cijena je po jedinici, iznos zaokružen na fening kao i sve ostalo, svako vaganje je svoja stavka. Sa stanja se skida tačno toliko (jedan pokret od -0,35), na svakom ekranu piše 0,35 kg, na računu i u fiskalnoj evidenciji stoji 0,35 kg po cijeni za kilogram. Artikal u komadima se i dalje prodaje u cijelim komadima.

    Za programere

    • POST /v1/counter/sales prima quantity kao razlomak; jedinica artikla odlučuje da li je to dozvoljeno. OrderItem.quantityMilli i unitSnapshot (migracija 20261104030000_weight_lines), quantityText na stavkama narudžbe u API-ju.

    0.76.11

    22. septembar 2026.

    Novo

    • Račun kupcu mailom sa kase. Salon, servis ili ordinacija naplati na kasi na ekranu i kupac koji hoće potvrdu do sada nije imao šta dobiti. Na ekranu PRODANO (i na ekranu plaćenog koda) je polje za e-mail: kupac dobije PDF istog oblika kao faktura, iz zatvorenog računa, sa svim stavkama, PDV-om po stopi, načinom plaćanja i pečatom PLAĆENO, s napomenom da nije fiskalni račun i brojem pod kojim je zaveden u fiskalnoj evidenciji. Ništa se o kupcu ne pamti osim adrese u dnevniku. Isti dokument može se i preuzeti kao fajl.

    Za programere

    • POST /v1/sessions/:id/receipt {email} i GET /v1/sessions/:id/receipt.pdf (osoblje, i uređaj s tokenom). Odbija se s not_closed dok račun nije zatvoren; settlement_unavailable kad server nema podešen e-mail.

    0.76.10

    22. septembar 2026.

    Novo

    • Radar prilika. Panel na stranici Portfolio u aplikaciji za banke: šta banka može ponuditi firmi kroz ovu platformu, po četiri pravila. Čeka pristanak (veza koju je banka aktivirala prije dvije sedmice ili više, a firma još ne dijeli podatke), naplata kroz banku (firma izdaje račune izvan XPaya, a banka nije gurnula nijedan red knjige, pa ništa od potraživanja ne stiže do banke), feed izvoda banke (firma izdaje račune, a nijedan feed pod okruženjem banke ne radi) i QR umjesto gotovine (40 % ili više naplate u gotovini). Svaka prilika je nazvana po ponudi, ne po firmi, i nosi činjenice na kojima se upalila; pragovi pišu ispod. Ništa ne profiliše, ne boduje i ne govori o kreditu.
    • Isključen dok ga banka ne uključi. Radar ne računa ništa dok administrator banke ne uključi prekidač u Podešavanjima, kartica Funkcije, kroz red čekanja promjena: jedan predlaže, drugi odobrava. Isključen, panel to i kaže.

    Za programere

    • GET /v1/bank/rm/radar?rule= (iste uloge kao portfolio) vraća enabled, redove s opportunities (rule i facts), sharing, crmUrl, counts po pravilu i thresholds; isključen vraća enabled: false bez redova. Nepoznato pravilo je invalid_request.
    • Portfolio i radar čitaju istu knjigu (BankRmService.book), pa se činjenice računaju jednom.
    • Provjere: bank-radar.test.ts, jedna provjera u scripts/smoke-bank.mjs.

    0.76.9

    22. septembar 2026.

    Novo

    • Opomene po pravilu. Kupci, panel Opomene same: prekidač i tri broja, koliko dana poslije roka ide prva opomena (3), pa svakih koliko dana (14), i najviše koliko puta po računu (3). Svako jutro oko 9 XPay šalje istu opomenu koju šalje dugme na kupcu: svi dospjeli računi s linkovima, na jeziku kupca, u trail-u piše da je poslao sistem. Kupac bez e-mail adrese se preskače, opomenut u zadnja 24 sata takođe, a broj opomena se broji po računu pa treći put ostaje vama. Isključeno dok firma ne uključi: opomena je pismo u njeno ime. Dugme Pošalji dospjele sad radi po istom pravilu kad god hoćete.

    Za programere

    • POST /v1/customers/remind-due (menadžer) vraća {customers, sent, failed, skipped}. Pravilo u invoiceSettings (autoRemind, remindAfterDays 1 do 60, remindEveryDays 1 do 90, remindMaxTimes 1 do 10). Invoice.remindedCount i lastRemindedAt, migracija 20261104020000_invoice_reminders. Cron 0 7 * * *.

    0.76.8

    22. septembar 2026.

    Novo

    • Kupci iz fajla, prije prvog računa. Komunalno preduzeće i stanodavac imaju spisak korisnika prije nego što izdaju išta; do sada su kupci nastajali usput, iz uvoza računa. Kupci, dugme Uvoz iz fajla: CSV s nazivom i, po želji, šifrom, adresom, e-mailom, JIB-om, telefonom, jezikom i napomenom, kolone na bosanskom ili engleskom, isti čitač fajla kao za račune. Prvo pregled: koliko je novih, koliko već poznatih (po šifri, pa po JIB-u, pa po nazivu), i svaki red koji ne valja s razlogom. Poznatom kupcu se dopune kolone koje fajl nosi, ostalo mu ostaje; novi se doda. Fajl s ijednim problemom ne upisuje ništa, ni dobre redove, jer se za pola uvezen spisak ne zna koja je polovina.

    Za programere

    • POST /v1/customers/import {csv, preview?} (menadžer). Čitač u apps/api/src/modules/customers/customer-file.ts, do 5000 redova.

    0.76.7

    22. septembar 2026.

    Novo

    • Portfolio. Nova stranica u aplikaciji za banke, na kojoj menadžer odnosa sada i slijeće: svaka firma koja dijeli podatke s bankom u jednom redu, sa naplaćenim u zadnjih trideset dana prema trideset prije, udjelom gotovine, zadnjom naplatom, otvorenim i kasnim potraživanjima, otvorenim slučajevima, poslovnicama, feedom banke, referencom i proizvodima banke. Firma koja još nije pristala je broj, ne red.
    • Deset signala s pravilima na ekranu. Nova, raste, pada, tiha, kasne potraživanja, otvoreni slučajevi, puno gotovine, bez feeda, bez CRM reference, bez proizvoda. Svaki signal je pravilo s pragom koji piše na istoj stranici, i svaki nosi brojke na kojima se upalio: menadžer vidi zašto, ne to da je neki bod tako rekao. Ništa ne boduje, ne rangira i ne predviđa. Filter po jednom signalu, brojač po svakom.
    • Link na CRM banke. Banka u Podešavanjima, kartica Funkcije, upiše adresu svog CRM-a s oznakom mjesta za referencu firme; nakon toga svaki red portfolija s referencom banke ima dugme Otvori u CRM-u. Adresa se mijenja kao i sve drugo u banci: jedan administrator predlaže, drugi odobrava, a promjena je na lancu revizije. Tu je i prekidač Radara prilika, za sljedeću stavku.

    Za programere

    • GET /v1/bank/rm/portfolio?signal= (sistemi banke, menadžer odnosa, operativa, direktor, administratori) vraća redove s facts, signals (key i facts), crmUrl, counts, sharing, waitingForConsent, crmConfigured i rules. GET /v1/bank/features vraća crmUrlTemplate i opportunityRadar.
    • Red čekanja promjena primjenjuje predmet FEATURE: after nosi crmUrlTemplate (https adresa sa {ref}, ili null za brisanje) i/ili opportunityRadar; odobrenje je na lancu kao bank.features_changed. Nova kolona bank_partners.settings (migracija 20261104000000_bank_settings, aditivna).
    • Provjere: bank-rm.test.ts, dvije provjere u scripts/smoke-bank.mjs, navigacija u nav.test.ts.

    0.76.6

    22. septembar 2026.

    Novo

    • Izvod otvorenih stavki na engleskom. Kupac čiji računi idu na engleskom dobija i izvod na engleskom: riječi, datumi (22 Sep 2026) i format brojeva (1,250.00 KM) kao na računu, a fajl se zove Statement umjesto IOS. Jezik je onaj koji piše na kupcu; kad ga kupac nema, odlučuju njegovi računi, pa kupac kome je sve išlo na engleskom ne dobija izvod na bosanskom zato što niko nije popunio polje.
    • Svi PDF-ovi serije u jednom ZIP-u. Na seriji iz fajla (Fakture, Uvoz) dugme Preuzmi PDF-ove daje jednu arhivu sa svim izdatim računima serije, po redu iz fajla, za štampariju: komunalno ima stotine računa bez e-mail adrese koji se štampaju i nose. Nacrti i stornirani nisu unutra, iz istog razloga iz kojeg se ne šalju. Isti PDF kao onaj koji kupac preuzima s linka.

    Za programere

    • GET /v1/customers/:id/statement.pdf prati Customer.language, pa jezik računa. GET /v1/invoice-batches/:id/pdfs.zip (menadžer) vraća application/zip sa zaglavljem X-Bill-Count; arhiva je pisana bez biblioteke (apps/api/src/common/zip.ts, store, UTF-8 imena).

    0.76.5

    22. septembar 2026.

    Novo

    • Dnevno zaključenje. Konzola, Fiskalizacija, Dnevno zaključenje: na kraju smjene menadžer pritisne Zaključi dan i XPay zapečati sve od prethodnog zaključenja, po načinu plaćanja: preko banke (ono što je stiglo na račun, u trenutku kad je stiglo), gotovina i kartica kako ih je osoblje upisalo pri zatvaranju stola, napojnice posebno, pa povrati, neto, stolovi koji su otišli bez plaćanja, stolovi zatvoreni kao uplata na račun koju banka još nije vidjela, isplaćene napojnice, ko je zatvarao stolove i koje račune iz fiskalne evidencije period pokriva. Zaključenje ima broj u svojoj seriji po godini (Z-1, Z-2), pečat koji ga veže za prethodno, i PDF. Do sada se isto vidjelo na Pregledu, ali ništa se nije zatvaralo; knjigovođa je dobijao mjesec u komadu.
    • Obračunski dan počinje u 6:00. Zaključenje u jedan ujutro pripada večeri prije, kao što bi ga svaka kasa svrstala. Sto plaćen poslije zaključenja ide u sljedeće. Kad se od prošlog zaključenja ništa nije desilo, dugme to kaže umjesto da napravi prazan izvještaj i potroši broj.

    Za programere

    • GET /v1/day-closes, GET /v1/day-closes/preview?locationId=, POST /v1/day-closes {locationId, note?}, GET /v1/day-closes/:id, GET /v1/day-closes/:id.pdf; menadžer i vlasnik. Model DayClose, migracija 20261104000000_day_close je aditivna.

    0.76.4

    22. septembar 2026.

    Novo

    • Račun za svaki zatvoreni sto, onako kako ga traži Zakon o fiskalizaciji transakcija FBiH. Zakon (Sl. novine 9/26) se primjenjuje najkasnije do avgusta 2027, a podzakonski akti još nisu izašli. Ono što se već zna iz samog zakona ugrađeno je sada: kad se sto zatvori, XPay upiše račun sa svim elementima iz člana 18, nazivom i JIB-om firme, PDV brojem, adresom poslovnice, svakom stavkom sa šifrom, količinom i cijenom, PDV-om po stopi (osnovica i porez u bruto cijeni), načinom plaćanja kako ga zakon dijeli (kartica je gotovinsko, prenos bezgotovinsko, oboje kombinovano), kodom operatera i kodom mjesta poslovanja. Broj je u tri dijela bez praznina (član 19): redni broj po poslovnici i godini, kod mjesta poslovanja, broj ESET-a, npr. 12/1/1.
    • Narudžbenica za svaku narudžbu i korektivni račun za svaki povrat. U ugostiteljstvu zakon poznaje narudžbenicu (član 5) i traži da račun navede na osnovu kojih je izdat; XPay je upiše u trenutku kad sto naruči, u vlastitoj seriji (N-12/1/1). Povrat novca dobije korektivni račun (član 71) koji navodi broj računa i vraća PDV po njegovim stopama srazmjerno. Napojnica nije na računu, pa povrat koji vrati samo napojnicu ne pravi korektivni račun, isto kao u knjizi napojnica.
    • Arhiva koja pokazuje praznine. Svaki dokument je nepromjenjiv i lančano potpisan po poslovnici, kako član 26 traži od arhive. Nova stranica Fiskalizacija u konzoli ima listu dokumenata sa detaljima, dugme Provjeri lanac koje sve izračuna iznova i imenuje prvi dokument koji ne odgovara, i Preuzmi arhivu za knjigovođu ili inspektora. Tu su i spremnost (šta samo firma zna, a račun mora nositi) i polja za kod mjesta poslovanja, broj ESET-a i kod operatera za firmu i za svakog zaposlenog. Dokument bez nekog podatka se svejedno upiše i kaže šta nedostaje; ništa ne zaustavlja prodaju.
    • Šifra artikla i PDV po artiklu. U meniju svaki artikal može imati svoju šifru (bez nje na račun ide šifra iz sistema) i PDV stopu koja odstupa od firme; stopa i šifra se upisuju uz svaku stavku narudžbe u trenutku naručivanja, kao naziv i cijena. Isto i za zalihe.
    • Račun na papiru zna za PDV. Račun koji se štampa preko konektora nosi PDV po stopi čim firma kaže gdje stoji s PDV-om, a zatvoren sto se može štampati ponovo, bez koda i s brojem svog dokumenta. Dok Porezna uprava ne vrati VBR, na papiru i dalje piše da to nije fiskalni račun; kad ga vrati, isti papir nosi naslov FISKALNI RAČUN. Konektor 0.3.1 zna to štampati; stariji štampa kao do sada.

    Šta ne radi dok ne izađe pravilnik

      Za programere

      • GET /v1/fiscal/readiness, GET /v1/fiscal/documents, GET /v1/fiscal/documents/:id, GET /v1/fiscal/export.jsonl, GET /v1/fiscal/chain?locationId=; menadžer i vlasnik. Dokumenti se pišu iz apps/api/src/modules/fiscal/fiscal-draw.ts poslije zatvaranja stola, narudžbe i povrata, a svakih deset minuta prolaz dopiše što je promaklo u zadnja 24 sata. MenuItem.code, MenuItem.taxRatePermille, StockItem.taxRatePermille, OrderItem.taxRatePermille i codeSnapshot, Location.fiscalPlaceCode i fiscalEsetNo, Merchant.fiscalOperatorCode, StaffMember.fiscalOperatorCode. Migracija 20261103000000_fiscal_record je aditivna.

      0.76.3

      22. septembar 2026.

      Ispravke

      • Prepoznato je prepoznato. Priliv knjižen na očekivanje po referenci klijenta brojao se kao prepoznat samo kad ga je matcher sam zatvorio; priliv kojem je matcher zbog razlike u iznosu otvorio slučaj nije ulazio u "prepoznato po referenci klijenta" iako je stajao pod manje ili više. Sada se broji svaki priliv knjižen na očekivanje, kako i riječ govori. Provjera u CI-ju je to našla na svježoj bazi.

      0.76.2

      22. septembar 2026.

      Novo

      • Knjiga korporativnih klijenata u analitici. Kartica Korporativno čita račune i knjigu potraživanja kao jednu knjigu za period: upisano i koliko, naplaćeno, otvoreno i koliko od toga kasni, preplaćeno, prosjek dana od upisa do priliva. Tok novca po danu: šta je dospjelo i šta je stiglo. Iste brojke po povezanoj firmi, najotvorenije prvo; klik na firmu otvara entitet (naziv, ID broj) i njene poslovnice jednu po jednu.
      • Faza 6 zatvorena. Knjiga klijenta kroz banku bez XPay kodova, Smart Lockbox koji imenuje šta je svaki priliv ispao, i analitika potraživanja i toka novca po firmi i poslovnici: sve prolazi u smoke testu banke pri svakom prolazu CI-ja.

      Za programere

      • GET /v1/bank/analytics/corporate?from=&to=&merchantId= vraća uz dosadašnje i receivables, cashflow, perLink i, s merchantId, breakdown (entitet i poslovnice). Tuđa ili nedijeljena firma je not_found.
      • Provjere: jedna provjera u scripts/smoke-bank.mjs.

      0.76.1

      22. septembar 2026.

      Novo

      • Smart Lockbox izvještaj. Za jednog klijenta ili za sve klijente banke koji dijele, za period (zadano trideset dana do danas, najviše godina): svaki priliv koji su izvodi i feedovi donijeli stoji pod jednom od sedam riječi, upareno, na pregledu, manje, više, kasno (plaćeno u cijelosti nakon dospijeća), duplo (slučaj kaže da je udvostručio već uzet priliv) i nepoznato (nema šta da se upari, ili odbačeno). Novac je važniji od otvorenog slučaja: priliv koji je matcher knjižio i uputio osobi zbog razlike stoji pod manje ili više, ne na pregledu. Riječi se broje i sabiraju nad svim prilivima; do pet stotina se izlista s uparenim očekivanjem i slučajem. Pored priliva, očekivanja dospjela u periodu (računi i potraživanja) s naplaćenim i otvorenim, i koliko je priliva prepoznato po referenci klijenta, a koliko po XPayevoj: lockbox radi na referencama koje klijent već štampa.
      • Panel Smart Lockbox na ekranu Naplata. Period, sedam pločica koje filtriraju listu, sažetak očekivanja, CSV izvoz koji ide na revizijski lanac banke.

      Za programere

      • GET /v1/bank/collections/lockbox?merchantId=|bankBusinessRef=&from=&to= i GET /v1/bank/collections/lockbox.csv (isti parametri; X-Rows, bank.export s ciljem lockbox na lancu). Riječ se izvodi u bank-lockbox.ts iz matchStatus, uparenog plaćanja i slučajeva.
      • Provjere: bank-lockbox.test.ts, jedna provjera u scripts/smoke-bank.mjs.

      0.76.0

      22. septembar 2026.

      Novo

      • Knjiga potraživanja kroz banku. Sistemi banke, operativa, platni promet i menadžeri odnosa guraju knjigu korporativnog klijenta (firme koja dijeli s bankom) kroz API, do hiljadu redova odjednom, ili kao datoteku koju izvozi knjigovodstvo: zaglavlje s uobičajenim nazivima kolona na našem ili engleskom, tačka-zarezi ili zarezi, iznosi i datumi kako ih Excel piše ovdje ili vani; prvo se pročita i imenuju neispravni redovi, pa se upiše. Svaki red je potraživanje: plaćanje s referencom klijenta i XPayevom pored, bez izdanog dokumenta. Ista knjiga dva puta ne upisuje ništa dva puta. S brojem kupca red se vodi pod kupcem klijenta (napravljenim od imena kad ga nema), pa ga sanduče računa pokaže čim banka veže svog klijenta za taj zapis.
      • Šest riječi za potraživanje. Otvoreno, kasni, djelimično, plaćeno, preplaćeno, otkazano; uz svako šta je stiglo, šta ostaje i šta je preko. Pregled po klijentu broji i sabira po riječi. Sistemi klijenta i dalje čuju kroz vlastite webhookove, s referencom klijenta kao orderRef.
      • Samo sravnjivanje s bankine strane. Poslovnica prebačena na samo sravnjivanje ne izdaje ništa kroz XPay (računi, kodovi i naplate se odbijaju), a knjiga, sravnjivanje, izvodi i webhookovi ostaju. Upisano na oba lanca.
      • Podsjetnici kroz banku. Svako jutro u sedam i na klik: svako potraživanje koje dospijeva u tri dana ili kasni, još nije naplaćeno i nije podsjećano zadnjih sedam dana, javi se adapteru banke s referencom, iznosom i danom; red se obilježi, a prolaz upiše na lanac. Aplikacija banke podsjeća svog klijenta.
      • Ekran Naplata u aplikaciji za banke. Klijent, brojke po riječi, poslovnice i način rada s prekidačem, knjiga za zalijepiti s čitanjem i upisom, podsjeti sada, lista potraživanja po stanju.
      • Potraživanja i za firme kroz API. POST /v1/receivables prima customerRef (broj kupca) i vodi red pod kupcem.

      Za programere

      • GET /v1/bank/collections?merchantId=|bankBusinessRef=, GET /v1/bank/collections/receivables?state=, POST /v1/bank/collections/ingest (receivables[]), .../import (csv, preview), .../mode (locationId, reconciliationOnly), .../remind. Sanduče računa (/v1/bank/customers/:ref/bills, /v1/embed/bills) sada nosi i kind: "receivable" redove; predaja bez adaptera i bez stranice vraća url: null uz referencu i iznos.
      • Lanac banke: bank.receivables_ingested, bank.collections_mode_set, bank.receivables_reminded; lanac firme: receivables.recorded (sistem), location.reconciliation_only_set_by_bank.
      • Provjere: bank-collections.test.ts, šest provjera u scripts/smoke-bank.mjs.

      0.75.10

      22. septembar 2026.

      Novo

      • Zahtjev za povrat kroz banku. Klijent banke želi novac nazad s uplate koju je XPay vidio da je sjela. Sistemi banke, operativa, platni promet ili podrška građanima traže povrat po pozivu na broj s izvoda ili po uplati, najviše koliko je naplaćeno umanjeno za ono što je firma već vratila i za ono što drugi otvoreni zahtjevi traže. Firma je obaviještena na svom lancu i odlučuje u svojoj konzoli: da ili ne, s napomenom koju banka čita; odbiti može dok novac nije otišao.
      • Banka vraća i potvrđuje, XPay upisuje. Banka javi da je vratila novac sa svoje strane, s vlastitom referencom povrata, pa potvrdi transakcijom kojom potvrđuje povrat. XPay tada upiše firmin vlastiti zapis o povratu, isti kakav piše povrat s ekrana plaćanja, s referencom banke na sebi. Ako zapis ne može (firma je u međuvremenu sama vratila), zahtjev ostaje potvrđen i odgovor kaže zašto; završetak se ponavlja. Ništa ne ide unazad.
      • Sravnjenje se ne prepisuje. Priliv koji je sravnio uplatu i naplaćeni iznos ostaju tačno kakvi su bili; povrat stoji pored njih, kao i kad firma sama vrati. Provjera u smoke testu to tvrdi brojkama.
      • Ekrani. Panel Povrati kroz banku na ekranu Građani (zahtjev iz transakcije s izvoda, "banka je vratila", "potvrdi povrat") i stranica Povrati u konzoli firme (čeka vašu odluku, ranije).
      • Faza 5 zatvorena. Zahtjev za plaćanje, sanduče računa, pametne transakcije i računi, povrati: sve prolazi u smoke testu banke pri svakom prolazu CI-ja, a tokovi u pregledniku prolaze zahtjeve, sanduče i platiočev račun u kontrolnom centru.

      Za programere

      • Banka: POST /v1/bank/refunds (reference ili paymentId, amount, reason, requesterRef), GET /v1/bank/refunds?state=&merchantId=, GET /v1/bank/refunds/:id, POST .../:id/sent (bankReturnRef), .../confirm (confirmationTransactionId), .../complete. Firma: GET /v1/refund-requests, GET .../:id, POST .../:id/approve i .../reject (note).
      • Modeli RefundRequest i RefundRequestEvent (migracija 20261102000000_refund_requests, aditivna), prefiksi rfq_ i rfqe_; Refund.request vodi nazad na zahtjev. Stanja REQUESTED, APPROVED_BY_MERCHANT, SENT_TO_BANK, RETURN_CONFIRMED, COMPLETED, REJECTED.
      • Lanac banke: bank.refund_requested, bank.refund_approved_by_merchant ili bank.refund_rejected_by_merchant, bank.refund_sent, bank.refund_confirmed, bank.refund_completed; lanac firme: refund_request.received, refund_request.approved, refund_request.rejected.
      • Odbijanja: over_refundable (s brojkama), nothing_collected, wrong_state, payment_required.
      • Provjere: bank-refunds.test.ts, četiri provjere u scripts/smoke-bank.mjs.

      0.75.9

      22. septembar 2026.

      Ispravke

      • Firma koja je izdala račun u toku ostaje s dijeljenjem. Tok sandučeta računa je na kraju gasio dijeljenje Studija Vrbas, a lista plaćanja je projekcija koja firmu ispušta tek pri sljedećem prolazu: tok koji odmah zatim otvara najnovije plaćanje dobijao je 404 na detalju. Studio Vrbas sada dijeli od početka, kao i Mrkva i Željo, i ostaje tako.

      0.75.8

      22. septembar 2026.

      Novo

      • Obogaćenje stavke s izvoda. Sistemi banke i njeni ljudi pošalju pozive na broj kako stoje na izvodu (RF, numerički ili XP oblik, do stotinu odjednom) i za svaki dobiju da li je to XPay uplata firme koja dijeli s bankom, kome i gdje je plaćeno, iznose i kada, sažetak svrhe na nivou koji politika vidljivosti daje bez svrhe (sažetak općeg konteksta, ništa od osjetljivog, nikad stavke) i koji dokument je uplata ostavila i dokle ga kanal banke doseže.
      • Pametni računi. Uplata ostavlja dokument izveden iz vlastitog snimka: račun sa stavkama, plaćeni račun ili potvrdu plaćanja. Ništa se ne kopira, pa se ništa ne briše: politika banke po vrsti kaže koliko mjeseci nakon plaćanja kanal banke doseže dokument, i ko ga u banci smije otvoriti: samo platilac, podrška uz svrhu i slučaj, ili svaka uloga po politici vidljivosti (sažetak bez svrhe, cijeli dokument sa svrhom, upisano kao osjetljivo čitanje). PDF na jednoj strani, s napomenom da nije fiskalni dokument.
      • Platiočev račun u aplikaciji banke. Token ugrađenog prikaza dobio je tvrdnju t: stavke s izvoda za koje banka jamči da ih je klijent platio. Iza takvog tokena račun se otvara cijeli, kakva god bila kategorija, jer je platiočev; transakcija za koju token ne jamči nije nađena. Stranica /embed/receipt prikazuje račun i PDF.
      • Politika dokumenata u Podešavanjima. Kartica Dokumenti pokazuje zadržavanje i pristup po vrsti (zadano 24, 36 i 24 mjeseca, po politici vidljivosti; granice 12 do 120) i predlaže promjenu kroz red promjena: jedan predloži, drugi odobri, primijeni se odmah.
      • Transakcija s izvoda na ekranu Građani. Podrška upiše poziv na broj i vidi obogaćenje kako bi ga vidjela aplikacija banke, PDF za banku na svom nivou, i otvara račun kako ga platilac vidi.

      Za programere

      • POST /v1/bank/transactions/enrich (references, do 100), GET /v1/bank/transactions/:reference/document?purpose=&caseRef= i .../document.pdf, GET /v1/bank/documents/policy. Javno: GET /v1/embed/transactions/:reference?token= i .../document.pdf?token=. POST /v1/bank/customers/:ref/embed-token prima transactions.
      • Red promjena prima predmet PRIVACY s after: { documentType, retentionMonths?, staffAccess? }; odobrenje piše BankDocumentPolicy (migracija 20261101000000_bank_document_policies, aditivna, prefiks bdp_) i bank.document_policy_changed na lanac. Čitanje dokumenta sa svrhom piše bank.document_read.
      • Odbijanja: document_expired, not_paid, customer_only, not_support, support_case_required, transaction_not_vouched.
      • Provjere: bank-smart.test.ts, četiri provjere u scripts/smoke-bank.mjs, tok u pregledniku apps/bank/e2e/bills.e2e.ts proširen na plaćeni račun i platiočev prikaz.

      0.75.7

      22. septembar 2026.

      Novo

      • Preuzimanje dodataka. Stranica Integracije na sajtu dobila je dio "Dodaci za prodavnice": WooCommerce, PrestaShop i OpenCart, svaki sa arhivom za preuzimanje, verzijom platforme koju traži i koracima za instalaciju. Arhive se pakuju iz repozitorija pri svakom izdanju, pa su uvijek na verziji koja je na produkciji. Uz njih piše i ono što je istina: dodaci su novi, prije prve prave narudžbe javite se, pomažemo pri prvoj probi od 1 KM.

      Za programere

      • scripts/webshop-plugins.mjs --pack-only --out <dir> pakuje bez PHP-a; slika sajta ga zove prije next build i arhive završe u apps/web/public/downloads/ (git-ignored).

      0.75.6

      22. septembar 2026.

      Novo

      • Promotivni videi za kafiće i restorane i za banke. U promo/ su dva videa na bosanskom (72 i 84 sekunde): prvi prati jedan račun u Ćevabdžinici Željo od naljepnice na stolu, preko menija, kuhinje i konobarovog tableta, do koda za plaćanje i konzole; drugi vodi banku od instant plaćanja koje postoji a nema gdje da se plati, preko kontrolnog centra nad deset firmi iz svih djelatnosti, do pilota u tri koraka. Svaki kadar je snimak aplikacije kakva radi. Podaci koji se vide, snimanje ekrana i render su tri skripte koje se ponove kad se proizvod promijeni; kako, piše u promo/README.md.

      Za programere

      • scripts/dev-postgres.mjs: ponovno pokretanje slušača je ograničeno na deset sekundi. Slušač čiji start nikad ne završi do sada je ostavljao port mrtav bez ijedne poruke poslije "restarting the listener"; sada preda proces nadzorniku, koji podigne novi.

      0.75.5

      22. septembar 2026.

      Novo

      • Sanduče računa (Bills Inbox) za klijente banke. Banka vodi svog klijenta pod vlastitom referencom koju XPay ne tumači; sistemi banke ili podrška građanima vežu tu referencu za zapis kod izdavaoca po broju potrošača s računa (firma koja dijeli s bankom). Od tada je sanduče izdati računi tih zapisa, u četiri riječi: predstoji, uskoro (u roku od sedmice), dospjelo i plaćeno, dospjelo prvo, svaki s referencom, iznosom za platiti i vlastitom stranicom računa. Izdavalac koji prestane dijeliti nestaje iz sandučeta odmah; kad se ukloni posljednji izdavalac, ide i referenca.
      • Plati odabrano. Za svaki odabrani račun jedna predaja u aplikaciju banke: referenca, iznos i link koji gradi adapter banke kad okruženje tvrdi predaju u mobilnu aplikaciju, inače stranica računa. Račun koji je plaćen, nije klijentov ili nema referencu odbija se po imenu. Domaći trenutni prenos je jedan nalog, pa je jedan račun jedna predaja. XPay ne pomjera novac.
      • Ugrađeni prikaz s tokenom koji banka potpisuje. Aplikacija banke otvara sanduče kao web prikaz s tokenom koji imenuje banku i klijenta i traje minute: potpisan HMAC tajnom koju okruženje banke već drži, pod vlastitom namjenom, pa token nikad ne prolazi kao obavijest ni obavijest kao token; ili ga XPay iskuje na zahtjev. Izmijenjen, istekao ili tuđi token odbija se jednako. Iza tokena se čita sanduče i traži predaja, ništa drugo.
      • Ekran Građani u aplikaciji za banke. Za operativu i podršku građanima: klijent po referenci, njegovi izdavaoci, vezanje po broju potrošača, sanduče, plati odabrano kako bi to uradila aplikacija, i link koji aplikacija otvara. Podrška građanima sada slijeće ovdje.
      • Zahtjevi za plaćanje se čiste nakon dvije godine. Završeni zahtjevi (odbijeni, istekli, povučeni, plaćeni) brišu se dvije godine nakon kraja, kako je obećano u klasifikaciji podataka; plaćanje izdano za zahtjev ostaje firmino.

      Za programere

      • GET /v1/bank/customers/:ref, POST /v1/bank/customers/:ref/billers (merchantId ili bankBusinessRef, customerRef ili customerId), DELETE .../billers/:id, GET /v1/bank/customers/:ref/bills?state=, POST /v1/bank/bills/handoff (customerRef, billIds), POST /v1/bank/customers/:ref/embed-token (minutes). Javno: GET /v1/embed/bills?token= i POST /v1/embed/bills/handoff.
      • Token: xbe1.<base64url {b, r, iat, exp}>.<hex HMAC-SHA256 nad "xpay-embed:v1:" + claims> HMAC tajnom okruženja; provjera nad tajnama svih uključenih okruženja, pa rotacija s preklapanjem zadržava stare tokene do kraja preklapanja.
      • Model BankCustomerBiller (migracija 20261031000000_bank_customer_billers, aditivna), prefiks bcb_; BankCustomerReference se pravi pri prvom vezanju i briše s posljednjim. Stranica /embed/bills u apps/bank radi bez sesije.
      • Čišćenje: HousekeepingService.sweepPaymentRequests svaki dan u 5.
      • Provjere: bank-bills.test.ts, pet provjera u scripts/smoke-bank.mjs, tok u pregledniku apps/bank/e2e/bills.e2e.ts; pomoćnik signInAtApi u apps/bank/e2e/helpers.ts.

      0.75.4

      22. septembar 2026.

      Popravljeno

      • Napojnica je neto, svuda isto. Vlasnikova odluka: napojnica je neto. Pravilo je i do sada postojalo na stolu i u knjizi napojnica (povrat prvo ide iz napojnice), ali ga pregled i izvještaj po stolovima nisu primjenjivali, a knjigovodstveni izvoz je cijeli povrat knjižio na robu s nulom u koloni Napojnica. Sada pločica "od toga napojnice" na pregledu i kolona napojnica po stolu odbijaju vraćeno, izvoz u redu povrata upisuje dio koji je vraćen iz napojnice u kolonu Napojnica a ostatak na robu, i napojnica na računu koji je stigao kraći više se ne broji ni u izvozu, kao što se ne broji ni na pregledu. Iste brojke za istu večer, ko god ih čita.

      Za programere

      • tipNetOf i refundSplit u apps/api/src/modules/tips/tip-ledger.ts su to jedno pravilo; pregled, izvještaj po stolovima, izvoz i knjiga napojnica ga dijele.

      0.75.3

      22. septembar 2026.

      Novo

      • Štampaj račun. Konobar na tabletu i menadžer u konzoli imaju dugme koje pošalje račun za sto na štampač lokala: svaka stavka, ukupno, plaćeno i preostalo, i kad lokal prima kodove, QR kod i poziv na broj za plaćanje s telefona. Gost skenira s papira, uplata legne, sto se sam zatvori. Račun s kodom zauzme sto isto kao dugme "Pokaži kod"; ako je kod već živ, štampa se s njim, ne izdaje se drugi. Bez štampača dugme kaže da ga nema i gdje se podešava. Ovo nije fiskalni račun i tako piše na papiru: fiskalni izdaje kasa.
      • Štampač na konektoru. Stranica konektora dobila je "Štampač računa": adresa termalnog štampača na mreži, širina papira (58 ili 80 mm), kodna strana 852 za Č, Ć, Š, Ž i Đ (uključi se kad probna štampa pokaže da štampač zna) i QR kod. "Probna štampa" ispiše probni papir sa svim tim slovima. Konektor javlja štampač u otkucaju, pa konzola pod Kasa vidi "Štampač računa" uz ono što konektor prati. Ako je već podešen printer-tap s pravim štampačem, koristi se on.

      Za programere

      • POST /v1/sessions/:id/print (STAFF, payments:write, withCode po izboru) vraća queued, printers i reference; 409 no_printer kad nijedan konektor sa štampačem ne javlja za tu poslovnicu. Račun putuje kao realtime događaj print.requested s cijelim računom u data; print.* se tretira kao događaj o novcu (traži payments:read, ne stiže na kuhinjske ekrane). Konektor 0.3.0: printer u konfiguraciji, lokalne rute POST /printer, DELETE /printer, POST /printer/test, ESC/POS render u receipt.ts (12 testova), printer.ts za port 9100.

      0.75.2

      22. septembar 2026.

      Novo

      • Zahtjevi za plaćanje (Request-to-Pay) na platformi za banke. Firma koja dijeli s bankom zamoli građanina ili drugu firmu da plati (B2P, B2B, institucija građanina kao I2P), ili građanin zamoli građanina (P2P) bez ikakve firme na XPayu. Primalac je klijent banke po referenci koju banka vodi, ili e-mail odnosno telefon na koji banka isporučuje. Zahtjev ima iznos, svrhu, referencu tražioca, dospijeće i pravilo za djelimično plaćanje; živi do kraja dana dospijeća, sedmicu kad dospijeća nema, ili do trenutka koji je zatražen, najviše devedeset dana.
      • Život zahtjeva, korak po korak. Nacrt, poslan (adapter banke je obaviješten kad okruženje to tvrdi), isporučen i pogledan kako banka javi, samo naprijed; zatim prihvaćen, odbijen, istekao po satu, povučen ili plaćen. Svaki korak je događaj na zahtjevu, s imenom onoga ko ga je napravio; prihvatanje, plaćanje, odbijanje i povlačenje su na revizijskom lancu banke. Druga banka za zahtjev ne zna.
      • Prihvatanje izdaje plaćanje i predaju. Kad primalac prihvati, firmin zahtjev postaje obično XPay plaćanje s referencom, otvoreno sat vremena, a odgovor kaže gdje aplikacija banke vodi primaoca: link koji gradi adapter banke kad okruženje tvrdi predaju u mobilnu aplikaciju, inače stranica samog plaćanja. Priliv koji sravni to plaćanje, kroz isti cjevovod kao svaki drugi, čini zahtjev plaćenim; djelimičan priliv samo kad je zahtjev to dozvolio. Firmin zahtjev se ne plaća izvještajem. Građaninov zahtjev banka izvrši sama i javi s vlastitom referencom.
      • Podsjetnici. Ručno najviše tri po zahtjevu i ne dva u istom satu; zahtjev koji dospijeva sutra dobije jedan sam od sebe. Povlačenje prihvaćenog zahtjeva otkazuje i plaćanje izdano za njega; novac koji je već stigao ostaje sravnjivanju.
      • Ekran Zahtjevi za plaćanje u aplikaciji za banke. Lista po stanju s brojem po stanju, obrazac za novi zahtjev (firma koja dijeli, primalac, iznos, svrha, dospijeće, odmah ili nacrt), detalj sa cijelom pričom i radnjama koje su kome dozvoljene: operativa, platni promet i podrška prave, šalju, podsjećaju i povlače; operativa i podrška građanima bilježe šta je primalac uradio i prihvataju za njega. Sekcija je u navigaciji tih uloga; direktor, analitičar, inženjer i revizor je nemaju.

      Za programere

      • POST /v1/bank/requests, GET /v1/bank/requests (filter po stanju i firmi, kursor, brojanje po stanju), GET /v1/bank/requests/:id sa događajima, POST /v1/bank/requests/:id/send, .../remind, .../accept (odgovor nosi handoff), .../progress (DELIVERED, VIEWED, DECLINED, PAID samo za P2P uz bankReference), .../cancel. Sistemski ključ banke prolazi sve; uloge su na svakoj ruti.
      • Modeli PaymentRequest i PaymentRequestEvent (migracija 20261030000000_payment_requests, aditivna); prefiksi preq_ i prev_. Plaćanje izdano za zahtjev nosi metadata.paymentRequestId i orderRef jednak referenci tražioca.
      • Adapter: deepLink gradi predaju kad okruženje tvrdi mobileDeepLink; sendNotificationContext čuje slanje i podsjetnik kad ga okruženje tvrdi. Bez okruženja koje tvrdi, predaja je stranica plaćanja.
      • Sat: svake minute istekli zahtjevi prelaze u EXPIRED, zahtjevi s dospijećem sutra dobiju podsjetnik, a prihvaćeni s plaćenim plaćanjem se povežu; isto povezivanje se dešava i pri svakom čitanju.
      • Provjere: bank-requests.test.ts (primalac, život, podsjetnici, stanja, šta sravnjuje), deset provjera u scripts/smoke-bank.mjs, i tok u pregledniku apps/bank/e2e/requests.e2e.ts.

      0.75.1

      22. septembar 2026.

      Novo

      • Redoslijed u meniju bira vlasnik. Umjesto jednog prekidača "po traženosti", svaka poslovnica bira pravilo po kojem se jela u kategoriji ređaju na telefonu gosta: kako sam posložio, najviše naručivano, najveći promet, najveća marža po porciji ili najviše zarađeno (marža puta prodano). Pravilo gleda zadnjih 30 dana narudžbi; dok ih nema dovoljno, meni stoji kako je posložen. Jela bez nabavne cijene ne učestvuju u dva pravila koja je traže i ostaju u vašem redoslijedu ispod rangiranih; rasprodano i dalje ide na dno, a oznaka "najtraženije" ne zavisi od pravila. Nema formule koja miješa maržu i prodaju: koliko koja vrijedi je odluka lokala, ne koda.
      • Računi zatvoreni kao uplata na račun se vide. Kad menadžer zatvori sto na gostovu riječ da je prenos poslan, to se i dalje ne knjiži u promet (promet broji samo ono što je banka vidjela). Ali pregled sada uz "čeka potvrdu" kaže koliko je računa tako zatvoreno i koliko od njih banka još nije potvrdila, pa veče s tri takva stola više ne izgleda kao veče bez ičega. Konobar na tabletu zatvara samo gotovinu i karticu, kao i do sada; prenos potvrđuje banka ili konzola.

      Za programere

      • Poslovnica ima menuRanking (VENUE, POPULARITY, REVENUE, MARGIN, PROFIT) umjesto sortMenuByPopularity; migracija prenosi uključeni prekidač u POPULARITY. Pregled (/v1/analytics/overview) vraća closedAsTransfer (broj i iznos).

      0.75.0

      21. septembar 2026.

      Novo

      • XPay za PrestaShop (1.7.6 do 8.x). Kupac na kasi izabere XPay, narudžba se napravi u statusu "Čeka uplatu (XPay)", modul napravi račun i pošalje kupca na stranicu s kodom. Webhook s provjerom potpisa označi narudžbu plaćenom (Payment accepted, s upisanom uplatom i brojem računa), "Stiglo manje (XPay)" kad stigne manje, bilješka za ostalo. Stranica potvrde sama provjeri stanje kad se kupac vrati, a kad kod istekne nudi "Plati ponovo QR kodom" za istu narudžbu. Nudi se samo za korpu u KM i tek kad je ključ upisan.
      • XPay za OpenCart (4.0.2.x). Isti tok: račun na "Potvrdi narudžbu", stranica s kodom, webhook s potpisom, tri statusa narudžbe po izboru (dok čeka, kad stigne, kad stigne manje), komentar u historiji za svaki ishod, a stranica uspjeha sama provjeri stanje kad se kupac vrati i kaže da je uplata stigla.
      • Arhive za preuzimanje. pnpm run plugins provjeri sva tri dodatka harnessom bez instalirane prodavnice i spakuje ih u obliku koji svaka platforma očekuje: xpay-woocommerce.zip, xpay-prestashop.zip i xpay.ocmod.zip. Harnessi se od sada vrte i u CI-ju.

      Za programere

      • Zajednički dio dodataka (tri poziva i provjera potpisa) je jedna klasa bez ijedne zavisnosti od prodavnice, ista u PrestaShop i OpenCart paketu, pa se harnessom provjerava odvojeno od svake platforme.

      0.74.8

      21. septembar 2026.

      Novo

      • Brojevi firmi na ekranu operatera. Svaka firma dobije stalni četverocifreni broj koji ide u svaki poziv na broj, pa ih ima 9000 i format se ne može proširiti bez dogovora sa svakom bankom koja ga je usvojila. API je to odavno brojao i upozoravao u svom dnevniku na 80% i 95%, a dnevnik niko ne čita; sada pregled operatera ima pločicu sa postotkom, trakom i brojem slobodnih, koja mijenja boju kad bi dnevnik upozorio.

      0.74.7

      21. septembar 2026.

      Novo

      • Provjera spremnosti za UAT. Petnaest scenarija nad adapterom i podešavanjima okruženja, bez dodira s firmom ili plaćanjem: adapter postoji i smije voditi okruženje, tvrdnje su u dosegu adaptera, HMAC tajna se čuva, obavijest potpisana njome prolazi a lažna, stara ili nepotpisana se odbija, omotnica i lista se čitaju, mapa polja banke čita, verzije sheme su postavljene, produkcija ima listu adresa ili traži certifikat, adapter odgovara na očitavanje i provjeru zdravlja, politika prijave je cijela i njen provider odgovara, i kaže se šta čeka u mrtvom pismu. Svaki scenarij prođe, padne ili se ne odnosi na okruženje. Izvještaj ostaje na okruženju; sve prošlo vodi nacrt u "spremno za UAT", pad vraća u nacrt. Ništa nikad ne kaže "dokazano u produkciji": to kaže samo prihvatni test stvarne banke, a ovaj proizvod to ne kaže ni za jednu. Svaka provjera je na lancu s onim što je palo.
      • Dugme i izvještaj na kartici okruženja na ekranu Integracije.

      Provjereno

      • Bank smoke sa šest novih provjera: demo sandbox prolazi sve i postaje spreman za UAT, izvještaj ostaje revizorima, politika prijave bez tajne pada i vraća u nacrt, analitičar i druga banka odbijeni, generički webhook na UAT okruženju prolazi iste scenarije preskačući što ne radi, svaka provjera na lancu. Provjera prođena u pregledniku.

      0.74.6

      21. septembar 2026.

      Novo

      • Portal za developere. Za jedno okruženje, sve što bankin developer treba, izvedeno iz okruženja i ove instalacije: adrese na koje njeni sistemi šalju obavijesti (i host za klijentski certifikat kad ga instalacija ima), zaglavlja i potpis s rokom, oblici obavijesti (jedna, lista, omotnica) i mapa polja, šta se dobije nazad i kad je odbijeno, ugovor očitavanja, događaji koje bankina sesija čuje, primjer politike prijave preko banke s demo izdavaocem.
      • Studio: potpiši i pošalji. Inženjer zalijepi HMAC tajnu, koja ostaje u stranici i ide samo u potpis, uredi tijelo obavijesti, potpiše je i pošalje u okruženje odavde; vidi zaglavlje potpisa, istu poruku kao curl i odgovor. Put od bankinog sistema do naplaćenog računa prođe se prije nego što postoji ijedna linija bankinog koda.
      • Uzorak izvoda camt.053 s jednom uplatom na upisani poziv na broj, koji firma učita u konzolu: drugi put do naplaćenog računa, bez ikakve integracije.
      • Dnevnik prijema s ponavljanjem iz 0.74.1 je preglednik obavijesti.

      Popravljeno

      • Zaglavlja omotnice u CORS-u. Preglednik nije smio poslati X-Message-Id, X-Correlation-Id i X-XPay-Schema-Version, pa je slanje iz studija padalo bez traga na serveru; sada smije, a X-Correlation-Id i X-Rows se i čitaju iz odgovora.

      Provjereno

      • Bank smoke s tri nove provjere: portal imenuje adresu feeda, zaglavlja, oblike i demo izdavalac; analitičar i druga banka odbijeni; uzorak izvoda napravljen za račun firma učita i račun je plaćen. Studio prođen u pregledniku od potpisa do naplaćenog računa.

      0.74.5

      21. septembar 2026.

      Novo

      • Poveži konektor. U konzoli, pod Kasa, vlasnik klikne "Poveži konektor" i dobije kod od osam slova koji vrijedi 30 minuta i radi jednom. Na računaru pored kase konektor ima svoju stranicu (http://127.0.0.1:9110); kod se upiše tamo, konektor sam uzme svoj ključ, sačuva ga kod sebe i javi se konzoli. Vlasnik ključ nikad ne vidi. U konzoli se ključ zove "Konektor <ime računara>" i može se opozvati kao svaki drugi.
      • Pronađi kasu, na samom konektoru. Stranica konektora ima dugme koje pretraži računar (fiskalni servis, folderi sa računima, instalirani programi kasa) i uz svaki folder ponudi "Prati ovaj folder". Ko zna putanju ili adresu, upiše je ručno: folder, adresu kase preko HTTP-a ili štampač (kasa štampa na konektor, konektor proslijedi pravom štampaču). Sve što se izabere odmah radi i upiše se u fajl konektora, pa preživi ponovno pokretanje. Ono što se prati može se i ukloniti, s iste stranice.
      • Konektor krene bez ičega. Prije je odbijao da se pokrene bez fajla i bez ključa; sada krene, kaže da nije povezan i čeka kod. Poziv kase na lokalni /payments prije povezivanja dobije jasan odgovor, ne grešku mreže. Ručno napisan fajl, --config i XPAY_API_KEY iz okruženja rade kao i prije.
      • Instalacija na računar pored kase. Konektor se sada pakuje u jedan fajl (xpay-konektor.js, sve unutra) uz install.ps1 koji na Windows računaru nađe ili instalira Node.js, stavi konektor u C:\XPay\konektor, podesi da se sam pokreće pri svakom paljenju i sam diže ako padne, i otvori njegovu stranicu. Uklanjanje je uninstall.ps1. Tehničar više ne piše ništa rukom.

      Popravljeno

      • Uputstvo za servisera imalo je znakove koji liče na oznake. Tekst koji se kopira sa stranice Kasa sadržavao je "<ključ>" i "<broj računa>", što je konzola tumačila kao oznake i bilježila grešku pri svakom prikazu stranice; sada su u uglastim zagradama.

      Za programere

      • POST /v1/connectors/pairing-code (vlasnik) izdaje kod; POST /v1/connectors/pair (bez prijave, deset pokušaja u minuti po adresi) zamijeni kod za ključ s pravima payments:read i payments:write i vrati apiUrl, poslovnicu i ime firme. Nepoznat, iskorišten i istekao kod dobiju isti odgovor (404, reason code_spent). Konektor 0.3.0: lokalne rute GET /state, POST /pair, POST /detect, POST /adapters, DELETE /adapters/:index uz postojeće GET /health i POST /payments.

      0.74.4

      21. septembar 2026.

      Novo

      • Dovedi firmu. Jedan poziv od bankine reference napravi firmu, njenu prvu poslovnicu s računom na koji stiže novac, vlasnikov nalog u konzoli s pozivnicom koja ide vlasniku na e-mail i nikad banci, i bankinu vezu s referencom i proizvodima od prvog trenutka. Veza je predložena: uvid ostaje na vlasniku, a banka firmu čita onog dana kad vlasnik uključi dijeljenje. Ista referenca dva puta je ista firma, napravljena jednom. Što banka ne kaže, adapter njenog okruženja može naći po referenci; adapteru se i javi da firma postoji, kad okruženje to tvrdi. Račun koji druga firma već ima odbija se prije nego što se išta upiše. Sve je na lancu banke i na lancu firme.
      • Obrazac na ekranu Firme za operacije i menadžere odnosa.

      Popravljeno

      • CI ne pada na skladištu artefakata. Spremište artefakata na GitHubu odgovorilo je 403 kad je prostor naloga bio pun i time srušilo cijeli prolaz, iako je kod bio ispravan. Slanje popisa komponenti i tragova prolaza kroz preglednik više ne obara prolaz, a čuva se kraće.

      Provjereno

      • Bank smoke sa sedam novih provjera: firma napravljena s vezom i bez predane pozivnice, ista referenca ponovo, naziv koji je našao demo adapter, tuđi račun odbijen, firma nečitljiva do uvida, analitičar odbijen, zapis na lancu. Obrazac prođen u pregledniku.

      0.74.3

      21. septembar 2026.

      Novo

      • Prijava preko banke. Banka koja svoje ljude prijavljuje svojim sistemom upiše u okruženje gdje je njen provider i kakva je politika (izdavalac, klijent, mapiranje grupa na uloge, da li se novi ljudi dodaju pri prijavi i s kojom ulogom), a tajnu klijenta čuva kao kredencijal. Osoba na ekranu za prijavu izabere "Prijava preko banke", upiše oznaku banke i ode kod providera; nazad dolazi s kodom koji API zamijeni za identitet, provjeri potpis, izdavaoca, primaoca, rok i nonce, pita adapter šta identitet znači i primijeni politiku banke: ko je već vezan za taj identitet ulazi kakav jeste, ko je poznat po e-mailu se veže, ko je nov dobije ulogu koju mapiranje daje njegovoj grupi ili podrazumijevanu, a bez uloge ili bez politike se odbija, s razlogom koji ekran zna reći. Aplikacija dobije jednokratnu kartu i zamijeni je za sesiju. Uloge nikad ne dolaze iz preglednika ni direktno od providera; mapiranje je bankino, na serveru. Drugi faktor je providerov.
      • Demo provider. Za okruženje na demo adapteru API je i provider: stranica za prijavu koja pita e-mail, ime i grupu i ništa ne provjerava, dokument otkrivanja i izdavanje tokena. Odgovara samo za demo okruženje čija politika imenuje baš taj izdavalac, a demo adapter nikad ne vodi produkciju.
      • Na lancu. Identitet, član kojeg je politika napravila i sesija, svaki put.
      • SAML nije tu. Traži provjeru XML potpisa s kanonizacijom, za koju u kodu nema biblioteke; napisati je rukom bila bi najmanje sigurna stvar u proizvodu. Dolazi s bibliotekom onog dana kad je banka zatraži.

      Provjereno

      • Bank smoke s jedanaest novih provjera: ponuda, dokument otkrivanja, početak sa stanjem i PKCE izazovom, osoba napravljena politikom u mapiranoj ulozi, karta vrijedi jednom, isti identitet ponovo kao isti član, podrazumijevana uloga, poznati član vezan po e-mailu, politika isključena odbija stranca, tuđe stanje odbijeno, demo provider samo za sandbox, lanac. Tok prođen u pregledniku od /sso do pregleda.

      0.74.2

      21. septembar 2026.

      Novo

      • Feed koji banka očitava. Banka čiji adapter zna očitavati napravi feed za firmu koja dijeli s njom, pod svojim okruženjem od prvog trenutka; firma ga vidi među svojima, a može i sama povezati izvor vrste "očitavanje sa banke" u konzoli, gdje čeka dok ga banka ne stavi pod okruženje. Svake minute planer očita svaki dospjeli feed: adapter se pita od kursora feeda, što nađe ide u isti tok kao obavijest (ne knjiži se dvaput), kursor se pomjeri, a feed pamti kad je zadnje očitan i kad slijedi. Očitavanje koje padne označi feed greškom s razlogom i odgađa sljedeće, duplo svaki put do sat vremena; sljedeći uspjeh sve briše. Tri pada zaredom stave okruženje u radu na narušeno, sljedeći uspjeh ga vrati.
      • Očitaj sada. Inženjer očita sve feedove okruženja odmah, sa ekrana ili s POST /v1/bank/integrations/:id/poll, i vidi po feedu šta je očitano, novi kursor, grešku i odgodu.
      • Ekran Integracije pokazuje uz svaki očitavani feed kad je zadnje očitan, kad slijedi i grešku, i ima obrazac kojim banka napravi feed za firmu.

      Popravljeno

      • Provjera tipova u CI-ju. Pomoćna funkcija u testu adaptera sudarala se s imenom polja koje opisuje; CI 0.74.1 je pao na tome, kod je bio ispravan. Test je preimenovan.

      Provjereno

      • Bank smoke sa šest novih provjera: feed napravljen i viđen kod firme, očitavanje naplati račun i pomjeri kursor, drugo očitavanje ne nađe ništa novo, pad označi i odgodi, uspjeh očisti, analitičar i druga banka odbijeni. Ekran prođen u pregledniku.

      0.74.1

      21. septembar 2026.

      Novo

      • Dnevnik prijema. Svaka obavijest na feedu pod okruženjem banke je jedan red: id poruke koji banka pošalje (ili hash tijela kad ga ne pošalje), korelacijski id iz zaglavlja banke ili iskovan ovdje i vraćen u odgovoru, verzija sheme, stanje (prihvaćeno, odbijeno, mrtvo pismo) s razlogom, koji je kredencijal potvrdio potpis i šta je naplaćeno. Ista poruka dva puta se odgovara iz dnevnika i nikad ne knjiži dvaput. Potpisana poruka koju niko ne može pročitati čeka u mrtvom pismu; inženjer je ponovi kad ukloni uzrok, i to je zapis na lancu. Odbijene poruke se čiste poslije sedmice, ostale poslije devedeset dana.
      • Kapije okruženja. Lista dozvoljenih adresa i mreža (kredencijal ALLOWLIST, provjeren stavku po stavku pri upisu), verzije sheme koje okruženje prima, i klijentski certifikat: okruženje s mtls: required prima samo zahtjev čiji otisak certifikata, kako ga nginx javi, odgovara certifikatu koji okruženje čuva.
      • Rotacija ključeva s preklapanjem. Novi kredencijal iste vrste ne ruši stari: stari potpisuje još dan (ili koliko se kaže, nula gasi odmah), oba se vide po otisku, a odgovor kaže do kada.
      • Host za sisteme banaka. Instaler na zahtjev (--bank-mtls-domain) služi poseban host na kojem nginx traži klijentski certifikat i prosljeđuje otisak API-ju; sajt, konzola i aplikacija banke to zaglavlje brišu, pa se otisak ne može podmetnuti kroz njih.
      • Ekran Integracije pokazuje dnevnik prijema s filterima i dugmetom za ponavljanje mrtvog pisma, uređivanje podešavanja nacrta ili sandboxa, i do kada stari kredencijal još vrijedi. Zdravlje banke broji šta je svako okruženje poslalo u zadnjem danu i šta čeka u mrtvom pismu.

      Provjereno

      • Jedinični testovi omotnice, liste adresa, otiska certifikata i potpisa rotiranim ključem; bank smoke s devet novih provjera od ponovljene poruke do zahtijevanog certifikata; ekran prođen u pregledniku. nginx blok je napisan i lintovan, a isproban biva onog dana kad banka predoči certifikat.

      0.74.0

      21. septembar 2026.

      Novo

      • Adapteri i sposobnosti. Instalacija nosi dva adaptera: demo banku, koja ne postoji i može sve, uvijek isto, i nikad ne vodi produkciju; i generički potpisani webhook, koji zna potpisati obavijest i ništa više, i time dokazuje da apstrakcija drži. Deset imenovanih sposobnosti; okruženje tvrdi najviše ono što njegov adapter ima.
      • Okruženja integracije. Inženjer integracije otvara sandbox, UAT i produkciju, po jedno; svako radi na jednom adapteru, ima podešavanja bez tajni (tajna upisana u podešavanja se odbije i uputi na kredencijale) i kredencijale po vrsti koji se upišu i nikad više ne pročitaju: poslije se znaju po vrsti i otisku. HMAC tajna i API token se mogu iskovati ovdje i pokazati jednom. Adapter odgovara na provjeru zdravlja, odgovor ostaje na okruženju, a zdravlje banke od sada nabraja okruženja umjesto praznog spiska.
      • Feed firme pod okruženjem banke. Feed firme koja dijeli s bankom stavlja se pod okruženje čiji adapter nosi tu vrstu. Od tada obavijest na tom feedu provjerava adapter kredencijalom okruženja i čita je u obliku banke, a sve što pročita ide u isti tok sravnjivanja kao i do sada. Vlastita tajna feeda više ne potpisuje. Feed se može vratiti firmi.
      • Promjene okruženja s drugom osobom. Nacrt i sandbox inženjer uređuje direktno. Sve dalje ide kroz red promjena: inženjer predlaže podešavanja, tvrdnje ili promjenu stanja, administrator odobrava, a stanje se mijenja samo dozvoljenim koracima (isključenje odakle god, nazad u nacrt samo iz isključenog, u rad samo iz spremnog ili narušenog).
      • Ekran Integracije u aplikaciji banke: adapteri, okruženja s tvrdnjama, zdravljem, podešavanjima, kredencijalima i feedovima, i dugmad za sve gore navedeno.
      • Partnerski API. GET /v1/bank/adapters, GET, POST i PATCH /v1/bank/integrations, kredencijali i zdravlje okruženja, GET /v1/bank/feeds, stavljanje feeda pod okruženje i vraćanje.

      Provjereno

      • Jedinični testovi adaptera (tabela sposobnosti, registar, čitanje obavijesti, determinizam demo banke, provjera potpisa, otisci) i pravila promjena. Bank smoke: 17 novih provjera, od odbijene demo produkcije do obavijesti provjerene adapterom i odobrenja administratora. Ekran prođen u pregledniku.

      0.73.11

      21. septembar 2026.

      Novo

      • Zaboravljena lozinka i pozivnice, linkom. Na prijavi stoji "Zaboravili ste lozinku?": upišete adresu i, ako nalog postoji, stiže mail sa linkom koji vrijedi sat vremena i radi jednom. Odgovor je isti za adresu koja postoji i za onu koja ne postoji, pa ekran nikome ne odaje koje adrese imaju nalog. Isti ekran za postavljanje lozinke služi i pozivnici: nalog dobija link na sedam dana, osoba sama izabere lozinku i niko je nikad ne kuca umjesto nje. Postavljanje lozinke odjavi sve ostale prijave na taj nalog, a iskorišten ili istekao link kaže da zatražite novi.
      • Pristup konzoli, u Podešavanjima. Vlasnik vidi ko se prijavljuje u konzolu (vlasnici i menadžeri, sa zadnjom prijavom ili "poziv poslan"), dodaje osobu po imenu i adresi kao menadžera ili vlasnika, i uklanja je. Link iz pozivnice se pokaže i vlasniku, jednom, jer je nova osoba često u istoj prostoriji, a mail ponekad kasni ili ne ode. Sebe ne možete ukloniti, ni zadnjeg vlasnika. Osoblje u sali ostaje pod Osoblje sa PIN-om.
      • Operater više ne kuca lozinke. Pri otvaranju firme polje za lozinku vlasnika je prazno po pravilu: vlasnik dobija link mailom, a link stoji i u odgovoru operateru ako mail ne stigne. Upisana lozinka i dalje radi za onoga ko stoji pored vlasnika.

      Ispravljeno

      • Podešavanja su pri otvaranju javljala "Request validation failed": crtač računa slao je prazne napomene zaglavlja i podnožja kao "ništa", a server je tražio tekst. Sada prima oboje, i na uzorku i pri čuvanju.
      • "Prije 52 s" umjesto "-52 s": vrijeme "prije koliko" na bosanskom se sad piše ručno, jer neki preglednici nemaju te podatke za bosanski i ispisivali su minus.

      Za one koji razvijaju

      • POST /v1/auth/forgot (javno, 5 u minuti po adresi, uvijek 201), GET /v1/auth/link/:token (kome je i do kad), POST /v1/auth/link/:token (postavlja lozinku, troši link, odjavljuje sesije). Tabela password_links (migracija 20261024000000_password_links) čuva samo hash tokena. GET, POST i DELETE /v1/merchant/members za vlasnika; owner.password na POST /v1/admin/merchants je opcionalan, odgovor nosi owner.inviteUrl i owner.invited. Link vodi na DASHBOARD_BASE_URL/lozinka/<token>. Opšti smoke prolazi cijeli put: poziv, link, lozinka, prijava, uklanjanje.

      0.73.10

      21. septembar 2026.

      Popravljeno

      • API podrazumijevano odgovara i aplikaciji banke. Kad CORS_ORIGINS nije postavljen, API je dozvoljavao samo konzolu na portu 3000, pa je prijava iz aplikacije banke na 3003 padala u pregledniku porukom "Failed to fetch", a nijedan test na serveru to ne vidi. Podrazumijevana lista sada ima konzolu, sajt i aplikaciju banke; CI to postavlja i izričito. Prolazi kroz preglednik iz 0.73.9 su ovo našli na prvom prolazu u CI-ju.

      0.73.9

      21. septembar 2026.

      Novo

      • Prolazi kroz preglednik za aplikaciju banke. Playwright s Chromiumom vodi stvarne ekrane: prva prijava s upisom aplikacije za kodove i kodovima za oporavak, pogrešna lozinka odbijena jednom rečenicom, odjava; pretraga po pozivu na broj i po imenu firme iz palete, gdje pogodak otvara baš to plaćanje; detalj plaćanja s činjenicama, kontekstom, vremenskom linijom i isporukama, bez tehničkog dijela za operacije. Prolazi rade nad pravim API-jem sa seedom, jedan po jedan, i sami dovedu seed u poznato stanje: zaborave telefone seedovanih ljudi, uključe uvid dvjema firmama i pokrenu projekciju.
      • Demo iz tri perspektive. Direktor (analitičar) vidi banku u brojkama i analitiku iza njih; šef platnog prometa (operacije) radi plaćanja i red sravnjivanja; CIO (vlasnik) čita zdravlje, prijavi incident i provjeri lanac. Svaka uloga vidi ono što tabela uloga kaže i ništa više. To je izlazni kriterij faze 3 i od sada je dio CI-ja.

      Popravljeno

      • Pogodak iz pretrage otvara plaćanje i kad ste već na plaćanjima. Stranica plaćanja je adresu čitala samo pri otvaranju, pa je pogodak izabran s te iste stranice mijenjao samo adresu i ništa nije otvarao. Sada prati adresu: otvori plaćanje iz pogotka i primijeni filter po firmi kad pretraga tamo vodi. Prolaz kroz preglednik je ovo i našao.

      Provjereno

      • Šest prolaza zeleni lokalno nad dev serverom i u CI-ju nad izgrađenom aplikacijom; tragovi neuspjelog prolaza se čuvaju kao artefakt CI-ja.

      0.73.8

      21. septembar 2026.

      Novo

      • Zdravlje sistema. Stranica koja jednom riječju kaže kako je instalaciji za ovu banku, pa po dijelovima: svježina projekcije, izvodi firmi koje dijele s bankom po vrsti izvora (aktivni, pauzirani, u grešci, kad su zadnji put povučeni), isporuke sistemima firmi u zadnjem danu (neuspjele, napuštene, zakašnjele), otvoreni incidenti i trideset dana historije: neuspjele isporuke, otvoreni slučajevi i istekla plaćanja po danu. Integracije banke stižu s fazom 4 i stranica to kaže, umjesto da pokazuje zeleno svjetlo za nešto čega nema.
      • Incidenti. Osoba u banci prijavi šta ne valja: naslov, ozbiljnost, opis i broj iz service deska ako ga ima. Incident ide kroz stanja otvoren, praćenje i riješen, svaki korak s bilješkom i imenom onoga ko ju je napisao. Prijava i svaka promjena su zapis na revizijskom lancu banke. Prijavljuju i vode ih uloge integracije, operacija i platnog prometa; čitaju svi koji čitaju zdravlje. Sistemski ključ ne prijavljuje incidente, jer incident prijavljuje čovjek.
      • Revizija. Revizor i compliance čitaju lanac banke od najnovijeg zapisa: ko, šta, nad čim, s podacima i hashom, uz filter po radnji i danima. Dnevnik osjetljivog pristupa je isti lanac sužen na čitanja koja je svrha otvorila iznad uobičajenog nivoa uloge: ko, koje plaćanje, koja svrha i predmet. Dugme za provjeru prođe svaki zapis i potvrdi da se svaki poziva na prethodni i da zapečaćeni vrh još odgovara.
      • Izvozi. Tri CSV fajla za period do godinu dana: plaćanja iz pogleda banke (analitičar, uprava, operacije, platni promet, revizor i compliance), revizijski lanac s hashovima (revizor i compliance, da se može provjeriti i drugdje) i slučajevi sravnjivanja s uplatom, plaćanjem i odlukom banke (operacije, platni promet, revizor i compliance). Svaki izvoz je i sam zapis na lancu, s periodom i brojem redova.
      • Partnerski API. GET /v1/bank/health, incidenti (GET, POST i PATCH /v1/bank/incidents), GET /v1/bank/audit, /audit/access, /audit/verify i GET /v1/bank/exports/{payments,audit,cases}.csv. Sve je ograničeno na banku i firme koje smije čitati; tuđi incident je 404, a na tuđem lancu ničega od toga nema.

      Provjereno

      • Bank smoke: zdravlje s projekcijom, izvodima, isporukama i historijom; incident kroz sva tri stanja s bilješkama, a zdravlje s njim narušeno; druga banka ga ne vidi i ne može ga dirati; lanac s odlukama, incidentom i čitanjima po svrsi; dnevnik pristupa; provjera lanca; izvoz kao CSV sa zapisom na lancu; analitičar ne čita lanac; period duži od godine je odbijen. Obje stranice prođene u pregledniku.

      0.73.7

      21. septembar 2026.

      Novo

      • Pet pogleda, jedan period. Analitika ima pet tabova nad firmama koje dijele s bankom, za 30, 90 ili 365 dana. Plaćanja: naplaćeno po danu i načinu, broj uplata, prosječan račun, potvrde banke i ručne, brzina potvrde s medijanom i 95. i 99. percentilom kad ima dovoljno uzoraka, i ritam po satu i danu u sedmici. Građani: QR naplata po veličini računa i vrsti posla, s jasnom porukom da brojke o pojedinačnim ljudima dolaze tek kad banka dostavi reference kupaca. Firme: povezane, aktivne, s uvidom, nove veze i uključeni uvidi u periodu, aktivne firme po danu, deset s najviše naplate, segmenti. Korporativno: naplata korporativnih vrsta po danu i vrsti, izdavaoci računa, izdati, plaćeni i serijski računi i šta je otvoreno. Sravnjivanje: otvoreno i riješeno po danu, razlozi, vrijeme do rješenja, uplate po stanju sparivanja, firme s najviše otvorenih slučajeva. Svaka brojka je ograničena na banku i firme koje s njom dijele.

      0.73.6

      21. septembar 2026.

      Novo

      • Svaka firma s uvidom ima svoju stranicu. Ko je, kako je povezana (stanje veze, od kada predložena, od kada dijeli, ko ju je i kad označio), njena dva prekidača kako ih je sama postavila, naplata za 30 i 90 dana po načinu iz pogleda banke s grafikonom po danu, brzina potvrde, zadnja naplata, šta kod nje traži čovjeka (otvoreni slučajevi, nesparene uplate, plaćanja koja čekaju), poslovnice sa svime što primaju, kako joj stižu izvodi i koliko webhooka ima, i računi kupcima ako ih izdaje.
      • Banka označi vezu svojom referencom. Operativa i menadžer odnosa (ili bankin sistem) upišu na vezu referencu pod kojom bankini sistemi vode firmu i proizvode banke koje ima; referenca je jedinstvena po banci, upis ide na revizijski trag, a uvid ostaje firmin prekidač i ne mijenja se.
      • Izdavaoci računa kao poseban pogled. Firme koje kupcima šalju račune (komunalno, kirija, freelanceri, usluge, webshop, veleprodaja, trgovina) s brojem izdatih i plaćenih računa u zadnjih 30 dana i onim što je još otvoreno.

      0.73.5

      21. septembar 2026.

      Novo

      • Drugi prekidač prema banci. Uz "uvid za banku", u Postavkama firme stoji i "banka može odlučiti umjesto vas". Isključen je dok ga firma ne uključi, i može se uključiti tek uz uvid. Dok je isključen, bankina riječ o slučaju sravnjivanja ostaje preporuka uz slučaj; kad je uključen, bankina potvrda da uplata pripada računu zatvara slučaj i knjiži uplatu na račun istim putem kojim to radi menadžer u konzoli, "nije naša" označi uplatu kao zanemarenu, a "dupla" je zapiše uz račun bez dodavanja novca. Na vremenskoj liniji računa piše da je to uradila banka, u aplikaciji banke uz odluku piše "primijenjeno", a firma uz riješeni slučaj vidi da je odluka banke primijenjena.

      Ispravljeno

      • Ko je zatvorio pitanje piše na računu. Kad se slučaj "iznos se ne slaže" riješi potvrdom, uplata je već bila uknjižena kad je slučaj otvoren, pa se stanje računa ne mijenja, i do sada na vremenskoj liniji računa nije ostajao nikakav trag da je neko zatvorio slučaj. Sada ostaje zapis s istim stanjem, razlogom i onim ko je odlučio, bio to menadžer u konzoli ili banka.

      Za one koji razvijaju

      • Rješavanje slučaja i knjiženje uplate na račun izvučeni su iz kontrolera sravnjivanja u ReconciliationService, pa firma i banka prolaze kroz isti kod; kontroler samo delegira. Veze banaka i firmi su u vlastitom BankLinksModule, jer bi inače modul banke, sravnjivanja, plaćanja i realtime-a činili krug.

      0.73.4

      21. septembar 2026.

      Novo

      • Banka vidi slučajeve sravnjivanja firmi koje dijele s njom. Tri taba (otvoreni, riješeni, odbačeni) s brojevima, red po slučaju: razlog, uplata iz izvoda, plaćanje koje je matcher imenovao, broj kandidata i posljednja odluka banke. Detalj nosi uplatu kako ju je izvor donio (bez podataka o uplatiocu), plaćanje, svakog kandidata s bodovima i dokazima iza bodova (poziv na broj, iznos, račun, rok, minute od izdavanja) i sve što je banka o slučaju rekla.
      • Banka može reći šta je uplata. Operativa i platni promet (i administratori) biraju: uplata pripada ovom plaćanju, nije ove firme, dupla je, ili napomena. Svaka odluka se zapiše i ode na revizijski trag banke. Dok firma ne dozvoli banci da odlučuje umjesto nje, odluka je preporuka: firma je vidi uz slučaj u svojoj konzoli ("Banka X kaže: ...") i sama odlučuje kao i do sada. Primjena odluke uz dozvolu firme dolazi u drugom dijelu ove stavke.
      • Firma vidi šta je banka rekla. U konzoli, uz svaki slučaj sravnjivanja, stoji posljednja preporuka banke s napomenom, označena kao preporuka koja se ne primjenjuje sama.

      0.73.3

      21. septembar 2026.

      Novo

      • Jedna linija, odgovor u grupama. Ctrl K (Cmd K) sa svake stranice otvara pretragu: poziv na broj ili ime firme nalazi plaćanja iz pogleda banke, ime ili porezni broj nalazi firmu, id uplate iz bankovnog izvoda (vanjski ili end-to-end) nalazi uplatu i plaćanje na koje je sparena, id slučaja nalazi slučaj. Strelice biraju, Enter otvara plaćanje u ladici ili listu filtriranu po firmi. Server odgovara samo iz okvira banke i firmi koje s njom dijele, prije nego što se išta nacrta; osjetljivi sažeci se ne prikazuju ni ovdje.

      0.73.2

      21. septembar 2026.

      Novo

      • Detalj plaćanja kaže i šta su sistemi firme čuli. Uz vremensku liniju, uplate, slučajeve i povrate, ladica sada nosi i isporuke webhooka za to plaćanje: koji događaj, kojim krajem prošao (čeka, isporučeno, nije uspjelo, odustalo se), koliko pokušaja i kad je stiglo. Vidi ga svako ko vidi plaćanje; bez adresa i odgovora.
      • Tehnički dio, samo za one koji istražuju. Revizija, usklađenost i integracija dobijaju odjeljak s identifikatorima, podacima svakog događaja, referencama uplata (vanjski i end-to-end id, izvor, pouzdanost) i onim što su krajnje tačke odgovorile (host, kod, greška, sljedeći pokušaj). Server odlučuje po ulozi da li odjeljak uopšte postoji u odgovoru; ekran ga ne može zatražiti.
      • Filter po firmi i sačuvani filteri. Lista plaćanja ima izbor firme uz stanje, vrstu posla i pretragu; kombinaciju filtera preglednik pamti pod imenom koje joj date, jednim klikom se primijeni, jednim ukloni.

      Ispravljeno

      • Firma s više od dvije hiljade plaćanja u pogledu banke nije u jednom prolazu izlazila iz pogleda kad prestane dijeliti, pa se pri povratku vraćala s pola historije. Uklanjanje sada ide do kraja u istom prolazu.

      0.73.1

      21. septembar 2026.

      Novo

      • Biblioteka fotografija za meni. Kod svakog jela, pića i kategorije u konzoli stoji "Izaberi sliku": 118 fotografija onoga što se ovdje stvarno prodaje (burgeri i sendviči, pizze, roštilj, pite, salate i jela, deserti, kafa i čaj, bezalkoholna pića, pivo, vino i žestoka), izrezanih na providnoj pozadini, pa izgledaju isto na svakom telefonu. Dovoljno je upisati naziv jela: za "Pizza Quattro formaggi" birač se otvori na pizzama sa tom pizzom na prvom mjestu, za "kafa" na kafama. Pretraga po imenu na oba jezika, grupe sa naslovnom slikom, i pored toga "Dodaj svoju" za lokal koji ima svoje fotografije. Nacrtane sličice koje je demo lokal imao do sada su zamijenjene ovim fotografijama, i kod novih lokala i kod postojećih demo menija.
      • Kategorija ima svoju sliku. Kartica kategorije na telefonu gosta nosi sliku koju vlasnik izabere; bez izbora i dalje uzima prvo jelo sa slikom. Fotografija iz biblioteke stoji na tamnom tanjiru u boji jela, cijela, a vlastita fotografija i dalje ispunjava okvir.

      Ispravljeno

      • Novo jelo bez nabavne cijene nije moglo da se sačuva iz konzole: obrazac šalje praznu nabavnu cijenu kao "ništa", a server je to odbijao kao neispravan iznos. Sada prima i ništa i iznos.

      Za one koji razvijaju

      • GET /v1/menu/library vraća grupe i slike sa adresama; fajlovi se služe sa /media/library/<id>.webp iz apps/api/assets/menu-art, manifest je apps/api/src/modules/menu/menu-library.ts. MenuCategory.imageUrl (migracija 20261007000000_category_images), PATCH /v1/menu/categories/:id ga prima, meni za gosta ga vraća. Slikar dish-art.ts je uklonjen; sajt uzima svoje četiri sličice iz iste biblioteke (scripts/site-dishes.mjs). Smoke narudžbi provjerava biblioteku, sliku kategorije i jelo bez nabavne cijene.

      0.73.0

      21. septembar 2026.

      Novo

      • Pregled banke kaže šta traži čovjeka. Na vrhu ekrana su živi brojevi nad firmama koje dijele s bankom: otvoreni slučajevi sravnjivanja, nesparene uplate, propale isporuke webhooka u zadnja 24 sata, plaćanja istekla danas i ona koja još čekaju uplatu; svaki broj vodi tamo gdje se rješava. Ako projekcija nije prošla više od pet minuta, ekran to kaže umjesto da stare brojke prikazuje kao svježe.
      • Osam grafikona, iz projekcije i iz izvora. Naplaćeno i broj uplata po danu, udio po vrsti posla i po načinu plaćanja, usvajanje (firme predložene, aktivne i s uvidom, po danu), segmenti po vrsti posla, kvalitet sravnjivanja (slučajevi po razlogu i koliko je uplata sparila mašina bez čovjeka) i izuzeci po danu, s brzinom potvrde ispod njih. Nacrtani u aplikaciji, u boji banke, bez biblioteke.
      • Pregled prati sobu banke uživo. Kad firma koja dijeli s bankom izda ili naplati račun, ekran sam povuče nove brojke koji trenutak kasnije; u zaglavlju piše da li je veza uživo.

      0.72.2

      21. septembar 2026.

      Novo

      • Demo banka jednom naredbom na serveru. Instalacija bez ijedne banke dobija demo partnera sa servera: seed-demo-bank.js uzme bankovne kodove iz računa firmi koje mu se navedu, napravi banku, sistemski ključ, četvero ljudi (uprava, administrator, operativa, analitičar) s lozinkama koje se ispišu jednom, i predloži linkove tačno kako ih API predlaže pri startu. Prekidač dijeljenja ostaje firmin: dok ga firma ne uključi u svojoj konzoli, banka o njoj ne vidi ništa. Ponovljena naredba ništa ne briše i ne mijenja lozinke. Opisano u uputstvu za postavljanje.

      0.72.1

      21. septembar 2026.

      Popravke

      • Provjera spremnosti lokala čeka svoj red umjesto da padne. Prijava u konzolu dozvoljava dvadeset pokušaja u minuti s jedne adrese. Na CI serveru svi smoke paketi idu s jedne adrese i, s provjerom uvida za drugu firmu koju je donijela Faza 2, u istoj minuti naprave tačno dvadeset prijava; provjera spremnosti lokala koja ide poslije njih bila je dvadeset prva i padala je na odbijenoj prijavi, iako s lokalom nije bilo ništa. Skripta sada sačeka da prozor prođe i tek onda kaže šta je s lokalom; ograničenje prijave ostaje kakvo jeste.
      • Gornja granica zahtjeva po adresi može se podesiti. Ograničavač zahtjeva ima zaštitni plafon od 900 zahtjeva u minuti s jedne adrese, preko svih ruta, koji nijedan lokal iza jedne NAT adrese ne dosegne. Plafon se sada zadaje kroz THROTTLE_CEILING_PER_MINUTE; u produkciji ostaje 900, a test server koji sve pakete tjera kroz jednu adresu dobija više.

      0.72.0

      21. septembar 2026.

      Novo

      • Svako plaćanje nosi snimak onoga za šta je izdato. Pri izdavanju (narudžba za stolom, faktura, serija računa, naplata iz konzole, naljepnica, vanjska evidencija, API) XPay u istoj transakciji zapiše vrstu posla, sažetak, dokument, period, iznose i stavke, s otiskom koji se pri svakom čitanju ponovo izračuna. Snimak se ne mijenja kad se kasnije promijeni narudžba ili faktura: kaže šta je važilo u trenutku izdavanja. Postojeća plaćanja su dobila snimak pri prvom pokretanju. Firma svoj snimak čita na GET /v1/payments/:id/context.
      • Banka vidi onoliko koliko joj uloga dozvoljava, i razlog ostaje zapisan. Tri nivoa: samo činjenice o plaćanju, sažetak, ili sve stavke. Stavke se nikad ne daju bez razloga; razlog za podršku ili reklamaciju traži broj slučaja; za osjetljive djelatnosti (usluge, freelanceri) stavke vide samo revizija i usklađenost. Svako otvaranje iznad uobičajenog nivoa piše se u revizijski trag banke s razlogom i brojem slučaja, i ekran to kaže onome ko je otvorio.
      • Brojke za banku iz posebnih tabela, ne iz operativnih. Projekcija svake minute prepiše promijenjena plaćanja firmi koje su dozvolile uvid u pogled za banku i sabere dane koje su dotakla, po Sarajevu; firma koja povuče uvid nestane iz pogleda pri sljedećem prolazu, a pogled se može izgraditi ispočetka jednom naredbom. Pregled u aplikaciji banke sada radi iz te projekcije: period od 7, 30 ili 90 dana, poređenje s prethodnim, udio po načinu plaćanja i po vrsti posla, brzina potvrde, i vrijeme kad je projekcija zadnji put osvježena.
      • Ekran Plaćanja u aplikaciji banke. Lista s filterima po stanju i vrsti posla, pretraga po pozivu na broj ili firmi, učitavanje dalje; detalj s činjenicama, kontekstom na dozvoljenom nivou, vremenskom linijom, uplatama na račun, slučajevima sravnjivanja i povratima. Uloge koje smiju navesti razlog imaju polje za razlog i broj slučaja.

      0.71.2

      21. septembar 2026.

      Popravke

      • Konektor primijeti da je veza mrtva. Živi tok događaja iz oblaka nije imao rok: kad ruter u lokalu nestane bez zatvaranja veze, čitanje čeka koliko operativni sistem dozvoli, a to su minute do sati. Cijelo to vrijeme konektor je vjerovao da je spojen, kasa nije čula ni za jednu uplatu, i nije se pokrenulo ni sustizanje koje postoji baš za taj prekid. Server šalje otkucaj svakih 25 sekundi; tok koji šuti 75 sekundi sada se proglašava mrtvim, veza se prekine i petlja ponovnog spajanja radi svoje, s testom koji to dokazuje. Ni jedan poziv konektora prema oblaku više ne čeka bez roka.
      • Mjesec od 31. januara je 28. februar, ne 3. mart. Pretplata započeta 31. u mjesecu dobijala je rok do 3. u mjesecu iza sljedećeg, jer JavaScript nepostojeći dan prebacuje naprijed, i svako sljedeće produženje je ostajalo na 3. Rok sada pada na isti dan u mjesecu, ili na zadnji dan koji mjesec ima; 29. februar plus godina je 28. februar.
      • Predračun koji ne može postati račun ne ostavlja nacrt. Nacrt računa se pravio prije izdavanja, pa je odbijeno izdavanje (poslovnica bez računa u međuvremenu, i slično) ostavljalo račun koji niko nije tražio u listi nacrta, a svaki novi pokušaj još jedan. Nacrt se sada povuče prije nego odbijanje stigne do onoga ko je kliknuo.
      • Iznosi na izvodu kupca prolaze kroz isti parser kao svugdje. Množenje decimalnog iznosa sa sto u pokretnom zarezu (4,35 puta 100 je 434,99999999999994) zamijenjeno je parserom koji API koristi za svaki iznos; ispis je bio tačan zbog zaokruživanja, način nije bio.
      • Oznaka uvezene serije računa nosi datum kakav je u lokalu, ne datum kontejnera: pola sata poslije ponoći u Sarajevu server je još pisao jučerašnji.

      0.71.1

      21. septembar 2026.

      Novo

      • Promjena traži drugu osobu. Administrator banke predlaže promjenu uloge ili isključenje člana osoblja; drugi administrator je odobri, i ona se primijeni u istoj transakciji u kojoj je odluka zapisana, ili je odbije s razlogom; predlagač je može povući dok čeka. Ko je predložio, ne može odobriti, kolike god uloge imao. Promjena koja bi banku ostavila bez ikoga ko može odobriti sljedeću se odbija; iz banke s jednim administratorom izlaz je operater platforme. Osoba čija se uloga promijenila je odjavljena i vraća se u novoj ulozi. Svaki korak je na revizijskom lancu banke, s onim prije i poslije.
      • Ekran Pristup u aplikaciji banke. Red promjena koje čekaju s dugmadima koje predlagač nema i rečenicom zašto, ljudi banke s ulogom i stanjem telefona, prijedlog nove uloge, i historija odlučenog. Revizija i usklađenost isti ekran čitaju i ništa ne mogu pritisnuti.
      • Vrste promjena koje dolaze kasnije se odbijaju, ne stavljaju u red. Integracije, tajne, privatnost, funkcije i endpointi postoje u shemi i odgovaraju fazom koja ih donosi, umjesto da čekaju odobrenje koje ništa ne bi primijenilo.

      0.71.0

      21. septembar 2026.

      Novo

      • Aplikacija za banku. Zasebna aplikacija, apps/bank, na vlastitom hostu, koja razgovara samo s bankarskim rutama; ništa iz konzole firme nije u njoj i ništa u njoj se ne otvara sesijom konzole. Prijava u tri koraka: lozinka, pa upis aplikacije za kodove s QR-om i ključem pri prvoj prijavi ili kod s telefona pri svakoj sljedećoj, pa kodovi za oporavak prikazani jednom, s dugmetom koje ne ide dalje dok osoba ne kaže da ih je sačuvala.
      • Svaka uloga vidi svoje. Navigacija pokazuje odjeljke koji toj ulozi trebaju i vodi je na njen prvi: direktor na pregled, operativa na plaćanja, podrška na firme, integracije na zdravlje sistema, revizija na reviziju. Vlasnik i administrator vide sve. Odjeljci koje tek kasnije faze pune stoje u navigaciji i kažu, otvoreni, da nisu još u ovoj instalaciji i u kojoj fazi dolaze: proizvod se vidi kakav će biti, a ono što je danas piše kao danas.
      • Pregled i firme, iz stvarnih brojeva. Pregled pokazuje naplaćeno QR-om, koliko je toga potvrdila banka svojim izvodom, koliko firmi ima uvid i koliko ga nema, po danu i po načinu plaćanja, iz ista dva čitanja koja sistemski ključ ima od 0.68.0. Firme su tabela onih koje su dozvolile uvid, s mjesecom naplate; o onima koje nisu, samo broj.
      • Izgled po hostu. Jedna slika aplikacije služi više banaka: prije prvog iscrtavanja aplikacija pita API čija je banka host na kojem je stigla i postavi njene boje i ime; host koji niko nije registrovao dobija XPay izgled. Boje statusa nisu dio toga: plaćeno je zeleno kod svake banke. Svijetla i tamna tema, bosanski i engleski.
      • Instalacija. Slika za Docker, servis u compose fajlu i blok u instalacionoj skripti: aplikacija banke se služi na banka.<domena> (ili --bank-domain) čim taj zapis pokazuje na server, sa certifikatom; dok ne pokazuje, skripta to kaže i ništa drugo se ne mijenja.

      0.70.3

      21. septembar 2026.

      Sigurnost

      • Ime se razrješava prije nego se pozove. Čuvar webhook adresa čitao je samo ime iz adrese i odbijao privatne opsege koje u njemu vidi; ime koje se razrješava u privatnu adresu prolazilo je. Sada se ime razriješi pri registraciji i ponovo prije svake isporuke, a privatan odgovor odbija adresu ili trajno napušta isporuku. Ime koje se ne razrješava pri registraciji prolazi, jer je to greška u kucanju ili host koji još nije podignut, i prva isporuka će to reći.
      • Suspendovana firma je suspendovana i na živom kanalu. Prijava korisnika suspendovane firme na živi kanal se odbija, kao što je HTTP odbija od 0.55.6.
      • CI provjerava ono što se isporučuje. Poseban posao pored testova: poznate ranjivosti u zavisnostima koje idu u sliku ruše provjeru (visoke i kritične), pune provjere se izvještavaju, historija se pretražuje za tajnama, stablo se skenira, i za svaki prolaz se pravi popis komponenti (CycloneDX) koji se čuva 90 dana; to je ono što nabavka banke traži. CodeQL ne, jer traži Advanced Security na privatnom repozitoriju; piše u modelu prijetnji.
      • Tri prelazne ranjivosti zatvorene, u parseru upita ispod express-a, u multipart parseru ispod adaptera i u pomoćniku za spajanje ispod prisma konfiguracije, verzijama na istoj liniji; nodemailer podignut na 9.1.1. Ono što se isporučuje sada nema poznatih ranjivosti; ostaju dvije umjerene u alatu za testove, koji se ne isporučuje.

      0.70.2

      21. septembar 2026.

      Novo

      • Banka čuje kad novac sjedne, i ništa drugo. Prijava banke na živi kanal ulazi samo u sobu svoje banke, ni u jednu sobu ijedne firme, i ne može pratiti račun po broju. U tu sobu stiže bankarski pogled na novčane događaje firmi koje su s njom povezane i pristale: ishod, iznosi i vrijeme. Ne stiže poziv na broj, broj narudžbe, sto, gost ni bilo šta s kase; ne stižu narudžbe, stolovi ni pozivi osoblja. Događaj firme nikad ne završi u sobi banke ni po imenu sobe.
      • Provjera izolacije je ulaz za svaku sljedeću promjenu. Pravila nad kodom: nijedna bankarska ruta ne čita banku iz parametra, upita ni tijela; svaka je označena za banku ili javna; svako čitanje banke uzima banku s prijavljenog identiteta. I živi test s dvije banke na jednoj instalaciji, postavljen s obje strane: šta svaka vidi, šta svaka čuje, šta nijedna ne može. Ništa bankarsko se ne spaja dok to ne prođe.

      0.70.1

      21. septembar 2026.

      Novo

      • Osoblje banke se prijavljuje lozinkom i kodom s telefona, uvijek. Kolone za dvostruku prijavu postojale su od prve verzije baze i ništa ih nije čitalo. Sada se čitaju: prva prijava upisuje aplikaciju za kodove i daje deset kodova za oporavak, jednom; svaka sljedeća traži kod s telefona ili jedan od tih kodova, koji radi jednom. Između lozinke i koda osoba drži privremeni token koji otvara samo sljedeći korak, deset minuta. Pogrešan kod broji se kao pogrešna lozinka, prema istom zaključavanju, i dobija isti odgovor.
      • Sesija banke otvara banku i ništa drugo. Token aplikacije banke ne otvara ni konzolu firme ni operaterske rute, a token konzole ne otvara bankarske. Ista osoba može biti i u firmi i u banci: to su dvije prijave u dvije aplikacije, nikad jedan token. Osvježavanje sesije ostaje u aplikaciji koja ju je napravila i u banci za koju je napravljena.
      • Dvanaest uloga u banci, od vlasnika i administratora do operative, platnog prometa, podrške, analitike, revizije, usklađenosti, integracija, menadžera odnosa i direktora. Svaka bankarska ruta imenuje uloge kojima je namijenjena; vlasnik i administrator prolaze sve. Sistemski ključ banke prolazi samo gdje je imenovan.
      • Operater vodi ljude banke i ugovor. Na stranici Banke svaka banka se otvara: ko je u njoj i u kojoj ulozi, je li upisao telefon, dodavanje osobe (postojeći nalog se koristi, novi dobija lozinku prikazanu jednom), isključenje, zaborav telefona kad se izgubi, suspenzija banke koja odmah gasi sve njene prijave. Ugovor su moduli, datumi i nivo podrške; polja za cijenu i broj transakcija nema, namjerno.
      • Probne banke imaju osoblje u seed podacima i vlastiti smoke test, scripts/smoke-bank.mjs, koji u CI prolazi cijelu prijavu i provjerava da dvije banke na jednoj instalaciji ne vide jedna drugu.

      Popravke

      • Nalog bez mjesta u konzoli, kakav je osoblje banke, više se ne može prijaviti u konzolu; odgovor je isti kao za pogrešnu lozinku, pa se preko konzole ne može saznati ko radi u banci.

      0.70.0

      21. septembar 2026.

      Novo

      • Banka je od sada vlastiti prostor, a veza s firmom je zapis, ne šifra. Do sada je banka partner bila ključ i spisak šifri banke, a vidjela je koju god firmu ima tu šifru u broju računa; dvije banke s istom šifrom vidjele bi isto. Od sada šifra iz računa samo predlaže vezu banka-firma, a veza je ono što se čita: napravi se kad operater doda banku, kad joj promijeni šifre i kad firma unese broj računa, i nikad se ne briše. Prekidač Uvid za banku ostaje jedan, ali svaka veza pamti svoj pristanak i svoj datum. Postojeće banke dobile su veze pri prvom podizanju, a firma koja je već pristala pristala je i na njima, s datumom kad je prekidač okrenut.
      • Ono što banka smije čitati čita se samo kroz njen identitet. Banka se uzima s prijavljenog ključa i ni sa čega drugog; nema parametra kojim bi jedna banka imenovala drugu. Banka bez veza vidi praznu platformu, ne tuđu.
      • Temelj za osoblje banke i njenu aplikaciju. Tabele za članove banke i njihove uloge, integracije i njihove tajne, izgled, hostove, ono što ugovor daje (bez brojanja transakcija i bez cijena) i red promjena koje traže drugu osobu. Samo tabele: ništa ih još ne čita ni ne piše, i tabela stanja u docs/en/bank-platform/STATUS.md kaže tačno to.
      • Revizijski trag ima lanac po banci. Zapisi banke idu na njen lanac, odvojen od lanaca firmi i lanca platforme; nova verzija sažetka obavezuje se i na to čiji je lanac, pa se zapis ne može premjestiti.
      • Dvije probne banke u seed podacima, "Demo banka" i "Probna banka", namjerno ničije, da demonstracija ima jednu koju pokazuje i drugu kojom dokazuje da se ne vide.

      0.69.7

      21. septembar 2026.

      Dokumentacija

      • Bankarska platforma: plan i arhitektura. Prije nego se napiše ijedna linija koda za banke, pregledan je stvarni sistem i zapisano šta postoji, šta se proširuje, šta se gradi i šta čeka. Osam dokumenata u docs/en/bank-platform/: stanje sistema, analiza praznina, arhitektura (zasebna aplikacija za banku, banka kao vlastiti prostor od prvog dana, nepromjenjivi snimak sadržaja svakog plaćanja, jedan adapter po načinu spajanja), model prijetnji, klasifikacija podataka s pravilom ko od osoblja banke šta smije vidjeti, plan po fazama s 33 numerisana koraka, tabela stanja svake sposobnosti i izvještaj s 20 tačaka za pregled.
      • Šta je u izvještaju rečeno naglas. Dvije vrste izvora sravnjivanja (upit banci, potvrda šeme) postoje samo kao naziv u bazi, ne kao kod. Ključ banke iz 0.68.0 gleda po šifri banke iz IBAN-a, pa bi dvije banke s istom šifrom vidjele isto; veza banka-firma postaje granica. Dvostruka prijava ima kolone u bazi, ali je kod ne čita. Ni jedno od toga se ne smatra riješenim dok tabela stanja ne kaže drugačije.
      • Šta se ne mijenja. XPay i dalje ne drži i ne prenosi novac; postojeći proizvod za firme ostaje kakav jeste; javni sajt ne dobija ni riječ o bankama dok tabela stanja ne kaže šta je istina. Faza 1 ne počinje bez pregleda ovog izvještaja.

      0.69.6

      21. septembar 2026.

      Popravke

      • Pitanje koje nije postavljeno nije odgovor "u redu". Provjera reverznog DNS-a tražila je ime servera u podešavanju koje API kontejner nema, pa nije ni pitala, a to je izvještavala kao "reverzni DNS je u redu". Sada uzima prvo ime koje postoji (adresa API-ja), a bez ijednog kaže da ne zna i stranica ne tvrdi ništa o razlogu.

      0.69.5

      21. septembar 2026.

      Popravke

      • Reverzni DNS se pita javno, ne lokalno. Provjera iz 0.69.4 pitala je resolver samog servera, a on adresu servera zna iz privatnog pogleda hostinga, pa je stranica rekla da je reverzni DNS u redu i okrivila listu blokiranih. Pitanje je da li svijet može pronaći adresu, pa se sada pitaju javni resolveri (8.8.8.8, 1.1.1.1), i to PTR upitom koji zadržava pravi odgovor: zona koja ne odgovara (SERVFAIL) i zona koja kaže da zapisa nema više se ne miješaju.

      0.69.4

      21. septembar 2026.

      Popravke

      • Pošta: čekanje se plaća jednom, ne po pismu. Server pošte pušta ovaj server da čeka petnaestak sekundi prije pozdrava, i to čekanje se plaćalo na svakoj vezi, a svako pismo je otvaralo novu: serija od 25 računa čekala je šest minuta. Veza se sada drži otvorenom između pisama, pa se čeka jednom, a ostala idu odmah. Brzo pismo na već otvorenoj vezi ne briše upozorenje o sporom pozdravu; ono se skida tek kad nova veza dobije pozdrav na vrijeme.
      • Status stranica kaže koji od dva razloga. Spor pozdrav dolazi od reverznog DNS-a za adresu servera, a to su dva različita kvara i dva različita zahtjeva hostingu: zona koja uopšte ne odgovara (server pošte čeka istek vremena; popravlja se delegacija zone) ili zona koja odgovara da zapisa nema (traži se PTR zapis). Stranica je za oboje govorila "nema PTR zapisa", pa je od hostinga traženo pogrešno. API sada sam pita reverzni DNS za svoju adresu (u pozadini, jednom u pola sata) i stranica kaže koje je od to dvoje, ili da je reverzni DNS u redu pa je adresa vjerovatno na listi blokiranih.

      0.69.3

      21. septembar 2026.

      Popravke

      • Izvor koji čeka prvu uplatu nije izvor koji šuti. Poslije 0.69.1 status stranica je i dalje bila žuta: webhook banke povezan 18. 9., prije ikakvog dogovora s bankom, kroz koji nikad ništa nije stiglo, brojao se kao izvor koji je "utihnuo". Utihnuti sada može samo izvor koji je već donosio uplate pa stao na dan; izvor kroz koji još ništa nije stiglo je "povezan i čeka prvu uplatu", u zelenom, jer to čeka na banku, a stranica koja je mjesec dana žuta je stranica koju niko ne čita kad zatreba.

      0.69.2

      21. septembar 2026.

      Popravke

      • Kopija koja napušta server je zaključana. Noćna kopija je slala izvoz baze i slike na drugi server u čitljivom obliku, a samo tajne šifrovane. Izvoz baze su imena kupaca i svi računi, i mjesto s dovoljno prostora rijetko je i mjesto s najboljom bravom. Kad je lozinka za kopije postavljena, sve što odlazi se šifruje istom lozinkom (.sql.gz.enc, .tar.gz.enc), pa je kopija bez nje bezvrijedna; lokalne kopije ostaju kakve jesu, jer ih restore.sh čita. Uputstvo za vraćanje s druge mašine je u docs/en/06-deployment.md.

      0.69.1

      20. septembar 2026.

      Popravke

      • Status stranica je javljala "sravnjivanje otežano" bez razloga. Pravilo "izvor koji dan nije donio uplatu je utihnuo" brojalo je i ručne potvrde: svaka firma kod koje menadžer nije jučer pritisnuo "Plaćeno" bila je "izvor koji šuti", pa je stranica pisala "1 od 2 izvora šuti" u žutom, na sistemu koji još nema nijedan automatski izvor iz banke. Utihnuti sada može samo ono što samo donosi uplate (webhook banke, provjera banke, IPS potvrda, obavijest mailom); ručna potvrda i izvod iz fajla ne mogu. Bez automatskog izvora stranica kaže tačno to, u zelenom. Greška na bilo kojem izvoru se i dalje javlja.

      0.69.0

      20. septembar 2026.

      Novo

      • Račun na engleskom. Freelancer koji radi za klijenta u inostranstvu slao je račun koji klijent ne može pročitati. Nova faktura sada ima izbor jezika, Bosanski / Engleski: na engleskom su riječi na PDF-u (INVOICE, Bill to, Due date, Payment details, Scan to pay), datumi (5 Oct 2026), format brojeva (1,250.00 KM), sitna slova, pečati (PAID, OVERDUE), naziv fajla (Invoice-41-2026.pdf), mail koji nosi račun i stranica koju kupac otvara, na kojoj su i dugmad na engleskom. Brojevi, poziv na broj i kod su isti; mijenja se samo jezik. Predračun i storno takođe.
      • Kupac pamti jezik. Kupac napravljen iz engleskog računa ostaje na engleskom, pa idući račun za njega počinje na engleskom bez biranja; u Kupcima se jezik vidi i mijenja. Opomena za dospjele račune ide na jeziku kupca.
      • API: language: "bs" | "en" na POST /v1/invoices (podrazumijevano jezik kupca, inače bs), language u odgovoru i na stranici kupca, language na kupcu (POST/PATCH /v1/customers).

      0.68.0

      20. septembar 2026.

      Novo

      • Banka partner ima svoj ključ. Priprema za banku obećava banci ono što niko drugi nema: ko od njenih klijenata koristi XPay i koliko naplati. Operater sada u admin konzoli (Banke) dodaje banku po nazivu i šifri banke (tri cifre s početka domaćeg broja računa, 129 za UniCredit) i dobija ključ xpb_live_..., prikazan jednom; novi ključ jednim klikom, isključenje jednim prekidačem. Ko banka kod koje čita se iz IBAN-a poslovnice, niko ne vodi spisak.
      • Šta banka vidi. GET /v1/bank/merchants: firme koje bankaju kod nje i dozvolile uvid, s mjesecom QR naplate; koliko ih nije dozvolilo, samo kao broj. GET /v1/bank/volume: naplata po danu, QR s načinom potvrde (banka, ručno, simulator), kartica i gotovina radi udjela, najviše 92 dana po pozivu. GET /v1/bank/references/:poziv: šta je poziv na broj i da li je još otvoren, za trenutak kad klijent skenira kod u aplikaciji banke, pa aplikacija zna kome plaća i odbija već plaćen kod. Ključ banke ne otvara ništa trgovačko, a ključ trgovca ništa bankarsko.
      • Uvid daje firma, ne mi. Postavke imaju prekidač Uvid za banku, isključen dok ga vlasnik ne uključi; trenutak uključenja se čuva jer to traži ugovor o obradi podataka. Šta banka vidi piše na prekidaču: naziv, JIB, grad, djelatnost i broj i iznos uplata po danu; nikad pojedinačne račune, goste ni stavke.
      • Dokumentacija za IT banke: docs/en/08-bank-partner-api.md.

      Popravke

      • Primjer računa u Postavkama (izgled računa) je odbijao firmu s dvije poslovnice različite vrste, jer je tražio poslovnicu za dokument koji ništa ne izdaje. Više ne traži.

      0.67.0

      20. septembar 2026.

      Novo

      • Predračun. Freelancer, servis i radnja po narudžbi traže uplatu prije posla, a XPay je znao samo za račun. Nova faktura sada gore ima izbor Račun / Predračun. Predračun je isti dokument s vlastitom serijom (P-1/2026), vlastitim pozivom na broj i QR kodom, jer se ovdje predračun plaća; šalje se i naplaćuje kao i račun, i na PDF-u i na stranici kupca piše šta je. Nije potraživanje: ne ulazi u pregled, izvod kupca, opomene ni stanje, dok ne postane račun.
      • Pretvori u račun. Jedno dugme na izdatom predračunu: račun dobija broj iz serije računa, a uplata prelazi na njega. Plaćen predračun daje odmah plaćen račun s napomenom "Plaćeno po predračunu P-1/2026"; neplaćen daje račun na istom pozivu na broj, pa kupac plaća kako mu je već rečeno. Predračun ostaje označen kao pretvoren, s pečatom broja računa na PDF-u, a njegova stranica kaže koji je račun postao. Roba sa police silazi tek kad nastane račun, ne na predračunu.
      • Serija računa broji bez predračuna. Brojevi računa ostaju bez rupa gdje su bile ponude; mjesto u seriji se sada čuva uz broj, pa serija s prefiksom ostaje prebrojiva.
      • Pomoć ima vodič "Predračun pa račun".
      • Forma imenuje poslovnicu. Firma s restoranom i radnjom nije mogla iz konzole napraviti nacrt (server je odbijao pogoditi koja poslovnica izdaje), a greška se vidjela tek iza dijaloga. Forma sada šalje poslovnicu i pokazuje odbijanje u dijalogu.
      • API: kind: PROFORMA na POST /v1/invoices, POST /v1/invoices/:id/convert, stanje CONVERTED u listi i filteru, kind, proforma i convertedTo u odgovoru; stranica kupca nosi kind i convertedToNumber.

      0.66.0

      20. septembar 2026.

      Novo

      • Mjesec računa iz fajla. Komunalno preduzeće, kućni savjet ili stanodavac s tabelom imali su formu za jedan račun i API za programere, a njihov mjesec je hiljadu istih računa iz sistema koji ih je obračunao. Fakture sada imaju Uvoz iz fajla: CSV s jednim redom po računu (šifra korisnika, naziv, period, rok, iznos) ili više redova za isti račun (opis, količina, cijena, PDV stopa). Kolone se prepoznaju po nazivu na oba jezika i bez kvačica, razdvojnik i decimalni zarez kako ih Excel ovdje piše, datumi kao 15.10.2026. Fajl se prvo pročita i pokaže: koliko računa, koliki iznos, koliko novih kupaca, i tačno koji red i koja kolona ne valja. Ništa se ne upisuje do dugmeta Uvezi, a s greškom se ne uvozi ništa, da pola mjeseca ne uđe. Primjer fajla je u dijalogu.
      • Serija se izdaje i šalje kao jedna. Uvezeni računi su serija s dugmadima Izdaj sve i Pošalji sve: brojevi idu po redu iz fajla, brojač pokazuje dokle je stiglo, a što zapne se imenuje s razlogom i ostaje za idući pritisak, koji nastavlja gdje je stalo. Računi bez e-maila se preskaču i broje, ne padaju. Serija broji šta je nacrt, izdato, poslano, plaćeno, dospjelo. Račun pamti kad je zadnji put poslan.
      • Kupac po broju korisnika. Račun koji nosi šifru kupca (kod komunalnog broj korisnika) nalazi kupca po njoj prije JIB-a i imena, pa pogrešno napisano ime idući mjesec ne pravi drugog kupca; kupac napravljen iz računa je zadrži. Isti period za istog kupca drugi put se odbija, pa se fajl ne može uvesti dvaput. Račun odbijen iz bilo kojeg razloga više ne ostavlja kupca za sobom.
      • Broj korisnika na računu. PDF računa štampa referencu s riječju koju ta djelatnost koristi: Broj korisnika, Nekretnina, Broj narudžbe, Otpremnica, Termin. Do sada je referenca bila samo u sistemu.
      • Pomoć ima vodič "Mjesec računa iz fajla" za djelatnosti koje obračunavaju po periodima.
      • API: POST /v1/invoice-batches/import (csv, preview), GET /v1/invoice-batches, POST /v1/invoice-batches/:id/issue i /send (po sto odnosno dvadeset pet po pozivu, remaining kaže koliko je ostalo), GET /v1/invoices?batchId=, customerRef na računu, sentAt i batchId u odgovoru. Najviše 5.000 računa po fajlu.

      0.65.0

      20. septembar 2026.

      Novo

      • Račun za robu sa police. Veleprodaja je vodila zalihe i pisala račune, ali jedno nije znalo za drugo: račun je bio samo riječi i cijene, a stanje je trebalo skidati rukom, po sjećanju. Stavka računa sada može da imenuje artikal sa police: u opis se kuca naziv ili šifra, izabere se s liste, i stavka nosi njegov naziv i cijenu s kase (cijena se može prepisati, npr. za akciju; artikal bez cijene traži cijenu na stavci). Izdavanje računa skida količine sa stanja, jednom po stavci, s kretanjem koje nosi broj računa, pa se ni ponovljeno izdavanje ni ponovljena obrada ne skida dvaput. Nacrt ne dira stanje. Ponovi (za idući mjesec) nosi artikle dalje.
      • Otpremnica. Uz robu ide papir bez cijena, jer vozač i skladištar koji primaju robu nisu ti koji su cijenu ugovorili. Dugme Otpremnica (PDF) na računu koji ima stavke s police: šta i koliko, šifra i jedinica, tri mjesta za potpis (izdao, vozač, primio) i napomena da cijene stoje na računu. Štampa se i za nacrt, jer roba često krene prije broja računa, i tada na njoj piše da je nacrt.
      • Storno ne vraća robu. Namjerno: storniran račun ne zna da li se roba vratila. Ako jeste, povrat se upisuje u Zalihama, s razlogom, kao i svaki drugi.
      • Pomoć ima vodič "Roba koja ide sa police", samo za djelatnosti koje vode zalihe.
      • API: stavka fakture prima stockItemId (opis i cijena tada nisu obavezni), vraća ga u lines[], a GET /v1/invoices/:id/delivery-note.pdf daje otpremnicu. Artikal koji nije na polici te poslovnice se odbija (stock_item_unknown), artikal bez cijene bez cijene na stavci takođe (stock_item_unpriced).

      0.64.0

      20. septembar 2026.

      Novo

      • Kasa prodaje s police. Prodavnica je imala zalihe s brojem komada i bez cijene, a kasa na ekranu je prodavala samo jela s menija koji prodavnica nema, pa je jedini način bio slobodan iznos za koji stanje nikad nije čulo. Artikal u Zalihama sada ima cijenu na kasi i barkod; kasa u prodavnici otvara policu: artikli s cijenom i stanjem, polje za skener (barkod ili šifra pa Enter, ili dio naziva), i kad se prodaja zatvori, prodano silazi sa stanja, jednom, s vezom na red prodaje, pa uplata viđena dvaput ne skida dvaput. Artikal bez cijene se vodi, ali se ne nudi.
      • Gotovina i kartica na kasi. Kasa na ekranu je do sada znala samo za kod: prodaja za keš ili karticu nije postojala ni u prometu ni na stanju. Svaka prodaja na kasi je sada račun kao i svaki drugi, na vlastitom računu uređaja: gotovina i kartica ga zatvore odmah (ekran kaže PRODANO), kod ga ostavi da čeka i zatvori se sam kad uplata legne. Promet po načinu plaćanja, osoba prijavljena PIN-om, povrat, sve što izvještaji već znaju o računu važi i za kasu bez ijednog novog izvještaja. Kasa se ne može pozvati iz kancelarije: prodaja se kuca na uparenom uređaju.
      • Šanker ima izbore. Kasa na šanku je svako jelo prodavala u osnovnoj verziji jer nije imala kako pitati. Jelo s izborom sada pita isto kao na konobarovom telefonu: kafa s mlijekom, ćevapi po veličini, s cijenom koju izbor nosi.
      • API: POST /v1/counter/sales (linije s menija ili s police, način plaćanja, isti clientRef vraća istu prodaju), GET /v1/stock/sellable za uređaje, price i barcode na artiklu zaliha. Kod koji se ne može izdati ne ostavlja polovičnu prodaju; linija koja se odbije takođe.

      0.63.0

      20. septembar 2026.

      Novo

      • Webshop: stranica za plaćanje koju XPay drži. Prodavnica na internetu je imala API i webhook i ništa što bi stavila pred kupca: sama je morala crtati kod, ispisivati račun i pitati da li je stiglo. Sada račun napravljen preko API-ja ili iz konzole nosi link na stranicu (checkoutUrl): kod za bankovnu aplikaciju, broj računa i poziv na broj za one koji ne skeniraju, koliko kod još važi, i stanje koje se samo mijenja u PLAĆENO (ili „stiglo više", „stiglo manje", „kod istekao") kad banka javi. Uz returnUrl (samo https) stranica vrati kupca u prodavnicu s ishodom u upitu. Link je jedina ključ do stranice, kao kod fakture: bez prijave, bez ijednog podatka osim tog jednog računa. Račun podignut na tabletu ili kasi nema stranicu; uređaj je stranica.
      • Dodatak za WooCommerce. integrations/woocommerce: kupac na kasi bira XPay, prodavnica napravi račun, preusmjeri ga na stranicu, primi webhook s provjerom potpisa i označi narudžbu plaćenom; stiglo manje ide na čekanje uz bilješku koliko fali; kad se kupac vrati, stranica narudžbe i sama provjeri stanje, pa spor webhook ne ostavlja plaćenu narudžbu kao neplaćenu. Podešavanje je pet polja. Napisan po WooCommerce API-ju i provjeren harnessom bez WordPressa (14 provjera potpisa i ishoda); prva proba na živoj prodavnici je proba od 1 KM.
      • Uputstvo za webshop u tri poziva, docs/bs/07-webshop.md, i vodič pod Pomoć. Integracije na sajtu dobile četvrti način: webshop.

      Popravljeno

      • Loš iznos ili loša adresa vraćali su „Internal server error". Sheme koje dijele API i konzola žive u ES modulu i njihove greške validacije filter API-ja nije prepoznavao, pa je amount: "abc" ili returnUrl na http bio 500 umjesto 400 s imenom polja. Oba su sada 400 i kažu šta ne valja.

      0.62.0

      20. septembar 2026.

      Novo

      • Operater mijenja svoju lozinku na ekranu. Operater ne pripada nijednoj firmi, pa je Postavke, gdje lokal mijenja lozinku, ekran do kojeg operater ne može doći: konzola prvo pita koju firmu gleda. Jedini nalog koji je najviše bitan mogao je promijeniti lozinku samo komandom na serveru. Sada pod Administracija, Moj nalog: traži se trenutna lozinka, najmanje 12 znakova za operatera, i nakon promjene sve prijave se odjavljuju, i ta. Isti obrazac kao u konzoli lokala, jedan kod za oba.

      0.61.0

      20. septembar 2026.

      Novo

      • Kupci, klijenti, stanari, korisnici: svako jednom, sa saldom. Svaka faktura je nosila kupca kao ime i tri neobavezna polja, i ništa nije povezivalo jednu fakturu s drugom, pa je „šta mi duguje ovaj stanar" bilo listanje faktura s imenom u glavi. Sada je to jedan ekran, nazvan po djelatnosti (Klijenti, Stanari, Korisnici, Kupci): svako jednom, s ID brojem, šifrom (broj korisnika, ugovor, stan), e-mailom i adresom, i uz svakog koliko duguje, koliko od toga kasni i koliko dugo (nije dospjelo, do 30 dana, 31 do 60, 61 do 90, preko 90). Dodir na ime otvara sve njegove račune.
      • Izvod otvorenih stavki. Jedno dugme, jedan PDF: svaki otvoren račun s datumom, rokom, iznosom, uplaćenim i dugom, zbir na dnu, dospjelo crveno, na dan izrade, s napomenom da je stanje prema računima kroz XPay. Dokument koji knjigovođa šalje na kraju kvartala.
      • Podsjetnik jednim dodirom. E-mail kupcu sa spiskom dospjelih računa, iznosima i linkom na svaki (poziv na broj i kod). Šalje ga osoba, nikad automatika: podsjetnik je odnos, a zakupodavac zna ko je ovog mjeseca ostao bez posla. Najviše jednom dnevno po kupcu; odbijeno kad nema e-maila ili ništa nije dospjelo, s razlogom na ekranu. Vidi se kad je zadnji poslan.
      • API: GET/POST/PATCH /v1/customers, GET /v1/customers/:id sa saldom i starošću duga, GET /v1/customers/:id/statement.pdf, POST /v1/customers/:id/remind. Faktura prima customerId; odgovor nosi customer.id. Drugi kupac s istim ID brojem se odbija uz id postojećeg.

      0.60.0

      20. septembar 2026.

      Novo

      • Konzola zna čime se bavite. Server je oduvijek znao koje je vrste svaka poslovnica; konzola je čitala samo šta se smije, i samo za navigaciju. Pa je knjigovođa bio pošteđen ekrana Stolovi, a onda dobio pregled o gostima i gotovini za stolom, Poslovnice koje nude kodove za stolove i tablet konobara, i Osoblje čije su jedine uloge konobar, kuhar i šanker. Proizvod je bio restoran sa sakrivenim restoranskim ekranima.
      • Pregled za one koji šalju račune. Četiri broja i jedan spisak: izdato u periodu, naplaćeno u periodu, dospjelo a neplaćeno (danas), otvoreno a još nije dospjelo (danas), i ko duguje, po kupcu, najveći dug prvi, crveno što je prošlo rok, sa datumom od kada kasni. Dodir na ime otvara njegove račune. Ispod, naplaćeno po danu i zadnji računi. Isto pravilo za „kasni" kao na listi faktura, pa se dva ekrana ne mogu razići.
      • Salon, servis, ordinacija, teretana. Nova vrsta posla: naplata na licu mjesta po posjeti, prijava osoblja PIN-om da se vidi ko je naplatio, fakture kad trebaju (osiguranje, firma), bez stolova, menija i zaliha. Na prijavi i u konzoli operatera.
      • Osoblje po djelatnosti. Trgovina dodaje prodavača, blagajnika i skladištara; salon radnika i recepciju; restoran ostaje kod konobara, kuhara i šankera. Uloga je riječ, ne pravo: uređaj odlučuje ekran.
      • Pretraga faktura po kupcu. Polje na listi faktura, i cilj linka sa spiska dužnika.

      Popravljeno

      • Probni podaci više ne daju knjigovođi dvanaest naljepnica za stolove.

      0.59.0

      20. septembar 2026.

      Novo

      • Gosti se presele, račun ide s njima. Četvero sjedne za Sto 3, naruči, i pređe na terasu kad se oslobodi. Račun je do sada pripadao naljepnici s koje je otvoren, pa ga je konobar nosio u glavi, ili zatvarao kao gotovinu i otvarao ponovo, dok je kuhinja dozivala sto za kojim više nije bilo nikoga. Premjesti na stolu nosi cijeli račun, s narudžbama, na drugi slobodan sto: kuhinjski ekran i sala odmah pišu novi sto. Odbijeno dok se sto plaća ili gost drži živ kod, i odbijeno na sto koji već ima račun. Gosti ponovo skeniraju naljepnicu novog stola i nađu svoj račun tamo.
      • Otkazivanje narudžbe s telefona. Uz svaku narudžbu koja još nije spremna stoji Otkaži, s razlogom u jednom dodiru: gost odustao, greška, nema više. Račun pada tačno za tu rundu, kuhinja vidi razlog. Ono što je već na tacni ne može se otkazati: to je razgovor o povratu, ne dugme.

      0.58.0

      20. septembar 2026.

      Novo

      • Konobar uzima narudžbu sa menija, na svom telefonu. Sala je pokazivala stolove i šta je ko naručio, a jedino što nije mogla bilo je uzeti narudžbu: gost koji radije kaže „dvije kafe" nego da skenira naljepnicu upisivao se kao slobodan iznos, koji kuhinja nikad ne vidi i sto ne pamti. U lokalu s cjenovnikom konobar je kucao brojeve.
      • Telefon javlja šta se promijenilo u sali. Poziv sa stola, nova narudžba s gostovog telefona, zahtjev za račun (i kako), tanjiri koje je kuhinja završila i uplata kodom koja je zatvorila sto: svako svojim zvukom, vibracijom i porukom na vrhu ekrana koja otvara taj sto. Ne javlja ono što je konobar sam uradio. Poruke ne dolaze iz događaja nego iz razlike između dva pogleda na salu, pa ispadnuti wifi ne može progutati poziv: sljedeći pogled ga nađe.
      • Izneseno. Uz svaku narudžbu na stolu koja još nije iznesena stoji dugme. Konobar je taj koji je nosi, pa je konobar taj koji kaže da je stigla; gost na svom telefonu vidi da je stigla. Sto na kojem kuhinja ima gotove tanjire piše spremno za iznijeti, plavo, da se vidi preko sale.
      • Izvještaj o osoblju broji i uzete narudžbe. Nova kolona uz zatvorene račune, gotovinu i korake: koliko je narudžbi ta osoba uzela za stolom. Nula, ne prazno, za kuhara; nula i za sve što su gosti sami poslali.

      Popravljeno

      • Narudžba je morala biti „preuzeta" prije nego što se iznese. Pravilo je bilo da kuhinja prvo pritisne preuzeto, pa tek onda iko smije reći da je izneseno. U kafiću bez ekrana na zidu nema ko da pritisne preuzeto, pa su narudžbe stajale kao „poslano" zauvijek, a konobar koji je kafu napravio i donio bio je odbijen kada je to rekao. Izneseno se sada može reći odmah.
      • Slobodan iznos je jedan dodir dalje i zove se kako treba. Dugme na dnu sale sada piše Račun bez stola, za bocu na vratima i šank pri odlasku. Sve što se dešava za stolom ide preko stola.
      • Kuhinjski ekran ne može uzeti narudžbu. Narudžba dodaje dug na sto, pa traži isto što i naplata: ekran koji dijele tri kuhara u prostoriji u koju svako može ući ima pravo na narudžbe, ne na novac.

      0.57.0

      20. septembar 2026.

      Novo

      • Račun koji knjigovođa proknjiži bez telefoniranja. Račun iz XPay-a je imao broj, datum, stavke, PDV i ukupno, i to je bilo dovoljno gostu. Nije bilo dovoljno onome ko ga knjiži: nedostajali su PDV broj izdavaoca, mjesto izdavanja, datum prometa i način plaćanja, a PDV je bio jedan red bez stope, pa se iz njega nije vidjelo da li je 17% na sve ili je nešto oslobođeno. Svaki od tih redova je pitanje koje knjigovođa mora postaviti, i svaki račun bez njih je račun koji se vraća.
      • „Izdavalac nije u sistemu PDV-a." Firma koja nije u sistemu mora to reći na računu, i sada se ta rečenica ispisuje sama u podnožju kada je u postavkama rečeno „ne". Ali samo na računu bez poreza: firma koja je prešla u sistem i promijenila postavku, ili obrnuto, ima stare račune sa 17% i novu postavku „ne", i tu bi rečenica ispod redova sa PDV-om bila laž na dokumentu. Zato se ne štampa dok na računu ima poreza, a izdavanje računa sa stopom za firmu koja je rekla „ne" se odbija s objašnjenjem, prije nego što dobije broj.
      • QR kod na računu je manji i na desnoj strani. Bio je velik koliko i blok za plaćanje i gurao je podatke o banci u drugi plan. Sada stoji desno, centriran uz IBAN, iznos i poziv na broj, dovoljno velik da ga bankovna aplikacija pročita s papira, i ništa više.

      Uputstvo

      • Svakodnevni rad opisuje salu. Poglavlje o naplati je pisano za tastaturu i kod; sada opisuje stolove kakve konobar vidi na telefonu, šta otvara dodir na sto, četiri stvari koje se rade s novcem, i kada se koristi račun bez stola.

      0.56.0

      20. septembar 2026.

      Novo

      • Konobar na svom telefonu vidi salu. Terminal je bio tastatura i kod: upiši iznos, pokaži QR, uzmi novac. Sto, narudžbu i poziv sa stola nije vidio - to je stajalo na zidu u kuhinji i na laptopu u kancelariji, dva mjesta gdje konobar nije. Osoba čiji je posao sala bila je jedina u lokalu bez pogleda na nju.
      • Konobar može podići QR kod za cijeli sto. Za gosta koji ne može skenirati naljepnicu ili bi radije da konobar to obavi. Do sada je jedini odgovor bila tastatura, koja je pravila račun za koji sto nije znao: novac stigne, sto ostane otvoren, neko ga zatvori kao „neplaćeno" ili „gotovina" da oslobodi sto, i izvještaj broji veče dvaput ili nijednom. Kod se sada veže za sto pod istom bravom koju koristi gostov tok, pa dva koda za isti novac ne mogu proći, i kada novac legne sto se zatvara sam - put koji ga zatvara ne razlikuje ko je kod podigao. Odbijeno dok bilo koji gost drži živ kod, i odbijeno gdje je lokal isključio plaćanje kodom.

      Popravljeno

      • Poništen kod za sto ostavljao je sto zaključan. Podizanje koda parkira sto (bez narudžbi, bez novih telefona). Otkaži na terminalu je poništavao samo kod, pa je sto ostajao parkiran bez ičega na što čeka: dugovao 20,00, nije držao kod i nije mogao naručiti kafu. Otkaži sada ide preko stola, kao i gostovo dugme, pa se sto oslobodi. A sto parkiran isteklim kodom dobio je Oslobodi sto, jer istekao kod parkira sto još sat vremena, a dugme za to se pokazivalo samo dok je kod živ.
      • Telefon konobara sada smije čitati spisak stolova svog lokala. Opseg tables:read uveden uz zatezanje API ključeva nikad nije dat uređaju, pa bi telefon vidio svaki otvoren račun i nijedan sto. Čita svoj lokal; tuđi i dalje ne postoji za njega.
      • „Sto Sto 3" na ekranu čekanja. Oznaka s tastature je broj, pa joj se dodaje riječ; oznaka sa sale je već „Sto 3".

      0.55.34

      19. septembar 2026.

      Novo

      • Vlasnik bira šta gost može da plati preko telefona. Podešavanja → Načini plaćanja: za svaku poslovnicu prekidači za kod za plaćanje (bankovna aplikacija), karticu na vašem terminalu i gotovinu. Što je isključeno, gost ne vidi. Kafić koji prima samo gotovinu isključi prva dva: gostu dugme Plati odmah zove konobara, bez ekrana sa izborom. Kad je isključeno sve, gost nema dugme za plaćanje i na računu mu piše da se plaća kod osoblja; naljepnica za plaćanje bez menija kaže da lokal ne prima kod sa telefona. Isto vrijedi i na strani servera: kod ili zahtjev za način koji je isključen se odbije, pa zaobilaženje ekrana ne pomaže. Tablet konobara, kasa na ekranu i API ključevi i dalje izdaju kodove, jer to radi osoblje.

      Za one koji razvijaju

      • Location.acceptsQr, acceptsCard, acceptsCash (migracija 20261006000000_payment_methods, sve tri podrazumijevano uključene), PATCH /v1/locations/:id ih prima, GET /v1/t/:slug vraća payments { qr, card, cash }. Odbijanje je 409 payment_method_off na POST /v1/t/:slug/session/pay, .../session/request-payment i POST /v1/t/:slug/payments. Smoke narudžbi dobio je odjeljak koji lokal prebaci na gotovinu, provjeri sva tri odgovora i vrati ga.

      0.55.33

      19. septembar 2026.

      Novo

      • Zvuk za osoblje na svakom ekranu. Konzola, konobarski tablet i kasa na ekranu sada zvone kad se nešto desi, kao što kuhinjski ekran već zvoni: nova narudžba (dva tona nagore), gost zove konobara (tri tona nadolje, dva puta), gost hoće da plati (dva kratka pa jedan duži), uplata stigla (akord) i otkazana narudžba (nadolje). Svaki ekran ima dugme za zvuk u zaglavlju i izbor se pamti na tom uređaju. Preglednik ne pušta zvuk dok se ekran jednom ne dodirne, pa dotle pored dugmeta piše "Zvuk je blokiran, kliknite da ga uključite" umjesto da zvoni u prazno. Osam narudžbi sa jednog stola je jedan zvuk, ne osam.
      • Stranica Kasa sa dugmetom "Pretraži kasu". U konzoli, pod Kasa, vlasnik ili menadžer vidi kako je kasa povezana sa XPay-om i traži je jednim dugmetom. Konzola je web stranica i ne vidi uređaje u lokalu, pa pretraga nalazi ono što se javilo XPay-u: konektor na računaru pored kase (javlja se svakih pola minute, sa onim što prati i onim što je njegov detektor našao na tom računaru: fiskalni servis, foldere, instalirane programe) ili kasu koja sama zove XPay ključem (piše kad je zadnji put zvala i koji program). Pretraga sluša minut i stane čim se nešto javi. Kad ne nađe ništa, kaže da je to uobičajeno, ne greška, i daje tri načina: kasa koja može zvati internet (ključ pod Za programere plus uputstvo za servisera koje se kopira jednim klikom), računar pored kase (zahtjev za instalaciju konektora jednim klikom) i kasa koja ostaje kakva jeste (tablet, kasa na ekranu ili naljepnica rade već danas, a račun se na kasi zatvori kao za gotovinu). Ispod toga su uređaji XPay-a po vrsti i svi ključevi sa zadnjim pozivom.
      • Konektor se sam javlja. Konektor 0.2.0 šalje otkucaj svakih 30 sekundi i svakih 15 minuta ponavlja detekciju koju je dosad trebalo pokrenuti ručno sa --detect.

      Za one koji razvijaju

      • POST /v1/connectors/heartbeat (API ključ, opseg payments:read) upisuje red u pos_connectors, jedan po računaru po lokalu; GET /v1/pos-links (vlasnik ili menadžer) vraća konektore, ključeve sa lastUserAgent i broj uređaja po vrsti. Migracija 20261005000000_pos_connectors. Ključ uz lastUsedAt sada pamti i lastUserAgent.
      • Zvuk: apps/dashboard/src/lib/alert-sound.ts je jedan hook za sve ekrane sa tonovima sintetizovanim u pregledniku, components/sound-control.tsx je dugme, a konzola sluša događaje u components/console-alerts.tsx.

      0.55.32

      19. septembar 2026.

      Novo

      • Gost vidi kada mu stiže narudžba. Poslije slanja narudžbe na ekranu je prsten koji se puni i sat koji odbrojava: "Vaša narudžba stiže za 11:40", ispod toga "2 narudžbe ispred vas" i, kad narudžba ima i piće i hranu, posebno "Pića ~3 min" i "Hrana ~14 min". Isti sat stoji na svakoj otvorenoj narudžbi u kartici stola. Kad kuhinja označi spremno, piše "Spremno je, stiže za tren"; kad procjena istekne a kuhinja nije gotova, piše "Još malo, kuhinja završava", nikad nula.
      • Procjena je pametna, ne fiksna. Računa se iz tri stvari: koliko traje svako jelo (novo polje "Vrijeme pripreme" na artiklu; prazno znači uobičajeno za stanicu, kuhinja 12 min, šank 3 min), koliko je narudžbi ispred u redu iste stanice (kuhinja radi tri odjednom, šank četiri) i koliko ta kuhinja stvarno treba u odnosu na ono što meni tvrdi (srednja vrijednost zadnjih 60 gotovih narudžbi u dvije sedmice, između 0,6 i 1,8 puta). Vrijeme pripreme se pamti uz stavku narudžbe kao i naziv i cijena, pa izmjena menija sutra ne mijenja ono što je gost večeras vidio.
      • Red u kuhinji je po vremenu narudžbe i to piše. Na kuhinjskom ekranu svaka kartica nosi "1. u redu", "2. u redu" i "do 20:35" (vrijeme obećano gostu). Kartica koja probije obećano vrijeme postaje crvena i piše "kasni", bez obzira na sat. Isto na listi narudžbi u konzoli.
      • Na artiklu u meniju piše "Priprema oko 12 min" kad gost otvori jelo, da onaj kome se žuri izabere burek a ne lonac. Demo lokal ima vremena za svih 26 jela.
      • Povrat sa izvoda se evidentira sam. Kad banka platioca povuče uplatu a banka lokala je vrati, na izvodu lokala stoji zaduženje sa originalnim pozivom na broj. Uvoz izvoda ga sada prepozna i upiše kao povrat na tom računu (sa referencom banke, pa ponovni uvoz istog izvoda ne upisuje dva puta); račun više ne ostaje "plaćen" bez novca. Zaduženja bez naše reference su plaćanja lokala prema drugima i samo se prebroje.

      Za one koji razvijaju

      • apps/api/src/modules/orders/eta.ts: čista funkcija procjene sa 20 testova (red po placedAt, pozicija, paralelnost stanice, kalibracija, zastarjela procjena). Migracija 20261004000000_prep_minutes dodaje prepMinutes na menu_items i order_items. API vraća eta u pogledu stola za gosta (/v1/t/:slug/session) i na tabli (/v1/orders).
      • POST /v1/settlement/sources/:id/camt vraća i returned, returnsDuplicate, returnsUnmatched; parser camt fajlova daje returns uz credits, sa referencama iz RtrInf/OrgnlTxRef.

      0.55.31

      19. septembar 2026.

      Popravke

      • Uparivanje čita i broj dokumenta iz strukturirane doznake. Poruka instant plaćanja nosi referencu ili kao slobodni tekst (do 140 znakova) ili strukturirano, a u strukturiranom bloku banka može upisati broj računa ili fakture kao "referentni dokument" umjesto kao poziv na broj. Uvoz izvoda (camt.052/053/054) sada čita i to polje i identifikatore stavki ispod njega, pa se uplata sa referencom na tom mjestu upari po referenci, a ne tek po iznosu i vremenu.

      Za one koji razvijaju

      • Dokumentacija Centralne banke za sistem instant plaćanja (specifikacije, sheme poruka, primjeri, pitanja i odgovori) stigla je 19. septembra i čuva se u CBBH_docs/ izvan repozitorija (.gitignore). Šta iz nje slijedi za proizvod sažeto je u docs/go-live-bih-ips.md: KM ide kroz ne-euro shemu platforme, deset sekundi od prihvatanja naloga, referenca staje u oba polja (140 slobodno, 35 strukturirano), račun između banaka je uvijek IBAN, alias direktorijum i QR model su najavljeni a nisu objavljeni. Pitanja za banke dopunjena (u koje polje aplikacija upisuje referencu, da li EndToEndId i UETR stižu na izvod klijenta, alias plaćanja, kako izgleda povrat).

      0.55.30

      18. septembar 2026.

      Popravke

      • README govori o svim djelatnostima. Opis projekta na GitHubu je bio napisan za ugostiteljstvo ("gost", "restoran", "konobar"). Sada vodi sa fakturom, kasom i izvodom: trgovine, servisi i samostalne djelatnosti, komunalna preduzeća i zakup, webshopovi, veliki izdavaoci računa, i tek onda kafići i restorani. Dodane grupe "Fakture i naplata, za svaku djelatnost" i "Trgovina, veleprodaja i webshop" sa onim što već postoji u proizvodu; tok novca i pravna napomena govore o kupcu i firmi, ne o gostu i restoranu.

      0.55.29

      16. septembar 2026.

      Novo

      • Novi logo, svuda. Sajt, konzola, stranica gosta, naljepnice za stolove, QR kod (znak u sredini), faktura u PDF-u, slika koja ide uz podijeljeni link, README i sva tri dokumenta za štampu nose novi XPay logo: veliko X sa trakom pločica i riječ "Pay". Dvije verzije, jedna za tamnu podlogu sa svijetlim slovima, jedna za svijetlu podlogu sa tamnim slovima, i svaka površina nosi onu za koju je nacrtana. Ikona u kartici preglednika je X iz tog loga, u tri veličine (16, 32 i 48 piksela), a ikona za početni ekran telefona sjedi na crnoj podlozi sajta. Stari logo, i onaj ljubičasti i onaj plavi od prije septembra, nigdje se više ne prikazuje.

      Za one koji razvijaju

      • scripts/brand-logo.mjs prima dva fajla od dizajnera (za tamnu i za svijetlu podlogu), čuva ih pod assets/brand/ i iz njih generiše sve ostalo: lockup za oba app-a, znak, ikone, favicon.ico i modul sa slikom za OG stranicu. Granica između X-a i riječi se nalazi po obliku (stub slova P je prva kolona poslije križanja u kojoj neprekinuti trag tinte naglo poraste), pa nova verzija crteža ne traži nova mjerenja.

      0.55.28

      16. septembar 2026.

      Novo

      • Stranica za banke: "Vrijednost za banku" i "Zašto sada". Odmah ispod prvog ekrana stoje četiri kolone kako ih banka sama mjeri: volumen (više transakcija kroz IPS, veća frekvencija), novi prihodi (monetizacija SME segmenta, transakcioni ili pretplatni model), retencija (trgovac drži račun i priliv kod banke, manje odliva), diferencijacija (konkretan proizvod, prednost pred konkurencijom). Zatim "Zašto sada": IPS infrastruktura već postoji, tržište nema standardizovano rješenje, konkurencija nije pozicionirana, i ljubičasti blok "Prednost prvog". PDF za štampu obnovljen iz istog sadržaja (osam strana).

      0.55.27

      16. septembar 2026.

      Popravke

      • Stranica za banke govori jezikom koristi. Naslov je sada "Povećajte korištenje instant plaćanja na prodajnim mjestima, pod vašim brendom", a odmah ispod prvog ekrana stoji nova sekcija "Šta banka dobija, mjereno": četiri koristi (više instant transakcija, aktivniji klijenti u aplikaciji, trgovac vezan za banku, bez rizika i bez razvoja), svaka sa naslovom, dvije rečenice i redom "Rezultat:" koji kaže šta se mjeri. Tehnika i tok novca su ostali, ali ispod toga. PDF za štampu obnovljen iz istog sadržaja (šest strana).

      0.55.26

      16. septembar 2026.

      Popravke

      • Sajt: jela na telefonu imaju slike. Ilustracija menija na početnoj, na stranici za firme i na Hospitality stranici crtala je uz svako jelo dva smeđa prstena umjesto slike, što je izgledalo kao prazan krug. Sada su tu iste naslikane sličice koje vidi gost na stranici lokala (ćevapi, Begova čorba, burek, bosanska kafa), napravljene iz istog crtača (scripts/site-dishes.mjs), pa telefon na sajtu izgleda kao telefon u ruci gosta.

      0.55.25

      16. septembar 2026.

      Novo

      • Dvije stranice za slanje linkom: za banke i za firme. xpay.ba/banke je prijedlog partnerstva za banke i velike partnere (white-label): tok novca u pet stanica sa jasno označenim mjestom gdje XPay nikad ne dodiruje novac, šta banka dobija, sedam djelatnosti, tehnički okvir za inženjere, tri modela saradnje, pilot u tri koraka i iskren popis onoga što još nije napravljeno. xpay.ba/za-firme je za lokale i sve druge djelatnosti: tri toka (skeniraj-naruči-plati, skeniraj-vidi fakturu-plati, kod na kasi ili stranici), tabela po djelatnosti, cijene i pitanja koja svi postave. Obje su u glavnoj navigaciji i u podnožju.
      • Verzije za štampu. Svaka stranica ima dugme "Verzija za štampu (PDF)": pet strana A4 u istim bojama, napravljene iz istog sadržaja kao stranica (scripts/partner-docs.cjs), pa PDF u ruci i stranica na ekranu ne mogu reći različite stvari. Word verzije su pored, za uređivanje.

      0.55.24

      16. septembar 2026.

      Novo

      • Priprema za razgovor sa bankom (dokument za štampu). U docs/bs/prilozi stoji Word i PDF sa 14 strana: šta je XPay u tri rečenice, kako radi korak po korak, šta banka dobija od white-label saradnje, pitanja koja banka postavlja (poslovna, tehnička, pravna, o riziku) sa odgovorima, tehnički list sa brojevima, devet pitanja koja mi postavljamo banci, tri modela saradnje sa polaznim cijenama, lista onoga što se ne obećava i zašto, i plan sastanka od 30 minuta. Skripta koja ga pravi je pored, pa se dokument obnavlja jednom komandom kad se proizvod promijeni.

      0.55.23

      16. septembar 2026.

      Popravke

      • Korpa: dugme "Naruči" više ne bježi van ekrana. Dugme "Dodaj još" trebalo je da bude usko, uz široko ljubičasto "Naruči", a zauzimalo je cijeli red i gurnulo "Naruči" desno, van ekrana. Uzrok: osnovna klasa dugmeta uvijek je dodavala punu širinu, pa je zahtjev za uskim dugmetom gubio. Sada dugme koje traži svoju širinu i dobije svoju širinu.
      • Stranica gosta na laptopu izgleda kao na telefonu. Na širokom ekranu svaka kartica se razvlačila preko cijele širine (1900 piksela), a trake na dnu (korpa, narudžba, navigacija) i list sa detaljima jela isto. Sada je sadržaj ograničen na širinu telefona i centriran, boja lokala ostaje po cijeloj pozadini, a trake na dnu i list prate istu širinu. Na telefonu se ništa ne mijenja.

      0.55.22

      16. septembar 2026.

      Novo

      • Za malu raju: igrice na stranici gosta. Porodica sjedne, roditelji naruče sa telefona, i sljedećih dvadeset minuta dijete hoće telefon. Na početnoj stranici gosta sada stoji kartica "Za malu raju" sa tri male igre koje ne traže ni signal ni nalog: Memori (nađi parove), Iks-oks protiv telefona, i Slagalica od slike lokala. Ništa od toga ne razgovara sa serverom, pa dijete koje pritišće sve redom ne može ništa pokvariti.
      • Demo meni za lokal, jednom komandom. Nova komanda na serveru (seed-demo-venue) napuni lokal kompletnim menijem: doručak, predjela, roštilj, pite, glavna jela, pizze, salate i prilozi, "Za malu raju", deserti, topli napici i hladna pića, sa cijenama, opisima, opcijama (veličina ćevapa, prilog, šećer u kafi) i prijedlozima (piće poslije roštilja, kafa poslije deserta). Svako jelo dobije naslikanu sličicu u jednom stilu (tanjir, zdjela, čaša, pita, pizza, sladoled...), nacrtanu bez ijedne biblioteke, tako da meni na prvi pogled izgleda kao meni. Postojeće kategorije i jela lokala se čuvaju: "Jelo" postaje "Sa roštilja", "Pice" postaje "Hladna pića", ćevapi i Coca-Cola koje je lokal sam upisao ostaju sa svojim fotografijama, a jela bez slike dobiju sličicu. Ništa se ne briše.

      Provjere

      • Test za sličice (35 vrsta, ispravan PNG od 480 piksela, ista slika za isto jelo); typecheck API-ja i konzole; i18n paritet; lint. Komanda provjerena na lokalnoj bazi u probnom načinu (--dry) i stvarno.

      0.55.21

      16. septembar 2026.

      Popravke

      • Lista za dan testa zna za "Novo plaćanje" u konzoli. Korak za prvu uplatu od 1 KM sada kaže da se kod može napraviti i sa laptopa, bez tableta: Plaćanja, dugme "Novo plaćanje", iznos 1,00.

      0.55.20

      16. septembar 2026.

      Novo

      • Novi račun iz konzole. Konzola je mogla da pregleda, vrati i potvrdi uplate, a nije mogla da napravi nijednu: kod su izdavali samo upareni tablet i kasa, a prevod za dugme "Novo plaćanje" postojao je sedmicama bez dugmeta. Na ekranu Plaćanja sada stoji "Novo plaćanje": iznos, sto i broj računa na kasi (oba nisu obavezna), poslovnica ako ih ima više. Kod se prikaže na ekranu da ga gost skenira, uz poziv na broj i do kad važi, a stanje se osvježava samo dok je prozor otvoren ("Plaćeno", "Stiglo više", "Stiglo manje", "Kod je istekao"). Dupli klik ne pravi dva računa.
      • Sto koji predugo stoji neplaćen se vidi na rasporedu. Jedina granica do sada bilo je dvanaest sati, poslije kojih sto ne prima narudžbe, a ništa na ekranu nije reklo da sto devet od ručka sjedi na neplaćenom računu. Sto sa narudžbom, dugom i više od 90 minuta otvoren sada svijetli žuto sa natpisom "Otvoren predugo" i "N min bez plaćanja. Provjeri sto.", a zaglavlje rasporeda broji takve stolove. Prazan sto (bez narudžbe) nije ovo: njega API sam sklanja poslije pola sata.

      Provjere

      • Typecheck konzole, i18n paritet, lint. Dijalog šalje isti zahtjev kao tablet (POST /v1/payments sa ključem idempotencije), koji je pokriven postojećim testovima i smoke paketima.

      0.55.19

      16. septembar 2026.

      Popravke

      • Lista za dan testa zna za prekidač zapisa računa u QR kodu. U tabeli "Ako nešto ne radi" stoji šta uraditi kad bankovna aplikacija pročita kod, a odbije račun primaoca: na serveru uključiti QR_ACCOUNT_FORMAT="domestic" i podići API, bez nove verzije. Red o kodu koji se ne izdaje sada kaže "račun", ne "IBAN", jer lokal može upisati i broj računa od 16 cifara.

      0.55.18

      16. septembar 2026.

      Novo

      • Broj računa umjesto IBAN-a: lokal upisuje ono što zna. U BiH je IBAN uglavnom služio za plaćanja prema inostranstvu; na kartici, u e-bankarstvu i na izvodu stoji domaći broj računa od 16 cifara (pisan 3-3-8-2, npr. 129-007-94010284-94). To je isti račun: IBAN je BA, dvije kontrolne cifre i tih 16 cifara. Polje za račun u konzoli (nova poslovnica i izmjena računa) sada prima jedno ili drugo; iz broja računa se IBAN izračuna sam, a kontrolne cifre oba oblika se provjere prije spremanja i greška kaže koje cifre da se pogledaju. Operaterski unos lokala prolazi istim putem.
      • Broj računa svuda gdje neko plaća ručno. Stranica gosta ("Prepišite podatke u svoju banku"), PDF fakture i javna stranica fakture uz IBAN sada pokazuju i broj računa od 16 cifara, jer domaći nalog u bankovnoj aplikaciji traži "broj računa", a ne IBAN. Kopira se bez crtica, kako ga obrazac traži.
      • Prekidač za zapis računa u QR kodu. BiH profil koda upisuje IBAN, a niko još nije potvrdio da bankovna aplikacija iz koda čita baš njega, a ne 16 cifara. Nova postavka QR_ACCOUNT_FORMAT ("iban" ili "domestic") mijenja zapis u kodu na računu, na naljepnici i na fakturi bez nove verzije: samo postavka na serveru i ponovno podizanje API-ja. Prazno znači da odlučuje profil, kao i do sada.

      Provjere

      • Novi testovi za broj računa: pretvorba u oba smjera na stvarnom primjeru, kontrolne cifre, ispis 3-3-8-2, i šta polje prima (16 cifara sa crticama ili bez, IBAN sa razmacima) i šta odbija (zamijenjene cifre u oba oblika). Postojeći testovi IBAN-a, QR kodeka, faktura, lokala i plaćanja prolaze; typecheck API-ja i konzole; i18n paritet; lint.

      0.55.17

      16. septembar 2026.

      Popravke

      • PIN tastatura: tipka za brisanje je strelica. Znak za brisanje koji je stajao na tastaturi za prijavu osoblja nema svaki font na tabletu, pa se na provjeri u pregledniku vidio kao pogrešan znak. Sada je obična strelica ulijevo, koju ima svaki font.

      0.55.16

      16. septembar 2026.

      Novo

      • Osoblje po imenu: konobari, kuhari i šankeri se prijavljuju PIN-om. Konzola ima korisnike sa e-mail prijavom, a sala ima tablete, kase i kuhinjske ekrane koje drži više ljudi. Ništa nije spajalo to dvoje, pa je svaki zatvoren račun, svaka pomjerena narudžba i svaki odgovoren poziv nosio ime uređaja: izvještaj je mogao reći "tablet na šanku zatvorio 40 računa", a nikad "Amir". Sada vlasnik na novom ekranu "Osoblje" dodaje ljude po imenu, ulozi (konobar, kuhar, šanker) i PIN-u od četiri do šest cifara. Na tabletu, kasi i kuhinjskom ekranu gore stoji dugme "Prijava": osoba izabere svoje ime, upiše PIN, i od tada sve što uradi na tom uređaju nosi njeno ime. Prijava traje jednu smjenu (14 sati), važi samo na tom uređaju i ne daje uređaju nikakva nova prava; uređaj bez prijave radi tačno kao do sada. Osam pogrešnih PIN-ova zaključava osobu na petnaest minuta, isto kao i lozinku u konzoli. Deaktivirana osoba prestaje da se imenuje odmah, i nestaje sa uređaja u roku od pet minuta.
      • Izvještaj "Ko je radio" imenuje ljude, ne samo uređaje. Prijavljena osoba se u izvještaju vodi kao osoba sa ulogom, uz konzolne korisnike; zajednički ekrani na kojima niko nije bio prijavljen ostaju označeni kao uređaji, kao i do sada. Isti izvještaj stoji i na ekranu "Osoblje", pored imena o kojima govori.

      Provjere

      • Cijeli tok provjeren od početka do kraja na lokalnoj bazi: vlasnik doda kuhara, kuhinjski ekran ga vidi na spisku bez PIN-a, pogrešan PIN se odbija, tačan vraća potpisan token, konzolna prijava ne može tražiti token za osoblje, gost naruči, prijavljeni kuhar prihvati narudžbu, izvještaj imenuje kuhara sa ulogom i jednom prihvaćenom narudžbom, deaktiviran kuhar nestaje sa spiska i njegov stari token pada na uređaj. Testovi potpisa tokena (šest) i PIN-a (tri), i18n paritet uključujući nove uloge, typecheck API-ja i konzole.

      0.55.15

      16. septembar 2026.

      Novo

      • Nova naljepnica za sto i novi izgled QR koda. U sredini svakog koda stajao je stari zeleni znak iz augusta, ručno prepisan u API kao vektorske linije sa ikone koja je iz projekta obrisana kad je stigao novi logo. Sada je u sredini novi znak XPay (isti na naljepnici, na stranici gosta i na fakturi u PDF-u), a kod na naljepnici za sto ima zaobljene module i zaobljene uglove tri velika kvadrata, dok kodovi koji nose novac (račun, faktura, bankovna naljepnica) ostaju klasični kvadrati koje svaka bankovna aplikacija sigurno čita. Naljepnica je redizajnirana: ljubičasta traka sa imenom lokala i stolom, kod na bijeloj ploči, tri koraka (Skeniraj, Naruči, Plati; kod bankovnog koda Skeniraj, Upiši iznos, Plati), adresa za telefon bez kamere, šifra stola i znak XPay. Stalak za sto je tamno ljubičast, kartica velika. Tabak A4 sada nosi devet naljepnica (tri puta tri), jer dvanaest nikad nije stalo na jednu stranu pri veličini koda koji se čita sa telefona u ruci.
      • Pregled naljepnice prije štampe. Na ekranu "Kodovi za stolove" sada stoji jedna prava naljepnica (prvi sto, u odabranom formatu i vrsti koda) napravljena istom komponentom kojom se štampa, pa pregled ne može da laže.

      Provjere

      • Zaobljeni kod se u testu iscrtava u piksele onako kako ga kamera vidi, sa prekrivenom sredinom, i dekodira istom bibliotekom; svi postojeći testovi čitljivosti (dug URL, bankovni nalog, znak preko sredine) i dalje prolaze.

      0.55.14

      16. septembar 2026.

      Popravke

      • Adresa API-ja u uputstvima, SDK-u i konektoru je sada ona koja postoji. Uputstvo za spajanje kase, engleska POS dokumentacija, SDK za Node i lokalni konektor upućivali su na api.xpay.ba, adresu koja nikad nije podešena (nema DNS zapisa ni certifikata). Ko bi sutra pratio uputstvo, dobio bi grešku "host nije pronađen" prije prvog poziva. Sve sada pokazuje na xpay.ba, gdje API stvarno radi (ista adresa na kojoj je i dokumentacija /docs), a uputstvo za tablet vodi na app.xpay.ba/terminal umjesto na izmišljenu domenu. Ekran "Za programere" u konzoli sada ispisuje osnovnu adresu API-ja, uzetu iz iste postavke koju konzola sama koristi, pa se ne može razići sa stvarnošću. Uputstvo je i ispravljeno da dugme zove onako kako se zove ("Novi ključ").
      • Prazan sto se sam sklanja poslije pola sata. Skeniranje koda ne otvara ništa: sto se u sistemu otvara tek kad gost naruči ili pozove konobara. Ali gost koji pozove konobara pa se predomisli, ili ode prije prve narudžbe, ostavljao je otvoren sto bez ijedne stavke: na rasporedu stolova svijetlio je kao "Čeka narudžbu" sa 0,00 KM i brojačem minuta koji nikad ne staje, pregled ga je brojao među otvorenim računima, a zatvoriti ga mogao je samo konobar sa ekrana narudžbi, dugmetom koje postoji za novac. Sada se sto bez narudžbe, bez uplate, bez otvorenog poziva i sa svim telefonima tihim 30 minuta sam zatvara, svakih pet minuta, bez ikakvog knjiženja (ne ulazi ni u promet ni u izvještaj po osoblju), uz zapis u dnevniku i događaj koji osvježava ekrane.
      • Ikona konzole u tabu preglednika je novi znak. Konzola je za ikonu i dalje koristila stari logo iz augusta, jedino mjesto gdje je još bio u upotrebi.

      0.55.13

      16. septembar 2026.

      Popravke

      • Smoke provjera: izbor slučaja radi i na bazi koja se ne briše. Dvije provjere iz 0.55.12 tražile su svoj slučaj po iznosu i razlogu NO_REFERENCE. Na bazi koja se ne briše između pokretanja uparivač vidi i račun sa istim iznosom iz prošlog pokretanja, pa razlog postane AMBIGUOUS_CANDIDATES i provjera bi pala iako sistem radi kako treba. Oba razloga znače isto za ovu provjeru (kredit koji niko nije mogao da smjesti), pa se sada prihvataju oba. Ništa u proizvodu nije mijenjano.

      0.55.12

      16. septembar 2026.

      Popravke

      • Statusna stranica: "prije X s" i odbrojavanje mjere od trenutka kad je provjera stigla. Stranica je računala starost zadnje provjere od vremena koje je server upisao, a ne od trenutka kad ju je preglednik primio, pa je na sporoj vezi ili u uspavanom tabu odbrojavanje do sljedeće provjere preskakalo ili odmah stajalo na nuli. Svaka primljena provjera sada pamti i kad je stigla. Natpisi "zadnje 3 provjere", "zadnjih 5 provjera" i "od 2 adrese" dobili su ispravne bosanske množine, a poruka za komponentu bez vremena odgovora razlikuje pad od tišine.
      • Skripte gledaju svoje podatke, ne tuđe. Provjera spremnosti lokala (venue-ready) ispisivala je sve prijemnike izvoda kao da slušaju, i one ugašene; sada ih dijeli na aktivne i one koji trenutno ne slušaju. Smoke provjera je birala "bilo koji otvoreni slučaj bez računa", što je na bazi koja se ne briše između pokretanja često bio slučaj iz prošlog pokretanja; sada traži tačno svoj kredit po iznosu, najnovije prvo. Provjera povrata mjerila je ukupan broj povrata umjesto razlike koju napravi upravo taj povrat, pa bi prolazila i sa ugašenom funkcijom.
      • SDK za Node: tipovi govore istinu. Odgovor o računu dobio je polja settledAmount i creditedToClosedTab koja API već vraća. Događaji sa živog toka bili su deklarisani kao webhook omotač (id, createdAt, livemode), a tok nosi drugačiji okvir (paymentId, at, data koja zavisi od vrste događaja); novi tip StreamEvent i pomoćna funkcija isPaymentEvent opisuju ono što zaista stiže. Verzija paketa 0.1.1.
      • API: vremenska zona lokala se provjerava na ulazu. Lokal je mogao da sačuva "Europe/Sarajvo" kao vremensku zonu, a greška bi iskočila tek kasnije, u analitici ili pri računanju dospijeća fakture. Sada se prihvataju samo zone koje sistem poznaje, sa jasnom porukom šta se očekuje.

      0.55.11

      16. septembar 2026.

      Popravke

      • Konzola: lista uplata koja nije mogla da se učita to i kaže. Kad prvi upit za listu uplata padne (istek veze, wifi u lokalu), ekran je ostajao na sivim placeholderima zauvijek, jer je poruka o grešci stajala u dijelu koji se crta tek kad ima redova. Sada se prikazuje poruka i dugme za ponovni pokušaj. Dugme "Učitaj još" više ne ostaje zaključano na "Učitavanje" kad sljedeća stranica ne stigne.
      • Konzola: novac i datumi u bosanskom obliku svuda. Dijalog za povrat prikazivao je naplaćeno, vraćeno i preostalo kao "19.50" umjesto "19,50 KM", a birač računa u uparivanju isto; zaglavlje pregleda pisalo je period kao "2026-09-01 do 2026-09-07"; tri ekrana (izvodi, zalihe, licenca) formatirala su datume kroz preglednik, što daje "10. 9. 2026. u 16:05" na jednom računaru i nešto drugo na drugom. Sve sada ide kroz iste pomoćne funkcije kao ostatak konzole.
      • Konzola: bosanske množine. "Vrijedi još 1 dana" i "21 dana" postaju "1 dan" i "21 dan"; "1 uparivanja, 1 webhooka" postaje "1 uparivanje, 1 webhook". Prazan grafikon na pregledu više ne piše bosansku rečenicu i u engleskoj konzoli.
      • Konzola: dva ekrana koja su se trkala sama sa sobom. Raspored stolova je pri promjeni lokala slao dva zahtjeva i primao odgovore bilo kojim redom, pa je spor odgovor za stari lokal mogao prekriti novi; operaterska pretraga slala je zahtjev na svaki otkucaj tipke bez reda. Oba sada prihvataju samo najnoviji odgovor, a pretraga čeka četvrt sekunde poslije zadnje tipke.

      0.55.10

      16. septembar 2026.

      Popravke

      • QR slika se ne služi za preplaćen račun. Slika koda odbijala se za plaćen, otkazan i vraćen račun, ali ne i za preplaćen, koji je svugdje drugdje isto što i plaćen; stari otisak mogao se ponovo skenirati u drugi prenos. Lista stanja za koja se kod više ne daje sada je na jednom mjestu, sa testom, i uključuje preplaćen i neuspio račun. Djelimično plaćen i istekao račun se i dalje služe, jer je za njih kod još namijenjen.
      • Vrijeme plaćanja se bilježi i kad je račun odmah preplaćen. Račun zaokružen naviše prelazio je iz "čeka" pravo u "preplaćen", a vrijeme plaćanja upisivalo se samo pri prelazu u "plaćen": takav račun nije ulazio u mjeru vremena potvrde, webhook je nosio prazno vrijeme, konzola datum kreiranja.
      • Djelimično plaćen račun nema prelaz u "otkazan". Tabela prelaza ga je dozvoljavala, a zaštita novca ga je uvijek odbijala, dok su dva komentara taj prelaz opisivali kao put za otpis. Uklonjen je; račun sa dijelom novca izlazi iz tog stanja samo kroz još novca ili kroz povrat.
      • Kod za udio računa koji izgubi trku otkazuje se kroz redovan put. Kad su dva telefona za istim stolom u isti tren tražila kod za iste stavke, kod koji je izgubio upisivao se kao otkazan direktno u bazu, bez događaja, webhooka i zapisa u dnevniku, pa je vremenska linija u konzoli pokazivala "kreiran" na kodu koji je čitao "otkazan". Sada ide kroz isti put kao svako otkazivanje.
      • Bakšiš koji je vraćen gostu ne računa se kao zadržan za osoblje. Povrat ide prvo iz bakšiša, ali knjiga bakšiša je i dalje brojala vraćeni bakšiš kao prikupljen i zadržan. Sada se za svaki račun sa povratom oduzima ono što je vraćeno, najviše do iznosa bakšiša.
      • Poslovni planovi kažu da imaju izvoz izvještaja. Izvoz u CSV i PDF postoji i prodaje se na planovima Business i više, a odgovor API-ja o planu je za njih govorio da izvoza nema. Sada govori da ga ima. Sam izvoz i dalje radi za sve planove sa analitikom, dakle i Start i Flex; da li treba, odluka je vlasnika, ne koda.

      0.55.9

      16. septembar 2026.

      Popravke

      • Pošta na portu 465 bez izričitog SMTP_SECURE ide kroz TLS. Kontejner dobija SMTP_SECURE kao prazan tekst kad ga niko nije upisao, a prazan tekst se čitao kao "nije sigurno", pa se port 465, koji od prvog bajta govori TLS, otvarao bez TLS-a i čekao trideset sekundi na pozdrav koji nikad ne stigne, za svaku poruku. Baš to je podešavanje koje uputstvo preporučuje. Prazan tekst sada znači "nije rečeno", pa odlučuje port; izričito true ili false i dalje važe. Produkcija koristi 587 i nije bila pogođena.
      • Status stranica ne javlja "Ne radi" zbog tihog dana. Izvor uplata koji 24 sata nije donio uplatu brojao se kao zamro, i to od trenutka kad ga operater poveže, jer nov izvor nema ni jednu uplatu; sa jednim izvorom to je cijeli XPay na javnoj stranici pisalo "Ne radi". Tih dan je sada upozorenje, ne kvar, i broji se tek od dana poslije povezivanja. "Ne radi" ostaje za izvore koji javljaju grešku ili se ne mogu pročitati.
      • Provjera spremnosti servera ne objavljuje interne poruke. Javna ruta readyz ispisivala je tekst greške baze, sa imenom hosta i korisnika. Sada piše samo "error", a tekst ide u dnevnik servera.
      • Zahtjev za update bilježi pravu verziju. Poslije svakog ručnog restarta kontejner ne zna verziju ni commit (0.0.0, prazno), a zahtjev za update je to upisivao u dnevnik. Sada i on čita fajl koji install.sh ostavlja pri svakom deployu, isto kao status stranica.
      • restore.sh vraća kopiju. psql 17 odbija način rada koji je skripta tražila bez fajla ("-1 can only be used in non-interactive mode"), pa je svaki povrat padao prije prve naredbe i ispisivao poruku o vraćenoj bazi nad netaknutom bazom. Uz to, kopija napravljena prije migracije koja je dodala tabelu padala je na "drugi objekti zavise". Skripta sada prvo isprazni šemu pa učita kopiju u jednoj transakciji, a migracije je dovedu do tekuće verzije.
      • doctor.sh gleda pravi direktorij za slike. Testirao je putanju kakvu vidi kontejner (/data/media) na hostu, pa je na svakoj docker instalaciji javljao da direktorij ne postoji i nudio pogrešan popravak; provjera pisanja radila je kao root umjesto kao korisnik kontejnera. Sada preslika putanju na host i probu pisanja radi iz kontejnera kad je podignut.
      • install.sh ne pada u grani koja treba samo da upozori. Grana za "postoji drugi postgres volumen" zvala je nedefinisanu funkciju info, pa je pod set -e prekidala instalaciju umjesto da upozori i nastavi.
      • Updater ne traži certifikat za www koji niko nije objavio. Otkucaj updatera javljao je "Bez HTTPS-a" za www.<domena> i app.<domena> kad god nemaju certifikat, i kad install.sh nije ni trebao da ih traži. Sada traži domenu, host konzole kakav je install.sh zabilježio, a www samo ako postoji DNS zapis.

      0.55.8

      16. septembar 2026.

      Popravke

      • Faktura je dospjela tek kad prođe cijeli dan roka. Kod za plaćanje uz fakturu istjecao je u prvom trenutku dana roka, a posao koji svake minute gasi istekle kodove označavao je fakturu kao dospjelu u ponoć, cijeli dan prije nego što je kupac iskoristio dan koji mu pripada. Kod sada istječe na kraju dana roka, stanje fakture gleda dan a ne minutu, a lista faktura i stanje na svakoj od njih računaju dan isto.
      • Rok upisan kao dan piše se kao taj dan. "15.09." se čuvao kao kraj tog dana po svjetskom vremenu, što je u Sarajevu dva sata ujutro 16.09., pa su PDF, stranica za kupca i mail, koji datum pišu po zoni lokala, štampali "16.09.2026." za rok upisan kao petnaesti. Rok se sada čita u zoni lokala.
      • Storniranje fakture ne prolazi ako je novac u međuvremenu stigao. Provjera novca bila je izvan transakcije, pa je uplata uparena u tom trenutku ostavljala plaćenu fakturu označenu kao storniranu, sa lažnim zapisom o otkazivanju koda. Storniranje sada uslovljava da je kod još otvoren i odbija ako nije; ponovljeno storniranje kaže da je već stornirano.
      • Godišnja pretplata podrazumijevano naplaćuje dvanaest mjeseci. Podrazumijevani iznos za godišnji plan bio je deset mjesečnih cijena, što ugovor koji lokal potpisuje izričito isključuje. Konzola uvijek šalje iznos, pa je to pogađalo samo API poziv bez iznosa; sada je dvanaest.
      • Uključene transakcije se računaju po periodu koji se naplaćuje. Naknada za produženje množila je mjesečni uključeni broj brojem mjeseci koji se prodaju, a brojala je transakcije od zadnje fakture. Lokal produžen za tri perioda poslije mjesec dana rada dobijao je tri mjeseca uključenih transakcija za jedan mjesec korištenja, a lokal produžen za jedan period poslije četiri mjeseca rada plaćao je prekoračenje za volumen koji je plan već pokrivao. Sada se uključeni broj računa po mjesecima korištenja.
      • Probni nalog dobija ključ licence na 48 sati, kao i rok. Prijava sa sajta skraćivala je rok na 48 sati poslije kreiranja, a ključ licence ostajao je na 30 dana; konzola je prikazivala jedno pored drugog. Rok ide u kreiranje, pa ključ i rok nose isti datum.
      • Istekla licenca više ne piše "još 0 dana" prvog dana. Zaokruživanje je prvog dana po isteku davalo nulu, pa je pregled pretplata pokazivao "ističe uskoro" za licencu koja je već istekla, dok su ostali ekrani govorili isteklo. Stanje licence sada računa jedna funkcija, sa testovima.
      • Broj XPay fakture se uzima pod bravom i po godini lokala. Dva produženja u istom trenutku čitala su isti zadnji broj i drugo je padalo na jedinstvenom indeksu; godina se uzimala po satu servera pa je faktura izdata između 23 i 24 sata 31. decembra po svjetskom vremenu nosila staru godinu uz datum 01.01. Broj sada čeka na brave i računa najveći broj brojčano, a godina je sarajevska, kao na fakturama lokala.
      • Plaćena stara faktura ne vraća isteklu licencu u "aktivno". Oznaka kašnjenja postavlja se kad licenca istekne, ne kad faktura kasni; plaćanje stare fakture brisalo je oznaku i jutarnji posao je vraćao. Sada se briše samo dok licenca još važi, a komentari uz rok plaćanja opisuju ono što kod stvarno radi (rok osam dana, bez grejs perioda).

      0.55.7

      16. septembar 2026.

      Dokumentacija

      • README nabraja planove koji postoje. Pisalo je "Free, Pro, Enterprise i Flex" i jedna cijena po transakciji; planovi su Flex, Start, Business, Pro i Enterprise, svaki sa uključenim brojem transakcija, a cijena preko toga zavisi od plana. Sada piše tačno ono što stoji na sajtu i u kodu.
      • Vodič za prodaju više ne obećava promet po konobaru. Pisalo je da se u izvještaju vidi "ko je koliko naplatio"; izvještaj "Ko je radio" namjerno pokazuje broj zatvorenih računa i gotovinu kroz ruke, ne promet po konobaru. Vodič sada kaže to, i upućuje na uputstvo za ekrane osoblja gdje je objašnjeno zašto.
      • Vodič za kasu: opsezi API ključa. Changelog za 0.52.0 upućivao je na ovaj vodič za popis opsega, a popis je postojao samo u engleskom uputstvu. Sada je i ovdje: šta nosi ključ iz konzole, koje opsege treba tražiti posebno i šta odgovara ruta kad ključ nema opseg.
      • Vodič za kasu: naljepnica na stolu. Pregled na vrhu još je govorio da gost sam upisuje iznos, iz vremena kad je to bio jedini način; naljepnica danas radi i za naručivanje i za plaćanje, a uplata se sama veže za sto.
      • Primjer okruženja ne tvrdi verziju. .env.example je nosio "0.37.3" kao verziju, pa je razvojna kopija prijavljivala staro izdanje; sada je 0.0.0, isto što kod uzima kad build fajla nema, a install.sh upisuje pravu.
      • Vodič za proizvođače kasa: imena profila i vrste adaptera. Pisalo je da su četiri načina povezivanja implementirana, ali ne i da su imena profila jedno, a vrijednosti kind u xpay-connector.yaml drugo. Sada su nabrojane jedne uz druge.
      • Uputstvo za instalaciju: promjena lozinke operatera. Pisalo je da skripta traži novu lozinku dva puta; traži je jednom, bez prikaza na ekranu.

      0.55.6

      16. septembar 2026.

      Popravke

      • Suspendovan lokal je suspendovan i za svoje ljude. Kad operater suspenduje lokal, API ključevi i terminali su odmah odbijani, ali korisnici konzole istog lokala nisu: mogli su i dalje izdavati QR kodove i primati narudžbe. Sada i oni dobijaju odgovor da licenca nije aktivna; podrška i dalje može otvoriti pregled tog lokala.
      • Rute koje nisu rekle ko ih smije zvati. Lista lokacija i lista bankovnih izvora nisu tražile ni ulogu ni opseg, pa ih je mogao čitati i token kuhinjskog ekrana, koji stoji u pregledniku na zidu. PDF fakture, pregled, primjer i unos primaoca tražili su ulogu bez opsega, a API ključ sa bilo kojim opsegom za pisanje računa se kao menadžer, pa je ključ samo za narudžbe mogao preuzeti svaku fakturu sa imenom, adresom i ID brojem kupca; isto za izmjenu lokacije (isključivanje, promjena QR profila) i za mjesečnu potrošnju. Sve te rute sada traže opseg koji već nose svi obični ključevi i konzola; nov test prolazi kroz kontrolere i pada čim se pojavi ruta bez ugovora.
      • Zaključavanje prijave se resetuje kad istekne. Osam pogrešnih lozinki zaključa nalog na petnaest minuta, ali brojač se nije vraćao na nulu: prva pogrešna lozinka poslije isteka pravila je devetu i ponovo zaključavala, pa je jedan pogrešan pokušaj svakih petnaest minuta držao nalog zaključan zauvijek. Istekla brava je gotova; brojanje kreće iznova.
      • Zaključan nalog odgovara jednako sporo kao svaki drugi. Odgovor za zaključan nalog stizao je za milisekundu, dok provjera lozinke traje desetine milisekundi, pa se po satu moglo zaključiti da nalog postoji. Sada se troši isto vrijeme.
      • Webhook adresa sa IPv6 zapisom više ne prolazi zaštitu. Provjera je poredila "::1" sa vrijednošću koja u zagradama glasi "[::1]", pa nijedna IPv6 adresa privatne mreže nije bila odbijena, a ni "localhost." sa tačkom na kraju. Zagrade i tačka se skidaju, a IPv6 adrese se odbijaju u potpunosti: nijedan lokal ne treba webhook na golu adresu.
      • Izmjena lokacije ostavlja trag. Bila je jedina izmjena lokacije bez zapisa u dnevniku; sada piše ko je i šta mijenjao.

      0.55.5

      16. septembar 2026.

      Popravke

      • Uplata koja stigne kroz dva kanala više se ne knjiži dva puta. Kad isti prenos stigne i webhookom i u izvodu, sistem otvori slučaj "dupla uplata". Dugme Poravnaj na tom slučaju dodavalo je novac drugi put: račun od 60,00 KM na koji je stiglo 30,00 KM postajao je plaćen za 60,00 KM. Sada Poravnaj samo zabilježi da je i drugi kanal vidio isti prenos, bez novog novca. Ako se zaista radi o drugom prenosu istog iznosa, put je Odbaci pa Priključi iz liste neuparenih uplata, gdje se dodaje kao nov novac.
      • Jedna uplata ne može stajati na dva računa. Kredit koji je već zabilježen na jednom računu mogao se preko API-ja priključiti ili poravnati na drugi, pa je njegov novac ostajao na oba. Sada se odbija, uz ime računa koji ga drži.
      • Kredit u drugoj valuti ne ide na račun u KM. Ručno priključivanje i poravnanje nisu gledali valutu, pa je 1000 najmanjih jedinica eura moglo postati 10,00 KM. Sada se odbija.
      • Izvod bez vremena, samo sa datumom, uparuje se i po iznosu. Kad banka u izvodu da samo dan, uplata stiže kao ponoć tog dana, pa je račun napravljen u podne izgledao kao da je nastao poslije uplate i uparivanje po iznosu ga je preskakalo. Sada gleda cijeli dan, kao što je uparivanje po pozivu na broj već radilo.
      • Ručna potvrda druge rate više se ne prijavljuje kao dupla uplata. Kad je osoba ručno potvrdila drugu polovinu računa, jednaku prvoj koja je stigla iz banke, sistem ju je tretirao kao isti prenos viđen dva puta, javljao "nije potvrđeno" i ostavljao uplatu u provjeri bez slučaja koji se igdje vidi. Osoba koja imenuje račun nije drugi kanal.
      • Faktura plaćena trećeg dana nalazi svoj račun. Kandidati za uparivanje birali su se samo među računima napravljenim u zadnjih 24 sata, pa faktura plaćena kasnije, i sa tačnim pozivom na broj u opisu, završavala kao neuparena bez slučaja. Sada se gledaju i računi kojima još teče rok i svaki račun čiji poziv na broj stoji u opisu uplate, ma koliko star.
      • Webhook banke sa nepoznatom valutom dobija jasan odgovor. "GBP" ili brojčani kod "977" prolazili su provjeru i rušili obradu, pa je banka dobijala grešku 500 i ponavljala zauvijek. Sada dobija 400 sa razlogom i listom valuta koje se prihvataju.
      • Filter otvorenih potraživanja radi i za "false". Upit open=false vraćao je samo otvorene stavke, suprotno od traženog. Sada vraća sve, kao i bez filtera; prihvataju se samo riječi true i false.
      • Naljepnica stola: sumnja na duplu uplatu ide na provjeru, ne spaja se tiho. Kad isti prenos na naljepnicu stigne kroz dva kanala bez bankovnog identifikatora, prepoznavao se samo ako je vrijeme bilo do milisekunde isto, što webhook i izvod nikad nemaju, pa je nastajalo drugo plaćeno plaćanje i promet je bio dvostruk. Sada se gleda isti dan, a takav par ide osobi na provjeru, jer isti iznos istog dana može biti i drugi gost.
      • Uvoz izvoda više ne baca uplate. Identifikator uplate uzimao se i iz polja koje popunjava banka platioca, a ono kod više banaka na svakoj liniji glasi NOTPROVIDED. Prva takva uplata iz izvoda bila je upisana, svaka sljedeća tiho odbačena kao "već poznata". Sada se identifikator uzima samo iz oznaka koje daje naša banka.
      • Iznos kao broj podliježe istom pravilu kao iznos kao tekst. API je 12.345 poslano kao broj zaokruživao na 12,35, dok je iste cifre kao tekst odbijao; dokumentacija je obećavala odbijanje. Sada se i broj odbija ako ima više od dvije decimale.

      0.55.4

      16. septembar 2026.

      Popravke

      • Kuhinjski ekran zvoni i za prvi tiket dana. Ekran uključen prije početka smjene učitao je praznu listu, pa prvi tiket koji je stigao nije oglasio; drugi je. Sada zvoni za svaki tiket koji stigne poslije prvog učitavanja, a ne zvoni za one koji su već bili na ekranu kad je uključen, ni za otkaz stariji od ponovnog pokretanja.
      • Jelo koje je jučer prebrojano do nule može se naručiti danas. Meni ga je prikazivao kao dostupno, jer broj porcija vrijedi za dan kad je unesen, a narudžba ga je odbijala kao rasprodano jer je gledala u jučerašnji broj. Jučerašnji ostatak se uz to tiho smanjivao današnjim narudžbama. Narudžba sada gleda samo današnji broj, isto kao meni.
      • Narudžba koju je gost već platio ne može se otkazati. Kod "plaćam svoje" veže linije za uplatu, a otkazivanje te narudžbe je prolazilo jer je provjera gledala samo ukupne iznose stola. Gost bi platio jelo koje nikad nije napravljeno, bez traga o tome. Otkazivanje sada odbija i kaže da se novac vraća povratom uplate; konzola to ispisuje razumljivo.
      • Uplata na račun zatvoren kao "plaćeno prenosom" knjiži se kao uplata. Konobar zatvori sto kao prenos kad mu gost pokaže ekran banke. Kad je novac zatim stigao, sistem ga je označavao kao vjerovatno dvostruko plaćanje, a sto je u izvještaju imao nula prometa. Sada se takva uplata knjiži do iznosa računa; samo ono što bi prešlo iznos i dalje ide na provjeru.
      • Dvostruki tap na "Pošalji" više ne javlja narudžbu dva puta. Kad su dva ista zahtjeva stigla u isti tren, gubitnik je ponovo oglasio pobjednikovu narudžbu (zvono, webhook, dnevnik) ako je bila mlađa od sekunde i po, a prava nova narudžba koja je duže čekala na broj ostala je neoglašena. Sada se oglašava samo ona koja je stvarno upisana.
      • Stavka bez stanice (ni kuhinja ni šank) ne blokira tiket. Tiket sa vodom ili čipsom čekao je stanicu koju nijedan ekran ne može označiti kao gotovu, pa se mogao završiti samo iz konzole.
      • Stari kod stola ne može se vratiti dok je novi za isti sto aktivan. Vraćanje povučenog koda pored aktivnog ponovnog otiska pravilo je dva aktivna stola istog imena i dva odvojena računa. Sada se odbija, sa objašnjenjem u konzoli i u API-ju.
      • POS: "Očisti" zaboravlja ključ prodaje. Ispravljen skup stavki sa istim iznosom bio je odbijen kao ponovljen zahtjev sa drugim sadržajem, sve dok se iznos ne promijeni. Terminal je to radio ispravno; POS sada isto.
      • Gostova stranica: podjela računa se vraća na cijeli račun kad se kod napusti. Izabrani dijelovi, broj dijelova i bakšiš ostajali su u memoriji, pa je "Na 3", pa Nazad, pa dugme banke pravilo kod za trećinu dok je ekran pokazivao cijeli račun, a linije plaćene ranijim kodom slane su ponovo i odbijane. Uz to: kod se više ne zaboravlja zbog prekida veze ili preopterećenja, nego samo kad server kaže da ga nema; poslije kratke uplate glavno dugme je opet "Plati", a tekst kaže da se cijeli iznos ne plaća ponovo; odbijenica "neko već drži kod" ima svoju rečenicu; kopiranje IBAN-a i poziva na broj izgovara "Kopirano" čitačima ekrana; datum na traci o starom meniju piše se kao i svi ostali datumi.
      • Bosanski oblici. "5 stavki" umjesto "5 stavke" u opisu uplate koji gost vidi u aplikaciji banke (isto pravilo sada dijele svi ekrani), "2 stavke su skinute" i "5 stavki je skinuto" u poruci o promjeni menija, a svrha plaćanja u QR kodu više ne ponavlja ime stola.

      0.55.3

      16. septembar 2026.

      Popravke

      • Račun preko 5.000,00 KM izlazi bez QR koda, i kaže zašto. Instant plaćanje u BiH prima najviše 5.000,00 KM odjednom i samo u KM (IPS BiH, član 13). Račun za veći iznos je sasvim običan i kupac ga plaća običnim prenosom, pa se račun izdaje kao i do sada: broj, poziv na broj, račun primaoca, PDF i stranica za kupca. Ono što se više ne štampa je QR kod, jer bi ga svaka bankarska aplikacija odbila na ekranu na kojem nema ni riječi od XPay-a, a kupac ne bi znao zašto. Na mjestu koda, i u PDF-u i na stranici za kupca, stoji rečenica koja kaže granicu i upućuje na prenos uz poziv na broj. Isto važi za račun u valuti koju instant plaćanje ne prima. Naplata za stolom je ovu provjeru imala od ranije; računi je nisu imali. Važi i za račune preko granice izdate prije ove verzije: od sada se i oni prikazuju bez koda, sa istom rečenicom, jer se pitanje postavlja računu, a ne samo zabilješci uz njega. Mail kupcu više ne obećava QR kod kad ga nema, nego ponavlja tu rečenicu, a u konzoli uz poziv na broj piše da je račun izašao bez koda i zašto. Djelimično plaćen račun preko granice zadržava pravi razlog, umjesto rečenice o kodu koji nikad nije ni postojao.

      0.55.2

      13. septembar 2026.

      Popravke

      • Ključ za ponavljanje zahtjeva (Idempotency-Key) važi jedan dan, kako i piše, a ne zauvijek. Kasa koja pošalje isti zahtjev dva puta sa istim ključem dobije isti odgovor umjesto drugog plaćanja; to je svrha ključa. Svaki zapis se upisivao sa rokom od 24 sata, ali rok niko nije čitao niti brisao: tabela je samo rasla, a ključ koji je kasa upotrijebila jednom bio je "već iskorišten" i godinu dana kasnije. Kasa koja kao ključ koristi broj računa, što je najčešći način, dobila bi odbijenicu umjesto novog QR koda čim se brojevi računa ponove. Sada istekli zapis znači da je ključ opet slobodan, a server jednom dnevno briše sve istekle zapise.

      0.55.1

      13. septembar 2026.

      Popravke

      • Kontrolni broj u pozivu na broj sada je pravi kontrolni broj po modelu 97. Dvije cifre ispred poziva na broj računale su se po formuli koja je bila dosljedna sama sebi, ali nije bila model 97. Za primjer koji stoji u uputstvima svake banke, poziv 016 sa kontrolnim brojem 50, XPay je računao 48. Banka koja provjerava model 97 pri unosu naloga ili pri skeniranju koda mogla je odbiti svaki naš poziv na broj, a gost bi vidio samo da njegova aplikacija neće. Od sada se kontrolni broj računa onako kako ga banke provjeravaju: ISO 7064 MOD 97-10, ispisan ispred broja.
      • Stari pozivi na broj se i dalje prepoznaju. Uparivanje uplata prima i pozive na broj sa stare formule, pa novac koji stigne po ranije izdatom računu ili po staroj naljepnici i dalje nađe svoj račun. U pregledu uplate takav poziv je označen kao stari oblik, da se vidi kad ih više nema. Naljepnice za stolove odštampane prije ove verzije nose stari kontrolni broj, pa ih treba ponovo preuzeti iz konzole i zalijepiti čim bude prilike.

      0.55.0

      13. septembar 2026.

      Novo

      • Gost koji skenira naljepnicu otvara aplikaciju, ne web stranicu. Prvi ekran je fotografija preko cijelog telefona sa imenom lokala krupno preko nje, logom u uglu, stolom i jezikom na dohvat palca. Lokal koji nema naslovnu fotografiju dobije najbolje slikano jelo sa svog menija, jer je tanjir njihove hrane bolja naslovna od bilo koje boje. Ispod su pozdrav, dugme za poziv konobara, najtraženija jela kao velike kartice sa cijenom na fotografiji i kategorije kao pločice sa brojem jela.
      • Meni sa ljepljivim zaglavljem i kategorijama koje se čitaju bez čitanja. Dok se jela listaju, na vrhu ostaju ime lokala, sto i red kategorija, svaka sa okruglom fotografijom nečega iz nje; ona u kojoj se gost nalazi svijetli u boji lokala. Svako jelo je kartica sa fotografijom, imenom, opisom i cijenom, a dugme za dodavanje postaje brojač čim je jelo u korpi, pa druga porcija i predomišljanje ne traže otvaranje korpe.
      • Detalj jela, korpa, račun i plaćanje u istom duhu. Fotografija jela puni vrh panela sa imenom preko nje, dodaci su kartice sa oznakom "Obavezno", količina i napomena imaju svoje kartice, a dugme sa cijenom stoji na dnu ekrana. Korpa je traka preko cijele širine sa brojem, nazivom i iznosom. Narudžbe pokazuju dokle je stigao tiket kao liniju koja se puni: poslano, preuzeto, priprema, gotovo, na stolu. Načini plaćanja imaju ikone, a ekran sa QR kodom, iznosom i podacima za ručni prenos je bijela kartica sa dugmadima za kopiranje.
      • Jedan font za gosta. Plus Jakarta Sans, sa pravim težinama od običnog do najdebljeg i sa našim dijakritičkim znakovima, preuzet pri gradnji i posluživan sa našeg servera; telefon gosta nikad ne pita Google ni za šta. Konzola ostaje na svom fontu.

      0.54.3

      10. septembar 2026.

      Popravljeno

      • Uspješno slanje brisalo je upozorenje o sporom serveru pošte. Slanje otvara istu vezu i čeka isti pozdrav kao i provjera, ali je poslije uspjeha bilježilo samo "radi", pa je status stranica poslije svakog poslanog računa skakala sa "sporo" na "radi" i nazad na sljedećoj provjeri. Slanje se sada mjeri kao i provjera, pa upozorenje stoji dok kašnjenje traje.

      0.54.2

      10. septembar 2026.

      Popravljeno

      • Pošta nije išla jer je server pošte odgovarao tek nakon petnaest sekundi, a sistem je čekao deset. Server pošte tako dočekuje pošiljaoca čija adresa nema reverzni DNS zapis (PTR): veza se otvori, a pozdrav stigne kasno. Deset sekundi čekanja pretvaralo je to u "server nije odgovorio" na svakom računu, na vezi koja bi prošla. Sistem sada čeka pozdrav do trideset sekundi, pa pošta ide; a kad odgovor stigne sporo, status stranica to kaže kao upozorenje i imenuje ko šta popravlja: hosting provajder treba da postavi PTR zapis za adresu servera.
      • Jučerašnja dijagnoza "hosting provajder filtrira SMTP portove" bila je pogrešna. Provjera je gledala samo da li se veza otvori i da li stigne pozdrav u deset sekundi, pa je sporog domaćina pročitala kao zatvoren port. Ista provjera je ranije, sa još kraćim čekanjem, pisala isto. Provjera sada broji i sporog domaćina, a "nijedan port ne odgovara" kaže samo kad je zaista probala svaki port; ako je vrijeme isteklo prije toga, kaže da nije stigla.
      • Odbijeni certifikat se računao kao tišina. Port koji progovori TLS-om i pokaže certifikat je odgovorio, makar mu se ne vjerovalo; provjera ga je brojala kao da niko nije odgovorio i krivila hosting provajdera. Sada kaže da port radi, a certifikat glasi na drugo ime ili mu se ne vjeruje, i to razlikuje i u uputi operateru.
      • Neuspjelo slanje računa čitalo se po riječima, a ne po tome gdje je puklo. Server koji odbija pošiljaoca ili prenos često to kaže tek kod primaoca, i stranica bi to progutala kao "pogrešna adresa kupca". Sada se gleda faza SMTP razgovora koju server imenuje: odbijena prijava ili pošiljalac je kvar pošte, odbijen primalac je greška u adresi, a odbijena poruka (kao neželjena ili prevelika) je upozorenje, ne kvar. Prenešeni zaključak probe ne vraća sat unazad, pa se proba ponovo pokrene kad joj je vrijeme.
      • Operaterska konzola sada pokazuje šta je server pošte zadnje rekao, prije nego što se išta pritisne. Status stranica je za razlog upućivala na taj ekran, a on je pokazivao četiri podešavanja i dugme.

      0.54.1

      10. septembar 2026.

      Popravljeno

      • Status stranica je za svaki kvar pošte pisala da server pošte odbija slanje. Ista rečenica je stajala i kad server pošte uopšte nije odgovorio, jer hosting provajder filtrira SMTP portove, i kad ime servera ne postoji, i kad certifikat glasi na drugo ime. Nijedno od toga nije odbijanje, i svako popravlja neko drugi. Provjera sada razlikuje sedam stanja i stranica za svako kaže samo ono što je stvarno utvrđeno i ko treba šta da uradi: odbijena prijava ili adresa pošiljaoca, filtrirani portovi kod hosting provajdera, server koji se ne može dosegnuti ni na jednom portu, ime servera koje ne postoji u DNS-u, pogrešan port ili način šifriranja, certifikat na drugo ime, i certifikat kojem se ne vjeruje.
      • Pogrešno ukucana adresa kupca više ne gasi poštu na status stranici. Server pošte je primio prijavu i odbio jednu adresu; to je odgovor o toj adresi, ne o pošti, a stranica ga je pet minuta pokazivala kao kvar sa uputom da se provjere podešavanja koja su bila ispravna. Isto tako, račun koji ne ode jer je port filtriran više ne briše utvrđeni uzrok: status je i dalje "filtrirani portovi", a ne "nepoznato".
      • Probna poruka u konzoli je javljala grešku preglednika umjesto odgovora servera pošte. Kad podešeni port ne odgovara, sistem proba i ostale portove da bi rekao čija je greška, i to traje do minutu; dugme je odustajalo poslije dvadeset sekundi i ispisivalo "TimeoutError: signal timed out", rečenicu o pregledniku na ekranu čiji je jedini posao da pokaže šta je rekao server pošte. Dugme sada čeka odgovor, a uputa pored njega kaže da provjera može potrajati.
      • Veza koja se nikad ne otvori nije probala port 26. Provajder koji filtrira SMTP ne odbija paket nego ga proguta, i to se javlja kao istek vremena, a ne kao neuspjelo rukovanje; provjera je u tom slučaju odmah odustajala bez ikakvog objašnjenja umjesto da proba portove koje takav provajder obično ostavi otvorene. Sada proba, kaže koje je portove probala, i stane na vrijeme ako server ima više adresa pa svaka proba traje duže.

      0.54.0

      10. septembar 2026.

      Popravljeno

      • Korpa gosta ipak nije preživljavala izlazak sa stranice. Ono što je 0.50.0 obećalo, radilo je u testu i nije radilo u pretraživaču: prvi prikaz stranice ima praznu korpu, a kod koji korpu čuva pri svakoj promjeni zapisao je tu prazninu prije nego što je meni uopšte stigao - pa je korpu koju je trebao sačuvati brisao isti taj kod, svaki put, sekundu prije nego bi je vratio. Nađeno tako što je stranica napuštena i vraćena, što je jedino čemu ta funkcija služi. Sada se ništa ne zapisuje dok se stara korpa ne vrati.
      • „Osoblje je vidjelo vašu narudžbu i priprema je" pisalo je u trenutku pritiska na Pošalji. Tada je jedino tačno bilo da je server primio narudžbu; niko je još nije vidio. Ekran sada kaže „Stiže kuhinji" i mijenja se u „Osoblje je vidjelo" onog trenutka kada neko na ploči pritisne Prihvati - provjereno u obje kartice.
      • „Račun se zatvara čim banka potvrdi" na izboru plaćanja. Tačno gdje je banka povezana, netačno svugdje drugdje - a u pilotu je to običan slučaj. Lokal bez veze sa bankom sada kaže „Račun zatvara osoblje kada vidi uplatu".
      • Konzola je za kod za povezivanje pisala „važi još 525462 min". Pravi kod živi 30 minuta i tu je odbrojavanje bilo u redu; kod iz probnih podataka živi godinu i tekst je izgledao kao da je konzola poludjela. Ispod sata pišu minute, ispod dana sati, iznad toga datum. I zaokružuje se nadolje: kod sa 29:50 kaže 29, a ne 30.
      • Ploča koju niko nije dodirnuo sada to kaže prije prve narudžbe. Traka „Dodirnite ekran da uključite zvuk" dizala se tek kada zvono pokuša i ne uspije - dakle kada je narudžba već stigla u tišini, baš one večeri zbog koje traka postoji. Sada se pretraživač pita pri paljenju.

      0.53.0

      10. septembar 2026.

      Novo

      • Status stranica sada pokazuje put uplate kroz sistem, a ne samo spisak dijelova. Naslov je stanje, ispisano krupno i u boji stanja, a cijela stranica je osvijetljena tom bojom: onaj ko dođe usred incidenta vidi drugu sobu prije nego što pročita ijednu riječ. Ispod naslova su dijelovi sistema poredani onako kako ih uplata zaista prolazi: baza, sravnjivanje, ekrani uživo, obavijesti kasi, e-mail, slike i sigurnosne kopije. Sa svakim odgovorom svjetlo pređe tu liniju i stane na prvom dijelu koji ne radi; ono što je iza njega crta se isprekidano, jer dotle ništa ne stiže.
      • Odziv sistema se mjeri u tvom pregledniku. Jedini broj na stranici koji nije riječ sistema o samom sebi: koliko je odgovor trebao da stigne, sa linijom svih prethodnih, pa spor odgovor strši kao vrh a ne kao broj koji treba upamtiti. Prsten pored sata pokazuje koliko je ostalo do sljedeće provjere, umjesto da se to samo tvrdi u fusnoti.
      • Otisak izdanja stoji uz verziju, datum puštanja i broj izdanja u jednom pečatu, i mijenja se sa svakim puštanjem.

      Promijenjeno

      • Historija verzija otvara zadnjih šest. Na stranici je bilo svako izdanje ikad pušteno, što ju je učinilo dugom preko šezdeset hiljada piksela i smjestilo podnožje tamo gdje niko ne dođe. Starije verzije su iza jednog klika, na istoj liniji, bez ikakve skripte.

      0.52.0

      10. septembar 2026.

      Popravljeno

      • API ključ izdat samo za plaćanja mogao je mijenjati meni, stolove i zalihe. Te rute su bile zaštićene samo ulogom, a ključ koji drži bilo koji :write opseg rangira se kao menadžer - pa je ključ sa kase mogao preimenovati jelo, ukloniti sto i otpisati zalihe. Najgore od svega: označavanje jela kao rasprodanog je namjerno otvoreno osoblju, a ključ bez ijednog :write opsega rangira se kao osoblje - pa je ključ samo za čitanje mogao skinuti cijeli meni sa prodaje.

      0.51.1

      10. septembar 2026.

      Popravljeno

      • Datum isplate napojnica pisao je 2026-09-10 umjesto 10.09.2026. Jedini red u konzoli koji je datum pisao drugačije od svih ostalih.

      0.51.0

      10. septembar 2026.

      Novo

      • Napojnice: koliko je stiglo, koliko je isplaćeno, i koliko lokal još drži. Napojnica koju gost doda pri plaćanju QR-om stiže u istom prenosu sa iznosom računa. Na izvodu je jedan iznos, a XPay ga oduvijek drži razdvojen: Iznos i Napojnica su dvije kolone na plaćanju i dvije kolone u knjigovodstvenom izvozu, račun se zatvara iznosom naručenog, i faktura napojnicu nikada ne nosi.

      0.50.0

      9. septembar 2026.

      Popravljeno

      • Limit od 5.000 KM se gasio zajedno sa QR formatom. Provjera je gledala u koji je dijalekt kod napisan. A dokumentovani izlaz iz nepotvrđenog BIH_IPS profila je prebacivanje lokala na EMVCO_MPM - čime se gasio i limit, i pravilo da nalog glasi samo na KM. Društvo od dvadeset zatraži jedan kod za cijeli račun od 5.400,00 KM, XPay ga uredno nacrta, a odbijenica se desi unutar bankovne aplikacije, na ekranu na kojem ne piše XPay, iz razloga koji niko u sali ne može pročitati.
      • Povrat je tražio broj naloga iz banke, a račun na koji se vraća nije bio nigdje. Vlasnik otvori Naplatu, nađe račun, pritisne Povrat. Piše, tačno, da XPay ne prenosi novac i da povrat šalje iz svoje banke - pa mu treba broj računa, kojeg nema ni na plaćanju, ni u izvozu, ni na Usklađivanju, jer se ta uplata uredno uparila i nikada nije ni došla u red za pregled. Završi tako što gosta zamoli da mu IBAN napiše na salveti, pred vlasnikom lokala kojem je pokazivao kako je sve uredno.
      • gotovina, ručna potvrda - ne piše ništa, umjesto praznog polja.
      • Korpa gosta je živjela samo u memoriji stranice. Gost dodirne ćevape, otvori se list sa sastojcima, on povuče prstom sa ivice da ga zatvori - jer je to na Androidu način da se list zatvori - i pretraživač umjesto toga napusti stranicu. Kada se vrati, osam stvari koje je izabrao više nema, i ništa na ekranu ne pokazuje da ih je ikada bilo. Počinje ispočetka ili zove konobara.

      0.49.0

      9. septembar 2026.

      Popravljeno

      • Otkazana narudžba je nestajala sa kuhinjske ploče bez riječi. Kuhar je pritisnuo „U pripremi" za sto 9, meso je na roštilju, a vlasnik u međuvremenu otkaže tu narudžbu iz konzole na laptopu. Kartica nestane usred servisa. Kuhar podigne pogled, vidi da je nema, i zaključi da ju je sam obrisao - pa ili nastavi kuhati ono što niko neće platiti, ili prestane kuhati ono što neko i dalje čeka.
      • Gost koji pozove osoblje nije proizvodio nikakav zvuk. Vlasnik sjedne za svoj sto i pritisne „Pozovi osoblje" da pokaže kako radi. Njegov telefon kaže da neko dolazi. U kuhinji se u tišini pojavi mala crvena oznaka, dok je šanker okrenut aparatu za kafu a kuhar roštilju, i brojač na njoj raste. Poziv sada zvoni, svojim zvukom, i ponavlja se svake minute dok neko ne ode.
      • Ploča koju niko nije dodirnuo od paljenja bila je nijema, a ikona je govorila da je zvuk uključen. Tablet je na zidu i pretraživač se sam otvara na /display. Osoblje ujutro upali struju i niko ne dodirne staklo, jer nema šta pritisnuti. U 19:40 stigne prva narudžba - bez zvuka, na ekranu okrenutom leđima roštilju. Sada preko vrha stoji „Dodirnite ekran da uključite zvuk", a ikona je precrtana dok pretraživač drži zvuk. Otključavanje sluša i dodire na dugmadima kartica, koji ranije nisu dopirali do njega.
      • Ekran koji se ne može držati budnim to sada kaže. Web API za to postoji samo na HTTPS-u, a dokumentovana instalacija zna biti običan HTTP na lokalnoj mreži - pa je obećanje „ekran se ne gasi" baš tamo gdje treba ćutke ništa ne radilo. Sada stoji napomena da se u postavkama tableta stavi „Nikad".
      • Sa zidnog ekrana su nestali iznosi. Uputstvo koje vlasnik dobije kaže da se na tom ekranu ne vidi novac, a oznaka je pisala „Sto 4 - keš - 23,50 KM", čitljivo sa susjednog stola. Sada piše sto, način plaćanja i koliko čeka.
      • Konzola više ne nudi otkazivanje već otkazane narudžbe.
      • „Skenirajte kod" je pisalo ispod koda na telefonu koji gost drži u ruci. Gost dođe na taj ekran tako što je tim istim telefonom skenirao naljepnicu sa svog stola. Koraci sada opisuju prepisivanje podataka, a ispod piše da je QR kod za nekoga ko plaća sa drugog telefona. Naslov bloka sa podacima više ne počinje sa „Ili".
      • Ekran isteklog koda obećavao je da će se novac prepoznati sam. Tamo gdje ništa ne potvrđuje uplatu bez čovjeka - a to je u pilotu redovan slučaj, jer se potvrđuje izvodom sljedeće jutro - to nije tačno. Gost spremi telefon vjerujući da lokal zna, a konobar dođe naplatiti. Stranica gosta sada zna ima li ovaj lokal automatsku potvrdu i, ako nema, kaže da pokaže ekran osoblju.
      • Objašnjenje kako se uplata potvrđuje ručno briše se samo od sebe. Konzola je brojala sve izvore potvrde bilo koje vrste - a potvrda rukom se upisuje kao izvor vrste MANUAL, koji nastaje upravo time što uradite ono što poruka govori. Prva uspješna potvrda je zato obrisala objašnjenje, a sat kasnije je četiri računa stajalo nepotvrđeno pored prometa koji se ne slaže. Sada se broje samo izvori koji mogu potvrditi bez čovjeka.

      Novo

      • Uputstvo za provjeru potpisa na webhooku (docs/bs/05-webhook-potpis.md). Uputstvo za spajanje kase je na tom koraku podebljano tražilo provjeru potpisa i linkalo na dokument koji nije postojao. Serviser kase je dolazio do koraka koji se ne može izvršiti kako je napisan, a najvjerovatniji ishod je webhook bez provjere - adresa je javna, pa je to račun koji svako može zatvoriti. Sada postoji, sa primjerima za Node, PHP i C#.

      0.48.0

      9. septembar 2026.

      Popravljeno

      • Gost koji se vrati iz bankovne aplikacije više ne zatiče prazan račun. Gost pritisne Plati, prepiše IBAN i poziv na broj, pređe u banku. Devedeset sekundi kasnije telefon je odbacio karticu pretraživača i ona se ponovo učita - a plaćanje je živjelo samo u memoriji stranice. Vratio bi se na račun koji traži cijeli iznos, bez poziva na broj koji je upravo upisao i bez ekrana koji će reagovati kada uplata legne. Pored vlasnika, to zvuči kao „platio sam, a još mi traži novac".
      • Kopiranje IBAN-a je moglo ne uraditi baš ništa. U pretraživaču unutar druge aplikacije, na starijem Androidu ili gdje je dozvola odbijena, navigator.clipboard odbije - a ekran bi se vratio u stanje kao da niko ništa nije pritisnuo. Gost pritisne još četiri puta pa počne prepisivati dvadeset jedan znak sa ekrana. Sada postoji stariji način kopiranja, a ako ni on ne prođe, broj ostaje označen uz rečenicu da ga treba prepisati.
      • Prazan bijeli kvadrat umjesto QR koda. Ako se slika koda ne učita, ostane bijela ploča sa iznosom ispod i kucajućom tačkom - gost uperi bankovnu aplikaciju u ništa. Sva tri ekrana (gost, konobar, kasa) to sada kažu i nude ponovni pokušaj bez pravljenja novog računa.
      • Gost pod „Čekam potvrdu banke" nije mogao znati da mu je pukao internet. Telefon ispadne sa wifija dok je bio u banci, tačka kuca dalje, i poslije dva minuta gost zaključi da uplata nije prošla i ponudi gotovinu - pa isti račun stoji i na kasi i u banci. Poslije tri neuspjela provjeravanja ekran to sada kaže, uz napomenu da uplata i dalje važi.
      • Crveni natpis „Nema veze sa serverom" na tabletu konobara nije se gasio. Ručni ruteri i wifi sa prijavnom stranicom redovno blokišu websocket, pa je natpis stajao cijelo veče - dok je tablet, sasvim vidljivo, naplaćivao preko običnog provjeravanja svakih pet sekundi. Natpis sada prati da li tablet uopšte može doći do servera, a ne da li je websocket živ.
      • Kasa nije imala nikakav znak da je veza pukla. Wifi padne na minut i po, gost je već uplatio, a ekran cijelo vrijeme pokazuje istu živu tačku. Osoba na kasi zaključi da nije prošlo i posegne za „Odustani" - dugmetom koje na već plaćenom računu radi upravo pogrešnu stvar. Sada, poslije tri neuspjela provjeravanja, stoji crveno „Nema veze sa serverom" i rečenica da se ne otkazuje.
      • „Otkaži" na mrtvoj vezi nije radio ništa, i to bez riječi. Gost kaže da ipak plaća gotovinom, konobar pritisne Otkaži, ništa. Pritisne još pet puta pred vlasnikom. Dugme sada pokazuje da je pritisnuto i, kada odgovor ne stigne, kaže da je račun i dalje otvoren i da će se srediti sam.
      • Izgubljen odgovor pri povezivanju uređaja trošio je kod, a krivio kod. Vlasnik pročita kod sa laptopa, konobar ga upiše, odgovor se izgubi na wifiju - tablet kaže „kod nije ispravan ili je istekao", pa ga upišu ponovo, pažljivije, i tek tada je zaista potrošen. Sada se odgovor koji nije stigao razlikuje od odbijenog koda i upućuje na Novi kod u konzoli, na sva tri ekrana koja se povezuju.
      • Konzola je istekao kod za povezivanje pokazivala kao živ. Kod važi 30 minuta, a konzola ga je pokazivala u okviru sa dugmetom za kopiranje dok god je red postojao. Sada piše koliko mu je ostalo, precrta ga kada istekne, i upozorenje „ovo prekida vezu sa uređajem" se više ne pokazuje za uređaj koji nikada nije ni bio povezan.

      Tačnije

      • Uputstvo za naljepnice preskakalo je bankovni račun. Korak „Napravi kodove" se bez njega odbija, a IBAN u malom kafiću zna značiti telefon knjigovođi - dok vi stojite za šankom. Sada je to korak 0, stoji i na listi onoga što nosite sa sobom, i rečenica za prodaju više ne obećava da ne treba baš ništa.
      • Uputstvo za ekrane sada pravi kod tek kada je tablet spreman. Redoslijed je bio: napravi ekran u konzoli, pa montiraj tablet. Kod živi 30 minuta i obično istekne prije nego se dođe do njega.

      0.47.0

      9. septembar 2026.

      Popravljeno

      • Kuhinjska ploča je za pukao wifi krivila kolegu. Kada dodir na karticu ne prođe, ploča je ispisivala „neko je već pomjerio ovu narudžbu" - i za slučaj kada je to istina, i za slučaj kada server uopšte nije odgovorio. Kuhar tada vjeruje da je karticu preuzeo pass, a nije je preuzeo niko. Poruka je i ostajala na ekranu zauvijek.
      • Ploča koja je izgubila server javljala je to tačkom od osam piksela. Jedini znak je bio mali kružić u uglu, sa objašnjenjem koje se vidi tek kada se mišem stane na njega - na ekranu zavrnutom za zid, gdje ništa ne stoji mišem i niko nije dovoljno blizu. Ploča koja više ništa ne prima izgledala je isto kao ploča na kojoj nema posla.
      • Firma se mogla otvoriti bez ijedne poslovnice, a poslovnica se nije mogla dodati. Polje za prvu poslovnicu u otvaranju naloga bilo je neobavezno. Vlasnik takve firme završi na ekranu Poslovnice, pročita „Dodajte prvu poslovnicu da biste mogli izdavati QR kodove" - i nema gdje. Ruta za otvaranje poslovnice postoji od početka i konzola je nikada nije pozvala, a traži vlasnika, pa to nije mogao uraditi ni neko sa naše strane.
      • Kada ponestane mjesta za stolove, poruka nije rekla koliko ih paket dozvoljava. Odbijenica je stizala kao „kodovi se nisu mogli napraviti" - ista rečenica kao za pokvaren server, a potez vlasnika je sasvim drugi. Server je sve vrijeme slao brojeve; ekran ih nije čitao. Sada piše koliko paket dozvoljava, koliko stolova već postoji i koliko ih je traženo.
      • Jutarnja provjera je za nepotvrđen QR profil pisala „profil je potvrđen (DRAFT)". Dvije tvrdnje u jednoj rečenici, koje jedna drugu pobijaju, sa kvačicom pored - na listi čiji je jedini posao da joj se vjeruje u devet ujutro. To što server pristaje izdati kod nije isto što i to da je banka profil potvrdila, a samo drugo znači da novac stigne.

      Tačnije

      • Uputstvo za osoblje tvrdilo je da šank ne prikazuje hranu. Ne prikazuje je samo kuhinjski ekran; šank i ekran bez postavljene stanice namjerno vide cijelu narudžbu, jer u malom lokalu šank drži pass. Ista tvrdnja stajala je i u listi za provjeru prije puštanja u rad, kao stavka koja nikada nije mogla proći. Oboje ispravljeno.
      • Isto uputstvo je obećavalo promet po konobaru. Izvještaj Ko je radio to namjerno ne kaže i ne može reći: gost naručuje sa svog telefona, pa narudžba nosi sto i uređaj, a ne osobu. Uputstvo sada opisuje ono što izvještaj zaista mjeri i kaže da su redovi terminala označeni kao uređaj, ne kao osoba.
      • Limit od 5.000,00 KM po instant plaćanju više nije glasina iz medija. Odluka Centralne banke o pravilima rada instant plaćanja, usvojena 10. jula 2026., postavlja ga u članu 13, uz pravilo da je valuta isključivo KM. Dokument za razgovor sa bankom sada citira odluku umjesto novinskog teksta, i bilježi da specifikaciju QR koda tek treba objaviti Centralna banka - zbog čega BIH_IPS i dalje stoji kao nacrt.

      0.46.0

      9. septembar 2026.

      Popravljeno

      • Izgubljen odgovor na „Plati" zaključavao je sto od QR plaćanja preko sat vremena. Gost pritisne, odgovor se izgubi na wifiju, gost pritisne opet - a server, koji mu je već napravio kod, odgovori da je svaki dio računa već zauzet. Telefon pokaže „trenutno nije moguće napraviti kod", račun je u stanju „plaća se" pa se ne može ni naručiti, i ništa na ekranu ne može doći do koda koji postoji. Zaglavljen dok kod ne istekne, za stolom, pred vlasnikom.

      0.45.0

      9. septembar 2026.

      Popravljeno

      • Konobarski terminal je na plaćen račun ispisivao 0,00 KM. Ekran je čuvao kopiju plaćanja od trenutka kada je kod izdat i mijenjao joj samo status - a plaćanje koje još nije plaćeno nosi settledAmount „0.00", ne prazno. Pločica čita settledAmount ?? totalAmount, a ?? ne hvata nulu.
      • Nijedan zahtjev u pretraživaču nije imao vremensko ograničenje. Kafić s debelim zidovima ne prekida vezu čisto: pristupna tačka ostane spojena a prestane prosljeđivati, socket ostane otvoren i tih, i fetch čeka. Obećanje se nikada ne razriješi, finally se ne izvrši, i ekran ostane u pola koraka - dugme za slanje mrtvo, ispod natpisa da se šalje, do kraja sjedenja. Pažljivo napisan ekran „ne možemo se povezati, pokušaj ponovo" je pritom nedostižan, jer se pali samo kada fetch odbije.

      0.44.0

      9. septembar 2026.

      Popravljeno

      • Server instaliran po vlastitom uputstvu nije mogao izdati nijedan QR kod, a jutarnja provjera je javljala da je sve spremno. install.sh upisuje NODE_ENV="production" i nikada ne upiše ALLOW_UNPROVEN_QR, pa je podrazumijevano false; svaka nova poslovnica dobija BIH_IPS, a taj profil je DRAFT; i API u produkciji odbija svaki profil koji banka nije potvrdila.
      • Konobar je dobijao „pokušajte ponovo" na dvije greške koje ponovni pokušaj ne rješava. Nepotvrđen QR profil se neće riješiti kucanjem, a račun preko 5.000,00 KM traži naplatu u dijelovima. Oba sada imaju rečenicu koja kaže šta uraditi, na kasi i na konobarskom terminalu.
      • Gost je na račun preko limita dobijao samo „nije moguće napraviti kod". Dugme za dijeljenje računa je na tom istom ekranu. Sada poruka na njega i upućuje - kroz mehanizam koji taj ekran već ima za ovakve odbijenice.

      0.43.0

      9. septembar 2026.

      Popravljeno

      • Kod je izdavan i na iznose koje instant plaćanje ne može izvršiti. QR kod je samo način da se nalog otkuca u aplikaciju banke; aplikacija ga onda predaje shemi, a shema ima pravila koja kod ne može zaobići. Odluka o pravilima rada sistema instant plaćanja CBBiH kaže u članu 13 da nalozi glase isključivo na BAM i da je najveća pojedinačna transakcija 5.000,00 BAM.

      0.42.0

      9. septembar 2026.

      Popravljeno

      • Menadžer vezan za jednu poslovnicu mogao je čitati brojke druge. Četiri izvještajne rute gradile su filter kao locationId ? { locationId } : locationFilter(principal), što izgleda kao ograničavanje a radi suprotno: proslijeđen locationId ZAMJENJUJE opseg pozivaoca umjesto da se provjeri u odnosu na njega. Pet drugih mjesta u istom fajlu već je prosljeđivalo traženu poslovnicu u locationFilter, koji odbija onu do koje pozivalac ne smije. Reprodukovano: menadžer vezan za Mrkva Centar dobio je stolove, izvještaj o osoblju i knjigovodstveni CSV za Mrkva Ilidžu, sve sa 200. Tri od četiri mjesta su bila starija od danas; četvrto je preslikalo obrazac.
      • Licenca izdata prije jučer prestala je važiti pri unosu. Dvije promjene iz istog puštanja, razmaknute sat vremena: zaokruživanje isteka pomjerilo je NOVE ključeve naprijed, a pravilo o starijem ključu je onda svaki ranije izdat ključ čitalo kao zastario. Firma koja zalijepi ključ koji joj je poslan - a to je cijeli način na koji se paket aktivira - dobila je poruku da je ključ stariji od onoga koji već ima. Poređenje je bilo pogrešne vrste: ključ nosi dan, licenca nosi trenutak. Sada se porede dani.
      • Kolona „Gotovina" brojala je i karticu. Vlastiti POS terminal lokala nije gotovina: novac ide akvajreru i stiže u banku danima kasnije, nikada u kasu. Pregled u istoj konzoli te dvije stvari drži odvojeno („Gotovina za stolom" i „Kartica na terminalu"), a ovaj ekran ih je spojio pod gotovinom. Menadžer bi u subotu ujutro pročitao da je Ana imala 1.000 KM gotovine, izbrojao 600 u kasi, i pitao imenovanog radnika gdje je ostatak.
      • Narudžbe su se brojale po satu gosta, ne po satu osoblja. Izbor je išao po placedAt, a tri trenutka koja se broje - primljeno, spremno, izneseno - imaju svoje vlastito vrijeme. Narudžba primljena u 23:50 i iznesena u 00:10 cijela je knjižena na raniju smjenu. Upit pored njega o računima obrazlaže upravo suprotno, u toliko riječi.
      • Poslovi platforme pisali su se kao „Obrisan nalog". Ime se traži samo za osobu i uređaj, pa je red koji je zatvorila sama platforma - kada zadnja uplata stigne - izgledao kao da ga je zatvorio obrisani radnik.
      • Panel „Ko je radio" bio je na ekranu svakom konobaru, a ruta iza njega je samo za menadžera. Svaki član osoblja koji otvori Stolove dobio je crvenu poruku o zabrani, na ekranu koji najviše gleda. Isto i stavka „Zalihe" u navigaciji: sposobnost kaže da firma vodi zalihe, uloga kaže ko smije.
      • Jedan pritisak dugmeta mogao je napraviti dva poziva osoblja, a jedan odlazak zatvoriti sve otvorene. Provjera pa upis bez zaključavanja: dva dodira u istoj sekundi - što nestrpljiv sto i radi - oba su prošla. A potvrda je označavala svaki neodgovoren red na računu, ne onaj za koji je neko otišao.
      • Količina zalihe i red koji je objašnjava pisali su se odvojeno. Cijeli modul je složen tako da se broj ne može pomjeriti bez reda koji kaže zašto - a sam upis je mogao uraditi upravo to: pomjeriti broj, pasti na redu, i ostaviti stanje za koje niko ne može odgovarati. Sada je jedna transakcija.
      • Ekran zaliha se utrkivao sam sa sobom. Promjena poslovnice pokreće učitavanje i ne prekida prethodno, pa je polica jedne poslovnice mogla biti prikazana pod imenom druge. Uz to: neuspjelo učitavanje javljalo je „Još nema artikala. Dodajte prvi artikal", a neuspjelo čitanje historije „Nema zapisa." - na ekranu čije je cijelo obećanje da svaka promjena ostavlja red.
      • Upisan minus na prijemu je oduzimao. Znak je bio nametnut samo razlozima koji oduzimaju, pa je „-3" pod Prijem prošlo kao minus tri.
      • Poruka o pogrešnom ekranu stizala je na engleskom. Na tri ekrana koja gledaju konobar i kuhar, gdje je svaka druga riječ bosanska.
      • Migracija je ostavila dvije mrtve kolone. Kada je oblik zapisa poziva osoblja zamijenjen tabelom, shema je vraćena a SQL nije. Nova migracija ih briše - stara se ne dira, jer Prisma pamti njen kontrolni zbir.
      • Naredba za postavljanje lozinke nije ostavljala nikakav trag. Ona sada postavlja lozinku, diže zaključavanje i gasi sve druge sesije - a jedina radnja na koju dnevnik nije mogao odgovoriti bila je preuzimanje vlasnikovog naloga s pristupom serveru. To je red koji najviše vrijedi imati.
      • Trideset i jedan zapis u dnevniku upisivao je vrstu aktera rukom. Ranija provjera je gledala samo da li je akter imenovan, pa je red koji kaže „korisnik" uz principal.id prolazio - a četiri najprometnije radnje u lokalu radile su tačno to. Kuhinjski ekran i integratorov ključ vodili su se kao osoba. Provjera to sada hvata.
      • Tri provjere koje nisu mogle pasti. Provjera da uplata nije gotovina zatvarala je račun kao QR_TRANSFER, a takvo zatvaranje po definiciji ne knjiži ništa u kasu - pa je prolazila i kada se pravilo obriše. Test o dužini lozinke tvrdio je f(x) === f(x). I datum u provjeri osoblja tražio se po satu servera, pa bi dva sata svake noći tražila dan pod kojim posao nije zaveden.
      • Seed nije postavljao lozinke koje ispisuje. Postojećeg korisnika je ostavljao na miru, pa bi ko god upotrijebi naredbu za postavljanje lozinke i onda ponovo zasije bazu dobio bazu koja protivrječi vlastitom ispisu - i grešku „Invalid email or password" koja izgleda kao kvar proizvoda a nije. Sada postavlja ono što ispisuje i skida zaključavanje uz to.

      0.41.0

      9. septembar 2026.

      Novo

      • Zalihe - novi ekran za prodavnice i skladišta. Prodavnica i skladište su odavno vrste djelatnosti i odavno nose oznaku da vode zalihe, a tu oznaku ništa nije čitalo. Konzola im je ispravno sakrivala stolove i meni i ponudila ništa umjesto toga: prodavnica se mogla registrovati, dobiti potvrdu da je prodavnica, i naći proizvod bez ijednog mjesta da kaže šta ima na polici.

      Popravljeno

      • Provjera pred otvaranje pitala je i prodavnicu može li primiti gosta. Skripta koja se pokreće ujutro pred pilot prolazila je kroz sve poslovnice, a pitanja koja postavlja - ima li menija, jesu li naljepnice odštampane, je li naručivanje uključeno - za prodavnicu ili skladište nemaju odgovor. Firma koja uz restoran ima i prodavnicu bila bi obaviještena, pred vlasnikom, da nije spremna - za prostoriju na koju se ništa od toga ne odnosi. Nikada se nije pokazalo jer takva poslovnica dosad nije ni postojala. Sada se takve preskaču, a razlog preskakanja se ne miješa: prodavnica nije ugašena, ona je prodavnica.

      0.40.0

      9. septembar 2026.

      Novo

      • „Ko je radio" - novi izvještaj ispod izvještaja po stolovima. Koliko je računa ko zatvorio, koliko je gotovine kroz čije ruke prošlo, koliko je narudžbi primio, pripremio i iznio, i na koliko se poziva sa stola odazvao.

      Popravljeno

      • Poziv osoblja se sada pamti. Zastavica se ranije samo brisala, pa su minutu kasnije poziv na koji je neko otišao i poziv koji se nikada nije desio izgledali isto: nigdje se nije vidjelo je li iko otišao, koliko je sto čekao, ni ko je otišao. Sada se svaki pritisak zapisuje zasebno - sto u toku večeri pozove dvaput, još jedna tura pa račun, i brojanje po računu bi prijavilo jedan.
      • Narudžba pamti ko ju je pomjerio. Vrijeme prihvatanja, pripreme i iznošenja je odavno zapisano, osoba nije - to je znao samo revizijski trag, koji je ulančan hešom i pogrešna stvar za sabiranje: odgovoriti na „kako je prošla večer" značilo bi proći kroz svaki zapis koji lokal ima.

      0.39.5

      9. septembar 2026.

      Popravljeno

      • Postavljanje nove lozinke javljalo je da je gotovo, a vlasnik i dalje nije mogao ući. Prijava provjerava zaključavanje računa prije lozinke, i tako mora biti: zaključavanje postoji da neko ne bi redom probavao lozinke, pa ni pogođena ne smije proći dok traje. Ali razlog zbog kojeg nekome i treba nova lozinka najčešće je upravo to da ju je osam puta ukucao pogrešno, dakle račun je zaključan u trenutku kada se komanda pokreće. Komanda bi ispisala „Password set", vlasnik bi ukucao novu lozinku, a prijava bi odgovorila istim „Invalid email or password" kao i prije. Namjerno istom porukom, da se ne odaje koje adrese postoje - što vlasnika ostavlja s tačnom lozinkom i ekranom koji kaže da je pogrešna, petnaest minuta, one večeri kada je zvao u pomoć. Sada se zaključavanje diže zajedno s lozinkom. Isto i kod promjene lozinke iz konzole, gdje brojač neuspjelih pokušaja nije nulirao ništa osim uspješne prijave.
      • Vraćanje iz sigurnosne kopije javljalo je „Restored" i kada nije vratilo ništa. psql je vedar po pitanju grešaka: kada mu se da skripta, odradi šta može, greške ispiše na stderr i izađe s kodom 0. Kopija od koje se nije primila nijedna naredba izgledala je skripti isto kao ona koja je prošla u cijelosti, pa bi se pokrenule migracije, digao API i ispisalo „Restored from 20260903T032000Z" iznad prazne baze. U dva ujutro, na jedinoj komandi kojoj je cijeli posao da joj se vjeruje. Sada prva greška prekida posao i vraća sve unazad, API ostaje ugašen namjerno, a ispis kaže gdje je baza od prije vraćanja.
      • Konzola je pokazivala cijenu s cjenovnika umjesto dogovorene. Ugovor obećava da lokal u svojoj konzoli vidi broj transakcija i iznos koji iz njega slijedi, a taj iznos se gradi iz dogovorene cijene zapisane na firmi. Ekran je čitao cjenovnik. Lokal kojem su odobrena tri mjeseca po pola cijene svaki je dan gledao punu. Uz to je godišnja licenca, koja se plaća jednom za godinu, bila dodavana u svaki mjesec te godine.
      • Licenca je isticala i po jednu večer ranije nego što je plaćena. Ključ nosi dan, a pravo traje do trenutka, pa se nešto mora zaokružiti - i zaokruživalo se naniže, čime se vrijeme u danu gubi unazad. Pretplata započeta u devet ujutro obnavlja se na 07:00Z, to se spusti na taj dan, i ključ ističe u 02:00 po sarajevskom vremenu na danu koji je lokal platio. Konektor provjerava ključ lokalno, bez interneta, pa bi tu zadnju večer servisa jednostavno rekao da licenca ne važi. Sada se zaokružuje naviše: najviše dan gratis na nečemu što je već plaćeno, umjesto jedne izgubljene večeri.
      • Stariji licencni ključ tiho je poništavao nadogradnju. Ključevi se ne povlače - provjera je potpis i ništa drugo, upravo zato da radi bez interneta - pa je prošlogodišnji STARTER ključ i dalje ispravan i i dalje u sandučetu. Zalijepljen u konzolu, upisao bi STARTER preko žive PRO licence i povukao datum isteka godinu unazad, uz istu zelenu potvrdu koju dobije prava nadogradnja. Ono što bi vlasnik primijetio jeste da su mogućnosti nestale, dan nakon što mu je ekran rekao da je licenca prihvaćena. Sada se ključ koji ističe prije one licence koja već važi odbija, s objašnjenjem. Gleda se datum a ne paket, da dogovorena prelazak na manji paket i dalje prolazi.
      • Četiri zapisa u dnevniku nisu imenovala nikoga. Dnevnik je ulančan hešom da bi lokal mjesecima kasnije mogao odgovoriti ko je nešto uradio, a ovi su govorili samo da se dogodilo: postavljanje adrese na već izdatu fakturu, otvaranje i brisanje webhook tačke, i povezivanje izvora uplata. Uz to su se aktori upisivali ručno na tri različita načina, pa je sve što nije API ključ zavedeno kao „korisnik" - uključujući kuhinjski ekran i poslove koje platforma radi sama. Sada postoji jedno mjesto koje to čita iz onoga ko poziva, a provjera prolazi kroz sav izvorni kod i pada ako ijedan novi zapis zaboravi aktera.
      • Kod za uparivanje prolazio je na pogrešnom ekranu. Uparivanje nije gledalo koji je ekran otvoren, pa je kod kuhinjskog ekrana ukucan na konobarskom tabletu prošao: ekran za uparivanje bi nestao, što izgleda kao uspjeh, a ostao bi tablet koji vozi zidni ekran. Obrnuto je gore - kuhinjska ploča uparena na tablet nema stanicu, pa šankerski ekran pokazuje i hranu, što je tačno ono što stanica postoji da spriječi. Sada se odbija, i to prije nego se kod potroši, pa uređaj kojem kod pripada i dalje ima šta ukucati. Poruka kaže o čemu se radi umjesto „kod nije ispravan", jer je to kod koji je ispravan, samo na pogrešnom mjestu.

      0.39.4

      9. septembar 2026.

      Popravljeno

      • Uputstvo je davalo uzorak koji račun od 1.234,56 KM čita kao 1,23 KM. Kod je za to bio popravljen, uputstvo nije - a uzorak iz uputstva se upisuje u konfiguraciju i time gazi ispravan ugrađeni. Kraći oblik ne može obuhvatiti grupu hiljada pa uhvati samo početak. Društvo od dvanaest ljudi plati 1,23 KM, uplata se poklopi u fening, slučaj se nigdje ne otvori, na svakom ekranu piše da je plaćeno - a lokalu fali 1.233,33 KM i ništa ne javlja.
      • Primjer konfiguracije se nije mogao učitati. Tri regularna izraza su bila u dvostrukim navodnicima, gdje \s nije ispravan znak, pa YAML puca. README kaže da se taj fajl kopira, a blok za kasu je jedini razrađen primjer za slučaj koji pilot i cilja - kasu koja ne zna ništa osim štampanja. Kad ga instalater odkomentariše, konektor se ne pokrene i dobije jednu poruku o koloni u YAML-u koja ne spominje XPay.
      • Uputstvo nije spominjalo bindHost, a govorilo je da se kasa uperi na IP ovog računara. Konektor po pravilu sluša samo na loopbacku - tok štampe nije zaštićen lozinkom i nosi svaki iznos računa - pa je veza s kase bila odbijena i kasa je prestajala štampati, ni račun za gosta ni kopiju za kuhinju, bez ijedne poruke. Uputstvo i primjer sada to traže i objašnjavaju zašto, a konektor pri pokretanju kaže da sluša samo lokalno i šta podesiti.
      • Zauzet port lokalnog API-ja više ne ruši cijeli konektor. Slušanje nije imalo rukovanje greškom, pa je svako neuspjelo zauzimanje porta - obično druga kopija koju je pokrenuo raspoređivač zadataka - gasilo proces. S njim je odlazio i sloj između kase i štampača, pa bi kasa koja je uredno štampala prestala zbog slušača koji u lokalu niko ne koristi. Sada se zabilježi kao otkazan dio i vidi se na /health, a štampanje ide dalje.
      • Provjera pred puštanje sada čita taj primjer onako kako ga čita instalater: odkomentariše blok za kasu, učita ga, i provjeri da uzorak zaista pročita 1.234,56 kao 1.234,56.

      0.39.3

      9. septembar 2026.

      Popravljeno

      • Uparivanje drugog ekrana više ne preusmjerava prvi. Sva tri ekrana uređaja - konobarski, kasa i kuhinjski - držala su token na istom mjestu, a svaki je svoj kontekst čuvao posebno. Uparite kasu pa na istom tabletu kuhinjski ekran, i kasa i dalje piše „Šank" dok svaki njen zahtjev nosi token kuhinjskog ekrana. Taj token ima prava samo na narudžbe, pa naplata dođe odbijena zbog nedostajućeg prava - a to je 403, ne 401 koji klijent koristi da primijeti mrtav token i ponudi ponovno uparivanje. Osoblje ostane da pritiska dugme koje ne može raditi, bez puta nazad. Prolazak kroz cijeli proizvod na jednom tabletu - a tako se i pokazuje - udari u ovo na drugom ekranu. Svaki ekran sada ima svoje mjesto; uređaj koji je već bio uparen zadrži uparivanje na ekranu koji prvi otvorite.
      • Kasa više ne naplaćuje jučerašnje cijene. Meni je učitavala jednom pri otvaranju i nikad više, a uparena kasa nema prijavu i niko je ne osvježava - to je i smisao uparivanja. Kad happy hour počne u pet, gost za stolom plati sniženu cijenu a šank punu, za istu rundu; poslije sedam se obrne i lokal naplati manje. Sada se meni čita svake minute, i kad se ekran probudi, ali nikad usred kucanja računa.
      • Ponovni pokušaj na kasi više ne pravi drugi račun. Ključ se pravio iz sata unutar samog slanja, pa je ponovni pokušaj - jedini razlog zbog kojeg ključ i postoji - nosio drugi ključ. Konobarski terminal je za to bio popravljen i pravilo živi u zajedničkoj datoteci; kasa nikad nije prebačena na nju.
      • Zidni ekran sada može skinuti poziv osoblja. Prikazivao ga je i nije imao čime da ga skloni: jedini ekran koji to može je pregled stolova u administraciji, koji u kuhinji niko ne drži otvoren. Gore od zaglavljene oznake: poziv koji već stoji ne objavljuje ništa kad isti sto pritisne opet, pa je neskinuta oznaka gutala sljedeći poziv tog stola do kraja računa. Endpoint je za ovo i napravljen - u njegovom opisu piše da to smije uraditi i zidni ekran u kuhinji - samo ga ekran nikad nije nudio.
      • Pločica „otvoreni računi" na pregledu vlasnika se sada osvježava. Svaki drugi živi ekran ima tajmer iza veze - zidni na dvadeset sekundi, narudžbe na trideset, terminal na pet - a ovaj nije imao nijedan, i događaje o stolovima je ignorisao. U lokalu gdje se najviše plaća gotovinom to je cijela pločica: otvorite konzolu u šest s četiri računa i 84,50 KM, i u jedanaest i dalje piše četiri i 84,50.

      0.39.2

      9. septembar 2026.

      Popravljeno

      • Prekid veze na dvije sekunde više vas ne odjavljuje zauvijek. Osvježavanje prijave je svaku grešku tretiralo isto: i server koji kaže da token više ne vrijedi, i wifi koji je pao u zgradi s debelim zidovima, i 502 dok se API restartuje. A postupak je bio isti - obrisati jedini podatak za prijavu s uređaja. Vlasnik bi se onda, tri sekunde nakon što se wifi vrati, kucao lozinku pred ugostiteljem. To se dešava otprilike svakih petnaest minuta na svakom otvorenom ekranu, pa je kroz jednu smjenu na tri uređaja to na desetine prilika, ne rijetkost. Sada se briše samo kad server stvarno odbije token.
      • Dva otvorena taba se više ne odjavljuju međusobno. Dijele jedan token i svaki ga osvježava sam, pa oba mogu poslati isti. Server tada poštedi porodicu tokena i odbije onaj drugi - a taj drugi je brisao token koji je prvi upravo upisao. Sada se briše samo ako je u međuvremenu niko drugi nije zamijenio.
      • Živa veza više ne šalje istekao token. Rukovanje pri ponovnom spajanju je napisano baš zato da ne pošalje istekao token, a čitalo je token iz memorije koji se pri isteku nigdje ne briše - pa je uzimalo tačno onaj token zbog kojeg je i napisano. Svako ponovno spajanje poslije prvih petnaest minuta je zato bilo odbijeno, i to je ono što je gornju grešku pretvaralo iz rijetke u svakodnevnu. Sada se čita rok iz samog tokena.
      • Kuhinjski ekran na zidu se više ne isključi do kraja smjene. Uređaj s uparenim tokenom je na svako odbijanje odustajao zauvijek, uz obrazloženje da takav token ne ističe pa nema šta da se osvježava. Tačno za osvježavanje, netačno za ponovni pokušaj: server šalje to isto odbijanje za bilo koju grešku pri spajanju, uključujući i bazu koja je na trenutak zauzeta. Zasićen konekcijski bazen tokom uvoza izvoda bi tako skinuo ekran s prijenosa do kraja večeri, a jedini povratak je da neko otlijepi tablet sa zida. Sada pokuša ponovo, nekoliko puta, s razmakom.

      0.39.1

      9. septembar 2026.

      Novo

      • Boja lokala na meniju koji gost vidi. U postavkama, pored logotipa, bira se jedna boja. Dugmad i naglasci na gostovom meniju idu u toj boji.

      Popravljeno

      • Logotip i boja se sada prikazuju samo na paketu koji ih uključuje. customBranding postoji u tabeli paketa otkad postoje paketi i nije se provjeravao nigdje: logotip svakog lokala je stizao na gostov meni bez obzira šta lokal plaća. Odluka se donosi na izlazu, ne na upisu - lokal koji pređe na niži paket zadrži ono što je izabrao, samo se prestane prikazivati, a povratak na viši paket vrati njegove boje istog trena.

      0.39.0

      9. septembar 2026.

      Novo

      • Nabavna cijena po jelu, pa marža postaje stvaran broj. Uz cijenu jela stoji i koliko vas košta da izađe iz kuhinje. Iz toga se na spisku vidi marža po jelu, a u zaglavlju kategorije marža cijele kategorije.

      0.38.12

      8. septembar 2026.

      Popravljeno

      • Napojnica na zaokruženom računu se više ne gubi s pregleda. Podred „od toga bakšiš" brojao je samo račune plaćene tačno, iako promet iznad njega uključuje i kratke i prekoračene. Gost koji ostavi napojnicu pa prebaci malo više nego što kod traži vidio bi svoj novac u prometu, a napojnica bi nestala s jedinog reda koji je imenuje. Sada se broji na istom paru statusa na kojem se knjiži i sto i na kojem se broji kolona po stolovima: napojnica se računa kad je novac za nju stigao. Kratko plaćen račun se i dalje ne broji, jer nije pokrio ni robu, pa ništa ne govori da je išta od napojnice stiglo.
      • Taj podred sada kaže i koje napojnice imenuje. Pisalo je samo „bakšiš", pored „gotovina" u istom redu - a napojnica u gotovini se ne upisuje nigdje i ne može biti u toj brojci. Lokal koji je uzeo 400,00 gotovine i 60,00 QR-om čitao je red koji zvuči kao sve napojnice te večeri, a opisuje samo QR dio.
      • Knjigovodstveni PDF sada podvlači i napojnicu. Jedini zbir na stranici je kolona Uplaćeno, a to je bankovni priliv - dakle na običnom računu nosi i napojnicu, i to nigdje nije pisalo. Knjigovođa koji je htio zbir napojnica morao ga je sabrati rukom niz stranicu koja zna imati desetak listova. Sada ispod zbira stoji „od toga napojnica", i to samo kad je ima, da se na običnom mjesečnom izvozu ne pojavljuje red s nulom.

      0.38.11

      8. septembar 2026.

      Novo

      • Kolona s napojnicama, po stolovima. Pored Prometa stoji koliko je napojnice stiglo na taj sto u odabranom periodu. Broji se po istom pravilu kao i Promet: iste uplate, isti računi, isti period, prije povrata - jer dvije kolone s novcem u istom redu koje broje različite stvari su greška, ne mogućnost.

      Popravljeno

      • Kod izdat na stolu više se ne prikazuje veći od računa koji plaća. Red na spisku otvorenih stolova je sabirao ukupan iznos uplate, dakle s napojnicom, a preostali iznos pored njega je po prirodi bez nje: sto se knjiži iznosom naručenog. Sto od 20,00 KM na kojem gost drži kod za cijeli račun i 2,00 napojnice pisao je „1 kod izdat · 22,00 KM" pored preostalih 20,00 - a kad uplata stigne, konobar vidi kako s reda nestaje 22,00, a s preostalog se skine 20,00. Ta dva broja stoje jedan pored drugog baš zato da se porede.

      0.38.10

      8. septembar 2026.

      Popravljeno

      • „Ponovi isto" dvaput više ne znači dvije runde. Ta putanja nije nosila nikakvu oznaku pokušaja, a telefon ne razlikuje odbijanje od odgovora koji nije stigao - što je u bučnom lokalu s lošim wifijem obična stvar. Narudžba ode, šank je natoči, odgovor se izgubi, gost pritisne opet i šank natoči drugi put: dva piva naplaćena kao četiri. Isti pritisak sada nosi isto ime, pa drugi dodir slegne na rundu koja već postoji.
      • „Pokreni ponavljanje" sada kaže zašto je odbijeno. Poruka o grešci se ispisivala na stranici iza modala, ispod njegovog vlastitog neprozirnog pokrivača: modal ostane otvoren, dugme oživi, i ništa čitljivo se ne pojavi. Najobičniji unos od svih vodio je tačno u to stanje - prvi datum danas, koji API odbija svaki put jer datum čita kao ponoć u zoni lokala, a ponoć je prošla. Poruka je sada unutar modala, a birač datuma više ne nudi dan koji će sigurno biti odbijen.
      • Datum sljedećeg pokretanja više se ne čita dan ranije. Sprema se kao ponoć u zoni lokala, što je 22:00 dan prije po UTC-u, a konzola ga je formatirala u zoni pregledača - pa je svakom ko je na UTC-u ili zapadnije pisalo da faktura ide dan ranije, i preko granice mjeseca i preko granice godine. Server sada šalje i sam dan, a ekran ga samo prepiše.
      • Pregled zanemarenih uplata više ne nosi naslov reda za uparivanje. Oba su pisala „Nepovezane uplate", a jedina razlika je bila ljubičasti prsten na dugmetu. Brojač ispod naslova je bio gori: „Prikazano 50 od 63 nepovezanih" iznad spiska uplata koje je neko namjerno odložio, dok je sam red bio prazan. Dugme sada imenuje mjesto na koje vodi.
      • Knjigovodstveni izvoz ima gornju granicu i po broju redova. Ograničenje je bilo samo na dužinu perioda, a godina mirnog i godina prometnog lokala nisu ista količina memorije: svi redovi se učitaju u jedan niz, a crtanje PDF-a drži svaku stranicu do kraja pa gotov fajl napravi još dvaput - i to u istom procesu koji poslužuje kasu i kuhinjski ekran, bez ijednog ograničenja memorije. Kvar ne bi bio spor izvoz nego ugašen kontejner i prekinuta veza svakom terminalu usred smjene. Sada se odbija s brojem redova i prijedlogom užeg perioda, jer skraćen knjigovodstveni fajl izgleda tačno kao potpun.

      0.38.9

      8. septembar 2026.

      Popravljeno

      • Promet na ekranu i knjigovodstveni fajl više se ne razilaze za svaki povrat. Kratko plaćeni i zaokruženi računi ušli su u promet, ali se povrat oduzimao samo ako je račun i dalje pisao kao plaćen u cijelosti. Gost koji zaokruži 48,00 na 50,00 i dobije 2,00 nazad ostavljao je ekran na 50,00 - s redom „od toga vraćeno 2,00" tačno ispod - dok je fajl za isti dan davao 48,00. Vlasnikov ekran i papir iz kojeg knjigovođa knjiži razlikovali su se za svaki povrat na računu koji nije namiren u fening.
      • Stari stolovi zatvoreni gotovinom više se ne broje dvaput. Popuna kolone o naplaćenom za table upisala je cijeli iznos računa na svaki stari sto zatvoren gotovinom ili karticom, uz obrazloženje da se dio plaćen QR-om „više ne može odvojiti". Može: uplate nose oznaku stola i to je tačno taj iznos. Sto od 100,00 KM gdje je jedan gost poslao 40,00 QR-om, a konobar uzeo 60,00 u gotovini, brojao se kao 40,00 preko banke plus 100,00 gotovine: promet 140,00 KM na računu od 100,00. Ista greška išla je i kroz pregled po prostorijama i kroz satni grafikon, a kako je pogrešna vrijednost bila upisana u bazu a ne računata, preživjela bi svaku kasniju ispravku čitanja. Nova migracija oduzima bankovni dio; provjerena je na sva četiri oblika reda koja može zateći.
      • Nadogradnja više ne ostavlja server zaglavljen na staroj verziji. Migracije su se primjenjivale dok je prethodna verzija još posluživala promet, a kontejneri su se mijenjali tek poslije. U tom prozoru migracija koja kolonu čini obaveznom pukne: stari kod upiše red bez te vrijednosti, provjera padne na tom redu, i Prisma zapiše migraciju kao neuspjelu. Od tog trenutka svaka sljedeća nadogradnja odbija da primijeni bilo šta, uključujući migracije poslije te - pa server ostaje na staroj verziji, a dugme za nadogradnju u konzoli to ne može popraviti; treba neko na serveru s Prisma alatom. Dvije migracije u ovom repozitoriju već imaju taj oblik. Aplikacija se sada zaustavlja prije migracija, a provjera pred puštanje pazi da tako i ostane.

      0.38.8

      8. septembar 2026.

      Popravljeno

      • Isti mjesec se više ne može fakturisati dvaput. Kad se draft upiše pa odmah poslije toga pukne upis koji samo bilježi koji je draft nastao, stara obrada je vraćala mjesec kao nenaplaćen - a faktura je već postojala. Sutra ujutru bi posao podigao drugi identičan draft za isti mjesec: dvije kirije za oktobar, dva broja potrošena iz serije, i 1.300,00 KM traženo od stanara koji duguje 650,00. Vraćanje mjeseca sada pokriva samo upis fakture; sve poslije toga je bilježenje nečega što se već desilo.
      • Raspored se više ne može trajno zaustaviti. Mjesec se zauzimao jednim upisom, a datum sljedećeg pokretanja pomjerao drugim, i proces koji umre između njih - novi deploy, OOM, restart mašine - ostavljao je red u jedinom stanju iz kojeg nema izlaza: zauzeti mjesec je tačno mjesec datuma koji se nije pomjerio, a oba testa koja odlučuju hoće li se raspored pokrenuti porede baš to dvoje. Raspored ostaje aktivan, posao ga čita svako jutro i ne podiže ništa. Stanodavcu kirija prosto prestane da se fakturiše, bez ijedne greške, a ni "pokreni sada" ga ne može oživjeti: vrati 200 i broj prošlomjesečne fakture. Datum se sada pomjera istim upisom kojim se mjesec zauzima.
      • Jedna faktura može imati samo jedan živi raspored, i to sada čuva baza. Provjera je bila čitanje pa upis, bez brave i bez indeksa iza sebe, pa su dva zahtjeva dovoljno blizu jedan drugom oba prošla: dvoklik koji prestigne ponovno iscrtavanje, dva menadžera na istom nalogu, ili integracija koja ponovi zahtjev čiji je odgovor izgubljen. Rezultat je dva rasporeda na istoj fakturi, svaki sa svojim zauzimanjem mjeseca, pa se svakog mjeseca podižu dva identična drafta za istog kupca - zauvijek, i ništa u proizvodu to ne označava. Zaustavljanje rasporeda oslobađa fakturu, pa se može ponovo pokrenuti.
      • Raspored napravljen 29., 30. ili 31. više ne gubi svoj dan. Prvi termin se namjerno skraćuje na dužinu mjeseca - 31. pada na 28. u februaru - ali se dan sidra čitao nazad s tog skraćenog datuma i tako trajno upisivao. Stanodavac koji 31. januara pritisne ponavljanje dobio bi raspored sidren na 28., pa bi se kirija podizala 28. marta, aprila i maja do kraja najma. Skraćivanje traje jedan mjesec, ne cijelu knjigu.

      0.38.7

      8. septembar 2026.

      Popravljeno

      • Jedna uplata koja je račun podigla dvaput. Kad je jedan transfer stigao s viškom, matcher prvo namiri račun pa odmah kaže za koliko je preko: dva poteza za jedan novac. Oba su knjižila na sto, pa je sto pisao da je naplaćeno duplo više nego što je stiglo. Na kodu za dio računa gosti koji još sjede dobiju manji dio nego što duguju i veče se zatvori kraće za tačno jedan dio, bez ijednog traga na ekranu. Na kodu za cijeli račun prvi transfer zatvori sto, pa drugi padne na zatvoren sto i obilježi ga kao vjerovatno plaćen dvaput: optužba protiv gosta koji je platio jednom. Knjiži se sada na ulasku u namireno, ne na svakom potezu unutar njega.
      • Uplata koja nije upisana više se ne prijavljuje kao uparena. Kad dvije uplate za isti račun stignu istovremeno, druga se odbija jer je iznos iz kojeg je računata u međuvremenu promijenjen - i njen novac nije upisan nigdje. To se javljalo istom riječju kojom se javlja i "račun je već namiren" i "potez nije dozvoljen", a obje te riječi znače da se može dalje. Obje grane matchera su tako i radile: obilježile bi izvod kao uparen s računom koji tu uplatu nikad nije primio. Novac je u banci, nije ni na jednoj pločici, manjka u knjigovodstvenom fajlu, a iz reda za uparivanje je ispao jer piše da je uparen. Niko u lokalu ga ne može naći.
      • Otkazivanje koda ne odbacuje novac koji je stigao. Dugme kojim konobar obara kodove sa stola pobroji žive kodove pa ih otkazuje jedan po jedan, i uplata koja stigne između popisa i otkazivanja bila je otkazana zajedno s kodom. Otkazan račun je van kandidata za uparivanje, van onoga što sto računa kao zauzeto i van onoga što se može vratiti, a sto nikad nije knjižen - pa konobar naplati cijeli račun u gotovini stolu koji je već poslao dio, i ništa u proizvodu taj dio ne može vidjeti, prikačiti ni vratiti. Pravilo je sada na samim vratima kroz koja svaka promjena statusa prolazi, i čita se unutar iste transakcije.
      • Provjera da kodovi ne premašuju račun sada čita stanje pod bravom. Ponovo je brojala žive kodove pod bravom, ali ih je poredila s iznosom pročitanim prije nego što je kod uopšte napravljen - a upravo se to i mijenja u tom prozoru. Sto od 20,00 KM gdje šank otkaže rundu od 8,00 dok se kod pravi: račun padne na 12,00, a gost dobije QR na 20,00. Uplata se poklopi s kodom u fening pa se namiri kao plaćeno, bez slučaja i bez obavijesti, i lokal zadrži 8,00 KM koje niko nije dugovao.

      0.38.6

      8. septembar 2026.

      Interno

      • CI se sada vrti ovdje, po koracima pročitanim iz same CI datoteke. GitHub od 7. septembra ne pokreće nijedan posao na ovom repozitoriju. Svako pokretanje završi za dvije sekunde, bez ijednog koraka, s jednom jedinom porukom: posao nije pokrenut jer plaćanje na računu nije prošlo ili treba podići limit potrošnje. Nije riječ o grešci u kodu. Provjereno je svih dvadeset zadnjih crvenih pokretanja i sva nose tu istu poruku i nijednu drugu. Ali kvačica pored svakog commita je crvena, a na push se ne provjerava ništa.

      0.38.5

      8. septembar 2026.

      Interno

      • Provjera da image nosi ono što kod traži. Dva posla u CI-ju koja grade image i dižu produkcijski stack ne rade od 7. septembra, jer ih GitHub ne pokreće dok se ne riješi naplata, a Docker na razvojnoj mašini ne radi. Klasa greške koju ti poslovi hvataju - kod koji u radu poseže za putanjom koje u imageu nema - trenutno se nije hvatala nigdje. To je ovaj projekat već jednom koštalo, u drugom smjeru: devetnaest fotografija jela upisanih u stablo iz kojeg server ne servira, nevidljivo u svim setovima jer su se obje polovine testa slagale oko toga koji je to direktorij.

      0.38.4

      8. septembar 2026.

      Popravljeno

      • Sto sa izdatim kodom izgledao je isto kao svaki drugi otvoreni račun. Broj živih kodova stoji u odgovoru otkad je popravljeno da podijeljeni kod ne blokira naplatu gotovinom, a ekran ga je koristio samo da odluči hoće li nacrtati dugme - pa je sto sa tri izdata koda izgledao kao bilo koji drugi, uz jedno dugme više. Iznos koji ti kodovi drže vraćao se i nije ga koristio niko. Sada red piše koliko je kodova izdato i na koliko, prije nego što konobar krene do stola, a ne poslije.
      • Iznos je izlazio u feningima. Prvi ekran koji ga je prikazao proveo ga je kroz isti formatter kao ostatak reda, koji očekuje decimalni zapis, pa je konobaru pisalo da je 6,50 KM računa na tuđem telefonu kao 650,00 KM. Novac sada izlazi iz servisa već ispisan, kao i svaki drugi iznos u tom redu.

      0.38.3

      8. septembar 2026.

      Popravljeno

      • Zanemarena uplata je sa svakog ekrana i dalje bila izgubljena zauvijek. Ruta koja izlistava zanemarene i ruta koja ih vraća u red napravljene su prije nekoliko sedmica, i na ploči je pisalo da je rupa zatvorena. Konzola nijednu nije koristila: zanemarivalo se jednim klikom bez pitanja, nije bilo gdje pogledati šta je odloženo, i nije bilo dugmeta za povratak. Tri prevoda koja je taj isti commit dodao stajala su neiskorištena. Sada se pita prije, sa iznosom u pitanju, postoji prekidač „Zanemarene" i svaki takav red ima „Vrati u red".

      0.38.2

      8. septembar 2026.

      Popravljeno

      • „Ponovi isto" nije postojalo na telefonu gosta. Ruta, servis i oznaka po narudžbi koja kaže može li se runda vjerno ponoviti postojali su sedmicama, i na ploči je stajalo da je gotovo. Telefon dugme nikada nije prikazao, pa nijedan gost nikad nije mogao ponoviti ništa: prevod „Ponovi isto" je stajao u oba kataloga i niko ga nije tražio. Sada stoji ispod svake runde koju je taj telefon naručio, i samo kada server kaže da se može ponoviti vjerno: ako je jelo u međuvremenu skinuto sa menija, dugmeta nema, jer je u bučnom lokalu gore pritisnuti dugme koje odbije nego ga ne vidjeti.
      • Runda se ponovo cijeni po trenutnom cjenovniku, ne prepisuje: kafa koja je poskupila između dvije ture naplaćuje se po onome što košta sada.

      0.38.1

      8. septembar 2026.

      Dodano

      • Ekran za ponavljajuće račune, na listi faktura. Panel iznad liste pokazuje koje se fakture same podižu, koliko često, kada je sljedeća i koji je nacrt podignut zadnji put; zaustavljeni ostaju u listi, sivi, sa datumom umjesto dugmeta. Ponavljanje se uključuje sa same fakture, jer je ona predložak: tako postoji jedno mjesto na kojem je račun opisan umjesto druge forme koja se vremenom razmimoiđe sa njom. Panel se ne prikazuje lokalima koji nemaju šta ponavljati.

      0.38.0

      8. septembar 2026.

      Dodano

      • Račun koji se sam ponavlja, mjesec za mjesecom. Dugme „ponovi" je skinulo prekucavanje i ostavilo pamćenje: neko je i dalje morao znati da je prvi u mjesecu. Za stanodavca sa devet stanova to je bio cijeli posao. Sada se izabere jedna faktura, kaže se koliko često - mjesečno, kvartalno ili godišnje - i od kojeg datuma, a posao svako jutro podigne kopiju.
      • Ono što podigne je nacrt, nikad izdata faktura. Izdavanje uzima broj iz vlastite serije dokumenata i može poslati račun kupcu, a nijedno od toga nije stvar koju treba raditi dok niko ne gleda: pogrešan iznos izdat u četiri ujutro mora se poništiti, a broj ostaje potrošen. Nacrt čeka na ekranu i neko pritisne „Izdaj".
      • Datum se ne pomjera. Raspored zakačen za 31. sleti na zadnji dan februara i vrati se na 31. u martu, umjesto da se povuče na 28. i tu ostane do kraja najma. Kvartal je tri mjeseca a ne devedeset dana, i sve se računa po ponoći u vremenu lokala, ne po UTC-u.
      • Isti mjesec se ne može obračunati dvaput. Posao ide svaki dan, pa bi raspored koji kasni jedan dan inače podizao račun svako jutro dok neko ne primijeti da stanar ima četiri fakture za oktobar. Mjesec se zauzme prije nego što se račun napiše, uslovnim upisom, pa ni dvije instance ne mogu uzeti isti. Ako pisanje ne uspije, zauzeće se vraća da bi sutra bio novi pokušaj.
      • Može se podići i ranije, ali samo jedan mjesec unaprijed, za stanodavca koji hoće oktobarsku kiriju na stolu u septembru. Drugi pritisak se odbija i kaže kada je sljedeći na redu.
      • Zaustavljanje se pamti. Raspored se ne briše nego se gasi, sa tim ko ga je ugasio i kada: „zašto se kirija prestala fakturisati u martu" je pitanje koje neko postavi u junu.

      0.37.33

      8. septembar 2026.

      Dodano

      • Dugme za PDF pored dugmeta za CSV, na ekranu Plaćanja. Isti mjesec, isti redovi, dva oblika: CSV se uvozi u knjigovodstveni program, PDF se odlaže u registrator. Koji od ta dva neko želi nije nešto što ovaj ekran može znati, pa se nude oba umjesto da se pogađa.

      0.37.32

      8. septembar 2026.

      Popravljeno

      • Faktura duža od jedne stranice imala je praznu stranicu iza svake pune. Broj stranice se ispisuje ispod donje margine, a PDF alat za svaki tekst ispod margine otvori novu stranicu. Numerisanje je tako dodavalo praznu stranicu za svaku koju je numerisalo: faktura od dvije stranice odlazila je kupcu kao četiri, svaka druga prazna. Ništa nije prijavljivalo grešku, a jedina provjera koja je postojala tražila je "više od jedne stranice", što je i ovako bilo tačno.

      Dodano

      • Pregled naplaćenog kao PDF, uz postojeći CSV. Knjigovođa uvozi CSV a u registrator odlaže papir, pa sada postoji i papir: isti redovi, isti redoslijed, ista zaglavlja, položeno na A4 jer izvještaj ima petnaest kolona i nijedna nije višak. Zaglavlje tabele se ponavlja na svakoj stranici, a na kraju stoji zbir kolone Uplaćeno, koji se može provjeriti sabiranjem same stranice. Oba dokumenta se prave iz istog čitanja podataka, jer bi dva odvojena upita vremenom počela odgovarati na malo različita pitanja i lokal bi ostao da bira kojem svom dokumentu da vjeruje. Ni ovdje se ništa ne odbija i ni ovdje to nije bankovni izvod, isto kao u CSV-u.

      0.37.31

      8. septembar 2026.

      Popravljeno

      • Kada neko za stolom plati jednu od dvije kafe, onome ko ih je naručio je pisalo da ne duguje ništa. Iznos "moje" na telefonu preskakao je svaku stavku za koju je bilo ko držao kod. To je bilo tačno dok je zahtjev išao na cijelu stavku, i pogrešno od trenutka kada je postao broj komada: jedna plaćena kafa je izbacila obje iz iznosa. Gost koji ih je naručio vidio je 0,00, platio to, i sto je otišao kući kraći za dvije i po marke sa stavkom koja je i dalje na računu. Sada se broji ono što je ostalo, po komadu.
      • Poništena faktura je pisala "Poništeno: Poništeno iz dashboarda". Konzola je slala razlog kao konstantu, pa je svako poništenje ikad zabilježeno reklo istu stvar, a ekran ga je ispisivao kroz "Poništeno: {razlog}". Sada se pita zašto, prije nego što se išta uradi: broj fakture ostaje zauzet, kod za plaćanje se gasi i to se ne može vratiti, pa pitanje ide uz potvrdu uplate kao stvar oko koje se ne prolazi jednim klikom. Knjigovođa koji pita zašto je faktura povučena sada ima odgovor na samoj fakturi.

      0.37.30

      8. septembar 2026.

      Popravljeno

      • U noći kada se sat pomjeri unazad svaki sto je pokazivao upola manje računa dnevno. Posljednja nedjelja u oktobru u Sarajevu traje dvadeset pet sati: sat ide unazad u tri ujutro i lokal prođe kroz dva sata dvaput. Kolona "Računa dnevno" dijelila je proteklo vrijeme sa dvadeset četiri sata i zaokruživala naviše, pa je ta jedna subota ispala dva dana i svaki sto na najjačoj noći jeseni pokazao polovinu onoga što je stvarno okrenuo. Mjesec koji sadrži pomjeranje dijelio se sa trideset jedan umjesto trideset, što je tiše i jednako pogrešno. Sada se broje kalendarski dani u vremenu lokala.
      • Grafikon prometa je crtan po satu lokala a označavan po satu preglednika. Server siječe stupce po danu lokala, upravo zato da promet petka uveče ne pripadne četvrtku, a oblačić iznad tačke je vrijeme ispisivao bez ijedne zone, pa je čitao onu na kojoj je mašina. Na laptopu u lokalu se to poklapa i greška se ne vidi; vlasnik koji gleda iz Minhena vidio je svaki stupac pomjeren za sat, a sa mašine ostavljene na UTC za dva.
      • Na mjesečnom grafikonu je oblačić pisao 00:00 za svaku tačku. Stupac širok jedan dan i dalje se ispisivao kao sat i minuta, pa oblačić nije govorio ništa što iznos iznad njega već nije rekao. Sada piše datum.
      • Broj uplata u oblačiću je bio u istom obliku za sve brojeve. Obje grane su bile ista riječ, pa su jedna uplata i dvije uplate izgledale isto, u jeziku koji to ne kaže tako.

      0.37.29

      8. septembar 2026.

      Popravljeno

      • Dva telefona koja u istoj sekundi označe istu stavku dobijala su oba svoj kod. Plaćanje odabranih stavki radi se u dva koraka koja nisu jedan: prvo se pročita šta drugi kodovi već drže, pa se onda kod napravi. Provjera poslije toga gledala je samo iznos, a iznos ne odgovara na pitanje o stavkama: dvije kafe od 3,00 KM na računu od 33,00 daju 6,00, što je uredno ispod računa, pa su oba koda ostala živa. Jedna kafa je plaćena dvaput, biftek koji niko nije uzeo ostao je neplaćen, a račun je pokazivao 6,00 od 33,00 bez ijedne stavke na koju se može pokazati. Sada se i stavke provjeravaju, pod istom bravom, i kod koji je prešao preko onoga što sto ima povlači se prije nego što ga gost uopšte vidi.
      • Povrati se nisu vidjeli u fajlu za knjigovođu. Puni povrat je bar prebacivao račun u status vraćenog. Djelimični nije: 20,00 vraćeno na račun od 80,00 ostavljalo je red koji piše 80,00 i ništa drugo nigdje, pa je knjigovođa knjižio osamdeset maraka prihoda na šezdeset maraka novca, dok je pločica prometa u konzoli povrate oduzimala sedmicama. Povrat sada ima svoj red, negativan, sa datumom dana kada je novac vraćen a ne dana računa na koji se odnosi, pa račun iz prošlog mjeseca vraćen ovog mjeseca ulazi u ovaj fajl.
      • Negativan iznos u fajlu se otvarao kao tekst. Zaštita koja sprječava da ime jela pokrene formulu u Excelu stavljala je apostrof ispred svega što počinje minusom. Dok u fajlu nije bilo negativnih iznosa to nije smetalo; sada bi značilo da kolona koju knjigovođa sabere pokupi novac koji je ušao a preskoči onaj koji je vraćen. Običan broj prolazi bez apostrofa, sve ostalo i dalje ne prolazi.

      0.37.28

      8. septembar 2026.

      Popravljeno

      • Promet po stolu je brojao stolove koji još sjede i one koji su otišli bez plaćanja. Kolona je sabirala cijeli račun svakog stola na kojem je nešto naručeno, bez obzira na to da li je novac stigao. Sto koji je u pola jedanaest još uvijek zauzet, sa četiri hoda na računu, ulazio je punim iznosom, pa je izgledao najbolje dok gosti još biraju desert i padao kada plate. Sto koji je otišao bez plaćanja brojao se cijeli, tako da je jedini broj koji je trebao pasti dizao taj sto u poretku onih koji zarađuju. Sada se broji novac koji je stvarno stigao. Prosječan račun se računa po zatvorenim računima, jer račun koji još traje nema konačan iznos, a računi koji nisu plaćeni ostaju u prosjeku, jer je račun bio stvaran i kada novac nije stigao.
      • Pločica koja pokazuje da li banka sama potvrđuje uplate mjerila je nešto drugo. U imenilac je ulazio svaki izdati kod, pa je gost koji odabere plaćanje telefonom, predomisli se i plati gotovinom obarao broj: lokal kod kojeg je svaka uplata stigla i bila potvrđena i dalje je čitao 62,9 posto, a pločica je stajala žuta. U brojnik je ulazio svaki plaćen račun, uključujući i one koje je neko ručno potvrdio gledajući u bankovnu aplikaciju, a to je upravo ono što banka nije potvrdila: što je veza lošija, to je osoblje više radilo, a broj se manje micao. Sada se računa udio uplata koje je banka potvrdila sama, kodovi koje niko nije platio imaju svoj broj jer su problem za stolom a ne u banci, a pločica piše "Automatska potvrda".
      • Vrijeme potvrde je znalo biti negativno. Novac uplaćen direktno na naljepnicu sa stola nema račun koji ga čeka: račun se kreira kada uplata bude pročitana, a nosi vrijeme kada ga je banka proknjižila, dakle ranije. Oduzimanje je išlo unazad, pa je kafić koji većinu novca prima preko naljepnica čitao potvrdu koja je trajala minus jedan dan. Takve uplate nemaju vrijeme potvrde i više se ne mjere, a pločica kaže na koliko računa je mjerena.
      • Pregled zdravlja naplate je pratio dužinu izabranog perioda, ali ne i to gdje se nalazi. Konzola je slala samo broj dana, pa je izbor prošlog mjeseca značio zadnjih 31 dan do danas, što je gore od sedmice koja je prije toga bila fiksna, jer izgleda kao da prati izbor. Sada se šalju isti datumi kojima se čita sve ostalo na ekranu.

      0.37.27

      8. septembar 2026.

      Popravljeno

      • Gotovina naplaćena prije uvođenja jedne kolone brojala se kao nula. Kolona bilježi koliko je konobar uzeo za stolom, a čitanje je za starije račune trebalo uzeti ukupan iznos. To je napisano kao zbir cijele grupe, a SQL zbir preskoči prazne vrijednosti i vrati prazno samo ako su baš svi redovi prazni. Čim je u periodu postojao jedan noviji račun, zamjena se nije primjenjivala i svaki stariji je vrijedio nula. Lokal koji je u sedmici prije nadogradnje zatvorio 120 računa gotovinom, i jedan poslije nje, tih 120 nije vidio nigdje na prometu. Stare vrijednosti su dopunjene, kolona više ne može biti prazna, i dvosmislenog čitanja više nema.

      0.37.26

      8. septembar 2026.

      Popravljeno

      • Sto zatvoren gotovinom vraćao se na spisak otvorenih ako gost u istoj sekundi odustane od koda. Kada gost napusti ekran za plaćanje, sistem poništi kodove i vrati sto u otvoreno stanje, ali je odluku donosio na osnovu stanja pročitanog prije toga. Konobar koji u tom trenutku naplati gotovinu bio je nevidljiv: sto se vraćao kao otvoren, sa vremenom zatvaranja i naplaćenim iznosom koji su ostali na njemu. Takav sto se prikazuje na podu, telefoni mu se mogu pridružiti i narudžbe se primaju, pa lokal posluži još jednu rundu na račun koji je već naplaćen.
      • Isto i u drugom smjeru: gost koji zatraži plaćanje dok konobar naplaćuje gotovinu ostavljao je zatvoren sto na kuhinjskom ekranu, u redu „želi platiti“, dok ga neko ne zatvori po drugi put.
      • Uplata koja stigne u trenutku zatvaranja podizala je iznos na zatvorenom stolu, bez ijednog traga. Provjera je gledala stanje pročitano ranije, pa je uplata koja izgubi tu utrku povećala naplaćeni iznos i tišina. Nije se upisala oznaka na uplatu, nije bilo unosa u dnevnik ni upozorenja, a upravo to su tri stvari po kojima se dvostruka uplata uopšte može pronaći. Gost je bez novca dok neko ne pogleda.

      0.37.25

      8. septembar 2026.

      Popravljeno

      • Grafikon prometa crtao je samo uplate preko banke. Čitao je isključivo tabelu uplata, a naplata gotovinom ili na vlastitom POS terminalu upisuje se na sto i ne pravi uplatu. Ispod naslova „naplaćeno po satu“ stajala je kriva koja pokazuje koliko je gostiju poseglo za telefonom. Kafić koji u petak uzme 4.000 KM, od toga 2.800 u gotovini, dobio je krivu koja zbraja 1.200. Vlasnik koji poredi dva petka poredio je proširenost QR-a, ne promet. Sada grafikon broji i gotovinu i oduzima povrate, pa daje isti iznos kao pločica iznad njega.
      • Grafikon nije poštovao lokal kojem korisnik pripada. Upit je pisan direktno u SQL-u, koji ne može preuzeti Prisma filter, pa nije primjenjivao nikakvo ograničenje: osoblje vezano za jednu poslovnicu vidjelo je krivu cijelog lanca, dok je svaka druga brojka oko nje bila ograničena na njihovu poslovnicu.
      • Prozor grafikona bio je pomjeren za dva sata. Kolona sa vremenom čuva UTC zidni sat bez oznake zone, a sirovi upit ju je poređivao sa vezanim parametrom koji nosi zonu, pa je Postgres jedno pretvarao u drugo prije poređenja. Uplate pri rubu dana ispadale su iz grafikona iako su na svim ostalim brojkama tu. Nađeno tako što se grafikon i pločica nisu slagali ni nakon prve popravke.

      0.37.24

      8. septembar 2026.

      Dodano

      • Odštampan kod za sto sada se može povući, i vratiti u upotrebu. Mogućnost je postojala u API-ju otkad je modul napisan, gdje limit plana broji samo aktivne stolove i naziv se oslobodi tek kad se red povuče, a nijedan ekran je nije zvao. Spisak stolova je sa svakog ekrana bio samo za dodavanje. Lokal koji na dan pilota odštampa dvadeset kodova sa pogrešnim prefiksom nije imao šta da uradi: kodovi ostaju živi, troše dozvoljeni broj stolova, a naljepnica je jedina stvar kojom gost otvara račun. Sada red ima dugme, pita prije nego što povuče, i povučeni sto ostaje na spisku sa oznakom i dugmetom za povratak.

      0.37.23

      8. septembar 2026.

      Popravljeno

      • „Zanemari uplatu“ je bila konačna, bez pitanja i bez povratka. Zanemarena uplata je dobijala oznaku koju nijedan spisak nije prikazivao i nijedna ruta nije poništavala: stvarna uplata koja je stigla u banku nestajala je sa svakog ekrana i iz svakog odgovora, zauvijek. Dugme je stajalo pored „Zakači“, koje je isključeno dok se ne izabere račun, pa je na običnom redu bilo jedino što se moglo pritisnuti. Sada pita prije nego što uradi, postoji spisak zanemarenih i dugme koje ih vraća u red.

      0.37.22

      8. septembar 2026.

      Popravljeno

      • Kod za podijeljen račun blokirao je naplatu gotovine, a dugme iz poruke nije bilo na ekranu. Kada gosti dijele račun ili plaćaju svoje stavke, sto ostaje otvoren, jer samo kod za cijeli račun mijenja stanje stola. Spisak otvorenih računa nije nosio nikakvu informaciju o kodovima, a dugme „otkaži kod“ prikazivalo se prema stanju stola. Sto sa tri aktivna koda izgledao je kao svaki drugi otvoren sto: naplata gotovine je odbijena porukom „prvo otkažite kod“, a to dugme nije bilo nigdje. Jedino dugme koje nije odbijeno je „naplaćeno prenosom“, pa je gotovina iz konobarove ruke završavala zavedena kao bankovna uplata koja nikada nije stigla. Sada spisak kaže koliko je kodova aktivno, a dugme se pojavljuje kad ih ima.

      0.37.21

      8. septembar 2026.

      Popravljeno

      • Računi zatvoreni poslije ponoći naplaćivali su se u pogrešan mjesec. Mjesec po kojem se broji promet računao se u UTC-u, pa je za Sarajevo ljeti trajao od prvog u 02:00 do prvog idućeg u 01:59. Bar koji radi poslije ponoći zatvori zadnje račune 30. septembra između 00:10 i 01:40 prvog oktobra, i ti računi su ulazili u septembar: i na ekranu gdje lokal gleda svoju potrošnju, i na računu koji noćni obračun izda. Svaka druga granica dana u proizvodu je odavno bila po vremenu lokala; ova, koja odlučuje o novcu, nije. Sada jeste.
      • Faktura izdata poslije ponoći na Novu godinu dobijala je broj iz stare godine. Datum na dokumentu se piše po vremenu lokala, a godina u broju fakture uzimala se iz sata servera, koji radi u UTC-u. Ugostitelj koji izda fakturu u 00:30 prvog januara dobio je dokument sa datumom 01.01.2027. i brojem 418/2026, koji nastavlja zatvorenu godinu, a sljedeća faktura tog jutra dobila je broj 1/2027. Ostaje dokument iz jedne godine numerisan u drugu i serija sa jednim unosom više nego što knjige pokazuju.

      0.37.20

      8. septembar 2026.

      Popravljeno

      • Kasa na šanku je tvrdila da novac nije stigao, i prestajala gledati. Kada kod istekne, matcher još sat vremena prima uplatu koja je iz gostove banke krenula na vrijeme. Kasa je u tom trenutku pisala „Novac nije stigao“ i prestajala pitati server, pa uplata poslana nekoliko sekundi prije isteka nikada nije stigla na ekran. Konobarski terminal je namjerno napravljen suprotno i nastavlja gledati. Sada i kasa nastavlja, a tekst kaže ono što se zna: kod se više ne može platiti, a ako je gost poslao uplatu, još može stići.
      • Poruka je gosta slala da traži nešto što nijedan ekran ne može. Kada je za stolom previše telefona, pisalo je „Pozovite osoblje da vas doda“, a nigdje u proizvodu ne postoji dugme koje dodaje telefon na otvoren račun. Konobar dođe i nema šta da uradi. Sada piše šta se stvarno može: sačekati da neko završi, ili zamoliti osoblje da naruči.
      • Poruka o fakturama upućivala je na postavku koje nema. Pisala je da se „promijeni tip billera u postavkama lokacije“, a to je izraz iz baze i takve postavke nema ni na jednom ekranu koji lokal može otvoriti.
      • Brojevi na ekranu sa stolovima nisu bili u pravom padežu. Pisalo je „1 narudžbi“ i „3 narudžbi“, i „2 od 4 stolova zauzeto“. Ekran sa narudžbama je isti podatak oduvijek pisao ispravno. Sada je i ovdje: 1 narudžba, 3 narudžbe, 8 narudžbi, i 2 od 4 stola.

      0.37.19

      8. septembar 2026.

      Popravljeno

      • Izvoz za knjigovodstvo nije se sortirao po vlastitoj koloni datuma. Redovi se biraju i ređaju po danu kada je račun izdat, a kolona „Datum“ je pisala trenutak kada je priliv obrađen, a to je kod izvoda koji se učitava ručno jutro nekoliko dana kasnije. Račun naplaćen 31. avgusta u 21:40 završio je u avgustovskom fajlu sa datumom 1. septembra, a u septembarskom ga nije bilo uopšte. Knjigovođa koji knjiži po toj koloni upiše septembarski datum u avgustovsku knjigu i za njega ne nađe ništa u septembru. Sada je „Datum“ dan izdavanja računa, isti po kojem se fajl bira i sortira, a kada je novac stigao dobilo je svoju kolonu „Datum priliva“, iz datuma knjiženja same banke, koji se ranije nije čitao nigdje.
      • Povrat se oduzimao od dana kada je račun izdat, a ne od dana kada je vraćen. Obje stavke o povratima filtrirale su se po datumu računa i nikada po datumu samog povrata. Menadžer koji u ponedjeljak vrati 50,00 na subotnji račun mijenjao je subotu: dan koji je vlasnik već zapisao pao je za pedeset, sa objašnjenjem koje se pojavilo naknadno, dok ponedjeljak, dan kada je kasa stvarno bila kraća, nije pokazivao ništa.

      0.37.18

      7. septembar 2026.

      Popravljeno

      • Uplata koja nije tačna u fening nije bila ni na jednoj pločici. Gost koji u banci upiše 45,00 umjesto 50,00 ostavlja račun u stanju „plaćeno manje“, a ko zaokruži naviše u „plaćeno više“. Oba znače da je novac na računu lokala, a nijedno se nije brojalo: ni u promet, ni u čekanje, ni u neuspjele. Račun nije bio nigdje, dok ga je izvoz za knjigovodstvo za isti period uredno navodio, pa se konzola i izvoz nisu slagali za iznos svake takve uplate. Sada se broji ono što je stiglo, i posebno se prikazuje koliko je takvih uplata, jer iza svake stoji slučaj za uparivanje i neko kome se vraća ili ko još duguje.
      • Pregled po poslovnici nije se slagao sa pločicom iznad njega. Brojao je samo tačno plaćene račune u punom iznosu: bez uplata koje nisu tačne, bez oduzetih povrata i bez gotovine. Lokal sa jednom poslovnicom koji je vratio jedno jelo čitao je 900,00 u prometu i 1.000,00 u redu za istu poslovnicu istog dana, dva panela jedan ispod drugog. Lanac čiji najprometniji lokal naplaćuje uglavnom gotovinom vidio je taj lokal na dnu liste. Sada se sve tri stvari broje po sobi.

      0.37.17

      7. septembar 2026.

      Popravljeno

      • Kod koji je istekao držao je sto sat i po bez mogućnosti plaćanja preko QR-a. Istekli kod još sat vremena čuva svoj dio računa, da bi uplata koja je već krenula imala gdje stići. Kod za cijeli račun čuva cijeli račun, pa nakon isteka sto nije mogao platiti ništa preko koda: ni cijeli račun, ni podjelu, ni svoje stavke. Ništa to nije moglo osloboditi, jer poništavanje nije bilo dozvoljen potez iz stanja „isteklo“: ni konobarevo dugme, ni gost, ni API. Sedamdeset pet minuta gotovine ili čekanja, usred smjene. Sada konobarevo dugme skida i istekle kodove.
      • Poništavanje koda sada ostavlja trag. Pisalo se pravo u red, bez zapisa o promjeni stanja, bez unosa u dnevnik i bez poruke prema kasi. Kasa koja zatvara račun na poruku o poništenju nikada nije saznala da je gost odustao, a ko kasnije pogleda taj račun nije mogao vidjeti ko ga je i kada završio.

      0.37.16

      7. septembar 2026.

      Popravljeno

      • Ekran u kuhinji je znao zaćutati do kraja smjene poslije prekida veze. Prijava za živi kanal traje petnaest minuta, a nova se traži prekasno da stigne u pokušaj koji je već krenuo. Server odbije istekli token, a ekran je na to gasio vezu zauvijek, iako je svježa prijava ležala spremna pored njega. Sada se poslije odbijanja jednom uzme nova prijava i pokuša ponovo. Ako i ona bude odbijena, neko se odjavio ili je uređaj odvezan, pa je odustajanje tačan odgovor.
      • Dva pritiska na „napravi QR“ pravila su dva računa. Ključ koji sprečava dupliranje uzimao se iz sata u trenutku slanja, pa je ponovni pokušaj dobijao drugi ključ. A ponovo se pritiska samo kad veza pukne, kada je prvi zahtjev već stigao do servera: gost je imao dva aktivna koda, a onaj koji ne skenira ostajao je otvoren u dnevnom pregledu. Sada ključ pripada prodaji, a ne pritisku, i mijenja se tek kada konobar promijeni iznos ili sto.

      0.37.15

      7. septembar 2026.

      Popravljeno

      • Gost je plaćao stari iznos kada se račun promijeni dok mu je kod otvoren. QR nosi iznos za koji je izdat i ne mijenja se. Šank javi da nema piva, konobar skine tu stavku, račun padne sa 20,00 na 12,00, a gost u banci šalje 20,00 koje se poklapaju sa kodom u fening. Uplata se zavodi kao tačna, ne kao višak, pa se ne otvara nijedan slučaj, ne šalje nijedna poruka i nigdje ne piše da lokal ima 8,00 KM koje gost nije dugovao. Sada se stavka ne može skinuti dok je kod aktivan: odbijanje se imenuje isto kao kod naplate gotovinom, a konobar prvo poništi kod, pa promijeni račun.

      0.37.14

      7. septembar 2026.

      Popravljeno

      • Kada konobar otkaže račun u istoj sekundi kada uplata legne, novac je nestajao iz evidencije. Svaka promjena stanja računa je čitala red, provjerila da li je potez dozvoljen, pa upisala samo po broju računa. Dva učesnika u istoj sekundi su oba prošla provjeru i oba upisala, a onaj koji je upisao drugi vratio je natrag i ono što nije njegovo: račun je završavao kao otkazan, bez uplaćenog iznosa i bez vremena plaćanja, dok je novac bio na računu lokala. Sada upis imenuje stanje na osnovu kojeg je odlučeno, pa gubitnik ne upiše ništa i pogleda ponovo. Isto važi i za dvije uplate koje stignu u istom trenutku.
      • Ako se pitanje izgubi, ekran više ne tvrdi da je račun otkazan. Kada otkazivanje ne prođe, tablet pita server šta je zaista bilo. To pitanje je i samo moglo propasti, jer ide istom vezom koja je upravo pukla, a ekran se tada vraćao na tastaturu kao da je sve u redu. Sada ostaje na QR kodu dok se ne sazna istina. Uz to, prepoznaje i „plaćeno više“ i „plaćeno manje“, ne samo tačan iznos.
      • Račun na koji je novac stigao ne može se više otkazati. Ako je gost platio dio, otkazivanje je uspijevalo i taj novac je ostajao na računu koji sistem više ne gleda, pa mu se ostatak uplate nikada nije mogao pripojiti. Sada se odbija i odbijanje se imenuje, a otpis razlike ostaje odluka koju čovjek donosi u konzoli sa iznosom pred sobom.
      • Uplata preko iznosa računa sada piše da je plaćeno više. Gost koji je platio dio, pa greškom pošalje cijeli iznos, ostavljao je račun u stanju „plaćeno“ sa više novca nego što je račun bio, i niko nije saznao da treba vratiti razliku.

      0.37.12

      7. septembar 2026.

      Popravljeno

      • Kasa na šanku nije vidjela uplatu koja nije bila tačna u fening. Prepoznavala je samo stanje „plaćeno“. Gost koji u banci zaokruži 19,90 na 20,00 ostavlja račun u stanju „plaćeno više“, a ko upiše manje u „plaćeno manje“, i nijedno nije stizalo do ekrana: kasa je zauvijek prikazivala isti QR dok je novac već bio na računu lokala. Sada piše da je stiglo, koliko je stiglo i koliki je bio račun, a kad kod istekne ili bude otkazan ekran to kaže umjesto da nudi QR koji se ne može platiti.
      • Kasa na šanku naplaćivala je punu cijenu dok je akcija trajala. Učitavala je meni onakav kakav se uređuje: cijene bez akcije i sve što je ugašeno. Za stolom dva metra dalje gost je u isto vrijeme dobijao sniženu cijenu, a jelo skinuto sa menija tog jutra i dalje se moglo prodati sa kase. Sada kasa učitava isti meni koji vidi gost, sa cijenom koju server naplaćuje.
      • Biblioteka za POS partnere: dvostruki račun i čekanje bez potrebe. Ako pozivalac ne pošalje broj računa, zahtjev je išao bez ključa jedinstvenosti, pa je ponovni pokušaj nakon prekida veze pravio drugi račun za istog gosta. Sada ključ uvijek postoji. Uz to, čekanje na uplatu nije priznavalo „plaćeno više“ i „plaćeno manje“, pa je držalo kasu do isteka od petnaest minuta na računu koji je odavno plaćen.

      0.37.11

      7. septembar 2026.

      Popravljeno

      • Izvod bez datuma knjiženja dobijao je datum uvoza. U camt izvodu datum knjiženja nije obavezan i ima banaka koje šalju samo datum valute. Čitanje je za sve što nedostaje upisivalo trenutni čas, i to kao tačno poznat trenutak. Ko u ponedjeljak učita petkov izvod dobio je sve uplate zavedene kao da su stigle u ponedjeljak ujutro, pa ih sistem nije mogao spojiti ni sa jednim računom: uparivanje gleda račune otvorene u zadnja dvadeset četiri sata prije uplate. Sada se uzima datum knjiženja, pa datum valute, pa datum kada je banka napravila izvod. Ako izvod ne kaže nijedan, stavka se preskoči i to piše u izvještaju o uvozu, umjesto da se datum izmisli.

      0.37.9

      7. septembar 2026.

      Popravljeno

      • Dio webhookova sa spiska nije slao niko. Na stranici o API-ju stoji spisak događaja na koje se sistem lokala može prijaviti, i taj spisak je obećavao više nego što je slato. order.placed i reconciliation.review_required išli su samo na ekrane u lokalu, a ne i pretplatnicima; payment.manually_confirmed i invoice.sent postoje samo kao zapis u dnevniku i ne šalju se nikome. Ko se prijavio čekao je zauvijek, bez greške i bez traga igdje. Prva dva se sada šalju, druga dva su skinuta sa spiska, a provjera u izgradnji od sada ne da spisku i stvarnosti da se raziđu.
      • Skinuti terminal.online i terminal.offline. Bili su navedeni kao događaji, a ništa ih nikada nije proizvodilo: uređaj ima vrijeme posljednjeg javljanja i niko ga ne prati. Ime na spisku je obećanje, pa ostaju vani dok iza njih ne bude nešto stvarno.

      0.37.8

      7. septembar 2026.

      Popravljeno

      • Račun je pisao DOSPJELO već na dan kada dospijeva. Rok plaćanja je dan, a ne trenutak: ko na računu piše „Rok plaćanja: 20. septembar“ ima cijeli dvadeseti. Datum unesen na ekranu čuva se kao početak tog dana, pa je račun prešao u dospjelo u ponoć tog istog dana i kupac je bio u kašnjenju prije nego što je banka i otvorila. Isto je bilo i na našim računima prema lokalima, koji dospijevaju petnaest dana od minute izdavanja. Sada račun postaje dospio tek kada cijeli dan roka prođe.

      0.37.7

      7. septembar 2026.

      Sigurnost

      • Ekran u kuhinji mogao je pratiti naplaćivanje, iako mu se novac ne pokazuje. Kada se ekran ili tablet spoji na živi kanal, dobije tačno ono što mu pripada: kuhinjski ekran vidi narudžbe, ne i iznose, a osoblje vezano za jedan lokal vidi samo taj lokal. Postojao je i drugi ulaz, kojim klijent naknadno traži jedan račun po broju, a on je provjeravao samo da li račun pripada istoj firmi. Time je kuhinjski ekran mogao pratiti iznos, napojnicu i poziv na broj, a konobar vezan za jedan lokal račun sa stola u drugom. Sada oba ulaza traže isto.

      0.37.6

      7. septembar 2026.

      Sigurnost

      • Naljepnica za sto mogla je biti uparena kao kasa. Stolovi se čuvaju kao uređaji vrste „naljepnica“, a naljepnica je papir: nema ekran, niko se na nju ne prijavljuje i ne ulazi u limit uređaja po lokalu. Ekran za dodavanje uređaja je ipak primao tu vrstu i za nju izdavao kod za uparivanje, a taj kod daje token koji smije naplatiti. Takav red se ne vidi na spisku uređaja, ne broji se u limit i „novi kod“ ga odbija, pa se token nije mogao ni vidjeti ni povući. Sada se naljepnica ne može ni napraviti kao uređaj ni upariti, a nadogradnja briše kodove i tokene koji su ranije možda izdati na naljepnice. Stolovi se i dalje prave sa ekrana za stolove, kao i do sada.

      0.37.5

      7. septembar 2026.

      Popravljeno

      • Gost koji zaokruži iznos naviše platio je, a kasa to nije saznala. Ko u banci pretvori 47,30 u 50,00 zatvorio je račun, ali takva uplata ide pravo u stanje „plaćeno više“ i nikada ne prođe kroz „plaćeno“. Konektor je slušao samo ovo drugo, pa kasi nije javio ništa: račun ostaje otvoren, a konobar traži od gosta koji je platio da plati ponovo. Isti propust bio je i u nadoknadi propuštenog nakon prekida veze. Sada se obje vrste uplate javljaju kasi, a u logu piše koliko je stiglo i koliko je dugovano, da se vidi šta treba vratiti.
      • Konektor je zaboravljao račune koji još nisu plaćeni. Spisak računa na koje se čeka jedino je što preživi pad interneta: bez njega uplata koja stigne dok veza ne radi nikad ne bude isporučena kasi. Taj spisak se čistio na svaku poruku sa servera, a četiri vrste poruka ne znače kraj računa: djelimična uplata, poruka da je račun tek napravljen, povrat i neuspjeh. Sada se račun skida sa spiska tek kada je naplaćen, istekao ili otkazan.

      0.37.4

      7. septembar 2026.

      Popravljeno

      • Godišnja pretplata se obračunavala kao da traje mjesec dana. Dodatak za ugostiteljstvo (49 KM po lokalu koji prima narudžbe za stolom) i broj uključenih transakcija cijene su po mjesecu, a račun ih je množio brojem perioda, a kod godišnje pretplate period je godina. Lokal koji plaća godišnje dobijao je jedan mjesec dodatka naplaćen za cijelu godinu i jedan mjesec uključenih transakcija da pokrije dvanaest: na istom računu manje naplaćeno na jednoj stavci, više na drugoj. Sada se sve što je cijena po mjesecu množi brojem mjeseci. Dogovoreni iznos licence ostaje kakav jeste, jer ta kolona znači koliko se naplaćuje po jednom periodu.

      0.37.3

      7. septembar 2026.

      Popravljeno

      • Dvoje gostiju za istim stolom, isti iznos, jedna uplata se gubila. Naljepnica ima trajni poziv na broj, pa svaka uplata za taj sto nosi isti. Kada banka ne pošalje svoj identifikator uplate, sistem je dvije uplate razlikovao po stolu, iznosu i trenutku knjiženja, a camt izvod smije dati samo datum bez vremena, i to ovdje šalju. „Isti trenutak" je time postalo „isti dan": drugi gost je pripojen prvome i njegov novac nije nigdje zaveden.

      0.37.2

      7. septembar 2026.

      Popravljeno

      • Kod za plaćanje na svakoj PDF fakturi bio je štampan magentom. Boja je zapisana sa osam cifara, jer biblioteka koja crta QR sliku prihvata i prozirnost. Biblioteka koja pravi PDF ne prihvata: od osam cifara pročita četiri broja i za ovu boju vrati crveni kanal jedanaest puta izvan opsega. QR se čita po kontrastu, pa to nije kozmetika - to je kod koji telefon možda pročita a možda ne, odštampan na dokumentu koji kupac čuva.
      • Djelimično plaćena faktura je u PDF-u i dalje nosila kod na puni iznos. Web stranica je to prestala raditi jutros, PDF nije - pa su dvije kopije istog računa tvrdile različit iznos, što je gore nego da nijedna nije popravljena. Odluka nosi li račun kod uopšte sada je na jednom mjestu i obje kopije je čitaju, pa se više ne mogu raziću.

      0.37.0

      7. septembar 2026.

      Dodano

      • Slučaj se sada može naći, ne samo prebrojati. Red za sravnjivanje ide od najstarijeg i staje na dvjesta - što je tačno kako se raščišćava zaostatak, i tačno pogrešno kad zazvoni telefon. Slučaj o kojem vas pitaju je onaj koji je stigao prije pet minuta, a iza dužeg reda nije ni na jednoj stranici koju neko otvori. Prošli put smo napisali koliko ih ima; to je reklo da postoji i ostavilo ga van domašaja.

      0.36.7

      7. septembar 2026.

      Popravljeno

      • Natpis ispod grafikona je uvijek pisao "po satu, danas". Grafikon crta po danu čim se izabere period duži od dva dana - i to je ispravno, jer bi po satu za mjesec dana bilo sedam stotina tačaka na crtici od dva centimetra. Ali natpis se nije mijenjao, pa je vlasnik koji pritisne "30 dana" gledao trideset dnevnih stubića ispod rečenice koja kaže "po satu, danas". Sada se širina stubića odlučuje na jednom mjestu i natpis čita to isto.
      • Spisak nepovezanih uplata se tiho sjekao na pedeset. Pregled broji sve i vodi na tu stranicu: poslije sedmice odsustva zdravstvena ćelija je pisala 63, stranica pokazivala 50, i nigdje ni riječi o preostalih trinaest. Ograničenje je u redu; ograničenje o kojem se ćuti je ekran koji tiho laže da je posao gotov. Sada piše "prikazano 50 od 63", isto kao što red slučajeva već radi.

      0.36.6

      7. septembar 2026.

      Popravljeno

      • Kuhinja i šank koji završe u istoj sekundi pojeli su jedno drugom upis. Tiket sa supom i pivom stoji otvoren dok obje stanice ne završe. Svaki ekran je pročitao spisak gotovih stanica, dodao sebe i upisao nazad - pa kad se pritisne u istoj sekundi, drugi upis obriše prvi. Tiket onda čeka stanicu koja je već završila i ne može nikad sići sa ploče: kartica stoji, niko ne zna zašto, i pritisne se ponovo. Supa i pivo u petak navečer nije izmišljen slučaj.

      0.36.5

      7. septembar 2026.

      Popravljeno

      • Djelimično plaćena faktura nudila je QR kod na puni iznos. Kod se pravi kad se faktura izda i nosi cijeli iznos. Plati se pola prenosom, i stranica je i dalje pokazivala taj kod pored linije na kojoj piše ostatak - pa bi kupac koji ga skenira dobio u svojoj banci opet cijeli iznos, sa tačnim brojem ispisanim šest centimetara dalje. Jedno od ta dva bi bilo vjerovano, i to ono koje telefon sam popuni. Sada kod nestane i piše zašto; račun, poziv na broj i iznos sa strane su ionako tačni i njih treba prepisati.
      • Odbijanje zbog nedostajućeg bankovnog računa sada se prepoznaje po oznaci. Konzola je to prepoznavala tražeći riječi "bank account" u engleskoj poruci servera. Server je slobodan tu rečenicu promijeniti, i onog dana kad je neko promijeni ekran bi pao na "nije uspjelo pravljenje kodova" - tačno, beskorisno, i vlasnik ne zna šta da uradi. Uz to se pokazivala i sirova engleska poruka u drugoj crvenoj traci iznad bosanske.

      0.36.4

      7. septembar 2026.

      Popravljeno

      • Konobarski terminal je javljao da je kod istekao dok je novac bio u banci. Ekran je slušao dva od sedam ishoda uplate, a dva koja je propuštao su baš ona koja znače da je prenos prošao: gost koji u svojoj banci zaokruži iznos naviše napravi uplatu veću od računa, a onaj ko otkuca manje - manju. Nijedna nije stizala do ekrana, pa bi odbrojavanje isteklo i konobar bi vidio "Kod je istekao" dok novac stoji na računu lokala. Onda gosta pita da plati ponovo.
      • Provjera se više ne prekida kad kod istekne. Kod prestaje biti skenirljiv kad mu prođe prozor, ali prenos poslan minut prije toga i dalje stigne i i dalje se poveže sa tim računom. Ekran je prestajao pitati baš u tom trenutku, pa je jedini prenos oko kojeg postoji sumnja bio i jedini koji nije mogao potvrditi.

      0.36.3

      7. septembar 2026.

      Popravljeno

      • Račun preko hiljadu maraka izdavao je kod na hiljaditi dio iznosa. Kada XPay čita račun sa trake printera - način koji koristi kasa koja ne zna ništa osim štampati - iznos se prepoznavao obrascem koji ne može preći hiljadicu. Na "UKUPNO: 1.234,56" se zaustavljao na prvoj tački i čitao 1,23. To je sasvim uredan iznos, pa ništa nije prijavilo grešku: kod je izdat na 1,23 KM, gost ga je platio, uplata se poklopila sa računom u fening, sistem ga zatvorio bez ijednog slučaja za pregled - a lokalu je falilo 1.233,33 KM dok je svaki ekran pisao da je plaćeno.

      0.36.2

      7. septembar 2026.

      Popravljeno

      • Promjena paketa je skraćivala licencu koju je neko platio. Ako operater promijeni paket a ne navede datum, rok je postajao mjesec dana od danas - pa je lokal plaćen do sljedećeg septembra ostajao sa licencom do idućeg mjeseca, bez ijedne riječi o tome. Sada se rok pomjera samo kada operater to izričito kaže, i nikad unazad: probni period pred istek i dalje dobije mjesec kad se nadogradi, a plaćena godina ostaje plaćena godina.
      • Licencni ključ je i dalje pisao stari paket. Ključ je potpisan i sam sebe opisuje, da bi program u lokalu mogao provjeriti šta smije raditi i kada internet ne radi - znači u sebi nosi paket i rok. Promjena paketa ih je mijenjala u bazi, a ključ ostavljala kakav je bio, pa je lokal prebačen na Business imao ključ koji kaže Starter, i svaka provjera bez interneta je primjenjivala paket sa kojeg je prešao. Sada se ključ izdaje ponovo.

      0.36.1

      7. septembar 2026.

      Popravljeno

      • Kasa u jednoj poslovnici mogla je pročitati bankovni račun druge. Tablet ili kasa uparena u jednom lokalu ima pravo da pročita podatke o firmi - treba joj za vlastitu poslovnicu - a dobijala je nazad sve poslovnice, sa računom, nazivom vlasnika računa i bankom. Ista ruta je jednom već stegnuta, protiv ekrana u kuhinji; da uređaj vezan za jednu poslovnicu vidi samo nju je druga polovina iste ideje. Za vlasnika i menadžera se ne mijenja ništa.
      • Brisanje PDV broja ili telefona je javljalo "Sačuvano" a ostavljalo staro. Prazno polje se slalo kao "ne diraj", pa je onaj ko je obrisao svoj PDV broj bio obaviješten da je sačuvano i našao ga na sljedećoj fakturi. Sada se prazno polje šalje kao izričito brisanje. Naziv firme se i dalje ne može obrisati - firma mora imati ime - nego samo promijeniti.

      0.36.0

      7. septembar 2026.

      Dodano

      • XPay sada zna prepoznati fiskalnu kasu u lokalu. Kasa u Bosni ne štampa sama fiskalni račun - to radi uređaj ovlaštenog proizvođača, a kasa razgovara sa njegovim programom, i to tako što mu ostavi datoteku sa komandama u jednom folderu i pročita odgovor iz drugog. Kroz taj folder prođe iznos svakog računa koji se odštampa, bez obzira koja je kasa gore. Sada postoji xpay- connector --detect: pokrene se na računaru u lokalu i kaže šta je našao, gdje, i šta dalje. Ne piše ništa, ne pokreće ništa i ne dira fiskalni tok - samo gleda.
      • Profili za sve registrovane proizvođače fiskalnih uređaja u BiH. Tring (Gračanica), Config (Mostar), SK Trading (Sarajevo), Mikroelektronika (Banja Luka), ERP Consulting (Sarajevo), KIMTEC (Vitez) i Digit RS COM (Banja Luka). Za dva čiji je način povezivanja objavljen upisano je šta piše u njihovoj dokumentaciji; za ostale stoji ime i pitanja koja treba postaviti, označeno kao nepotvrđeno - jer profil napisan po nagađanju izgleda gotov i pukne prvi put kad se sretne sa pravom kasom.
      • Čitanje računa koji je uređaj već odštampao. Format je dokumentovan: jedna komanda po redu, S za prodatu stavku i T za kraj računa sa načinom plaćanja i iznosom. Iznos se prijavljuje samo kada ga datoteka stvarno kaže; izračunat iznos bio bi nagađanje tuđeg zaokruživanja i popusta. Račun plaćen kešom ili karticom se ne dira - taj je već naplaćen prije nego što datoteka postoji, pa bi nuditi kod za njega značilo nuditi da se plati dvaput.

      0.35.0

      7. septembar 2026.

      Popravljeno

      • Kuhinjski ekran nije mogao skinuti tiket sa dvije stanice. Narudžba sa supom i pivom ostaje otvorena dok obje stanice ne završe, što je ispravno. Ali ekran je pitao za sve narudžbe umjesto za svoje, pa se kuharu ista kartica vraćala čim pritisne Preuzeto i stajala tu dok šank ne završi - a to u kuhinji izgleda kao da dugme ne radi, pa se pritisne opet. Server prima taj podatak otkad je predaja između stanica napisana; jedini ekran zbog kojeg postoji ga nikad nije slao.
      • Gost koji je platio manje ili više ostajao je zauvijek na "Čekam potvrdu banke". Ekran je znao za četiri ishoda; uplata veća ili manja od računa nije bila među njima. Ko zaokruži iznos u svojoj banci - a to je ovdje običan petak - gledao je pulsirajuću tačku dok ne odustane i ne plati drugi put. Sada: veće od računa je plaćeno, a manje ima svoj ekran koji kaže da je uplata prošla i koliko je stiglo od koliko.
      • Promjena cijene je zaključavala korpu. Kad happy hour istekne dok gost bira, server odbije narudžbu jer je cijena druga - i to je ispravno. Meni se osvježio, korpa nije, pa je gost čitao "provjerite iznos i pošaljite ponovo" pored iznosa koji se ne može promijeniti, i svaki sljedeći pokušaj je odbijen isto tako. Sada se osvježi i korpa; šta je u međuvremenu skinuto sa menija, kaže se.
      • "Nazad na račun" je poništavalo kod za plaćanje. Ko je već poslao uplatu iz svoje banke pa se htio vratiti da vidi račun - najprirodnija sljedeća stvar - poništio bi kod, a poništen kod se ne povezuje sa uplatom kad ona stigne. Novac dođe, ne nađe svoj račun, i sto koji je platio biva zamoljen da plati opet. Sada ekran pita ko si: "Već sam platio" ne dira ništa, a "Odustani od plaćanja" piše šta radi.
      • Potpuno vraćen novac oduzimao se dvaput. Račun vraćen u cijelosti izlazi iz prometa sam od sebe, a oduzimao se i drugi put kao povrat - pa je stotina vraćena skidala dvjesta sa dana. Na mirno popodne to padne na nulu i ekran kaže da lokal nije uzeo ništa, dok novac stoji na računu. Iznos vraćenog novca koji se prikazuje ostaje isti: sve što je stvarno vraćeno.

      0.34.5

      7. septembar 2026.

      Popravljeno

      • Dva paketa su se u spisku zvala svojim ključem. U operaterskoj konzoli padajući spisak nudi svih šest paketa, a prevedena su bila četiri - Flex i Business su se ispisivali kao plans.FLEX i plans.BUSINESS, i u spisku i u redu svakog lokala koji je na njima.
      • U istoriji narudžbi status je bio prazan. Istorija traži samo servirane narudžbe, a ekran je znao imenovati samo one četiri koje su još u toku, pa je na svakoj kartici mjesto za status ostajalo prazno. Sada piše "Servirano", a i "Otkazano" ima svoju riječ prije nego što zatreba.
      • Provjera sada gleda i vrijednosti, ne samo tekstove. Oba gornja su ključevi koje ekran sastavi dok crta, pa ih jučerašnja provjera nije mogla vidjeti. Sada se svaki popis vrijednosti koji baza može vratiti poredi sa riječima koje za njih postoje, na oba jezika. Gdje ekran namjerno nema riječ za neku vrijednost, to je zapisano i obrazloženo, pa provjera ne pada na tuđoj odluci.

      0.34.4

      7. septembar 2026.

      Popravljeno

      • Dva dugmeta za brisanje pisala su svoje ime umjesto riječi. Na pravilima za happy hour i na pravilima za preporuke dugme je pisalo common.delete umjesto "Obriši". Prevod za tu riječ nije nikad napisan, a kada ga nema, sistem ispiše sam ključ - ne padne, ne javi grešku, samo ispiše. Sada je napisan, a uz njega i provjera koja prolazi kroz sve ekrane i traži isto to: svaki tekst koji ekran traži mora postojati na oba jezika, i to se sada gleda prije svakog objavljivanja. Provjera je pregledala 960 tekstova; ova dva su bila jedina koja nedostaju.

      0.34.3

      7. septembar 2026.

      Popravljeno

      • Adresa na naljepnici dobija veličinu i širinu formata na kojem se štampa. Bila je postavljena za naljepnicu koja ide dvanaest na tabak: sitna i uska. Na kartici preko cijele stranice to je bio najmanji red na papiru, a duži domen bi se i na kartici i na stonom stalku lomio u dva reda iako prostora ima. Sada svaki format daje toj liniji onoliko koliko ima.

      0.34.2

      7. septembar 2026.

      Popravljeno

      • Adresa na naljepnici se uzima odande odakle i QR kod. Uzimala se iz adrese na kojoj je vlasnik otvorio konzolu, a to je ista stvar samo dok jeste: u punoj instalaciji konzola ima svoje ime (app.domen), pa bi vlasnik koji uđe preko IP-a ili drugog zapisa odštampao šezdeset naljepnica sa adresom koju njegovi gosti ne mogu otvoriti. Sada se čita iz iste postavke koju nosi i sam QR kod, pa oba vode na isto mjesto.

      0.34.1

      7. septembar 2026.

      Popravljeno

      • Kod koji ne radi sada nudi da se ukuca ponovo. Ekran "Ovaj kod nije u upotrebi" je do sada značio samo jedno: naljepnicu koju je lokal povukao, pa je jedini savjet bio da se pita osoblje. Otkad naljepnica štampa i adresu za telefon koji ne može da skenira, isti ekran vidi i onaj ko je pogriješio jedan znak - a tome ne treba konobar, nego polje za kod, koje je sada tu.

      0.34.0

      7. septembar 2026.

      Dodano

      • Kod sa naljepnice sada ima gdje da se ukuca. Ispod QR koda na naljepnici stoji i kod od šest znakova, za telefon čija kamera neće da uhvati: napukao ekran, masna naljepnica, mrak u baru, stariji telefon bez skenera u kameri. Taj kod dosad nije vodio nigdje - nije postojala stranica na koju se unosi, a na papiru nije pisalo ni gdje da se ode. Sada naljepnica štampa i adresu, a na toj adresi je polje za kod. Polje prašta ono što ljudi zaista otkucaju: mala slova, crticu, razmak, cijeli link koji im je neko poslao, i slova koja se ne razlikuju od cifara (I i l čita kao jedinicu, O kao nulu - zbog toga ih u kodu i nema). Kod koji nije u upotrebi to i kaže, na mjestu, i ostavlja ostalih pet znakova u polju da se ispravi jedan.

      0.33.0

      7. septembar 2026.

      Popravljeno

      • Lokal se naplaćivao za goste koji nisu ništa platili. Jedna transakcija je jedan račun sa kojeg je naručeno i koji je zatvoren - svejedno da li kešom, karticom ili prenosom. Dvije stvari su se brojale a nisu to: račun zatvoren kao neplaćen (gost otišao bez plaćanja, ili se dug otpisao) i račun na kojem nema ničega (neko skenirao naljepnicu, predomislio se, konobar sklonio račun - u kafiću uveče to nije rijetkost). Prvo je i inače izuzeto iz prometa, pa se faktura nije slagala sa ekranom koji prati.
      • Preštampana naljepnica nije radila. Naljepnica se prolije ili joj kod vidi ko ne treba, lokal je povuče i odštampa ponovo - a sistem je vraćao povučeni red. Odgovor 201, u konzoli se pojavi sto, neko odštampa i zalijepi, i svaki gost koji skenira dobije 404, bez ijedne riječi zašto. Sada je ponovno štampanje nova naljepnica koja radi.
      • Povučena naljepnica više ne troši mjesto u paketu. Kod u kanti nije sto: ne može primiti nijednu uplatu i njegov link je mrtav. Brojao se, pa je limit postajao sve gori što se proizvod duže koristi - lokal koji jednom preštampa cijeli sprat biva odbijen zbog stropa kojem nije ni blizu. Broji se koliko ih radi u isto vrijeme, što je i ono što paket prodaje.

      0.32.0

      6. septembar 2026.

      Dodano

      • Isti račun ponovo, za sljedeći period. Stanodavac šalje istom podstanaru isti iznos svaki mjesec, a komunalno preduzeće cijeloj ulici. Do sada se sve to prekucavalo iz početka - kupac, njegov PDV broj, svaka stavka, rok plaćanja - što je upravo posao koji ovaj proizvod postoji da ukloni, i mjesto gdje se slučajno promijeni jedna cifra.

      Promijenjeno

      • Sposobnost recurring je do sada pisala „računi koji se ponavljaju po rasporedu", a raspored nije postojao nigdje - to je bila tvrdnja o proizvodu, ne opis. Sada piše šta stvarno radi. Pravi raspored vrijedi napraviti i nije napravljen.

      0.31.0

      6. septembar 2026.

      Popravljeno

      • Dvije djelatnosti se uopšte nisu mogle izabrati. Proizvod opisuje sedam vrsta posla, sa svojim mogućnostima i poljima na računu, a ruta koja poslovnici dodjeljuje vrstu imala je svoj prepisan spisak od pet. Prodavnica sa pultom i veleprodaja koja fakturiše šta izađe bile su opisane do kraja i nije ih se moglo postaviti. Spisak se sada izvodi iz registra, pa dodavanje nove vrste više ne traži da se neko sjeti i drugog mjesta.
      • Pogrešno ime polja na stavci računa se tiho gutalo. Količina se šalje u hiljaditim dijelovima, što se izvana ne može znati, pa je integrator koji pošalje obično quantity: 3 dobijao 201 i fakturu na jedan komad - kupac plati trećinu onoga što je uzeo, na dokumentu koji izgleda potpuno ispravno. Sada se takva stavka odbija i kaže se koje polje ne valja.

      0.30.3

      6. septembar 2026.

      Popravljeno

      • Svako dugme za dodavanje na meniju zvalo se isto. Naziv jela stoji na kartici, a ne na dugmetu, pa je gost koji koristi čitač ekrana dobijao meni od trideset jednakih dugmadi „Dodaj" bez ijednog podatka koje šta dodaje. Sada svako kaže i jelo.

      0.30.2

      6. septembar 2026.

      Popravljeno

      • Ekran za plaćanje je gostu obećavao dvije stvari koje XPay ne može garantovati. Pisalo je „Odmah dobijete potvrdu" - a kad će uplata biti potvrđena odlučuje banka, ne XPay, i to isto stoji u Uslovima korištenja. Sada piše da se račun zatvara čim banka potvrdi, isto što piše i na ekranu koji gost gleda dok čeka. Druga je bila značka „Bez naknade": banke mogu gostu naplatiti svoju naknadu i Uslovi to izričito kažu, pa značka sada kaže ono što jeste - „Direktno banci".

      0.30.1

      6. septembar 2026.

      Dodano

      • Provjera da li je lokal spreman za goste. Sve što lokalu treba prije nego prvi gost skenira naljepnicu razbacano je po pet ekrana, a red kojim se to radi ne piše nigdje: naljepnica se ne može odštampati prije nego postoji bankovni račun, meni bez ijednog pića izgleda kao pokvarena aplikacija, a naručivanje je prekidač kojeg se neko mora sjetiti uključiti. Nova provjera pita sistem isto ono što će za koji minut pitati gostov telefon, i odgovara redom kojim se stvari moraju popraviti - odvojeno šta zaustavlja lokal, a šta je samo napomena. Ništa ne mijenja.

      0.30.0

      6. septembar 2026.

      Dodano

      • Jelo i piće se sada mogu urediti. Do sada se artikal mogao samo dodati i obrisati - a svaki lokal mijenja cijenu. Jedini način je bio obrisati jelo i napraviti ga iznova, čime se gubi slika, izbori uz jelo i mjesto u kategoriji. Sada svaki red ima „Uredi": naziv, cijena, opis, slika i mjesto pripreme, u istoj formi u kojoj se jelo i dodaje.
      • Već poslana narudžba zadržava cijenu po kojoj je poslana. Promjena cijene važi od tog trenutka naprijed i ne dira račun koji gost gleda. To je bilo tako i prije - svaka stavka pamti svoju cijenu - ali sada to i provjeravamo, jer je sad prvi put moguće mijenjati cijenu usred servisa.
      • Gost može napisati napomenu uz svaku stavku u korpi. „Bez luka", „dobro pečeno". Polje je i ranije postojalo, ali samo na jelima koja imaju obavezan izbor - sve ostalo se dodaje jednim dodirom i polje se nikad nije pokazalo. Sada stoji na svakoj stavci u korpi, tamo gdje se narudžba i pregleda prije slanja. Kuhinja to već ispisuje.

      Popravljeno

      • Klik na kategoriju u meniju nije radio ništa. Trakа kategorija je označavala aktivnu po tome dokle je meni skrolan, a to prepoznaje samo uski pojas pri vrhu ekrana. Na meniju koji cijeli stane na telefon nema se gdje skrolati, taj pojas se nikad ne pređe, i druga kategorija se uopšte nije mogla izabrati: pritisneš i ekran se ne pomjeri i čip se ne promijeni. Lokal sa dvije kategorije prvog dana je tačno taj slučaj. Sada čip reaguje na pritisak.
      • Naslov kategorije je završavao ispod trake. Skok na kategoriju je dovodio njen naslov tačno pod ljepljivu traku, pa se stiglo na kategoriju čije se ime ne vidi.
      • Limit stolova je brojao i stolove koji već postoje. Naziv koji lokal već ima se ne pravi ponovo nego se vraća postojeći, ali se limit ipak naplaćivao za njega - pa je lokal na granici bio odbijen kad ponovo pošalje spisak stolova koje već ima, uz poruku da nema mjesta za stolove koji su već tu.

      Interno

      • Izmjena artikla se sada provjerava na serveru. Ranije je tijelo zahtjeva išlo neprovjereno u bazu: naziv je mogao stići kao broj, opis bilo koje dužine, a jedino je cijena bila provjerena i to slučajno.
      • Ordering suite više ne štampa novu naljepnicu na svakom prolazu i sam zatvara račun koji je zaostao, pa se može vrtjeti koliko god puta bez da udari u limit stolova.

      0.29.9

      6. septembar 2026.

      Sigurnost

      • Javna status stranica je objavljivala tuđe adrese. Provjere su na javni odgovor prosljeđivale ono u šta se greška pretvori, a te rečenice imenuju stvari koje javna stranica ne smije reći: Prisma javi „Can't reach database server at db.interni:5432", odbijena prijava na poštu nosi SMTP host i port koje je vlasnik upisao, a skripta za kopije nosi odredište na koje kopira. Niko to nije objavio namjerno - stizalo je kao „detalj", jedna biblioteka po jedna. Sada odgovor nosi samo rečenice koje smo mi napisali; pravi tekst ide u dnevnik, gdje ga čita onaj ko može nešto uraditi. Smoke provjerava da se ne vrati.

      Promijenjeno

      • Status stranica sada pokazuje i kako se sistem ponaša, ne samo kakav je ovog trenutka. Svaka provjera ostavlja crtu na traci, pa se za vrijeme kvara vidi oblik problema, a ne jedna tačka. Traka govori samo ono što je vidjela otkad je stranica otvorena - to nije zapis koji se negdje čuva, i tako i piše ispod nje.
      • Ako se nešto promijeni dok gledaš, stranica to i kaže. Ispod dijelova stoji spisak promjena viđenih u toj sesiji: vrijeme, dio, iz čega u šta.
      • Otisak izdanja. Uz naslov stoji mreža izvedena iz commita koji trenutno odgovara - ista slika za isto izdanje na svakom ekranu, druga čim se nešto pusti. Ukras, ne kod: nema šta da se skenira, i tako i piše ispod njega.
      • Historija verzija je dobila kičmu, sa trenutnom verzijom označenom na vrhu.

      Popravljeno

      • Provjera koja ne dobije odgovor sada ostavlja trag. Traka je pamtila samo odgovore, pa je kvar koji je preglednik gledao uživo nestajao iz nje čim se sistem vrati - ostajao je neprekinut niz zelenih crta preko baš onih minuta kad ništa nije radilo. To je jedina laž koju status stranica ne smije reći. Sada takva provjera ima svoju šuplju crtu i broji se posebno.
      • Jedan neuspio zahtjev više ne briše cijelu tablu. Prije je crveni okvir zamijenio sve, pa su traka i spisak promjena nestajali tačno onda kad su najpotrebniji. Sada stoji zadnji odgovor, jasno označen kao zadnji.
      • Sravnjivanje je javljalo „Radi" kad su svi izvori u kvaru. Izvor koji padne prelazi u stanje greške, a provjera je brojala samo ispravne - pa je lokal kojem je jedina veza sa bankom crkla vidio zeleno i rečenicu da nijedan izvor još nije povezan. Novac tog trenutka prestaje biti prepoznat.
      • Nepodešena adresa sistema se prikazivala kao kvar na XPay-u. Ako stranica nije građena sa adresom, nema koga pitati - to je propust u postavci, ne ispad, i sada tako i piše, bez crvenog.
      • Dva dijela sistema nisu imala ime na stranici. „Slike" i „Sigurnosne kopije" su se javljale, a stranica ih je ispisivala engleskim ključem, bez ijedne riječi šta su - baš onome ko je došao za vrijeme kvara.
      • Razlozi su bili na engleskom. Server je slao tehničku rečenicu, a stranica ju je prepisivala takvu kakva je. Sada razlog putuje kao kod sa brojevima uz njega, a stranica ga sama sroči na bosanskom. Poređenje po engleskom tekstu se namjerno ne radi: rečenica se jednom prepravi i podudaranje tiho prestane raditi, tačno onog dana kad neko čita ovu stranicu.
      • Odbijena pošta se javljala kao pošta koja ne odgovara. To su dvije različite kvarove: pogrešna lozinka odgovori, mrtav server ne.
      • Broj uz imenicu sada ima ispravan oblik („2 provjere", ne „2 provjera"), i glagol se slaže sa brojem.
      • Na telefonu je traka bila šira od ekrana i odsijecala najnovije provjere.
      • Sitna traka po dijelu razlikovala je „Otežano" od „Ne radi" samo bojom.

      Interno

      • Nova provjera hvata zalutale kontrolne znakove u skriptama. Dvaput je koštalo: jedan carriage return u CI fajlu oborio je cijeli prolaz bez ijednog posla i bez ijednog zapisa, a jedan backspace u regularnom izrazu pretvorio je provjeru curenja u provjeru koja može samo proći. Oba su nevidljiva u diffu i u editoru. Prvi takav znak je već bio u repozitoriju i ova provjera ga je našla.

      0.29.8

      6. septembar 2026.

      Popravljeno

      • Kolona „Poziv na broj" i izvještaj za knjigovođu pisali su dva različita broja pod istim naslovom. Lista plaćanja je pokazivala čitljivi oblik (XP-1042-0000-0091), a izvoz, faktura, QR i gostov dugme za kopiranje nose četrnaest cifara. Ko upoređuje jedno s drugim vidio je dva broja za istu stvar. Sada lista piše iste cifre - one koje kupac pročita preko telefona i koje stoje na izvodu iz banke.

      0.29.7

      6. septembar 2026.

      Popravljeno

      • Ista uplata na dva kanala se računala dva puta. Ponovo poslan izvod se prepoznaje po banci i njenom broju stavke, ali jedan te isti priliv koji stigne i preko live veze i preko noćnog fajla to su dva izvora, dva broja, dva reda - a jedan transfer. Račun koji je već zatvoren bio je zaštićen slučajno; onaj koji je djelimično plaćen nije, pa je druga kopija bila dodana na već upisani iznos. Lokal bi tada u svojoj evidenciji imao više novca nego što je banka pomjerila, a povrat se računa upravo po tom iznosu. Sada se takav priliv ne upisuje sam: ide čovjeku, kao slučaj „Dupla uplata". Ni ne broji dvaput, ni ne baca pravi novac.
      • Panel poslije učitavanja izvoda nije se slagao sam sa sobom. Uplata koja je djelimično platila račun nije bila ni u jednoj koloni, pa je zbir bio manji od ukupnog broja, a baš ta uplata je ona koja nekome još duguje odgovor. Sada ima svoju kolonu („Razlika u iznosu"), a stavka koja se ponovila broji se jednom - kao duplikat - umjesto u dvije kolone odjednom.

      0.29.6

      6. septembar 2026.

      Popravljeno

      • Uparivanje: „Poveži i naplati" nikada nije radilo na razlici u iznosu. Kada dođe manje ili više nego što račun traži, sistem sam upiše priliv na račun i onda pita čovjeka je li to u redu. Dugme je tražilo stanje u kojem je račun već bio, a to je čitano kao odbijanje - 409, slučaj ostaje otvoren. To je najčešći slučaj u redu za uparivanje, pa se red nije mogao očistiti. Sada se zatvara, a priliv se ne broji drugi put.
      • Neuspješan pokušaj je i dalje mijenjao datum priliva u izvještaju za knjigovođu. Upis u izvod se dešavao prije nego se zna hoće li naplata proći, pa je zahtjev koji je vratio grešku ipak pomjerio red u fajlu koji je neko već predao. Sada se upisuje tek kada je odluka prošla, a ponovni pritisak ne pomjera datum prvog uparivanja.
      • „Zanemari uplatu" je govorio da novac nije naš, a ostavljao ga na računu. Priliv koji je već upisan na račun sada se ne može proglasiti tuđim - isto pravilo koje ista datoteka već primjenjuje na nesparen priliv. Poruka kaže i na kojem je računu.
      • „Odbaci" je odbacivao i novac. Slučaj se zatvarao, a priliv je ostajao u stanju koje nijedan ekran ne prikazuje - pravi novac koji je stigao u banku nestajao je iz proizvoda. Odbacivanje znači „ovo nije taj račun", ne „ovo nije novac": priliv se vraća u listu nesparenih uplata, gdje se može povezati ili pošteno označiti kao tuđi.

      0.29.5

      6. septembar 2026.

      Popravljeno

      • Djelimično plaćen račun nije govorio koliko je stiglo. Lista plaćanja je pokazivala iznos računa i obojenu riječ: „Manje uplaćeno, 50,00 KM". To kaže da nešto nije u redu i ne kaže šta dalje - a duguje li gost pet ili četrdeset pet maraka je cijelo pitanje. Sada red piše i koliko je stiglo i koliko nedostaje, odnosno koliko je više uplaćeno. Podatak je server slao od ranije; ekran ga nije čitao.

      0.29.4

      6. septembar 2026.

      Popravljeno

      • Poziv na broj se nije mogao pretražiti. Gost nazove i pročita broj sa svoje uplate, a to je četrnaest cifara i ništa drugo. Konzola je sama pogađala šta je ukucano po obliku teksta: same cifre znače iznos. Tako je jedini broj koji gost sigurno ima uvijek završavao u filteru za iznos, i lista se vraćala prazna - a prazna lista izgleda kao odgovor „ta uplata ne postoji". Sada postoji jedno polje i jedan upit: server traži po svim oblicima odjednom.
      • Broj računa se nije nalazio onako kako je odštampan. Referenca se prije poređenja čisti od razmaka i crtica, a broj računa iz kase se čuva tačno kako ga je kasa napisala - sa crticama. „RN-2026-09-06-0042" prekucan sa računa nije nalazio ništa. Sada se traži i tačno tako, i bez razmaka, i potpuno očišćeno.
      • Referenca i iznos zajedno su tražili samo po iznosu. Oba filtera prave isti oblik upita i jedan je tiho brisao drugi, pa je pretraga izgledala kao da poštuje oba uslova. Sada se sužavaju međusobno, kako drugi filter i služi.
      • Prekratak unos - dva znaka - ne vraća više cijelu listu. Dva znaka se nalaze u skoro svakoj referenci izdatoj danas; puna lista izgleda kao pretraga koja je uspjela.

      0.29.3

      6. septembar 2026.

      Popravljeno

      • Tabla narudžbi je bila jedan ekran za sve poslovnice. Lanac je jedan trgovac, pa je kuhinja u jednom lokalu gledala i tikete drugog - a oba lokala stolove broje isto, tako da ih je razlikovao samo naziv stola. Sada tabla ima izbor poslovnice, kao što ga spratni plan već ima, i podrazumijevano pokazuje prvu.
      • Nema opcije „sve poslovnice", namjerno: ovo je ekran koji se gleda za vrijeme servisa u jednoj prostoriji, a „sve" je stanje koje je i pravilo zabunu.
      • Lokal sa jednom poslovnicom ne vidi birač i sve mu je isto kao prije.

      0.29.2

      6. septembar 2026.

      Popravljeno

      • Od papirne naljepnice za sto mogao se napraviti uređaj koji prima novac. Stolovi se čuvaju kao uređaji posebne vrste, i brojanje uređaja za paket to zna i izuzima ih - ali spisak i „Novi kod" nisu. Pritisak na naljepnicu je kovao kod za uparivanje, kod se uparivao, a dobijeni token može naplaćivati - izvan ograničenja paketa i izvan ičije pažnje. Sada se naljepnica ne može upariti, a spisak uređaja prikazuje uređaje.
      • Kutija „koliko stolova" nije dodavala, iako je ispod nje pisalo da dodaje. Uvijek je brojala od jedan, pa je vlasnik sa dvanaest stolova koji upiše 4 dobio nazive 1-4, koji već postoje - i poruku da su četiri stola napravljena, a nijedan nije. Sada broji dalje od onoga što je na podu i preskače zauzete brojeve.
      • Tablet kojem je token opozvan ostajao je na radnom ekranu zauvijek. Ekran je odlučivao po tome postoji li token, nikad radi li - pa je tablet koji je menadžer stao izgledao živ, a nijedan poziv nije prolazio. Sada se vraća na ekran za uparivanje, gdje osoblje može unijeti novi kod.

      0.29.1

      6. septembar 2026.

      Popravljeno

      • Narudžba poslana dok veza pada mogla je stići dvaput. Telefon ne može razlikovati „server je odbio" od „odgovor se izgubio", pa ekran zadrži korpu i pozove gosta da pošalje ponovo. To je tačno kad ništa nije stiglo, a druga tura u kuhinji kad jeste - a u prostoriji sa debelim zidovima drugo je uobičajeno.
      • Sada telefon imenuje svoj pokušaj, i ista oznaka na istom računu je ista narudžba. Ponovni dodir vrati onu koja već postoji; dva dodira u istoj sekundi takođe, jer o tome odlučuje baza.
      • Nova tura je i dalje nova tura - to je ono što nije smjelo puknuti.

      0.29.0

      6. septembar 2026.

      Popravljeno

      • „Odaberi stavke" nije dozvoljavalo da platite jedan komad. Dvije kole naručene zajedno su jedan red, pa je izbor bio „2x Coca Cola" ili ništa - a to je obična situacija: dvoje ljudi, jedna tura pića, svako plaća svoje.
      • Sada red od dva komada nudi dva izbora. Odaberete jedan, plaćate jedan, a drugi ostaje na računu za onoga ko ga je popio.
      • Račun pokazuje i cijenu jednog komada, jer to je ono što duguje neko ko plaća jedan.
      • Ako je neko već uzeo jedan komad, drugi je i dalje na raspolaganju - do sada je cijeli red nestajao sa liste čim ga neko dotakne.

      0.28.0

      6. septembar 2026.

      Popravljeno

      • Jedan tiket, dvije stanice: ko prvi završi, obriše onom drugom karticu. Narudžba sa jelom i pićem ima jedan status, a ekrani su po stanicama - kuhinja vidi čorbu i ne vidi piva, šank vidi piva i ne vidi čorbu. Dugme ispod bilo koje kartice pomjeralo je cijelu narudžbu, pa je šank, označivši svoja dva piva, označio i čorbu kao posluženu i skinuo kuhinjsku karticu sa svih ekrana. Čorba nikad nije skuhana.
      • Sada „gotovo" pripada paru narudžba i stanica. Šank završi svoje, tiket mu nestane sa table, a kuhinji ostane. Narudžba je poslužena tek kad završi posljednja stanica.
      • Lokal sa jednim ekranom, bez podešene stanice, radi kao i do sada: kad ništa nije sakriveno, „gotovo" znači gotovo.

      0.27.3

      6. septembar 2026.

      Popravljeno

      • Konobarski tablet je mogao stornirati cijeli plaćen račun. Nije mogao potvrditi da je uplata stigla - za to treba menadžer - ali je mogao skinuti naplaćen račun sa dnevnog prometa, jer storniranje nije tražilo nikakvu ulogu. Opasnija radnja je bila ona bez brave. Sada i ona traži menadžera.
      • Ključ koji ima samo narudžbe mogao je pretplatiti bilo koju adresu na sve događaje o plaćanju. Nije mogao ni pročitati listu pretplata, ali je mogao napraviti novu - trajan kanal kojim podaci o novcu odlaze na tuđu adresu. Sada kreiranje, brisanje i ponovno slanje traže isto pravo kao i čitanje.

      Šta se mijenja u praksi

        0.27.2

        6. septembar 2026.

        Popravljeno

        • Spratni plan jednog lokala prikazivao je račune drugog. Lanac je jedan trgovac, a lokali stolove broje isto - „Sto 1" postoji dva puta. Ekran je tražio sve otvorene račune i spajao ih sa stolovima po nazivu, pa je prazan sto u jednom lokalu svijetlio kao zauzet, sa tuđim novcem, a zbir u zaglavlju je bio oba lokala sabrana.
        • Lista otvorenih računa sada kaže u kojem je lokalu koji račun. Bez toga su „Sto 6" i „Sto 6" dva ista reda, svaki sa dugmetom za naplatu - a zatvaranje pogrešnog knjiži gotovinu tamo gdje je niko nije uzeo, i ništa je ne vraća. Lokal se prikazuje samo kad ih ima više od jednog.

        0.27.1

        6. septembar 2026.

        Popravljeno

        • Gost koji zatraži kod pa odustane zaključao je sto na petnaest minuta. Dok je kod živ, sto ne prima narudžbe i ne može se naplatiti - ni keš, ni kartica, ni „nije plaćeno". Konobar kojem gost pruža novac dobio je poruku da otkaže kod, a nigdje nije bilo dugmeta koje ga otkazuje.
        • Sada postoji: „Otkaži kod" stoji prvi u redu na računu koji čeka uplatu. Kod prestaje biti plativ, sto ponovo prima narudžbe i može se naplatiti kako god.
        • Poruka o toj odbijenici je do sada stizala na engleskom, na bosanskoj konzoli. Sada je na jeziku koji čitate, i konzola je tako naučila prevoditi i buduće odbijenice, jer ide po oznaci a ne po tekstu.

        0.27.0

        6. septembar 2026.

        Dodano

        • Ograničenje koliko jedan sto može poslati. Kod na stolu je odštampan i javan, pa je ograničenje na broj narudžbi do sada bilo vezano za telefon - a telefon je besplatan: ko pročita naljepnicu može otvoriti novu sesiju i dobiti novo pravo. Sada se broji po stolu, gdje novi token ne donosi ništa.
        • Najviše 12 telefona na jednom računu. Preko toga to više nije sto nego proslijeđen link, i odgovor je konobar, a ne trinaesto tiho pridruživanje.
        • Najviše 15 narudžbi u pet minuta po stolu. Osam telefona koji naruče u istoj sekundi prolazi normalno - to je obična petak večer.
        • Račun otvoren duže od 12 sati prestaje primati narudžbe i traži osoblje. Niko ne sjedi dvanaest sati; to se dešava kad niko ne zatvori sto uveče, pa kod fotografisan jučer naručuje doručak danas. Račun se ne zatvara sam, jer zatvaranje odlučuje o novcu.

        Šta je izbačeno, i zašto

          0.26.0

          6. septembar 2026.

          Dodano

          • Sto koji je otišao bez plaćanja može se tako i zatvoriti. Do sada su postojali samo načini naplate - keš, kartica, uplata na račun - a sto se svejedno mora zatvoriti, inače drži mjesto cijelu večer. Zato je odlazak bez plaćanja završavao u prometu kao da je neko platio. Dan je onda pokazivao više nego što je u kasi, i to u smjeru koji lokalu laska.
          • Dugme „Nije plaćeno" stoji zadnje u redu i traži potvrdu koja kaže šta to znači: iznos se neće voditi kao promet.
          • Ako je sto platio pola pa otišao, ta polovina ostaje uknjižena. Gubitak je samo ono što nije stiglo.
          • Na Pregledu se sada vidi „otišlo bez plaćanja", pored gotovine, bakšiša i povrata. Dan se tek tako sabere: naplaćeno, vraćeno, i ono što je otišlo.

          Napomena o provjeri

            0.25.11

            6. septembar 2026.

            Popravljeno

            • Na Pregledu je ispod naplaćenog pisalo „gotovina 90,00 KM KM" - valuta dvaput. Iznos je već nosio oznaku, a šablon ju je dodavao još jednom.
            • Grafikon prometa je iznose pisao na engleski način, 1,107.30 umjesto 1.107,30, odmah pored ispravno napisanih na istom ekranu. Koristio je sistemsko formatiranje, koje za bosanski daje pogrešne separatore.

            0.25.10

            6. septembar 2026.

            Popravljeno

            • Ograničenje broja prijava bilo je zajedničko za cijelu platformu, a ne po korisniku. API u kontejneru nije prepoznavao pravu adresu posjetioca nego je svaki zahtjev vidio kao da dolazi sa iste, pa je dvadeset pokušaja prijave u minuti bilo ograničenje za sve zajedno. Jutro sa tri lokala koja se otvaraju i par pogrešno ukucanih lozinki zaključa četvrti lokal koji nikoga nije ni dotakao. Isto je pogađalo i zapis u dnevniku, koji je bilježio adresu mreže umjesto korisnika.
            • Instalacija bez DNS zapisa za app.<domena> upisivala je https:// kao adresu konzole. Skripta ispravno ostavi konzolu na glavnoj adresi i to i kaže, ali je adresu svejedno sastavljala od praznog imena. Instalacija bi „uspjela uz upozorenje", a konzola bi se izgradila tako da gađa nepostojeću adresu. Sada koristi glavnu adresu, a upisivanje adrese bez imena se odbija sa objašnjenjem.

            0.25.9

            6. septembar 2026.

            Popravljeno

            • Povrat uplate koja je bila manja od tražene brisao je tuđi novac sa računa stola. Račun se zadužuje tek kad uplata bude potpuna; nedoplaćena ga ne dodiruje. Ali povrat je svejedno skidao sa računa - a skidao je ono što je tamo bilo, dakle plaćenu polovinu drugog gosta. Sto je onda ponovo tražio novac koji je jedan od njih već dao.
            • Sada se sa računa skida samo ono što je ta uplata na njega i stavila.

            0.25.8

            6. septembar 2026.

            Popravljeno

            • Otkazivanje jela koje je neko već platio guralo je račun u minus. Gost plati svoju stavku QR-om, kuhinja pokvari to jelo, konobar ga otkaže - i račun stola padne ispod onoga što je već naplaćeno. Ostatak stola je onda na svom telefonu gledao negativan iznos i nije mogao platiti ono što duguje.
            • Sada se takvo otkazivanje odbija sa objašnjenjem: za to ide povrat, ne otkazivanje. Obično otkazivanje neplaćene narudžbe radi kao i do sada.

            0.25.7

            6. septembar 2026.

            Popravljeno

            • Dok se račun plaća, drugi gost za stolom nije mogao ni naručiti ni pozvati konobara, a obje poruke su mu govorile da pokuša ponovo. Nijedno od toga nije moglo uspjeti: neko je za kasom, i dok to ne završi telefon bez svog računa ne može ništa. Sada piše šta se dešava i da će za koji trenutak moći dalje.
            • Poziv konobara je pao iz istog razloga: dugme prvo otvori račun za taj telefon, a to je upravo ono što server u tom trenutku odbija.

            Zašto je to ostalo neprimijećeno

              0.25.6

              6. septembar 2026.

              Popravljeno

              • Kad konobar zatvori račun, gostu na telefonu se ekran pretvarao u slijepu ulicu. Gost gleda račun, konobar uzme gotovinu i zatvori sto na tabletu, i osam sekundi kasnije telefon napiše „Za platiti 0,00 KM" i „Još niste ništa naručili" - čovjeku koji je upravo platio. Na ekranu nije ostalo nijedno dugme; jedini izlaz je bio ručno osvježavanje stranice.
              • Sada piše da je račun zatvoren i nudi povratak na meni. Naljepnica i dalje radi, pa sljedeća narudžba otvara novi račun, što je tačno ono što sto traži kad naruči još jednu turu.
              • Isto je popravljeno i na ekranu „Vaše narudžbe", koji je u istoj situaciji bez riječi prelazio u puni meni.

              0.25.5

              6. septembar 2026.

              Popravljeno

              • Zadnja porcija se mogla obećati dvama stolovima. Provjera zalihe je čitala stanje prije nego što transakcija počne, pa su dvije narudžbe u istoj sekundi obje vidjele „ostala jedna" i obje prošle. Umanjenje jeste bilo uslovno i drugom nije obrisalo ništa, ali se rezultat nije gledao, pa se narudžba svejedno upisala. Broj je izgledao ispravno, a kuhinja je imala dva stola za jednu porciju. Sada onaj ko izgubi trku dobije odbijenicu.
              • Svrha plaćanja je pisala „Sto Sto 1". Riječ „Sto" se dodavala na naziv koji je lokal već tako napisao. Sada se dodaje samo kad je naziv gol broj, pa „1" postane „Sto 1", a „Sto 1", „Terasa 3" i „Šank" prolaze kako su napisani. To je polje koje bankovna aplikacija pokaže gostu.

              Zna se, nije dirano

                0.25.4

                6. septembar 2026.

                Dodano

                • Generalna proba sada provjerava da svaka fotografija na meniju zaista stigne. Jučerašnja greška sa praznim kvadratima nije pala nijednom testu, i nije mogla: postojeće provjere šalju sliku kroz API pa je kroz API i pročitaju, a te dvije strane se po definiciji slažu bez obzira gdje je direktorij. Puklo je ono što upisuje neko drugi.
                • Gleda se vrsta sadržaja, a ne samo status. Ona 404 se vraćala kao ispravan JSON, a pregledač takav odgovor odbije kao sliku bez ijedne poruke koju bi čovjek negdje vidio.

                0.25.3

                6. septembar 2026.

                Popravljeno

                • Meni je gostu prikazivao prazne kvadrate umjesto fotografija jela. Slike su se upisivale u jedan direktorij, a posluživale iz drugog, pa je svaka bila 404. Ništa u zapisima nije to prijavljivalo, jer fajl zaista nije postojao tamo gdje ga je server jedino i tražio. Od 20 fotografija u demo meniju učitavala se jedna.
                • Uzrok: podrazumijevana putanja je bila ./data/media, što nije direktorij nego pitanje o tome ko pita. Seed pita iz korijena projekta, server iz svog foldera, i dobiju dva različita odgovora.
                • Sada je podrazumijevana putanja stvarno mjesto, izračunato na jednom mjestu koje i seed i server koriste. Ko je ranije sam postavio putanju, njegova i dalje vrijedi.

                0.25.2

                6. septembar 2026.

                Popravljeno

                • Promet poslije ponoći se knjižio na pogrešan dan. Grafikon je dan sjekao po UTC-u, a ne po satu u lokalu, pa je sve što je naplaćeno poslije ponoći padalo na dan ranije. Za kafić koji radi do dva ujutro to znači da je najbolji dio petka bio upisan u četvrtak. Sada dan počinje u ponoć tamo gdje je lokal.
                • Grafikon prometa se nije crtao. Prikazivali su se samo sati u kojima je bilo uplata, pa je dan sa svim uplatama u jednom satu davao jednu tačku i panel bi napisao „nema dovoljno podataka" iznad pločica koje su pokazivale promet. Sada se crtaju sva 24 sata, a prazni sat je nula.
                • I krivulja je sada iskrena. Tačke su bile razmaknute po redoslijedu, a ne po vremenu, pa su uplata u devet ujutro i uplata u devet navečer izgledale kao dva susjedna sata. Ko je gledao oblik večeri, gledao je oblik broja uplata.

                0.25.1

                6. septembar 2026.

                Dodano

                • Generalna proba. Cijela večer u jednom sjedenju, na jednom stolu: naljepnica se odštampa, telefon je skenira, gosti naruče, narudžba se podijeli na kuhinju i šank, neko pozove konobara i konobar poziv zatvori, račun se podijeli po stavkama na dva telefona, plati se prenosom, ujutro se ubaci bankovni izvod i sto se zatvori. Vrti se na svakoj izmjeni koda.
                • Dosad je svaki test izmišljao uplatu; sada prvi put kroz sistem prolazi pravi camt.053 XML fajl iz banke, od parsera do zatvaranja stola. To je spoj na kojem pilot stoji, a nije bio provjeren s kraja na kraj.
                • Dugme za poziv konobara je prvi put pritisnuto u testu.

                Vrijedi znati prije nego se sjedne za sto

                  0.25.0

                  5. septembar 2026.

                  Dodano

                  • Zaliha po jelu. Kuhinja ujutro upiše koliko ima porcija; kad odu, jelo se samo skine sa menija. Bez toga niko ne pritisne „rasprodano" dok gost već nije naručio dvadeset prvu porciju, pa se konobar vraća za sto da objasni.
                  • Narudžba veća od onoga što je ostalo se odbija, a ne skraćuje. Tri i izvinjenje je gore od odbijanja na koje gost još može reagovati.
                  • Broji se u istoj transakciji koja upisuje narudžbu, pa dva stola koja u istoj sekundi naruče zadnje dvije porcije ne mogu oba dobiti potvrdno.

                  Tri odluke koje su oblikovale ostalo

                  • Zaliha pripada danu. Broj upisan ujutro ništa ne znači sutra, pa nosi datum. Jučerašnja nula nije današnja nula nego *nema brojanja* - da je obrnuto, svako brojano jelo bilo bi rasprodano zauvijek prvo jutro nakon što je neko ovo uključio.
                  • Kad ponestane, ništa se ne upisuje. Zastavica „rasprodano" ostaje ono što je čovjek postavio, a zaliha se čita pored nje. Jelo koje je neko namjerno skinuo ostaje skinuto; jelo koje je juče nestalo se danas vraća samo od sebe. Da se zastavica upisuje, trebala bi druga zastavica da pamti ko ju je upisao.
                  • Nema broja znači nema ograničenja. Sva jela na svim menijima danas nemaju broj, a lokal koji zaboravi upisati prodaje jelo umjesto da ga sakrije. Meni koji tiho prestane nuditi hranu je gori kvar, jer ga niko ne primijeti.

                  0.24.0

                  5. septembar 2026.

                  Dodano

                  • „Šta ponuditi i kada", u Meniju. Meni je do sada znao samo da uz ćevape ide piće - pravilo o tome *šta je naručeno*. Ovo je pravilo o *sali*: nakon 45 minuta za stolom ponudi deserte, ili uvečer ponudi koktele.
                  • Oba uslova su neobavezna i oba moraju vrijediti. Restoran traži samo minute, bar traži samo sate; da su oba obavezna, oba česta slučaja bi se nezgrapno pisala.
                  • Pola prozora se odbija - i početak i kraj, ili nijedno. Pogađati koja je polovina mišljena je način da pravilo radi na pogrešnom kraju dana.
                  • Ista kategorija iz dva pravila se nudi jednom, i to nakon kraćeg čekanja.

                  Gdje se šta odlučuje

                  • Sat odlučuje server, u vremenu poslovnice. Jedini sat koji gostov telefon ima je gostov telefon, a on može biti podešen na drugu državu.
                  • Minute za stolom broji server, pa ih telefon samo poredi. Trajanje je isti broj u svakoj vremenskoj zoni, a meni se posluži jednom i gleda sat vremena - da telefon računa razliku od svog sata, gost sa pogrešno podešenim satom dobio bi desert sat ranije ili nikad.

                  Ostalo

                  • Računanje sata i prozora izdvojeno je iz happy houra u zajednički fajl, jer ga sada koriste dvije stvari. Svih 20 postojećih testova za happy hour prolazi nepromijenjeno, što je i bila svrha da se to provjeri tim putem.

                  0.23.4

                  5. septembar 2026.

                  Popravljeno - server se nije dizao

                  • API se nije mogao pokrenuti ako SMTP_SECURE nije postavljen. Docker ne može uslovno izostaviti ključ, pa se svaka neobavezna postavka u compose fajlu piše ${SMTP_SECURE:-} i stiže kao prazan string kad je niko nije postavio. Prazan string nije „nije postavljeno", pa ni .optional() ni .default() ne važe - enum ga odbije i API padne u petlju pri startu:
                  • SMTP_SECURE: Invalid enum value. Expected 'true' | 'false', received ''
                  • Ovo je čekalo svaku instalaciju koja SMTP nije podesila. install.sh ne piše SMTP_SECURE, a u compose je dodan tek nedavno - upravo zato da bi se mogao postaviti. Prvi sljedeći uspješan update bi ga aktivirao.
                  • Tiša polovina istog kvara: Number('') je 0, pa je prazan broj prolazio bez riječi. SMTP_PORT bi postao port 0, a PAYMENT_DEFAULT_TTL_SECONDS kod koji ističe u trenutku izdavanja.
                  • Prazne vrijednosti se sada odbacuju prije provjere, pa svaka zadana vrijednost dobije priliku. Razmaci se broje kao prazno: varijabla sa dva razmaka je omaška, ne namjera.

                  Kako je nađeno

                  • Poslom koji od jučer diže produkcijski stack u CI-ju. Migracije su prošle, kontejner se pokrenuo i nikad nije odgovorio na /readyz - a logovi su rekli zašto. Tri pokušaja da sam taj posao proradi, i onda je na prvom prolazu do API-ja našao pravi kvar.

                  0.23.3

                  5. septembar 2026.

                  Popravljeno - postavljanje

                  • Ažuriranje na serveru nije prolazilo. MAIL_REPLY_TO je u docker-compose.prod.yml bio naveden dva puta - jednom među ostalim mail postavkama, jednom u bloku dodanom kasnije za postavke koje nisu stizale do kontejnera. YAML sa dva ista ključa compose odbija, pa se stalo prije nego što je išta počelo da se gradi: line 131: mapping key "MAIL_REPLY_TO" already defined at line 97.

                  Dodano

                  • Provjera fajlova iz deploy/ u CI. Sve u tom folderu je jedini dio projekta koji nijedan test ne dotiče i nijedan build ne kompajlira - prvi put se pokrene na serveru, pred nekim ko čeka. Ovaj kvar je stajao iza više od dvadeset zelenih CI prolaza: svi testovi su prolazili, a proizvod se nije mogao postaviti.
                  • Provjerava se dvoje: da svaki YAML fajl prolazi parser, sa duplim ključem kao greškom - jer ga compose tako i tretira - i da svaka shell skripta prolazi bash -n, što uhvati nezatvoren navodnik ili fi koji fali. Ništa se ne pokreće; ovo su greške koje se mogu naći bez servera.
                  • Provjereno tako što je greška namjerno vraćena i potvrđeno da provjera pada, pa isto i za pokvarenu shell skriptu.

                  0.23.2

                  5. septembar 2026.

                  Dodano

                  • Oznaka „Stiglo na zatvoren račun" na ekranu Plaćanja. Gost uzme kod, ne iskoristi ga, kod istekne, konobar naplati gotovinu i zatvori račun - a transfer stigne sat kasnije ipak. Gost je platio dvaput.
                  • Blokirati zatvaranje cijeli sat nije rješenje: bankovni transfer stvarno može toliko da putuje, a kasa koja sat vremena neće da primi gotovinu je gori problem od onog koji rješava. Zato se sudar zabilježi, a ne sprječava: na samom plaćanju, u revizijskom tragu i kao oznaka u listi.
                  • Do sada je to bio jedan red u serverskom logu, a to nije mjesto sa kojeg gost koji je platio dvaput dobije novac nazad.

                  0.23.1

                  5. septembar 2026.

                  Popravljeno - novac

                  • Kod izdat u trenutku zatvaranja računa vezao se za već zatvoren račun. Zatvaranje na gotovinu odbija se dok je kod živ - ali kod se za račun veže tek na kraju procesa plaćanja, pa konobar koji zatvori u tom razmaku ne vidi ništa živo, zatvori, a kod poslije toga sleti na plaćen račun. Gost prebaci novac i lokal ga ima dvaput: u kasi i na računu u banci, a jedino što o tome negdje piše je jedan red u logu.
                  • Obje strane sada zaključavaju isti red u bazi, pa jedna čeka drugu. Ko izgubi dobije rečenicu: gost da je račun u međuvremenu zatvoren, konobar da je kod još živ. Kod koji je izgubio se poništi prije nego što ga gost uopšte vidi.
                  • Zatvaranje sada čita iznose iz zaključanog reda, a ne iz onog pročitanog ranije - uplata je mogla stići dok se čekalo, a uzeti gotovinu za novac koji je već stigao je upravo ono što se ovdje brani.

                  0.23.0

                  5. septembar 2026.

                  Dodano

                  • Happy hour i zakazane akcije. U Meniju se postavi pravilo: ovim danima, između ovih sati, toliko posto popusta - na cijeli meni ili na jednu kategoriju. Gost vidi novu cijenu, precrtanu staru i naziv akcije.
                  • Vrijeme je vrijeme u sali. Prozor postavljen na 17:00 je 17:00 u lokalu i ljeti i zimi; čuvaju se minute od ponoći u vremenskoj zoni poslovnice, a ne trenutak i ne pomak. Testovi prolaze i kad server radi u UTC, New Yorku, Tokiju i na UTC+14.
                  • Prozor preko ponoći, jer bar to i traži: 22:00 do 02:00. Sitni sati pripadaju danu u kojem je prozor počeo, pa petak pokriva ranu subotu, a ne rani petak.
                  • Ako se dva pravila preklapaju, važi ono sa većim popustom; ne sabiraju se. Dva puta po 20% koja se pomnože u 36% je broj koji niko nije postavio.
                  • Zaokruživanje ide u korist gosta: gdje postotak ne dijeli tačno, fening ide sa cijene, a ne na nju.

                  Šta ovo štiti

                  • Cijena na ekranu je cijena koja se naplaćuje. Telefon uz narudžbu šalje iznos koji je pokazivao; ako server izračuna drugi - akcija se u međuvremenu zatvorila, ili je neko promijenio cijenu - narudžba se odbija i gostu se kaže da se cijena promijenila, umjesto da se naplati iznos koji niko nije vidio. Meni se pritom osvježi.
                  • Popust ide na jelo, ne na dodatke. 20% na kafu je 20% na kafu; duplo je onoliko koliko je lokal odredio.
                  • Postotak je ograničen na 90. Pravilo koje skida sve nije popust nego besplatna hrana objavljena svakome ko ima naljepnicu sa stola, i mnogo je vjerovatnije greška u kucanju nego namjera.
                  • Pravilo bez ijednog dana, ili sa istim početkom i krajem, se odbija umjesto da se nagađa - takvo pravilo se nikad ne otvori, a vlasnik bi grešku tražio u popustu.

                  0.22.1

                  5. septembar 2026.

                  Popravljeno

                  • Provjera u smoke testu tražila je BOM u dekodiranom tekstu, a UTF-8 dekoder ga po standardu skida - pa ta provjera nikada nije mogla vidjeti oznaku, bila ona tu ili ne. Fajl je bio ispravan, provjera nije. Sada se gledaju bajtovi, jer je oznaka svojstvo bajtova, i isto je dodano u jedinični test.

                  0.22.0

                  5. septembar 2026.

                  Dodano

                  • Izvoz za knjigovođu, dugme na ekranu Plaćanja. CSV sa jednim redom po uplati koja je stvarno stigla: datum i vrijeme u vremenu poslovnice, poziv na broj, iznos, napojnica, uplaćeno, način i - kolona koju niko ne treba tražiti - da li je uplatu potvrdila banka ili je neko potvrdio ručno. To su dvije različite vrste činjenice i ko ih ne razlikuje ne može se osloniti ni na jednu.
                  • Fajl je napravljen da se otvori iz prve: tačka-zarez kao razdjelnik, zarez kao decimalni, i BOM na početku da Excel na Windowsu pročita naša slova. Bez toga svako č, ć, š, ž i đ u nazivima jela stigne kao nešto drugo, a knjigovođa zaključi da izvoz ne radi.
                  • Naziv koji počinje sa =, + ili @ se neutralizuje. Ime kupca nije nešto čime neko treba da može pokrenuti nešto u tuđem Excelu.

                  Šta ovaj fajl nije

                  • Nije bankovni izvod. Novac ide sa računa na račun i XPay ga nikad ne drži, pa su ovo XPay-evi zapisi o uplatama koje je prepoznao, a ne bankin zapis o njima. Banka ostaje mjerodavna i tako i piše u opisu.
                  • Ništa se ne odbija. Kartica ideje je tražila i „0,02 KM naknade" po transakciji - takve naknade nema. 0,02 KM je cijena transakcije preko uključenog broja na Business planu, i naplaćuje se na mjesečnoj XPay fakturi koja postoji zasebno. Oduzimati izmišljenu naknadu od ovih iznosa pogrešno bi prikazalo i prihod i trošak.
                  • PDF verzija nije napravljena. Knjigovođa uvozi CSV; PDF je za arhivu i može sačekati red iza stvari koje se koriste svaki dan.

                  0.21.0

                  5. septembar 2026.

                  Popravljeno - novac

                  • Ponovljeni zahtjev sa istim Idempotency-Key mogao je napraviti drugo plaćanje. Zapis o ključu upisivao se tek nakon što je odgovor već poslan, i to bez čekanja - pa je kasa koja je istekla i pokušala ponovo, a to je jedini razlog zbog kojeg to zaglavlje i postoji, mogla stići u taj razmak, ne naći ništa i naplatiti sto dva puta. Ključ se sada zauzima prije nego što se zahtjev obradi, a odgovor upisuje prije nego što se vrati.
                  • Time se zatvara i slučaj dva istovremena identična zahtjeva: onaj koji izgubi upis dobija odgovor da je prvi još u obradi, umjesto da napravi drugo plaćanje pored njega.
                  • Zahtjev koji ne uspije oslobađa svoj ključ, da plaćanje odbijeno zbog pogrešnog IBAN-a ne zaključa vlastiti ključ na 24 sata.
                  • Ovo je uhvatio smoke test koji pravi plaćanje pa ga odmah ponovi. Prolazio je mjesecima i pao na opterećenom CI serveru - tačno onako kako bi i pao u sali.
                  • Povrat je sa računa stola skidao i napojnicu. Na stol se knjiži samo hrana i piće - napojnica se namjerno ne knjiži - a povrat je skidao cijeli iznos, sa napojnicom. Kod stola koji plaća jedan gost to je sakrivalo ograničenje na nulu; kod stola koji plaćaju dvoje nije: gost A plati 20 uz 2 KM napojnice, gost B plati 30, i povrat gostu A ostavi račun na 28 od 50 - pa se sljedećem gostu naplati 2 KM koje je neko već platio.
                  • Pravilo je da povrat prvo ide iz napojnice. To je čitanje koje nikada ne traži od stola da ponovo plati hranu koju je već platio, i tačno se poklapa sa onim što je na stol i knjiženo.

                  0.20.3

                  5. septembar 2026.

                  Popravljeno

                  • Odlazak sa ekrana sa QR kodom bljesnuo bi meni. Ekran se crta dok postoje i pogled i plaćanje; kod se brisao prije nego što se čekao odgovor servera, pa je pogled ostajao na „čekanju" bez ičega da nacrta - i crtanje bi propalo do dna komponente, a to je meni. Trajalo je koliko i zahtjev. Isto se dešavalo i pri otkazivanju zahtjeva za gotovinu ili karticu.
                  • Sada se odredište i ono što se napušta mijenjaju zajedno, prije bilo kakvog čekanja, pa React nacrta jedan kadar i to onaj pravi.

                  0.20.2

                  5. septembar 2026.

                  Popravljeno

                  • „Biram stavke" je gostu nudio dugme za plaćanje 0,00 KM. Biranje unaprijed označi ono što je taj telefon naručio, a to je prazno kad je narudžbu ukucao konobar - pa je gost sa ukucanom narudžbom pritisnuo „Biram stavke" i dobio aktivno dugme za nula maraka. Sada na tom mjestu piše šta treba uraditi, umjesto da stoji ugašeno pored nule - isto kao što list jela kaže koju grupu opcija niste odabrali.

                  0.20.1

                  5. septembar 2026.

                  Popravljeno

                  • Ekran Izvodi je pokazivao ključ umjesto naziva za svaku vrstu izvora osim dvije koje trgovac može sam napraviti. Godinama nevidljivo, jer ništa u konzoli nije pravilo takav izvor - a onda je jučerašnje dugme „Plaćeno" napravilo prvi „Ručna potvrda" i naziv se pojavio kao statements.kind.MANUAL. Sada su prevedene sve vrste koje server uopšte može napraviti.
                  • Uz to test koji čita spisak vrsta iz Prisma šeme, ne iz kopije, i pada ako se doda vrsta bez naziva. Kopija bi se slagala sama sa sobom i ne bi rekla ništa o šemi.

                  0.20.0

                  5. septembar 2026.

                  Popravljeno - novac

                  • Ručna potvrda uplate knjižila je isti novac dva puta. 0.19.0 je popravio iznos, ali ne i put: potvrda se zavede kao priliv, matcher je odmah pripiše računu, a onda ju je kod pripisivao još jednom. Račun od 1000 KM sa 400 KM uplate, nakon potvrde preostalih 600, ispao je poravnat sa 1600 KM. Uslov je bio prenizak - gledao je samo da li je matcher rekao „poravnato", a matcher pripisuje priliv i kad ga ocijeni kao manjak ili višak. Sada se pita ono što je jedino pouzdano: kojem računu je priliv na kraju pripisan.
                  • Uhvatio ga je smoke test koji je uz to dugme i napisan. Prvi put je vratio 1400, drugi put 1600; obje brojke su bile pogrešne na različit način.

                  Dodano

                  • „Po stolovima" na ekranu Stolovi: promet, prosječan račun, koliko se puta sto dnevno okrene, koliko dugo račun stoji otvoren, i koliko skeniranja sa tog stola uopšte završi narudžbom.
                  • Vrijeme je sredina, ne prosjek. Jedan račun zaboravljen preko noći pomjeri prosjek za sat, a sredinu nimalo - a zaboravljen račun se dešava skoro svake sedmice.
                  • Prosječan račun se računa samo po računima na kojima je nešto naručeno. Skeniranje koje nije završilo narudžbom nije jeftin račun, nego nije račun; da se broji kao nula, najprometniji sto bi ispao najgori.
                  • Sto sa premalo računa se označi, a ne sakrije. Sto sa dva računa nema loše brojeve nego još nema brojeve, a da se izbaci iz tabele izgledalo bi kao da stola nema.

                  Šta ovaj broj nije

                  • Minute nisu koliko je gost sjedio. Mjere se od skeniranja koda do zatvaranja računa: gost često skenira usred obroka, a osoblje zatvori račun kad stigne. Dobro za poređenje stolova međusobno, loše kao stvarno vrijeme za stolom - i tako i piše ispod tabele, jer se po ovom broju premješta namještaj.

                  0.19.0

                  5. septembar 2026.

                  Popravljeno - novac

                  • Ručna potvrda uplate na djelimično plaćenom računu knjižila je novac koji nikad nije stigao. Potvrda se zavodi kao priliv, a priliv se dodaje na ono što je već uplaćeno - pa je račun od 1000 KM sa 400 KM uplate, nakon potvrde na puni iznos, ispao poravnat sa 1400 KM i prešao u PREPLAĆENO. Preplaćeno je iznos koji ekran za povrat rado ponudi da se vrati kupcu. Sada se potvrđuje ono što je preostalo, a ne cijeli račun.
                  • Ako na računu nema šta da se potvrdi, potvrda se odbija umjesto da se zavede kao priliv od nula.

                  Dodano

                  • Dugme „Plaćeno" na fakturi koja čeka uplatu. Ovo je vlasnikovo pitanje postavljeno naglas: firma izda račun sa QR kodom, kupac skenira svojom bankom i plati - hoće li XPay to primijetiti? Hoće, čim stigne izvod. Do tada je jedini put bio ručno slanje priliva kroz API, a sad je dugme.
                  • Zavodi se kao ručna potvrda, sa imenom onoga ko je potvrdio, i ostaje odvojivo od uplate koju je potvrdila banka. Pita se naglas prije nego što se zavede, jer se ovim novac knjiži kao stigao.
                  • Nudi se samo vlasniku i menadžeru, jer server i traži tu rolu. Dugme koje postoji samo da kaže ne gore je od dugmeta kojeg nema.
                  • Jedna rečenica na ekranu Fakture koja kaže kako se račun uopšte zatvara: uvezete izvod, XPay prepozna uplatu po pozivu na broj i zatvori ga sam. To je cijeli odgovor i nigdje nije pisao.

                  0.18.0

                  5. septembar 2026.

                  Dodano

                  • Dugme Štampaj, u Fakturama. Pregled je otvarao PDF u kartici, koju pretraživač zna odštampati - ako znate da je to ono što treba uraditi. Ko hoće papir traži riječ „štampaj", a ne karticu sa alatnom trakom.
                  • Nacrt se štampa kroz pregled i izlazi sa oznakom NACRT, što je tačno ono što treba da stoji na papiru koji još nije račun.

                  Promijenjeno

                  • Štampanje sada svuda znači štampanje PDF-a. Dugme na stranici koju kupac otvori zvalo je window.print() nad samom stranicom, a to je drugi prikaz istog računa - pa je kupčeva kopija na papiru bila složena drugim kodom nego ona koju firma arhivira. Stranica i PDF su se upravo usaglasili oko toga šta pišu; štampa se morala usaglasiti oko toga šta proizvodi.
                  • Ako pretraživač odbije da otvori dijalog za štampu nad fajlom, fajl se otvori u kartici. Ko gleda PDF uvijek ga može odštampati; dugme koje naizgled ne radi ništa je kvar koji vrijedi izbjeći.

                  0.17.1

                  5. septembar 2026.

                  Popravljeno

                  • Crtanje primjera računa vraćalo je 201 Created iako ništa ne stvara. POST je zato što postavke koje se isprobavaju idu u tijelo zahtjeva, a ne u adresu - ali odgovoriti „napravljeno" na zahtjev koji ništa nije napravio je laž na koju se klijent prije ili kasnije osloni. Sada 200.

                  0.17.0

                  5. septembar 2026.

                  Dodano

                  • Izgled računa, u Postavkama. Trgovac sada bira šta stoji na njegovom računu: svoja adresa, svoj ID broj, svoj kontakt, ID broj i adresa kupca, i QR kod. Uz to dvije vlastite linije - jedna u zaglavlju, jedna na dnu.
                  • Primjer računa koji se crta dok mijenjate, umjesto da se račun mora izdati da bi se vidio. Do sada je jedini način da se vidi kako račun izgleda bio da se izda - a to uzima broj iz vlastite serije dokumenata i ne poništava se brisanjem. Primjer nosi vaše zaglavlje i vaš logo, izmišljene stavke i izmišljenog kupca, oznaku PRIMJER na licu, i QR koji nije nalog za plaćanje.
                  • Primjer crta isti kod koji crta pravi račun. Pregled iz drugog renderera je pregled nečeg drugog - to je greška iz koje je ovaj dio upravo izvučen.
                  • Ništa se ne snima dok se ne pritisne Sačuvaj, i slanje jednog prekidača ne briše ostalih šest.

                  Šta se ne može isključiti

                  • Sitna slova na dnu. Ona kažu šta dokument jeste, a ne šta neko preferira, i račun koji se može natjerati da ih prestane pisati nije račun.
                  • ID broj i adresa kupca i dalje idu samo na PDF koji firma arhivira. Stranica koju kupac otvori ih nikad nije nosila i ne nosi ni sada - link se prosljeđuje knjigovođi, a proslijeđen račun ne treba nositi više od računa.

                  Zadano

                  • Sve uključeno, obje linije prazne. Trgovac koji nikad ne otvori ovaj ekran vidi tačno ono što je vidio i prije - jedino prihvatljivo zadano stanje za postavku koja mijenja pravni dokument.

                  0.16.0

                  5. septembar 2026.

                  Popravljeno

                  • Kupac i firma su gledali dvije različite verzije istog računa. PDF koji firma arhivira i stranica koju kupac otvori bile su dva ručno pisana prikaza istog dokumenta i razišle su se na četiri načina. Sada postoji jedno mjesto koje odlučuje šta račun kaže, a oba prikaza samo crtaju to.
                  • Sitna slova su govorila različite stvari. Na stranici je pisalo da je fiskalizacija obaveza izdavaoca, a na PDF-u da je račun izdat elektronski i punovažan bez potpisa i pečata. Jedan dokument ne može govoriti dvoje.
                  • Datum se računao po vremenskoj zoni čitaoca. Račun izdat u 01:30 ujutro u Sarajevu kupcu nekoliko sati zapadno prikazivao se sa datumom prethodnog dana
                  • na stranici sa koje se traži da plati. Datum na računu je činjenica o računu, ne o tome ko ga gleda. Sada se piše u vremenskoj zoni poslovnice, na obje kopije.
                  • „PDV 0,00" na računu firme koja nije u sistemu PDV-a. Stranica je uvijek štampala red za PDV, PDF samo kad ga ima. Nula na tom mjestu čita se kao tvrdnja da je izdavalac registrovan. Sad ga nema kad ga nema.
                  • Uplaćeni novac se vidio samo u jednom od četiri stanja. Stranica je prikazivala uplaćeno i preostalo samo dok je račun DJELIMIČNO plaćen, pa djelimično plaćen račun koji je u međuvremenu dospio nije kupcu govorio ništa o uplati koju je već poslao - a to je upravo slučaj kad mu to najviše treba.
                  • IBAN se grupisao u četvorke na dva mjesta, a QR kod se crtao u dvije različite boje. Po jedno mjesto za oboje.

                  Zašto ovo prije dizajnera računa

                  • Sljedeći korak je da trgovac bira šta stoji na njegovom računu. Da je to napravljeno prije ovoga, izbor polja bi se morao implementirati dva puta i razišao bi se na isti način - a to znači da kupac čita jedan dokument, a firma arhivira drugi.

                  0.15.0

                  5. septembar 2026.

                  Dodano

                  • Promjena vlastite lozinke iz konzole, u Postavkama. Endpoint postoji od početka i nijedan ekran ga nikad nije pozvao, pa je zaboravljena ili podijeljena lozinka značila da neko mora pokrenuti komandu na serveru - što je sasvim u redu kao zadnje rješenje i loše kao prvo. Račun je vlasnikov; promjena lozinke je njegova stvar.
                  • Traži se trenutna lozinka, da telefon ostavljen na šanku ne bude način da nekog zaključate iz vlastite konzole. Nakon promjene sve prijave se odjavljuju, i ova - pa ekran to i kaže i vodi na prijavu, umjesto da vas izbaci u nekom nepredvidivom trenutku kasnije.

                  Popravljeno

                  • Promjena lozinke je bila način da se zaobiđe pravilo za operatera. Pravilo o dužini živjelo je na pet mjesta i zbog toga je bilo tačno na četiri: forma za promjenu tražila je deset znakova od svih, pa je račun napravljen pod pravilom od dvanaest mogao sa ekrana preći na deset. Račun koji može doći do svakog trgovca na platformi završio bi sa najslabijom lozinkom na njoj. Sada postoji jedno mjesto koje kaže koliko, i svih pet ga čita.

                  0.14.0

                  5. septembar 2026.

                  Dodano

                  • Meni se čita i kad padne internet. Wifi u staroj kamenoj zgradi pada, a ekran koji iz toga ispadne je najgori kvar u proizvodu: gost skenira naljepnicu, dobije stranicu koja kaže da ne može ništa dohvatiti, i zaključi da naljepnica ne radi. Lokal onda čuje da XPay ne radi. Sve što treba da se meni pročita bilo je na telefonu minut ranije.
                  • Meni se čuva na telefonu pri svakom uspješnom otvaranju i vrijedi tri dana. Stariji se ne prikazuje - cjenovnik se u međuvremenu promijenio, a biti samouvjereno pogrešan pred nekim ko sprema novac je gore nego ne reći ništa.
                  • Traka na vrhu kaže kad je meni sačuvan i da su se cijene možda promijenile, sa dugmetom za ponovni pokušaj.
                  • Slika koja se ne može učitati sada pada na isti onaj crtani placeholder umjesto da ostane prazan okvir. Bez veze su sve slike takve.

                  Šta ovo namjerno ne radi

                  • Ne prima narudžbe u red čekanja. Narudžba koja piše „poslano" a nije poslana je najgori mogući ishod u sali: gost sjedi i čeka, kuhinja je nikad ne vidi, a dok se veza vrati možda je već otišao, ili se cijena promijenila, ili je jelo nestalo. Čitati meni bez veze je korisno. Naručivati u prazno nije, koliko god bolje izgledalo na spisku funkcija.
                  • Dok je meni sa telefona, dugmad za dodavanje i za poziv osoblja se ne prikazuju. Dugme koje ne može doći do servera gore je od dugmeta kojeg nema.
                  • Naljepnica koja stvarno ne postoji i dalje kaže da ne postoji. Keširani meni za sto kojeg nema primao bi narudžbe koje niko ne može donijeti.

                  0.13.0

                  5. septembar 2026.

                  Dodano

                  • Ekran za goste govori jezik telefona. Do sada je govorio jezik lokala, što je tačan odgovor za redovne goste i pogrešan za razlog zbog kojeg lokal u Sarajevu ovo i želi u augustu: turista sa telefonom koji nije na bosanskom dobijao je ekran koji mora pogađati, na mjestu gdje niko nema vremena da mu objašnjava.
                  • Telefon na hrvatskom, srpskom ili crnogorskom čita isti katalog kao bosanski. Poslati ih na engleski zato što oznaka nije tačno „bs" bilo bi besmisleno.
                  • Telefon koji ne govori nijedan od ta dva dobija engleski. Gost iz Njemačke je bolje uslužen engleskim nego bosanskim.
                  • BS / EN prekidač gore desno na naslovnoj strani, i njegov izbor se pamti. Nije zastava - zastava je država, a ovo je jezik, i to nije isto. Većina gostiju ga nikad neće ni pritisnuti jer je telefon već odgovorio.

                  Šta ovo ne radi

                  • Ne prevodi meni. „Ćevapi, 10 komada, somun, luk" je ono što je lokal napisao i tako i ostaje, na svakom jeziku. Dugmad i natpisi su naši i njih prevodimo; hrana nije. Turista dobije ekran kojim zna rukovati oko menija o kojem bi ionako pitao - to je pošten dio problema i dio koji vrijedi riješiti.

                  Ostalo

                  • Konzola je dobila svoj test runner. Do sada nije imala nijedan test, a jeste najveći dio koda u projektu.

                  0.12.0

                  5. septembar 2026.

                  Dodano

                  • Meni koji zna šta se prodaje. Do sada je meni bio ono što je neko utipkao u junu, u tom redoslijedu, sa rasprodanom ribom na trećem mjestu. XPay sada čita zadnjih 30 dana narudžbi u toj poslovnici i s tim radi tri stvari.
                  • Rasprodano pada na dno kategorije - i nikad se ne skriva. Gost koji je došao zbog ribe zaslužuje rečenicu „ne večeras". Meni koji se tiho smanjio tjera ga da traži, pa da ipak pita konobara - a to je razgovor zbog kojeg ekran za naručivanje i postoji.
                  • Oznaka „Najtraženije", na najviše tri jela po kategoriji i najviše na trećini nje. Oznaka na devet od jedanaest jela ne znači ništa. Kod izjednačenja na granici oznaka se ne dodjeljuje nikome: tri jela sa po osam narudžbi i mjesto za jedno nije izbor koji se može napraviti pošteno.
                  • Traka na naslovnoj strani sada vodi ono što se stvarno naručuje. Slika je i dalje ulaznica - ta traka je jedino mjesto gdje bi slika koje nema bila cijela pločica - ali među slikanim jelima prvo ide ono što gosti biraju.
                  • Poredaj meni po traženosti, prekidač po poslovnici u Meniju. Isključen dok ga neko ne uključi: vlasnik je svoj meni posložio, a mašina koja mu ga preko noći prerasporedi je bezobrazna. Uključen, diže jela koja se traže na vrh njihove kategorije, a sve ostalo ostaje gdje je i bilo.

                  Kako ovo ne laže

                  • Ispod praga se ništa ne pomjera. Traženost druge večeri je tri narudžbe i slučajnost, a poredati po tome znači tu slučajnost zamrznuti: jelo koje se zateklo na vrhu naručuje se više, pa ostaje na vrhu. Poslovnica mora imati najmanje 30 naručenih stavki, a jelo najmanje 5, prije nego što broj bilo šta uradi.
                  • Prozor se kotrlja. Jelo koje se prestalo prodavati prestaje biti traženo.
                  • Otkazane narudžbe se ne broje. Otkazana narudžba nije dokaz da je neko to htio - najčešće je dokaz da je kuhinji ponestalo.
                  • Broji se po poslovnici, ne po firmi. Ljetna bašta i gradski kafić istog vlasnika nemaju isto najtraženije jelo.
                  • Marža se ne dira. Ideja iz koje je ovo nastalo tražila je i da se guraju jela sa većom maržom. XPay ne zna koliko jelo košta da se napravi, samo po čemu se prodaje. Poredati po cijeni i to zvati maržom značilo bi gurati skupo jelo, a to nije isto jelo. Za to prvo treba nabavna cijena u meniju.

                  Popravljeno

                  • Test za „Ponovi isto" je držao svoju kopiju logike umjesto da je uveze - ista greška zbog koje je test za vremenske zone jednom prolazio dok je original bio pogrešan. Sada uvozi pravu stvar.

                  Uputstva

                  • Novo poglavlje u Pomoći: kako se pravi meni, šta radi Rasprodano i zašto se artikal ne briše.

                  0.11.0

                  5. septembar 2026.

                  Dodano

                  • „Ponovi isto" - jedan dodir za istu rundu. Za barove: runda je istih četiri pića, a mahati konobaru da to kaže je upravo ono što ovo zamjenjuje. Server je iznova sastavi iz onoga što je narudžba zapisala i pošalje je običnim putem - cijena se čita iz menija, a jelo koje je u međuvremenu rasprodano se odbija. Jedino što se ušteđuje je kucanje.
                  • Dugme se pojavljuje samo kad se runda može ponoviti vjerno. Narudžba čije je jelo obrisano iz menija, ili čije opcije potiču od prije nego što su im se pamtili ID-evi, ne nudi dugme - jer „isto ponovo" koje tiho izostavi duplu kafu koju je neko platio gore je od dugmeta kojeg nema.

                  Promijenjeno

                  • Izbor opcije se sada pamti i po ID-u, ne samo po nazivu i cijeni. Naziv i cijena su dovoljni da se sačuva šta je gost pristao platiti; da se runda ponovi treba znati i koja je opcija to bila.

                  0.10.6

                  5. septembar 2026.

                  Popravljeno

                  • Dva gosta koja u istoj sekundi zatraže kod dobijala su oba kod za isti novac. Koliko naplatiti se računa čitanjem tuđih živih kodova, pa se kod tek onda pravi - dva koraka bez ičega između. Sada se, pod zaključanim redom računa, prebroji sve živo uključujući i taj novi kod, i ako je sto prekoračen kod se poništava prije nego što ga gost uopšte vidi.
                  • „Zatraži novi kod" nije tražio novi kod, nego vraćao na prethodni ekran.
                  • Neuspjela narudžba je ostavljala gosta na ekranu preporuka bez izlaza - jedino dugme je bilo ono koje je upravo palo.
                  • Dugme za konobara ostajalo je zaključano do kraja obroka na početnom ekranu, jer se taj ekran nikad nije osvježavao.
                  • Lokal s dvije poslovnice nije mogao pogledati drugu: mapa stolova se vraćala na prvu čim se izbor promijeni, a na Poslovnicama je sklapanje jedne otvaralo prvu.

                  0.10.5

                  5. septembar 2026.

                  Sigurnost

                  • Ekran u kuhinji je preko WebSocketa dobijao tok plaćanja. Njegov token nosi samo dozvole za narudžbe, SSE mu plaćanja filtrira, a socket je svaki terminal stavljao u istu sobu - pa je zidni ekran, koji svako u prostoriji može pročitati, dobijao iznose, napojnice, reference i stolove. Soba za narudžbe je sada odvojena od sobe za novac.
                  • Tri rute nisu imale ni ulogu ni dozvolu, pa ih je dosezao svaki autentifikovan token uključujući isti taj zidni ekran: podaci firme s licencnim ključem i bankovnim računima, fakture koje XPay ispostavlja lokalu, i mjesečna potrošnja.

                  Popravljeno

                  • Firma s više poslovnica nije mogla ništa uraditi s fakturom. Šest ruta adresira fakturu po ID-u i ne spominje poslovnicu, a kapija je tražila da se poslovnica imenuje - na ruti koja za nju nema mjesta. Sada se izvodi iz same fakture.
                  • Povrat je bio nedostupan za potplaćene i preplaćene račune, a nudilo se „Potvrdi uplatu" - koje na njima knjiži drugu, izmišljenu uplatu na pun iznos.
                  • Uvoz izvoda je uvijek išao zadnjem izvoru u listi. Jedan ref dijeljen na više polja za odabir datoteke pokazuje na ono koje se zadnje montiralo, pa su stvarne uplate završavale pod pogrešnim bankovnim računom.

                  0.10.4

                  5. septembar 2026.

                  Popravljeno

                  • Sto se mogao naplatiti više nego što račun iznosi. Plaćanje odabranih stavki nije poredilo zbir s onim što je preostalo, niti je vidjelo kodove koji drže novac a ne imenuju stavke. Četvero gostiju za računom od 40,00 moglo je uzeti po četvrtinu, pa jedan od njih odabrati sve četiri stavke i biti zatražen za još 40,00.
                  • Plaćena stavka se vraćala u ponudu. Čim uplata sjedne, kod izlazi iz živih statusa i njegove stavke opet postaju izabirljive - pa je sljedeći telefon mogao izabrati ćevape koje je neko već platio.
                  • Uplata veća od iznosa nije knjižena na račun stola. Gost koji uzme dio od 5,00 i u banci zaokruži na 6,00 ide pravo u PREPLAĆENO, a račun se knjižio samo na tačno PLAĆENO - pa je novac stajao u banci, pripisan uplati, dok je sto i dalje dugovao cijeli iznos i nije se mogao zatvoriti.

                  0.10.3

                  5. septembar 2026.

                  Popravljeno

                  • Ista uplata se knjižila dvaput. Kada matcher nađe neslaganje iznosa, on već upiše novac i tek onda otvori slučaj koji pokazuje na tu istu uplatu - pa je pritisak na „Podmiri" dodavao isti iznos ponovo. Račun od 60,00 na koji je stiglo 30,00 završavao je kao plaćen u cijelosti: lokal prestane tražiti ostatak, promet je pogrešan, a povrat se odobrava do iznosa koji nikad nije stigao.
                  • Uplata manja od računa zatvarala je račun. Status je bio samo PLAĆENO ili PREPLAĆENO, nikad POTPLAĆENO. Zakačiti uplatu znači „ovaj novac pripada ovom računu", a to nije isto što i „ovaj račun je plaćen".
                  • Iznos se čitao van transakcije, pa su dvoje koji rješavaju u istom trenutku oboje čitali stari zbir i oboje dodavali svoje.
                  • Potvrda „vidio sam uplatu" nije bila zaštićena od dvostrukog pritiska. Vanjski ID nosi vrijeme u milisekundama, pa provjera duplikata nikad nije vidjela dvije potvrde kao istu - dva pritiska su knjižila dvostruki iznos.

                  0.10.2

                  5. septembar 2026.

                  Popravljeno

                  • Backup van servera nije radio ni jednom. Tri odvojene greške, sve moje od jučer: noćni timer nije učitavao .env, pa su BACKUP_REMOTE i BACKUP_PASSPHRASE bili prazni svake noći; rsync je uvijek dobijao putanju do šifrovanih tajni čak i kad taj fajl nije napravljen, pa je svaki backup sa podešenim odredištem padao; a status je javljao „degraded" s razlogom koji je bio tačan iz pogrešnog razloga.
                  • Obnova bez argumenta vraćala je snimak koji je napravila prethodna obnova. Sigurnosne kopije se zovu xpay-db-before-restore-..., glob ih je hvatao, a „before" sortira iza svake cifre - pa je „najnoviji backup" uvijek bio taj. Ko obnovi dvaput vratio bi baš onu bazu od koje bježi.
                  • SMTP_SECURE i ALLOW_UNPROVEN_QR nisu stizali do kontejnera. Postoje u .env.example i u shemi, a compose ih nije prosljeđivao - postavka koju operater upiše i koja ne radi ništa. Provjerio sam svih 34; fali još JWT_ACCESS_TTL i JWT_REFRESH_TTL_DAYS, i oni su dodani.
                  • Verzija se upisivala prije nego što su slike izgrađene, pa je status javljao novo izdanje dok su kontejneri vrtjeli staro - a ako bi build pao, javljao bi verziju koja nikad nije ni startala.
                  • install.sh je zvao nepostojeću funkciju na grani čiji je jedini posao upozoriti operatera; pod set -e to je rušilo instalaciju umjesto upozorenja.

                  0.10.1

                  5. septembar 2026.

                  Popravljeno

                  • Dan je na serveru počinjao sat ranije, dva puta godišnje. Granica dana se računala tako što se pomak zone uzme u podne i primijeni na ponoć - a na dan kada se sat pomjera to su dva različita pomaka. Radilo je na mom računaru jer on dijeli sarajevsko ljetno računanje vremena; na serveru, koji radi u UTC-u, nije.
                  • Kraj dana je bio fiksnih 24 sata. Dan kada se sat vraća traje 25 sati, pa se gubio zadnji sat večeri - onaj u kojem je lokal otvoren.

                  Testovi

                  • Test je do sada držao vlastitu kopiju te aritmetike umjesto da je uveze, pa je kopija prolazila dok je original bio pogrešan. Sada uvozi pravi kod i provjerava oba dana pomjeranja sata, u tri vremenske zone servera.

                  0.10.0

                  5. septembar 2026.

                  Dodano

                  • Postavljanje lozinke sa servera. Zaboravljena lozinka vlasnika je do sada značila ručno upisivanje argon2id hasha u bazu - postupak koji niko nije zapisao i koji se ne smišlja u osam uvečer dok lokal čeka. Odjavljuje i sve ostale sesije, jer je razlog za promjenu lozinke obično to što je neko drugi možda zna.
                  • Drugi operater se može napraviti. Komanda je to odbijala i upućivala na „Admin konzolu" i „password reset flow" - ni jedno ni drugo nije postojalo. Jedan operater je loše mjesto za biti: ode na godišnji, ode iz firme, a nalog koji može suspendovati svaku firmu je onaj u koji niko drugi ne može ući.

                  0.9.9

                  5. septembar 2026.

                  Dodano

                  • Pretraga plaćanja. Jedna kutija: upišete poziv na broj ili iznos. Do sada se moglo tražiti samo po tačnom broju računa iz kase - jedinom broju koji gost koji pita nema. Poziv na broj se traži u svim oblicima (sa izvoda, sa računa, RF), bez obzira na razmake i velika slova.

                  0.9.8

                  5. septembar 2026.

                  Dodano

                  • Forma za fakturu pita ono što ta djelatnost stvarno treba. Registar na serveru odavno deklariše koja polja koja vrsta posla ima i kako ih zove, a niko to nije čitao - pa su i zakupodavac i komunalno pitani za „Predmet", dok je server znao da jedan hoće mjesec a drugi obračunski period. Sada stanodavac vidi „Mjesec" i „Nekretnina", komunalno „Obračunski period" i „Broj korisnika", a skladište „Otpremnica".

                  0.9.7

                  5. septembar 2026.

                  Popravljeno

                  • „QR profile BIH_IPS has not been confirmed with a bank" pisalo je ugostitelju na engleskom. Poruka je tačna i napisana za onoga ko drži server, a stizala je pred onoga ko drži restoran - koji nije birao jezik i ne zna šta je QR profil. Sada se prevodi i kaže mu šta može uraditi.

                  0.9.6

                  5. septembar 2026.

                  Popravljeno

                  • Jedna greška je crtala dvije crvene trake. Ekrani koji sami prikazuju grešku nisu gasili opštu traku iz rasporeda, pa je isti neuspjeh izgledao kao dva - a onaj ko broji trake zaključi da su se pokvarile dvije stvari. Opcija za to postoji odavno i ovi ekrani je nisu koristili.

                  0.9.5

                  5. septembar 2026.

                  Popravljeno

                  • Pregled je pisao „Naplaćeno danas" i kad je izabran prošli mjesec. Sada natpis prati period.
                  • Povrati se konačno vide. Analitika ih vraća i oduzima od prometa otkako povrati postoje, a nijedan ekran ih nije spominjao - pa je menadžer koji vidi manji broj ostajao bez objašnjenja zašto je manji. Sada stoje ispod glavnog iznosa, i na svakom redu u Plaćanjima.
                  • Uspješnost uparivanja je bila zakovana na 7 dana bez obzira na izabrani period, pa je uz prošli mjesec stajao postotak za sedmicu koja s njim nema veze.

                  0.9.4

                  5. septembar 2026.

                  Popravljeno

                  • Prihvatanje ugovora se nije nigdje zapisivalo. Forma za registraciju šalje taj zapis otkako je napisana, a shema ga nije deklarisala - pa ga je zod odbacivao na svakoj prijavi. Ugovor sam kaže da se čuva zapis o tome koja je verzija prihvaćena. Sada se piše i na firmu i u lanac revizije, jer zapis o pristanku vrijedi tačno onoliko koliko se može dokazati da nije naknadno mijenjan.

                  0.9.3

                  4. septembar 2026.

                  Popravljeno

                  • Status stranica je javljala verziju 0.0.0. Verzija je stizala do kontejnera kao promjenljiva iz ljuske, koja postoji samo dok install.sh traje - pa ju je gubio svaki ručni docker compose up -d, tačno ono što se uradi nakon uređivanja .env. Sada se upisuje u datoteku koju API čita, i prepisuje se pri svakoj instalaciji.

                  0.9.2

                  4. septembar 2026.

                  Popravljeno

                  • Slučaj uparivanja s više mogućih računa nije se mogao riješiti. Slučaj pamti račun samo kada je tačno jedan bio uvjerljiv, a zatvaranje traži račun - pa je situacija u kojoj čovjek najviše treba, dva računa koja oba odgovaraju, bila ćorsokak na svakom ekranu. Sada se bira iz liste, istom onom koju već koristi lista neuparenih uplata.
                  • Kandidati se sada vraćaju s iznosom, referencom i stolom. Slučaj ih je čuvao samo kao paymentId i bod - sve što je matcheru trebalo i ništa od onoga po čemu čovjek bira.

                  0.9.1

                  4. septembar 2026.

                  Popravljeno

                  • Poziv konobara se nije vidio nigdje gdje osoblje gleda. Prikazivao se na mapi stolova u konzoli - jedinom mjestu gdje niko ne stoji tokom smjene. Sada stoji na vrhu ekrana u kuhinji i za šankom, iznad stolova koji čekaju naplatu, jer čovjek koji te gleda ima prednost pred čovjekom koji vadi novac.
                  • Gost koji još nije naručio nije mogao pozvati konobara. Dugme je živjelo samo unutar ekrana računa, iza računa koji već ima narudžbe - pa ga osoba kojoj najviše treba, ona koja je upravo sjela, jedina nije mogla pritisnuti.

                  0.9.0

                  4. septembar 2026.

                  Popravljeno

                  • Jedan gost je zaključavao cijeli sto. Kada bi neko zatražio QR za svoj dio, cijeli račun je prelazio u „čeka se uplata": niko drugi se nije mogao pridružiti, sto nije mogao naručiti ništa više, a izlaz je bio zvati konobara. Sada samo kod za cijeli račun zaključava sto; kod za dio ga ostavlja otvorenim, što je i smisao dijeljenja računa.
                  • Izlazak sa QR ekrana je poništavao tuđe kodove. Poništavali su se svi živi kodovi na stolu, uključujući onaj kojim je neko drugi upravo plaćao - a taj kod je već držao njihove stavke, pa bi novac stigao na poništenu uplatu. Sada se poništava samo taj gost, a sto se otvara tek kad nijedan kod nije živ.

                  Dodano

                  • Vidi se ko je za stolom i čija je koja narudžba. Server tu listu vraća otkako grupno naručivanje postoji i niko je nikad nije nacrtao, pa se drugi telefon priključivao računu u potpunoj tišini.

                  0.8.9

                  4. septembar 2026.

                  Dodano

                  • Firma konačno može sama unijeti svoj bankovni račun. Endpoint postoji od početka i nijedan ekran ga nije zvao, a konzola je poručivala „dodajte ga u postavkama lokacije" - ekran koji ne postoji. Bez računa se ne mogu izdati ni QR kodovi za stolove, ni naplata, ni fakture, pa firma koja se sama registrovala nije mogla uraditi ništa što donosi novac.
                  • IBAN se provjerava kontrolnim ciframa prije spremanja. Svaki QR kod koji ta firma ikad odštampa nosi taj broj, a zamijenjene dvije cifre ne padnu glasno - banka ili odbije uplatu danima kasnije ili je uplati na tuđi stvarni račun.

                  0.8.8

                  4. septembar 2026.

                  Popravljeno

                  • Provjera pošte sada proba i port 26. cPanel serveri slušaju na 26 baš zato što hosteri filtriraju uobičajene portove, a relay servisi nude 2525. Proba je gledala samo 465 i 587, pa je zaključivala „hosting blokira" u situaciji koja ima izlaz koji radi odmah.
                  • Odbijena lozinka se više ne prijavljuje kao zatvoren port. Proba se autentifikuje, a gutala je svaku grešku - pa je na serveru gdje su i način šifriranja i lozinka bili pogrešni ispadalo da nijedan port ne odgovara, i krivio se hosting. Ako server odgovori i odbije lozinku, to dokazuje da je port otvoren, i sada tako i piše.
                  • MAIL_REPLY_TO nije bio nigdje dokumentovan iako kod čita tu postavku - a ona odlučuje gdje stiže odgovor kupca.

                  0.8.7

                  4. septembar 2026.

                  Popravljeno

                  • Poruka o pošti sada kaže i ko je kriv. „Pitajte ih da otvore" ne kaže koga, pa tiket putuje između dva dobavljača sedmicu dana. Jedna TCP veza to rješava: ako port 443 na istom hostu radi a nijedan SMTP port ne, ruta je ispravna i adresa nije blokirana - filtriraju se SMTP portovi, a to je hosting. Ako ni 443 ne prolazi, mail host odbija ovaj server.
                  • Stari status backupa čitao se kao ispravan. Fajl bez novih polja pisala je starija skripta, što znači da kopija sigurno nije napustila mašinu i tajne sigurno nisu unutra - a odsutno polje se čitalo kao „nema problema". To je bila tačno ona laž zbog koje je provjera i dodana.

                  0.8.6

                  4. septembar 2026.

                  Dodano

                  • Backup ide i van servera. BACKUP_REMOTE je bilo šta što rsync prima. Do sada su sve kopije padale na isti disk na koji piše i baza, pa bi gubitak mašine odnio i podatke i svih četrnaest kopija odjednom.
                  • Tajne ulaze u backup, šifrovane. .env nosi ENCRYPTION_KEY, bez kojeg se nijedan webhook secret ni šifrovana konfiguracija u vraćenoj bazi ne mogu pročitati. Obnova na novom hardveru je izgledala uspješno dok neko ne otvori prvi zapis. Šifruje se lozinkom koju drži vlasnik, jer backup je datoteka koja završi na mjestima o kojima niko pažljivo ne razmišlja.
                  • Status stranica javlja kada backup ne bi pomogao. Ako kopija ne napušta mašinu ili tajne nisu unutra, stanje je „degraded" s razlogom - oboje su nevidljivi do dana kada niko ne može provjeriti.

                  Popravljeno

                  • Dokumentacija je i dalje slala operatera da sam napravi pg_dump cron, a automatika postoji i radi svaku noć. Monitoring je bio uperen u /readyz, koji javlja „ok" dok backup nikad nije prošao i pošta pada.

                  0.8.5

                  4. septembar 2026.

                  Dodano

                  • Period u pregledu poslovanja. Danas, jučer, 7 dana, 30 dana ili vlastiti raspon. Sve na tom ekranu bilo je zakovano za tekući dan jer pozivi nisu nosili nijedan parametar, a server prima raspon oduvijek - pa se „koliko smo uzeli prošle subote" nije moglo pitati nigdje u konzoli.

                  Popravljeno

                  • Datum se čitao kao UTC ponoć. „1. septembar" je u Sarajevu počinjao u dva ujutro, pa bi dan obuhvatio dva sata prethodne noći i izgubio zadnja dva sata večeri - a to je za restoran najprometniji dio. Sada se goli datum tumači u vremenskoj zoni lokala, i ljeti i zimi i na dan pomjeranja sata.

                  0.8.4

                  4. septembar 2026.

                  Dodano

                  • Povrat novca u konzoli. Backend je bio gotov i pažljiv od ranije, a nijedan ekran ga nije zvao - i još gore, dva druga toka odbijaju operaciju i poručuju menadžeru „umjesto toga napravite povrat", pokazujući na dugme kojeg nije bilo. Prozor pokazuje koliko je naplaćeno, koliko je već vraćeno i koliko ostaje, i traži broj naloga iz banke jer XPay ne prenosi novac.

                  Popravljeno

                  • Djelimičan povrat nije ostavljao trag. Zapis u historiji plaćanja pisao se samo kada povrat pokrije cijeli iznos, pa je račun vraćen u dvije rate imao jedan zapis za oboje i nijedan za prvi.
                  • Filter na Plaćanjima nije imao REFUNDED ni OVERPAID, pa se vraćen račun nije mogao naći na jedinom ekranu koji ih nabraja.

                  0.8.3

                  4. septembar 2026.

                  Popravljeno

                  • Uplata koja se ne uklopi ni sa čim sada se može zakačiti za račun. Gost zaokruži 19,50 na 20,00 i uplata ostane bez doma. Lista je bila samo za čitanje, pa je jedini način da se račun zatvori bio „Potvrdi uplatu" - a to ubaci drugu, izmišljenu uplatu na iznos računa. Lokal je ostajao sa izmišljenih 19,50 označenih kao uparenih, stvarnih 20,00 i dalje neuparenih, i onih 0,50 koje su zaista stigle nigdje zapisanih.
                  • Uplata se kači na iznos koji je stvarno stigao, pa račun može završiti kao preplaćen. To je istina, i ništa ne odlučuje umjesto čovjeka da je razlika napojnica.
                  • Uz to i Zanemari, za priljev koji nema veze s naplatom.

                  0.8.2

                  4. septembar 2026.

                  Dodano

                  • Izvodi. Novi ekran: povežete izvor, učitate izvod iz e-bankarstva i vidite šta je od toga zatvorilo račun. Do sada je jedini dokumentovani način bio curl sa XML-om ugniježđenim u JSON polje, a ovo je posao koji se radi svako jutro.
                  • Preskočene stavke se konačno vide. Parser ih vraća oduvijek i njegov komentar tvrdi da se prikazuju u dashboardu. Nisu se prikazivale nigdje.
                  • Zadnja greška izvora se vidi. Zapisivala se pri svakom neuspjelom uvozu i nije se prikazivala, pa lokal čiji izvodi tjedan dana padaju nije imao načina saznati zašto.

                  Testovi

                  • Parser bankovnih izvoda je konačno testiran. 281 linija koja čita pravi bankovni XML nije imala nijedan test ni jedan uzorak u repozitoriju. Osam testova, među njima i onaj za slučaj koji sam parser opisuje kao „pravi novac koji stigne i nikad ne bude evidentiran": dva stola koja isti dan plate isti okrugli iznos, kod banke koja ne popunjava nijedno polje reference.

                  0.8.1

                  4. septembar 2026.

                  Popravljeno

                  • Gost s jednim telefonom nije mogao platiti. Skenira naljepnicu sa stola telefonom koji drži, a mi mu na tom istom telefonu nacrtamo QR i kažemo mu da ga skenira bankom. Niko ne može skenirati vlastiti ekran. Sada ispod koda stoje primalac, IBAN, poziv na broj i iznos - svaki red se dodirom kopira.
                  • Gost čiji je kod istekao čekao je zauvijek. Provjera je gledala samo status PLAĆENO, pa je onaj ko nije dovršio ostajao pod natpisom „čeka se potvrda banke" koliko god je bio voljan gledati. Sada dobije jasnu poruku i dugme za novi kod, i piše mu da ne plaća dvaput ako je već uplatio.

                  0.8.0

                  4. septembar 2026.

                  Dodano

                  • Licenca se sada aktivira sama. Firma zalijepi ključ koji je dobila nakon uplate i paket radi odmah. Ključ se ne može izmisliti - potpisuje se tajnom koju ima samo server - i nosi broj firme kojoj je izdat, pa tuđi ključ ne radi ništa.
                  • Pomoć i uputstva u konzoli. Kako gost plaća telefonom, kako se upari tablet konobara, ekran u kuhinji, postojeća POS kasa, stara kasa koja samo štampa, ko šta vidi od osoblja, i kako se zna da je neko platio. Pisano za nekoga ko to nikad nije radio, i pokazuje se samo ono što ta djelatnost ima.
                  • Trgovina i skladište kao djelatnosti, sa vlastitom sposobnošću vođenja zaliha. Ekrani za zalihe još nisu napravljeni; vrsta postoji da se konzola već sada ponaša ispravno - prodavnica ne dobija stolove ni meni.

                  Napomena o fiskalizaciji

                    0.7.2

                    4. septembar 2026.

                    Popravljeno

                    • Račun napravljen u konzoli nije se mogao poslati mailom. Dugme „Pošalji" se prikazuje samo kad račun ima e-mail kupca, a forma za novi račun to polje nije imala - pa se nije prikazivalo nikada. Dodano je polje, i dodan način da se adresa upiše i naknadno, jer izdani račun se ne može poništiti pa je bez toga to bio ćorsokak. Upisuje se samo ako je prazna: adresa se ispisuje na računu, a izdani račun je zapis, ne formular.
                    • invoice.paid se nije slao kada je račun uredno plaćen. Obavijest se šalje iz prelaza stanja i čita iznos s reda koji je taj prelaz upravo upisao - a novac se upisivao tek poslije, običnim update-om. Radnja koja čeka invoice.paid da zatvori narudžbu nije čula ništa. Stizalo je samo za neuredna plaćanja, što je najteža verzija ovog buga za primijetiti.
                    • RAW_TEXT je tvrdio da je potvrđen s bankom. Kapija koja čuva neprovjereni domaći QR profil propušta sve što nosi status PRODUCTION, a RAW_TEXT ne tvrdi ništa o svojim bajtovima - to mu je cijeli opis. Jedan poziv sa qrFormat: 'RAW_TEXT', s tokenom terminala, prolazio je pored provjere.
                    • Dokumentacija je tvrdila da se račun šalje kao link bez priloga. Šalje se i link i PDF, i tako je već neko vrijeme.

                    0.7.1

                    4. septembar 2026.

                    Dodano

                    • Pregled računa prije izdavanja. Do sada se izgled računa mogao vidjeti jedino tako da se račun izda - a izdavanje uzme broj iz serije firme i to se brisanjem ne vraća. Pregled crta isti PDF koji se šalje, samo je nacrt pečatiran sa NACRT i nema ni broj ni referencu ni kod, jer ih zaista nema.
                    • PDV se konačno može unijeti iz konzole. Model ga nosi po stavci od početka, a forma za novi račun nije imala nijedno polje za njega - pa se račun s PDV-om nije mogao napraviti bez API-ja. Jedna stopa za cijeli račun, 17%, uključena po difoltu; firma van sistema PDV-a je isključi i tada se porez uopšte ne ispisuje.

                    0.7.0

                    4. septembar 2026.

                    Promijenjeno

                    • Konzola se sada prilagođava struci. Knjigovođa, advokat i slobodni profesionalac dobijali su Stolove i Meni. Struka se bira pri otvaranju firme i server je cijelo vrijeme znao šta koja može - registar, čuvari ruta i forma računa to čitaju - a navigacija je bila jedino mjesto koje nije, pa je konzola svima nudila restoran.

                    Dodano

                    • Postavke. Puni naziv, naziv u upotrebi, JIB/PDV broj, kontakt i logo - sve što se ispisuje na fakturi. API je to primao od početka, ekrana nije bilo, pa firma nije mogla ni ispraviti vlastito ime ni dodati porezni broj koji na fakturi u BiH mora stajati.
                    • Logo firme na fakturi, i u PDF-u i na stranici koju kupac otvori.

                    Popravljeno

                    • Paketi Flex i Business pisali su se kao admin.plans.FLEX. Nedostajali su prevodi, pa su se ispisivali sirovi ključevi.
                    • PDF je u svojstvima dokumenta pisao „XPay" kao tvorca. Sada piše firma koja je fakturu izdala.

                    0.6.9

                    4. septembar 2026.

                    Popravljeno

                    • Matcher je uzimao hiljadu kandidata bez sortiranja. Preko te granice baza je vraćala proizvoljnih hiljadu - najvjerovatnije najstarije račune, a svježa uplata pripada najnovijima. Gore od izgubljene uplate: rezervni mehanizam po iznosu ju je onda mogao zakačiti za drugi račun s istim ukupnim. Sada ide najnovije prvo.
                    • Zatvaranje računa iz liste otvorenih uvijek je knjižilo gotovinu. Sto koji je platio uplatom evidentiran je kao novac preko šanka, pa je dnevni zbir keša bio pogrešan za taj iznos. Dodano dugme za uplatu na račun.
                    • Poziv konobara se nije mogao potvrditi. Endpoint postoji od početka i nijedan ekran ga nije zvao, pa je sto ostajao crven cijelo sjedenje, brojač je rastao preko dva sata, a gostu je dugme ostajalo zaključano.

                    Promijenjeno

                    • Tri vrste settlement izvora se više ne mogu napraviti. BANK_API_POLL, EMAIL_NOTIFICATION i IPS_CONFIRMATION nemaju ni adapter ni posao koji ih poziva ni inbound secret - izvor te vrste stajao bi u listi kao aktivan i čekao nešto što ne može stići. Dokumentacija je prebačena u buduće vrijeme.
                    • reportExport je isključen na sva tri paketa koja su ga prodavala. API ga vraća direktno na kredencijal firme koja plaća, a endpointa nema nigdje.

                    0.6.8

                    3. septembar 2026.

                    Uklonjeno

                    • „Provizija 0,00 KM" sa nacrtanog računa. Isti argument kao i sekcija „0%", samo napisan kao stavka na računu - a stavka na računu se čita kao činjenica. Bez nje su „Iznos" i „Ukupno plaćeno" bili isti broj pod dva imena, pa je ostalo ono što račun stvarno kaže: broj računa, plaćeni iznos i vrijeme.

                    0.6.7

                    3. septembar 2026.

                    Uklonjeno

                    • Sekcija „0%" sa naslovnice. Naknada po transakciji kod Flex paketa i kod prekoračenja jeste fiksna, ne postotak - ali ogromna nula na ekranu je prvo što se pročita, a ostalo je sitno ispod nje. Restoran koji plati prekoračenje neće se sjetiti pasusa. Cijena je već jasno napisana u tabeli paketa i tamo joj je mjesto.

                    0.6.6

                    3. septembar 2026.

                    Popravljeno

                    • Provjera pošte sada proba i drugi port, ne samo drugi način šifriranja. Produkcija je javila „Greeting never received (mail.xpay.ba:587, STARTTLS)" - a taj host odgovara i na 465 i na 587 kada se pita izvana. Kada nijedan port ne odgovori, to nije postavka nego mreža, i sada tako i piše: server ne može doći do mail hosta, pa to treba otvoriti kod hostinga.

                    0.6.5

                    3. septembar 2026.

                    Popravljeno

                    • Status stranica je pisala da pošta radi dok nije radila. Zeleno je bilo vezano za to da su četiri postavke unesene, a ne za to da server odgovara - pa je ostajalo zeleno kroz svaki neuspjeli račun. Sada se prikazuje ono što je server zadnje rekao, uključujući razlog. Provjera se radi u pozadini, pa javna stranica nikada ne čeka na SMTP.

                    0.6.4

                    3. septembar 2026.

                    Popravljeno

                    • Ime se i dalje pisalo dvaput. Dostavljeni logo sadrži veliki ukrasni X, pa zatim riječ XPAY - a riječ već počinje na X, tako da cijeli fajl pročitan slijeva nadesno kaže XXPay. To nije lockup nego dvije varijante iste stvari, pa se sada razdvajaju: riječ ide svuda gdje stoji ime, a X samo tamo gdje ima mjesta jedino za kvadrat.

                    Dodano

                    • SMTP_SECURE. Do sada je način šifriranja zaključivan iz porta, što je tačno za 465 i 587 a netačno za sve ostalo. Sada se može reći izravno.
                    • Test pošte kaže šta ne valja. „Greeting never received" ne imenuje ni server ni postavku. Kada se to desi, XPay isproba suprotni način šifriranja i, ako server odgovori, napiše koju vrijednost treba postaviti. Greška uz to nosi host, port i način koji je pokušan.

                    0.6.3

                    3. septembar 2026.

                    Popravljeno

                    • Logo je bio u crnoj kutiji. Priprema logotipa je pretpostavila da je slika na bijeloj podlozi, jer je svaki preglednik tako prikazuje. Datoteka je već imala prozirnost, pa je obrada svaki prozirni piksel pretvorila u crni. Otuda crna pozadina, mutan znak i favicon sa kockom - sve tri stvari su bile ista greška.
                    • Ime se pisalo dvaput. Pored znaka X stajala je i riječ „xpay", pa je ispadalo XXPay. Logo već sadrži i znak i ime, pa se koristi cijeli.

                    0.6.2

                    3. septembar 2026.

                    Dodano

                    • Dugme za probnu poruku. Provjera e-mail podešavanja je sada u konzoli, na stranici za e-mail: unese se adresa i pošalje prava poruka. Ako mail server odbije, prikazuje se njegov odgovor, jer razlog je skoro uvijek u odbijanju.

                    0.6.1

                    3. septembar 2026.

                    Promijenjeno

                    • Novi logo. Znak je sada pravi logo umjesto ranije nacrtane zamjene, na sajtu, u konzoli i na prikazima proizvoda.
                    • Logo u kartici pregledača. Favicon u tri veličine i ikone za telefone, pa se XPay prepoznaje u nizu otvorenih kartica.

                    0.6.0

                    3. septembar 2026.

                    Dodano

                    • Objekat sam podešava račun na koji stiže novac. Ko se sam prijavi dobija lokaciju bez bankovnog računa, namjerno, da se ništa ne može naplatiti prije nego što neko kaže gdje novac ide. Do sada to nije imao gdje reći: račun se mogao dodati samo pri otvaranju nove lokacije ili preko operatera. Sada se postavlja i mijenja iz same konzole.
                    • IBAN se provjerava prije nego se upiše. Kontrolne cifre hvataju upravo ono što se stvarno kuca pogrešno: jednu pogrešnu cifru i dvije zamijenjene. Pogrešan IBAN je novac koji ode negdje drugdje, a onaj ko ga je ukucao to nikada ne sazna. Provjerava se i dužina po državi, a greška kaže šta je pogrešno umjesto da samo odbije.

                    Promijenjeno

                    • Jedna provjera IBAN-a umjesto dvije. Ista logika je postojala na dva mjesta. Dvije implementacije pravila o tome gdje novac slijeće je jedna previše.

                    0.5.0

                    3. septembar 2026.

                    Dodano

                    • Noćna sigurnosna kopija. Baza i sve postavljene slike se svake noći u 03:20 sami arhiviraju i čuvaju četrnaest dana. Do sada je jedina uputa bila da operater ručno pokrene pg_dump, što znači da kopije nije bilo.
                    • Kopija se provjerava, ne samo pravi. Arhiva manja od praga se odbacuje jer to nije baza nego poruka o grešci, a svaka arhiva mora proći vlastitu kontrolnu sumu. Prekinut zapis na punom disku izgleda ispravno po veličini i ne može se pročitati, a to bi se otkrilo tačno u trenutku kada zatreba.
                    • Vraćanje podataka. Skripta koja izlistava dostupne kopije i vraća odabranu. Prije vraćanja pravi kopiju trenutnog stanja, jer se dešava da vraćena kopija nije ona prava.
                    • Stanje kopija na status stranici. Ako kopije nema ili je stara, to se vidi pored ostalih komponenti. Kopija koja je tiho prestala raditi je gora od nikakve, jer se vjeruje da postoji.

                    Promijenjeno

                    • Doctor provjerava kopije. Da li je tajmer instaliran, da li je posljednja kopija uspjela i koliko ih ima.

                    0.4.1

                    3. septembar 2026.

                    Dodano

                    • Provjera e-mail podešavanja. Operater sada može poslati probnu poruku sa servera i vidjeti šta je mail server odgovorio. Do sada se znalo samo da li su podešavanja upisana, a ne i da li rade: pogrešna lozinka je i dalje izgledala ispravno, svaka faktura bi tiho pala, a prvo što bi se čulo bilo bi pitanje klijenta gdje mu je ugovor.

                    0.4.0

                    3. septembar 2026.

                    Dodano

                    • Povrat novca. Do sada se povrat nije mogao ni evidentirati: postojala je tabela i status, ali nijedna ruta koja bi ih napunila. Sada se povrat bilježi, djelimično ili u cijelosti, sa razlogom i sa referencom banke.
                    • Djelimični povrati se sabiraju. Jedno pogrešno jelo za stolom od šest ne poništava cijeli račun. Plaćanje ostaje PLAĆENO dok povrati ne pokriju sve što je stiglo, jer novac je i dalje najvećim dijelom objekta.

                    Promijenjeno

                    • Promet je ono što je objekat zadržao. Djelimičan povrat nije skidao ništa sa prometa: plaćanje je i dalje bilo PLAĆENO i cijeli iznos se brojao. Jedno vraćeno jelo je svaki dan uvećavalo prikazani promet za cijenu tog jela, bez ijednog traga na ekranu. Povrati se sada oduzimaju i posebno prikazuju.
                    • Vraća se ono što je stiglo, ne ono što je traženo. Račun koji je plaćen manje nego što glasi primio je manje; povrat punog iznosa bi vratio novac koji nikada nije ni uzet.
                    • Otvoren račun za stolom se umanjuje. Ako je račun još otvoren, vraćeni novac se skida sa plaćenog iznosa. Zatvoren račun se ne prepravlja - povrat stoji pored njega kao zaseban zapis.

                    Važno

                      0.3.0

                      3. septembar 2026.

                      Dodano

                      • Više telefona za jednim stolom. Do sada je sto pripadao onom ko prvi skenira; svi ostali su dobijali „račun je već otvoren, pitajte osoblje". Sada se svako ko skenira pridružuje istom računu, dobija svoj naziv (Gost 1, Gost 2) i svoja narudžba se vodi na njega.
                      • Plaćanje samo svojih stavki. Podjela na jednake dijelove nije poštena podjela kada je jedno jelo, a drugo kafa. Gost sada može odabrati stavke koje plaća; iznos se računa na serveru iz samih stavki. Kada se otvori odabir, stavke tog telefona su već označene, pa je najčešći slučaj bez ijednog dodira.
                      • Poziv osoblja. Dugme koje ne znači ništa osim „dođite". Ranije se konobar mogao pozvati jedino tako što gost kaže da plaća gotovinom, što je račun prebacivalo u stanje plaćanja i zaustavljalo dalje naručivanje. Poziv koji već stoji zadržava svoje vrijeme, pa sto koji najduže čeka ostaje prvi na ekranu.
                      • Stolovi koji zovu na tlocrtu. Poziv ima prednost nad svim ostalim stanjima, uključujući čekanje na plaćanje, i pokazuje koliko minuta traje.

                      Promijenjeno

                      • Račun koji se plaća ne prima nove goste. Jedina vrata koja ostaju zatvorena: dok neko poravnava račun, novi telefon se ne može pridružiti, jer račun koji naraste nakon što je dogovoren je gori od gosta koji čeka pola minute.
                      • Stavka koju neko već plaća ne može se platiti dvaput. Šta je zauzeto izvodi se iz živih kodova, istim pravilom i istim vremenskim prozorom koji već koristi podjela na jednake dijelove.

                      0.2.0

                      1. septembar 2026.

                      Dodano

                      • Fakture. Merchant izdaje račun svom kupcu: napravi nacrt, izda ga, pošalje kupcu link. Uplata koja ga plaća sravnjuje se istim putem kao i račun za stolom: kada stigne odgovarajuća potvrda o uplati, transakcija se povezuje sa fakturom.
                      • Link za kupca. Izdavanje pravi nepogodiv link na kojem stoji iznos, poziv na broj i QR koji čita bankovna aplikacija. Štampa se, jer tako račun stigne do knjigovođe.
                      • Potraživanja. Biller koji ima svoj billing može poslati šta mu se duguje, sa svojim brojem računa, i matcher ga prepozna u izvodu.
                      • Mod samo za sravnjivanje. Lokacija se može podesiti da uparuje uplate i ne izdaje ništa.
                      • Vrsta posla. Operater pri otvaranju bira je li firma restoran, freelancer ili agencija, kirija, komunalno ili webshop. To odlučuje šta nalog uopšte nudi.
                      • Javni sajt. Devet stranica, na istim dizajn tokenima kao konzola.
                      • Status stranica. Ova, sa stanjem sistema i historijom verzija.

                      Promijenjeno

                      • Jedna paleta. Konzola je prešla na paletu koju koristi sajt. Zelena sada znači jedno te isto na oba mjesta: ova uplata je sravnjena.
                      • QR profili nose status. Produkcija odbija svaki profil koji nije potvrđen s bankom. BIH_IPS je nacrt dok se to ne desi.
                      • Otvaranje firme pravi firmu koja može naplatiti. Ranije je merchant nastajao bez poslovnice i bez računa na koji novac stiže, pa je prva radnja padala.

                      Popravljeno

                      • Kucanje u dijalogu je pomjeralo kursor na dugme za zatvaranje. Svaka forma u konzoli je to radila nakon jednog slova.
                      • Slanje fotografije javljalo je "internal server error". Ograničenje veličine zahtjeva bilo je manje od bilo koje prave slike, pa je zahtjev odbijan prije nego što bi ruta koja bi ga prihvatila uopšte bila pokrenuta.
                      • Provjera merchanta nije granica. Osoblje vezano za jednu poslovnicu moglo je otkazati narudžbe, zatvarati račune i gasiti kodove za stolove u drugoj poslovnici istog lanca.
                      • Refresh tokeni. Ukraden token upotrijebljen nakon rotacije sada se primijeti i gasi sve tokene te sesije.
                      • Zapisnik sada pokriva ko i odakle, i kaže koliko je dug, pa brisanje zapisa s kraja više nije nevidljivo.
                      • Brojevi merchanata potrošeni neuspjelim otvaranjem vraćaju se u pool, a popunjenost se prijavljuje prije nego prostor nestane.
                      • Red za uparivanje kaže koliko slučajeva zaista ima. Prikazivao je pedeset najstarijih i ništa o ostatku, pa najnoviji slučaj nije bio dohvatljiv.