ravien
← Kõik postitused

Restorani laoarvestus liikumiste logil: meie pilootprojekt

Tallinna toitlustusettevõttel on kaks kohta, kus kaup seisab: ladu ja toiduauto ehk treiler. Kaup ostetakse lattu, köök valmistab osa sellest ette, treiler viib hommikul kaasa ja müüb päeva jooksul maha. Küsimus „kui palju meil tegelikult alles on?” ei tohiks nõuda kellegi mälu ega käsitsi peetud tabelit.

Ehitasime neile piloodina laoarvestuse programmi. Selles postituses räägime, kuidas see töötab, milliseid otsuseid tegime ja miks.

Probleem: laoseis ei tohi olla number, mida keegi üle kirjutab

Enamik lihtsaid laotabeleid hoiab iga toote kohta üht lahtrit: „Coca-Cola, ladu, 48”. Kui keegi midagi võtab, muudab ta seda numbrit. See töötab seni, kuni keegi eksib. Siis on number vale ja keegi ei tea, millal või miks see valeks läks.

Meie lähtekoht oli teistsugune: laoseisu ei salvestata üldse. Salvestatakse ainult liikumised:

  • ost (kaup saabus lattu või otse treilerisse);
  • ümberpaigutus (laost treilerisse);
  • köögi tootmine (toorainest valmis pooltoode);
  • mahakandmine;
  • inventuuri korrektsioon;
  • müük kassast.

Iga toote seis igas asukohas arvutatakse nende liikumiste summana. Logi on ainult täiendatav, olemasolevaid ridu ei kirjutata üle.

Miks liikumiste logi on parem kui muudetav number

Omaniku jaoks tähendab see kolme asja.

Iga numbri taha saab vaadata. Kui ülevaatel on laos 12 kasti, näeb logist täpselt, millised ostud, äraviimised ja müügid selle kokku andsid, kes need sisestas ja millal.

Viga parandatakse jälgi kaotamata. Valesti sisestatud rida tühistatakse ja vajadusel asendatakse uuega. Tühistamisel peab olema kolm asja korraga: kes, millal ja miks. Põhjuseta tühistamist andmebaas vastu ei võta. Algne rida jääb alles, lihtsalt läbikriipsutatuna.

Ladu ei saa miinusesse minna. Treilerisse ei saa viia liha, mida pole kunagi ostetud. Kui ühes sisestuses on kümme rida ja üks neist viiks seisu alla nulli, lükatakse tagasi kogu sisestus, mitte ainult see üks rida. Pooleldi salvestatud kogust ei teki.

Siin on üks teadlik erand: kassa müük võib seisu miinusesse viia. Kassa ei väljenda kavatsust, vaid kirjeldab, mis juba juhtus. Kui müük ja logi omavahel ei klapi, on keegi jätnud ümberpaigutuse sisestamata. Seda on ausam näidata kui müüki tagasi lükata.

Mida töötajad telefonis teevad

Kõik sisestusvormid on tehtud eelkõige telefoni jaoks. Kui laoarvestus võtab liiga palju aega, jäetakse see lihtsalt tegemata. Ekraanid on järgmised:

  • Ost. Kuupäev, tooted ja kogused ning koht, kuhu kaup saabus. Hindu ega tarnijaid ei sisestata, sest see süsteem jälgib, mis riiulil on, mitte seda, mis see maksis.
  • Võta kaasa. Laost treilerisse. Suured nupud ja kogusesammud, eesmärk on saada sisestus tehtud alla 20 sekundiga.
  • Köök. Tooraine marineerimine või mahakandmine. Mahakandmine küsib enne kinnitust, sest see kustutab koguse, mida enam tagasi ei saa.
  • Loendus. Inventuur riiuli juures, kus parasjagu seistakse. Erinevus arvutatud ja loendatud seisu vahel salvestub korrektsioonina, mitte uue seisuna.

Kiirnupud on iga toote puhul eraldi ja suunast sõltuvad. Joogid saabuvad kastide kaupa, aga lahkuvad ükshaaval, seega pakub ostuvorm teisi samme kui väljaviimise vorm. Tooteid näidatakse igal ekraanil samas järjekorras, mille omanik on ise paika pannud, et toode oleks alati samas kohas.

Köök toodab, mitte ainult ei kuluta

Köök ei võta laost ainult kaupa välja, vaid valmistab sellest midagi uut. Toorest lihast saab marineeritud liha, mis on päris laokaup: see liigub treilerisse, seda loendatakse ja kantakse maha.

Marineerimine ei ole üks-ühele. Enne marinaadi panemist liha puhastatakse ja kaal väheneb. Seepärast salvestab süsteem kaks kaalu: kui palju toorainet võeti ja kui palju valmistoodet tekkis. Vahe on näha kaona. Seda ei kirjendata eraldi mahakandmisena, sest toorainest on täiskaal juba maha läinud ja kaotus läheks siis topelt arvesse.

Sama mõte kehtib marinaadisegu kohta. See segatakse retsepti järgi kuuest vürtsist ja üks segu partii on üks tegu seitsme toote peal. Kui partii tühistada, tühistuvad kõik selle read korraga.

Kassa ja lao ühendamine

Kassasüsteem saadab iga päev e-postiga neli aruannet. Programm loeb postkasti ise ja impordib need, ilma et keegi peaks faile käsitsi ümber tõstma. Laoseisu mõjutab neist ainult müüdud toodete aruanne, ülejäänud annavad statistikavaatesse päeva käibe.

Siin tuli lahendada restoranides tavaline vastuolu: kassa müüb roogasid, ladu hoiab tooraineid. Kassa teab, et müüdi kolm rooga ja kaks jooki, aga riiulilt kaob liha, sibul ja pakend. Seepärast on igal kassa artiklil vastavus selle kohta, mida see riiulilt võtab. Joogid on sama mehhanismi osa: nende retseptis on üks rida kogusega 1.

Mõned otsused, mis tegid selle usaldusväärseks:

  • Seos käib kassa artiklikoodi, mitte nime järgi. Kassas on nimedes kirjavigu ja nende parandamine ei tohi vastavust katki teha.
  • Kuupäev võetakse faili nimest. Aruande enda päises olev kuupäev näitab, millal see koostati, ehk järgmist hommikut.
  • Sama päeva topeltimport on ohutu. Käibenumbrid kirjutatakse üle, laomüük salvestatakse ainult esimesel korral.
  • Tundmatu artikkel ei kao vaikselt. Kui kassasse ilmub uus jook, millel vastavust pole, jääb see avalehel hoiatusena nähtavale, kuni vastavus on lisatud.

Mõni kaup kulub äraviimisel, mitte müügil

Kastmete, pakendite, kinnaste ja salvrätikute puhul ei hakka keegi treileri aknal iga kahvlit maha märkima. Esimeses versioonis loeti need maha nii äraviimisel kui ka iga müüdud roa pealt. Tulemus oli ühe toote puhul treileris sügavalt miinuses seis, samal ajal kui laos seisis kümneid pakke.

Lahendus oli üks tootepõhine märge: see kaup loetakse kulunuks hetkel, kui see laost treilerisse viiakse, ja kassa müük seda enam ei puuduta. Tellimisvajadust hinnatakse selliste toodete puhul lao järgi. Omanik saab märke iga toote juures ise sisse või välja lülitada.

Tellimise märguanded sisetunde asemel

Avalehel on iga toote seis laos, treileris ja kokku. Kui toode langeb alla omaniku määratud piiri, saab see märke „tellida”. Lisaks on kõrgem, kollane piir, mis annab märku juba enne, kui kaup päriselt otsa saab.

Esimeses versioonis olid kõigil toodetel meie pakutud piirid. Need näitasid tellimisvajadust ka toodetel, millega oli kõik korras. Nüüd on piirid vaikimisi tühjad ja märguanne tekib alles siis, kui keegi, kes ettevõtet tunneb, on piiri ise määranud. Valesti karjuv hoiatus õpetab inimesi hoiatusi eirama.

Treilerile saab määrata ka sihtkoguse. Kaasavõtmise nimekiri võrdleb seda treileri tegeliku seisuga ja pakub, mida kaasa võtta.

Omanikule on ka lauaarvuti vaade: tabel laoseisuga, tellimist vajavad tooted ja viimased liikumised. Samad arvutatud numbrid saab alla laadida CSV-failina.

Tehniline pool lühidalt

Hoidsime lahenduse lihtsana, sest tegu on piloodiga:

  • FastAPI taustal ja SQLite andmebaasina;
  • serveris renderdatud lehed Jinja2 ja HTMX-iga, ilma eraldi ehitusetapita;
  • laoseisu arvutab ainult üks moodul ja sellel on automaattestid;
  • andmebaasi muudatused on nummerdatud SQL-migratsioonid;
  • sisselogimine ja õigused: omanik, köök ja treiler näevad ainult neile lubatud ekraane;
  • kassa postkasti loeb rakendus ise, IMAP-i kaudu.

Alus automaatsele tellimisele

Kui laoseis on usaldusväärne, saab selle peale ehitada automaatika. Selle jaoks on rakendusel juba masinatele mõeldud API: see annab välja arvutatud laoseisu koos tellimispiiridega ja võtab vastu oste, äraviimisi ja loendusi läbi samade reeglite, mis kehtivad töötajate ekraanidele. Ka API kaudu ei saa ladu miinusesse viia ega köögis valmistatud toodet „osta”.

Mida me teadlikult ei ehitanud: hindu ja kulusid laopoolel, arvete automaatset lugemist ega kastmete jagamist roa kaupa. Kassa ei tea, kas klient võttis küüslaugu- või tšillikastet, ja oletus, mida esitatakse mõõtmisena, on halvem kui lünk, mille iganädalane loendus niikuinii katab.

Kas teie laoarvestus vajab sama?

Kui teie restoranis, kohvikus või toitlustusettevõttes on ladu mitmes kohas, kassa ei räägi laoga ja tellimine käib kõhutunde järgi, siis räägime. Alustame sellest, kuidas kaup teil päriselt liigub, ja ehitame just nii palju, kui vaja.

Võta meiega ühendust.

Kas mõni töövoog võiks paremini käia?

ALUSTA VESTLUST →