Negy raktar, 18.400 SKU, es egy ertekesito, aki azt kerdezi: "van keszleten?". Ez a Netorigo Logistics legszemelyesebb teljesitmenyteszttje, es az elmult fel evben sokat tanultunk arrol, hogy miert nem trivialis egy multi-warehouse stock view.
A naiv megoldas miert nem mukodik
Az elso verzionk minden lekerdezeskor osszeszedte a stock_movements tablabol a futo egyenleget per SKU per warehouse, hozzaadta a reservations tablabol a fuggo foglalasokat, kivonta a in_transit tetelket, es 4 masodperc alatt visszaadta a valaszt. Negy masodperc egy ertekesito beszelgetes kozben az orokkevalosag. A megoldas: materialized view, ami SKU+warehouse szintu aggregalt sorokat tart, es minden stock_movement insert utan async job triggerezi a refresh-t (PostgreSQL pg_notify + worker). A stock view ma 280ms alatt tolt, raktartol fuggetlenul.
A fogalmi modell, ami szamit
Minden SKU-nak harom szinten van keszlete:
- at_warehouse: fizikailag a polcon, nem foglalt.
- in_transit: ket raktar kozott utazik (cross-stock vagy replenishment).
- reserved: aktiv cart, ajanlat vagy rendeles tartja vissza.
- available: at_warehouse mainusz reserved.
Ez a negy oszlop minden drill-down nezeten ott van. A logisztikai vezeto a at_warehouse + in_transit osszeget nezi ("mennyi van a halozaton osszesen"), az ertekesito az available-t ("mennyit igerhetek meg ma"), a beszerzes a available - safety_stock kuszob alatti SKU-kat ('mit kell rendelni').
Miert hagytuk az available-t szandekosan optimistanak
A legforradalmibb dontesunk: az available mezo nem dekremental cart-add-kor. Csak akkor csokken, amikor a pick-list legeneralodik (rendeles + warehouse-allocator dontes utan). Igy ket cart parhuzamosan tudja foglalni ugyanazt az utolso darabot, es csak az nyer, akinek a pick-list-je elobb generalodik. Az indok: a B2B kereskedelmi cart-elhagyasi arany 67%. Ha minden cart-add azonnal foglal, a keszlet artificialisan elfogy, es a kovetkezo latogatonak hibaisan azt jelezzuk, hogy nincs raktaron. Igy 30 percenkent rebooting-olnank a keszlet-feedbacket egy idle cart-cleanup job-bal, ami sajat magaban race condition forras.
A reservation lifecycle
A reservations tabla allapotai:
cart- vasarloi kosaron van, soft hold, 24 oran utan TTL alapjan torlodik.quote- ajanlatban szerepel, 30 nap TTL, kemenyebb hold.order- megrendelve, varjuk a pick-listet.picking- aktiv pick-list-en, a pick-warehouse-bol nem mozdithato.shipped- kuldve, mar nem a Logistics modul problemaja.
Minden allapotvaltas audit-traillel kerul be a reservation_events tablaba. Volt egy bug 2026 marciusban, hogy a quote -> order atmenet nem indexelte a reservation-t a warehouse-allokatorra, igy a pick-list a rossz raktarrol generalodott (cross-stock-szal kerult kezbesitesre, +18 ora SLA-csuszas). Az auit-trail meg az este meglatatta a hibat.
A drill-down
A stock view alapertelmezett nezete osszevont (4 raktar, egy szam per SKU). Egy kattintas a SKU-ra megnyitja a per-warehouse breakdown-t: melyik raktarban mennyi van, melyikbol mennyi utazik, melyik raktar reservation-jei tartjak vissza. Egy kattintas a reservation szamra megnyitja a reservation-listat: melyik cart-/quote-/order-ID, mikor jart le.
A managerek 80%-a az osszevont view-on dolgozik. A 20% specializalt raktarmenedzser hasznalja a drill-down-t, foleg amikor egy cross-stock dontest hoz: "a 18-as raktarban van 4, a 33-asban 12, kuldjunk 6-ot at a 18-ra a holnapi pick-wave-hez". A cross-stock muvelet direkt a drill-down-bol triggerezheto, es a stock view 280ms-on belul reflektalja.
Amit a kovetkezo iteracioban csinalnank maskepp
A materialized view megoldas mukodik 18.000 SKU-ra es 4 raktarra. 100.000 SKU es 12 raktar felett valoszinuleg event-sourced megoldasra valtanank (Kafka + KSQL), es a stock view-t streaming-bol epitenenk. Egyelore nincs ilyen meretu partnerunk, igy a materialized view a kovetkezo 12 honapra elegendo.