Pavol Rašev
Prijímam nové projekty
Všetky projekty

Canteen

Objednávky a výdaj obedov vo firemných jedálňach. Zamestnanci si obed vyberú na webe alebo na kiosku, kuchyňa vie počty vopred a pri výdaji stačí načítať kartu.

Klient
Fellow Bytes, vlastný produkt
Moja rola
Architektúra, všetky štyri frontendy, API
Obdobie
Apríl 2026 – dodnes
Stav
Vo vývoji, pracujem na offline režime
Technológie
Next.js 16, React 19, Vite PWA, NestJS, Prisma, PostgreSQL, Redis, Socket.IO, Python
Canteen: screenshot
Canteen on a phone

Prečo vznikol

Firemná jedáleň varí pre zamestnancov niekoľkých firiem. Každý zamestnanec má nárok na jeden dotovaný obed denne a firme sa účtuje podľa počtu takých obedov, ktoré jej ľudia zjedli, nie podľa sumy. Tento počet sa zvyčajne vedie na papierových zoznamoch a na konci mesiaca v tabuľke.

Kuchyňa nevie, koľko má navariť, na výdaji hľadajú mená vo vytlačenom zozname a vyúčtovanie znamená deň ručného počítania. Canteen nahrádza všetky tri jedným systémom, do ktorého prevádzkovateľ, kuchyňa, výdaj aj zamestnanci vidia každý zo svojej strany.

Štyri aplikácie, jedno API

Každá rola dostane obrazovku, ktorú potrebuje, a nič navyše. Všetky štyri komunikujú s tým istým NestJS API. Typy, formátovanie súm a biznis pravidlá sú v spoločných balíčkoch, takže sa aplikácie nemôžu rozísť v tom, čo znamená dotácia alebo uzávierka objednávok.

Výdajný terminál po načítaní karty: dve dnešné objednávky stravníka pripravené na výdaj

Výdajný terminál

Pre toho, kto vydáva obedy. Vite PWA na tablete s Windows a čítačkou čiarových kódov.
  1. Po načítaní karty sa otvoria dnešné objednávky stravníka. Čítačka sa správa ako klávesnica, takže funguje akákoľvek USB čítačka.
  2. Terminály sú prepojené naživo. Obed vydaný na jednom z ostatných zmizne, cieľ je pod 200 ms.
  3. Dotovaný obed a všetko navyše sú samostatné objednávky, pretože firma platí za každý dotovaný obed.
  4. Výdaj je jedno ťuknutie a požiadavka je idempotentná: dvojité ťuknutie alebo opakovanie po výpadku spojenia vydá obed iba raz.
Nasledujúci týždeň s počtom jedál na každý deň
Výber polievky a hlavného jedla so sumou po dotácii

Web pre zamestnancov

Pre zamestnancov klientskych firiem. Next.js, navrhnutý najprv pre mobil.

Týždeň dopredu, denné menu s alergénmi, priebežný súčet, ktorý ukazuje, čo pokryje dotácia, a história objednávok s kreditom.

Kiosk po načítaní karty: záložky dní, jedlá s alergénmi, súčet a potvrdenie

Kiosk

Pre tých, čo prídu bez objednávky alebo nemajú mobil po ruke. Vite PWA na tablete pri vchode.

Stravník priloží kartu, na veľkých dotykových tlačidlách vyberie deň a jedlá a potvrdí. Kiosky sa s jedálňou spárujú cez QR kód a každé zariadenie má limit požiadaviek.

Mesačný report na vyúčtovanie: vydané obedy, dotované obedy, nevyzdvihnuté obedy, tabuľka po zamestnancoch a export do XLSX

Administrácia

Pre prevádzkovateľa, vedúceho jedálne a administrátora každej klientskej firmy.

Menu, firmy, zamestnanci, kredit, kiosky a mesačný report na vyúčtovanie, ktorý predtým znamenal deň počítania. Report sa pripraví na pozadí a príde ako XLSX.

Ako to do seba zapadá

AdminNext.jsWeb pre zamestnancovNext.jsKioskVite PWA, offline frontaVýdajný terminálVite PWA, offline frontaFirmFlow appExpo, React NativeCanteen APINestJS, REST + Socket.IOshared domain packageidempotent writesFirmFlow APISymfony 8, identityPostgreSQL 16row-level securityRedis + BullMQlive sync, report jobsParser menuPython, .docx na jedlánaživotoken stravníka, 15 min

Rozhodnutia, ktoré stoja za zmienku

  • Dáta firiem oddeľuje databáza.Každá požiadavka nastaví na svojom spojení aktuálnu firmu cez SET LOCAL a PostgreSQL row-level security (pravidlá prístupu k jednotlivým riadkom) filtruje každý dotaz. Zabudnutý WHERE tak nemôže jednej firme ukázať objednávky inej firmy.
  • Výdaj funguje aj bez internetu.Kiosk aj terminál zapíšu každú akciu najprv do offline fronty v IndexedDB a keď sa spojenie vráti, odošlú ju znova. Každý záznam nesie svoj Idempotency-Key, takže opakované odoslanie po timeoute nemôže vydať obed dvakrát.
  • Menu nikto neprepisuje.Kuchyňa už teraz píše týždenné menu vo Worde. Malá služba v Pythone z toho .docx vytiahne jedlá, dni a alergény. Ceny sa pri zverejnení menu doplnia z cenníka platného k danému dátumu.
  • Účty personálu je ťažké ukradnúť.Refresh tokeny sa pri každom použití vymenia a ukladajú sa ako hash. Keď niekto použije starý token, zneplatní sa celý reťazec. Personál si môže zapnúť druhý faktor TOTP (kód z autentifikačnej appky) s obnovovacími kódmi.
  • Uzávierka mesiaca beží na pozadí.Report na vyúčtovanie počíta worker v BullMQ a hotový príde ako XLSX s notifikáciou. Požiadavka tak nemusí čakať otvorená, kým sa spočíta celý mesiac obedov.

Kde je projekt dnes

398 commitov od apríla 2026 a 123 testovacích súborov vo Vitest a Playwright. Objednávky, výdaj, kiosk, reporty a prihlásenie s druhým faktorom sú hotové. Teraz pracujem na odolnosti voči výpadkom internetu. Ďalší krok je malý lokálny server (edge node) v každej jedálni, aby sa kiosk a terminál videli, aj keď budova stratí pripojenie.

Z rovnakého backendu čerpá aj FirmFlow, mobilná appka, v ktorej si zamestnanci obed objednajú a vyzdvihnú.