RFID výdej obědů

RFID výdej slouží k rychlému a auditovatelnému potvrzení, že strávník skutečně dostal své jídlo. Strávník přiloží čip ke čtečce u výdejního okénka, systém okamžitě označí dnešní objednávku jako vydanou a zapíše událost do auditu. Tato stránka popisuje, jak operátor RFID výdej zprovozní a spravuje. Pro denní provoz obsluhy (kuchařky) máme samostatnou stránku Obsluha — výdej obědů.

Architektura: tři vrstvy autentizace

Pochopení vrstev pomáhá řešit problémy a navrhovat tok zaměstnanců:

VrstvaCo identifikujeToken / hesloKde žije
User JWTOperátora kuchyně (admin akce)Email + heslo → JWT + refresh cookieMemory (access) + httpOnly cookie (refresh)
Device tokenKonkrétní kuchyňské PC = terminálX-Device-TokenlocalStorage prohlížeče (klíč edumeal.scan-config.v1)
Staff sessionKonkrétní směnu obsluhyX-Staff-SessionlocalStorage prohlížeče (klíč edumeal.staff-session.v1), TTL 8 hodin

Pickup endpointy (POST /pickups, POST /pickups/manual, POST /pickups/{id}/void) ověřují device token + staff session, ne user JWT. Obsluha tedy nemá uživatelské jméno + heslo — místo toho má PIN nebo služební čip, kterými otevírá staff session přímo na terminálu. Operátor user JWT používá jen pro nastavení (pairing zařízení, vystavení PINu, přiřazení čipu).

Co RFID výdej řeší

  • Kontrola, kdo si jídlo skutečně vyzvedl — objednávky bez výdeje lze dohledat v reportech.
  • Zamezení dvojitému výdeji — partial unique index na úrovni DB blokuje druhý aktivní pickup pro stejnou objednávku, i přes manuální cestu.
  • Audit pro spory — každý sken (úspěšný i odmítnutý) je zaznamenán s časem, místem a obsluhou, která jej provedla.
  • Rychlý provoz u okénka — jeden tap čipem, žádné papíry ani podpisové archy.

Hardware a předpoklady

Čtečka

Edumeal podporuje USB RFID čtečky pracující v režimu emulace klávesnice (HID keyboard wedge). Čtečka po přiložení čipu “napíše” UID čipu do aktivního pole jako sekvenci znaků zakončenou Enterem — nepotřebuje žádný ovladač ani instalaci.

Ověřené modely (HF 13,56 MHz + LF 125 kHz, USB HID keyboard wedge):

ModelFrekvencePoznámka
ACS ACR1281U-C2125 kHz + 13,56 MHzDoporučená čtečka. Dual-frekvence, plug & play HID keyboard mód (žádný ovladač), podporuje MIFARE Classic 1K/4K, DESFire, NTAG, ISO 14443A/B i ISO 15693 — pokryje ISIC i běžné kuchyňské čipy bez zvláštní konfigurace.
R20DC125 kHz + 13,56 MHzLevná dual-frekvenční alternativa, plug & play HID keyboard mód (žádný ovladač), pípák a LED potvrzují sken. Čte MIFARE Classic 1K/4K (S50/S70) a čipy typu EM4100 na 125 kHz. Výstup přepněte na hex (dodávaná Windows utilita umí i desetinný formát, ten se s uloženými UID nesejde). Podporu ISIC karet výrobce neuvádí, ověřte si ji přiložením karty v Testu čtečky níže.

Tip: Edumeal je tolerantní k formátu UID. Čtečka může vysílat UID jako čistý hex (044E2EAA031C90) nebo se separátory mezi byte páry (04 4E 2E AA 03 1C 90, 04:4E:2E:AA:03:1C:90, 04-4E-2E-AA-03-1C-90). Frontend i backend separátory stripují a UID ukládají kanonicky uppercase hex bez separátorů, takže scan i ručně zadaný UID se vždy match-ují.

Čipy

Strávník může použít:

  • Vlastní RFID čip nebo náramek vydaný kuchyní (typicky MIFARE Classic 1K, NTAG, nebo DESFire).
  • ISIC kartu, pokud ji strávník vlastní — edumeal umí ISIC číst přes UID, není potřeba žádná dodatečná aplikace. (ISIC vydává ISIC ČR, ne kuchyně.)

Pozor: Edumeal čte pouze UID (sériové číslo) čipu, nikdy nepřistupuje k chráněným sektorům karty. ISIC ani jiné karty nejsou nijak modifikovány.

Síť

Kuchyňské PC potřebuje LAN/Wi-Fi připojení do internetu. Edumeal má vestavěný režim pro krátké výpadky sítě (5—15 minut) — výdej pokračuje lokálně a po obnovení sítě se data automaticky doplní. Pro plně offline provoz bez připojení edumeal navržen není.

Krok 1: Spárování terminálu

Každé výdejní okénko má v systému svůj vlastní terminál vázaný na konkrétní výdejní místo. Tato vazba je trvalá — terminál nelze sdílet mezi výdejními místy. Pokud máte v jedné kuchyni dvě okénka, vytvořte dva terminály na dvou PC.

  1. Na kuchyňském PC zapojte USB čtečku.
  2. Otevřete prohlížeč a přihlaste se jako operátor e-mailem + heslem.
  3. Jděte na Výdej v sidebar → pokud PC ještě není spárované, edumeal vás přesměruje na Spárovat terminál (cesta /operator/scan-setup).
  4. Vyberte výdejní místo z rozbalovacího seznamu a zadejte popisný název terminálu (např. “Hlavní okénko — ZŠ Dlouhá”).
  5. V sekci Test čtečky přiložte testovací čip ke čtečce. Pod inputy se hned objeví přečtené UID — to znamená, že čtečka i klávesnicový layout fungují správně.
  6. Klikněte na Spárovat. Systém vytvoří záznam terminálu v API a vrátí device token, který se okamžitě uloží do localStorage tohoto prohlížeče.
  7. Po spárování se UI automaticky přesune na /scan/start — to je obrazovka pro obsluhu, na které se kuchařka přihlásí. Operátor se může nyní odhlásit — terminál pojede dál bez něj.

Tip: Device token se po spárování nikde nezobrazuje — žije pouze v localStorage daného prohlížeče. Pokud PC nebo prohlížecí profil vyměníte, projděte setup znovu a v UI vytvořte nový terminál (starý zneplatněte z RFID → Zařízení).

Klávesnicový layout

Edumeal čte stisknuté klávesy přes fyzické scan kódy (KeyboardEvent.code), ne přes znaky, které OS vygeneruje. Díky tomu funguje výdej i na české klávesnici — fyzická “0” je vždy Digit0, i když ji OS jinak mapuje na é. Žádná konfigurace klávesnice ani čtečky není potřeba pro hex UID.

Pozor — platí jen dokud nemáte zaostřené (klikem aktivované) textové pole. Toto čtení scan kódů funguje, když stránka jen “poslouchá” čtečku na pozadí (test čtečky, přiřazení čipu při nezaostřeném poli). Jakmile kliknete přímo do input pole a snímáte/píšete do něj, znaky už jdou normální cestou přes OS layout — a na české klávesnici se číselná řada změní na +ěščřžýáíé (přežijí jen písmena A—F). Pokud tedy v poli vidíte české znaky místo číslic, buď do pole neklikejte (nechte čtečku, ať ho vyplní sama), nebo si pro ruční zadání přepněte klávesnici do angličtiny.

Krok 2: Onboarding obsluhy

Každá kuchařka má v systému vlastní uživatelský účet s rolí kitchen_staff. Tato role je oddělená od role operator — obsluha nevidí ceny, recepty ani uživatele, vstupuje pouze do výdejního UI a autentizuje se PINem nebo čipem.

  1. V levé navigaci RFIDObsluha (cesta /operator/kitchen-staff) → klikněte + Přidat uživatele obsluhy.
  2. Vyplňte jméno, příjmení, e-mail a heslo. Heslo je technický seed účtu — obsluha se nepřihlašuje do aplikace e-mailem, ale heslo musí být platné kvůli interní konzistenci uživatelských záznamů.
  3. Po uložení se otevře detail panel obsluhy. Zde nastavíte buď čip, nebo PIN, nebo oba (záleží, jak chcete, aby se obsluha přihlašovala).

Přiřazení služebního čipu

V detail panelu obsluhy je sekce Čip obsluhy:

  1. Přiložte čip ke čtečce — pole UID nového čipu se vyplní automaticky tím, co reader emituje (uppercase hex). Neklikejte do pole — musí zůstat nezaostřené, aby čtení fungovalo nezávisle na klávesnici. (Na přihlašovací obrazovce terminálu tohle omezení neplatí, čtečka tam čte i přes zaostřené pole; sem se to zatím nepřeneslo.) Alternativně lze UID napsat ručně v jakémkoli formátu (lowercase, s mezerami atd.) — edumeal ho znormalizuje při uložení; pro ruční zadání na české klávesnici si přepněte layout do angličtiny (viz Klávesnicový layout).
  2. Klikněte Přiřadit.
  3. V seznamu se objeví aktivní čip. Vedle něj je tlačítko Odebrat pro zneplatnění (ztráta, výměna).

Pozor: Služební čip musí být fyzicky jiný než čip strávníka. Edumeal udržuje služební čipy v separátní tabulce identity.staff_chips oddělené od identity.diner_chips — stejný fyzický čip nelze přiřadit zároveň jako služební a jako strávnický (chrání před záměnou v auditu).

Vystavení PINu (fallback)

  1. V detail panelu obsluhy sekce PIN obsluhy.
  2. Zadejte 4—8 číslicový PIN.
  3. Klikněte Vydat PIN (nebo Rotovat PIN, pokud už existuje aktivní). PIN se hashuje (bcrypt) a uloží — raw hodnotu si zapamatujte teď, později ji systém znovu nezobrazí.
  4. Předejte PIN obsluze osobně.

PIN musí být v rámci provozu unikátní. Pokud zadáte PIN, který už používá jiný člen obsluhy, edumeal ho odmítne. Není to formalita: přihlášení na směnu se dělá jen podle PINu, bez výběru jména, takže dva stejné PINy se nedají rozlišit — směna i všechny výdeje v ní by se připsaly tomu, koho databáze vrátí první. Rotace PINu na stejnou hodnotu u téhož člověka je v pořádku.

Ochrana proti hádání PINu: po 5 neúspěšných pokusech se další pokusy na daném terminálu na 15 minut odmítnou (obsluha vidí hlášku, že má vyčkat). Totéž platí pro PIN vyžadovaný u storna, tam se počítadlo vede per člen obsluhy. Zámek se počítá zvlášť pro každý terminál, takže zablokované okénko neblokuje druhé. Služební čip zámek neomezuje — pokud si obsluha PIN nepamatuje, přihlásí se čipem a nemusí čekat.

Tip: PIN i čip mohou pro stejnou obsluhu koexistovat. Obsluha pak má fallback — když zapomene čip doma, přihlásí se PINem. Na přihlašovací obrazovce jsou obě cesty vedle sebe, nepřepíná se mezi nimi.

Ověření u storna. Stornování už zapsaného výdeje mění historii, takže si vyžádá čerstvé ověření obsluhy — služebním čipem, nebo PINem, jedno za celý výběr. Manuální výdej ověření nevyžaduje: PIN u něj dřív byl, ale u okénka znamenal psát ho pokaždé, když někdo zapomněl čip. Zapsaný výdej dál nese, kdo ho pořídil, na jaké směně a s jakým důvodem.

Krok 3: Přiřazení čipu strávníkovi

Strávník dostane svůj RFID čip a operátor ho jednorázově spáruje s profilem strávníka v systému:

  1. Sekce RFID → Čipy (cesta /operator/chips).
  2. Vyhledejte strávníka — jméno, příjmení, nebo variabilní symbol (stejné hledání jako v seznamu strávníků; celé jméno naráz nefunguje, hledejte jedním slovem). U nalezených strávníků se vpravo ukazuje VS, takže poznáte, kterého vybíráte.
  3. Klikněte na strávníka ve výsledcích.
  4. Sekce Přiřadit čip: přiložte čip ke čtečce. Pole se vyplní automaticky uppercase hex hodnotou. Neklikejte do pole — nechte ho nezaostřené, jinak na české klávesnici dostanete místo číslic +ěščřžýáíé (viz Klávesnicový layout).
  5. Klikněte Přiřadit.

Jeden strávník může mít vždy maximálně jeden aktivní čip. Při ztrátě nebo výměně:

  1. U aktivního čipu klikněte Odebrat.
  2. Zadejte důvod (ztracen, poškozen, vrácen, jiné).
  3. Přiřaďte nový čip stejným postupem.

Pozor: Zneplatnění je okamžité — od té chvíle už ztracený čip nikdo nemůže použít k cizímu výdeji. Do reportu anomálií se pak promítne, pokud se ztracený čip přiloží.

Krok 4: Předání terminálu obsluze

Po krocích 1—3 je vše nachystané. Operátor se z kuchyňského PC odhlásí (nebo zavře prohlížeč). Když přijde kuchařka, otevře edumeal — systém vidí, že je PC spárované, a přesměruje rovnou na /scan/start (Přihlášení obsluhy).

Detailní popis flow obsluhy je v sekci Obsluha — výdej obědů.

Údržba

Ztráta služebního čipu obsluhy

  1. /operator/kitchen-staff → detail obsluhy → Odebrat u aktivního čipu.
  2. Přiřaďte nový čip.

Rotace PINu obsluhy

Pokud má kuchařka podezření, že její PIN někdo zná:

  1. /operator/kitchen-staff → detail obsluhy → sekce PIN obsluhyRotovat PIN.
  2. Zadejte nový PIN — starý se okamžitě zneplatní.

Revoke / přepárování terminálu

Pokud potřebujete terminál přesunout, vyřadit, nebo měnit přiřazení k výdejnímu místu:

  1. RFID → Zařízení (cesta /operator/devices).
  2. U konkrétního terminálu klikněte Zneplatnit, zadejte důvod.
  3. Od té chvíle device token na příslušném PC vrací 401 — obsluha dostane na /scan/start hlášku “Terminál není spárovaný nebo bylo jeho oprávnění odebráno”.
  4. Pro znovu-použití PC projděte krok 1 (Spárování) znovu.

Lokální unpair (PC bez admin zásahu)

Operátor přímo na kuchyňském PC může terminál odpárovat bez revoke v admin UI:

  1. Přihlaste se na PC jako operátor.
  2. /operator/scan-setup → sekce Browser už je spárovaný → tlačítko Odpárovat.
  3. Localstorage se vymaže. Záznam terminálu v API zůstane platný — můžete nyní stejný token namapovat na jiný browser/PC (přes API, ne přes UI), nebo nechat token expirovat.

Reporty a audit

RFID výdej generuje data do několika reportů v sekci Kuchyně:

  • Denní výdejka — kolik porcí bylo vydáno, kolik objednaných, kolik nevybraných. Rozděleno podle výdejního místa, slotu a věkové kategorie.
  • Anomálie — strávníci s vysokým podílem manuálních výdejů, strávníci s opakovaným “Již vydáno”, ztracené čipy, které se znovu objevily.
  • Audit log — kompletní historie každého skenu (i odmítnutého) s časem, obsluhou, terminálem a důvodem. Zdroj pravdy pro řešení sporů s rodiči.

Řešení sporů

Pokud rodič tvrdí, že dítě dnes nedostalo oběd:

  1. V auditu vyhledejte strávníka a datum.
  2. Zkontrolujte, zda existuje záznam pickup.created nebo pickup.rejected.
  3. Pokud existuje úspěšný výdej s časem, sdělte rodiči čas a obsluhu.
  4. Pokud existují jen odmítnuté pokusy (např. “Žádná objednávka”), zkontrolujte historii objednávek — objednávka mohla být zrušena nebo nikdy nevznikla.

Časté otázky

Můžeme provozovat dvě okénka současně na jednom výdejním místě?

Ano. Vytvořte dva samostatné terminály (každý na svém PC s vlastní čtečkou). Každá kuchařka má vlastní směnu a vlastní službu, audit pak ukáže, kdo a na kterém okénku vydal.

Funguje výdej i pro hromadné objednávky organizací (mateřinky)?

Hromadné objednávky organizace se aktuálně nevydávají přes RFID, protože organizace nemá fyzické čipy. Vydávají se obvykle hromadně podle dodacího listu na výdejním místě organizace.

Mohu změnit služební čip kuchařce, aniž bych vystavoval nový PIN?

Ano. Sekce Čip obsluhy a PIN obsluhy v detailu kuchařky jsou nezávislé — můžete měnit jednu věc, aniž byste sahali na druhou.

Je možné používat ISIC kartu jako čip?

Ano, edumeal čte ISIC karty na frekvenci 13,56 MHz a ukládá jejich UID stejně jako u jakéhokoli jiného čipu. Při výměně ISIC karty (např. po prodloužení platnosti) UID zůstává stejné — není potřeba čip znovu přiřazovat.

Co když operátor nemá fyzický přístup k kuchyňskému PC?

Spárování vyžaduje fyzický přístup, protože device token se ukládá do localStorage konkrétního prohlížeče. Pro remote setup (vzdálená kuchyně) musí někdo na místě otevřít edumeal a potvrdit pairing. Lze to udělat například přes vzdálenou plochu, ale localStorage musí zůstat v browseru na PC, ne ve vaší relaci.

Kuchařka tvrdí, že po reloadu obrazovky ji to odhlásilo. Co teď?

V dnešní verzi staff session přežívá reload (uloženo v localStorage s 8h TTL). Pokud reload obsluhu odhlásí, něco není v pořádku — možnosti:

  • localStorage prohlížeče byl vyčištěn (privátní okno, restart prohlížeče s “mazat data” nastavením).
  • Session reálně vypršela (8h od přihlášení).
  • Operátor mezitím revoke-nul device — session už nemá platný terminál.

Ve scanning mode obrazovce by se objevil toast “Směna vypršela, přihlas se znovu” a UI by skočilo na /scan/start. Pokud obsluha tvrdí něco jiného, požádejte ji o screenshot a kontaktujte support.