codeven
Blog · Ze zakázek

Co nás naučil prodej vstupenek na maturitní ples

839 míst v pěti prostorech Domu kultury Vsetín, přednostní prodej pro maturanty, platby převodem a skener na vstupu. Prodej vstupenek na ples Masarykova gymnázia vypadá jako malá zakázka. Dokud se u jedné židle nesejdou dva kupující.

Jedna židle, dva kupující

Když se otevře prodej, stovky lidí kliknou ve stejné minutě na stejné stoly u parketu. Kontrola „je místo volné?“ v kódu aplikace tady nestačí: dva požadavky ji projdou současně a místo se prodá dvakrát. Proto to hlídá databáze. Držení místa v košíku má na židli unikátní index a jedno místo smí být nejvýš v jedné aktivní objednávce, což hlídá částečný unikátní index. Převod košíku na objednávku je jedna transakce, která dotčená místa zamkne a teprve pak znovu ověří vlnu, kvótu i kapacitu.

Na každé takové pravidlo existuje test, včetně souběžného nákupu stejného místa. Když prohraje druhý kupující, nedostane chybovou stránku, ale jasnou zprávu a nabídku vybrat si jinde.

Osamocená židle u stolu

Drobnost, na kterou by v zadání nikdo nepřišel: kupující vezmou u osmimístného stolu sedm míst a jedno zbyde. Takovou židli už nikdo nekoupí, protože nikdo nechce sedět sám mezi cizí rodinou. Aplikace proto nedovolí dokončit nákup, který by u stolu nově nechal jedno osamocené místo. Upozorní na to hned při výběru a nabídne, jak výběr posunout nebo doplnit. Místo, které zůstalo osamocené kvůli dřívějším nákupům, nákup neblokuje.

Celá škola za jednou IP adresou

Proti lidem, kteří by v košíku drželi půl sálu, se obvykle nasazuje limit na IP adresu. Jenže maturanti nakupují ze školy a celá budova sdílí jednu veřejnou adresu. Limit na IP by zablokoval celou třídu. IP proto sama nikdy neblokuje. Rozhoduje kombinace session, IP a otisku prohlížeče, ze kterého se ukládá jen hash. Smazání cookies ani anonymní okno limit nevynuluje, a třída přitom může nakupovat z jedné učebny.

K tomu pár pravidel proti „točení“ míst: držení vyprší po deseti minutách, stejné zařízení nesmí stejné místo hned znovu podržet a jedno místo drží zařízení nejdéle půl hodiny celkem.

Nic nepropadne, dokud to nepotvrdí banka

Platí se převodem a nezaplacená objednávka po splatnosti propadne. Zní to jednoduše, ale co když lidé zaplatili a jen výpis z banky ještě nikdo nenahrál? Kdyby aplikace jela jen podle kalendáře, zrušila by objednávky lidem, kteří mají peníze na cestě, a jejich místa prodala dál.

Proto platí jedno tvrdé pravidlo: objednávka smí propadnout jen tehdy, když jsou platby na účtu zpracované nejméně do dne splatnosti plus ochranné lhůty na mezibankovní převod. Dokud výpis ten den nepokryje, nepropadne nic. Splatnost se počítá v pracovních dnech, včetně českých svátků.

Uvolněná místa až v 18:00

Místa z propadlých objednávek se nevracejí do prodeje okamžitě. Kdyby se vracela, vyhrál by ten, kdo nejčastěji obnovuje stránku. Vracejí se v ohlášené dávce jednou denně. Mezitím jsou na plánku šedá s popiskem, že čekají na uvolnění. Je to férovější pro kupující a klidnější pro server.

Bezpečnostní audit před spuštěním

Před spuštěním prodeje prošel kód bezpečnostním auditem zaměřeným nejen na klasické útoky na web, ale i na chování kupujících: hromadění rezervací, obcházení kvót, přeprodej vstupenek. Nejzajímavější nález byl nenápadný. Funkce „Ztratil jsem odkaz“ hledala objednávky podle e-mailu porovnáním, ve kterém podtržítko znamená libovolný znak. Kdo si založil adresu jan_novak@…, mohl si nechat poslat odkazy na objednávky adresy jan.novak@….

Oprava byla na pár řádků: přesná shoda adresy a odeslání vždy na e-mail uložený u objednávky, ne na ten zadaný. Tenhle nález i většinu ostatních jsme opravili ještě týž den. Poučení je obecné: nejnebezpečnější chyby nejsou v složitém kódu, ale v pohodlných zkratkách, které vypadají neškodně.

Skener, který vydrží bez signálu

V přeplněném vestibulu kulturního domu mobilní data často nefungují. Skener vstupenek je proto webová aplikace, která si seznam vstupenek stáhne přímo do telefonu, odbavuje i bez připojení a výsledky synchronizuje, jakmile se síť vrátí. QR kód nese podepsaný token, takže se nedá vyrobit podle vzoru. Po předání vstupenky jiné osobě starý kód přestane platit.

Aplikace na každý rok

Ples je každý rok a pravidla se mění: jiný počet maturantů, jiná kvóta pro hosty, jiné rozmístění stolů. Proto v kódu nejsou žádná pravidla natvrdo. Splatnost, ochranná lhůta, limity, čas uvolňování míst i kvóty jsou nastavení ročníku a nový ročník vznikne zkopírováním loňského. Pořadatelé si plánek upraví v editoru sami a programátora potřebují, jen když se mění samotná logika prodeje.

  • Integritu hlídat v databázi, ne v aplikaci. Unikátní indexy a zámky řádků fungují i při souběhu, kontrola v kódu ne.
  • Znát skutečné uživatele. Jedna školní IP, telefon v přeplněném sále, rodina, která chce sedět pohromadě. Tohle se v zadání neobjeví, dokud se nezeptáte.
  • Nerušit nic na základě neúplných dat. Když chybí výpis, správná odpověď je počkat.
  • Pravidla jako nastavení, ne jako kód. Aplikace, která má sloužit roky, se musí dát přenastavit bez programátora.

Rozsah, technologie a čísla projektu najdete v případové studii Ples MG Vsetín. A pokud řešíte prodej, rezervace nebo cokoli, kde se lidé přetahují o omezenou kapacitu, napište nám.

Mohlo by vás zajímat

Lekce z přepisu Hlídače firem

Limity veřejných registrů, dotaz zrychlený z 293 sekund na 0,26 ms a proč nevěřit hlášení o úspěchu. Zkušenosti z přepisu systému s 3,5 miliony subjektů.

Vlastní aplikace, nebo hotový software?

Kdy si aplikaci na míru nenechávat stavět, kdy se vyplatí, jak spočítat náklady na pět let a pět otázek pro rozhodnutí.

Prodáváte něco, čeho je omezeně?

Vstupenky, termíny, kapacity kurzů nebo rezervace. Postavíme systém, který souběh unese a nic neprodá dvakrát. Napište, co řešíte.