Skip to main content

VECTON Raktárkezelési Rendszer (WMS) — Műszaki Rendszerterv

Verzió: 4.1 Utolsó frissítés: 2026-03-19 Státusz: Tervezési fázis Backend: tenant-backend-warehouse (Laravel) Frontend: tenant-frontend (Vue 3 + Vuetify)


Tartalomjegyzék

  1. Jelenlegi állapot
  2. Rendszer alapelvek
  3. Raktár típusok
  4. Beszállítói katalógus (Supplier Catalog)
  5. Lokáció menedzsment és Layout Editor
  6. Készletkezelési modell
  7. Rendelés-routing (Order Fulfillment Routing)
  8. Készletmozgások (Inventory Transactions)
  9. Áruátvétel (Receiving / Inbound)
  10. Komissiózás és rendelés-teljesítés (Picking & Fulfillment)
  11. Csomagolás és kiszállítás (Packing & Shipping)
  12. Dropshipping
  13. Beszerzés (Procurement)
  14. Visszáru kezelés (RMA)
  15. Leltározás (Inventory Audit / Cycle Count)
  16. Termék életút-követés (Traceability)
  17. Teljesítmény és gyorsítótár
  18. Címke generálás (Label Generator)
  19. Integrációk
  20. Adatbázis séma
  21. API végpontok
  22. Megvalósítási fázisok

1. Jelenlegi állapot

Ami már kész van (production-ready)

ModulBackendWeb Frontend
Warehouse CRUD
Layout Editor (gráf-alapú)✅ (verziózás, SVG)✅ (SVG editor)
Route Planning (TSP)✅ (single + multi-warehouse)✅ (vizualizáció)
Label Generation (QR)✅ (PDF, thermal, sticker)✅ (preview + letöltés)
Product Model✅ DB séma (webshop backend)

Ami hiányzik (a WMS mag)

  • Raktár típusok — fizikai, virtuális (beszállítói), dropship
  • Beszállítói katalógus — melyik beszállítónál melyik termék elérhető, milyen áron
  • Order routing — honnan teljesítsük a rendelést (saját raktár / beszállítói rendelés / dropship)
  • Összevárás és batch rendelés — rendelések gyűjtése, majd napi/időszakos PO generálás beszállítóknak
  • Beszállítói export PDF — összesített megrendelés PDF a nagykernek
  • Dropshipping — beszállító közvetlenül a vevőhöz szállít
  • Inventory management — készlet nyilvántartás, készletmozgások
  • Location hierarchy — SHELF-ROW-SPACE-BOX
  • Layout Editor → Lokáció — a layout editor = lokáció kezelő
  • Áruátvétel, Komissiózás, Csomagolás, Beszerzés, RMA, Leltár
  • Label Generator átdolgozás — csak regisztrált lokációkra

2. Rendszer alapelvek

2.1. Fizikai vs. logikai készlet szétválasztás

A rendszer alapja a fizikai valóság (mi van ténylegesen a polcon) és a logikai állapot (mi van lefoglalva, zárolt, stb.) szigorú elkülönítése. A fizikai készlet soha nem mehet mínuszba. A virtuális (úton lévő, vagy beszállítónál lévő) készlet igen.

2.2. Eseményvezérelt architektúra

Minden készletmozgás egy InventoryTransaction rekord, ami immutable. Az inventory_summary tábla csak gyorsítótár — bármikor újraépíthető a tranzakciókból.

2.3. Atomi műveletek

Készletmozgások adatbázis-tranzakcióban futnak. Nincs félig végrehajtott mozgás.

2.4. Tenant izoláció

Minden tenant külön service-ként fut külön adatbázissal. Nincs tenant_id a táblákban.

2.5. Layout Editor = Lokáció kezelő

A layout editor és a lokáció rendszer egy és ugyanaz. A layout editor közvetlenül a locations táblát kezeli. API-n keresztül is lehet lokációt létrehozni.

2.6. Pontos helykövető rendszer

Minden fizikai hely regisztrált lokáció. Nincs ad-hoc hely, nincs szabad szöveges lokáció kód. A QR címke generátor kizárólag regisztrált lokációkra dolgozik.

2.7. Multi-forrás teljesítés

Egy rendelés tételei különböző forrásokból teljesíthetők:

  • Saját fizikai raktár → normál pick/pack/ship
  • Beszállítói rendelés (virtuális raktár) → PO → áruátvétel → ship, VAGY összevárás
  • Dropship → PO a beszállítónak a vevő címével, közvetlenül szállít

A rendszer automatikusan vagy manuálisan dönti el a forrást a rendelés-routing szabályok alapján.


3. Raktár típusok

3.1. Áttekintés

TípusKódFizikai lokációkLayout EditorKészletLeírás
Fizikaiphysical✅ SHELF/ROW/SPACE/BOXValós polconSaját raktár, minden WMS funkció elérhető
Virtuálisvirtual❌ nincsBeszállítónál lévő logikai készletNagykereskedő/beszállító raktára, amit mi nem kezelünk fizikailag
Dropshipdropship❌ nincsBeszállítónál, közvetlen kiszállításBeszállító közvetlenül a vevőnek szállít

A warehouses.type mező határozza meg a típust. Egy rendszerben bármennyi raktár lehet, bármilyen kombinációban.

3.2. Fizikai raktár (physical)

A jelenlegi raktár koncepció. Teljes WMS funkcionalitás:

  • Layout editor / lokáció kezelés
  • Készlet nyilvántartás fizikai lokációkon
  • Áruátvétel, komissiózás, csomagolás, szállítás
  • Route planning, label generation
  • Leltározás

3.3. Virtuális raktár (virtual)

Egy beszállító/nagyker készletét reprezentálja logikailag. Nincs fizikai lokáció, nincs layout.

Mire jó:

  • A webshopban megjelenik a termék mint "elérhető" (a beszállítónál van)
  • Rendelés beérkezésekor a rendszer tudja, hogy innen kell rendelni
  • Az összevárási logika erre az "érhető" készletre épül

Készletkezelés virtuális raktárban:

  • Nincs locations tábla kapcsolat
  • Az inventory_summary tábla warehouse_id-je mutat a virtuális raktárra
  • A készlet szint karbantartása:
    • Manuális: admin frissíti a beszállítói készletet (pl. kapott egy Excel-t)
    • API: beszállító API-n keresztül szinkronizálja (ha van ilyen)
    • Import: CSV/Excel import a beszállítói árlista alapján
  • A virtuális készlet a webshop felé available-ként jelenhet meg (konfig alapján)

Fontos: A virtuális raktárban a készlet "ígéret" — a beszállító azt mondja van, de nem mi ellenőrizzük. Ezért a foglalás és teljesítés logikája más mint a fizikainál.

3.4. Dropship raktár (dropship)

Speciális virtuális raktár, ahol a beszállító közvetlenül a vevőhöz szállít.

  • Nincs fizikai készlet nálunk, nincs lokáció
  • Rendeléskor PO jön létre a beszállítónak a vevő szállítási címével
  • A csomagolás és szállítás a beszállító dolga
  • Mi csak a tracking számot és a státuszt követjük
  • Profit = eladási ár - beszállítói ár (- egyéb költségek)

Részletek a 12. Dropshipping fejezetben.

3.5. Raktár-beszállító kapcsolat

Minden virtuális és dropship raktár pontosan egy beszállítóhoz tartozik:

warehouses.supplier_id → suppliers.id   (NULL fizikai raktárnál)

Egy beszállítónak lehet:

  • Egy virtuális raktára (a készletük)
  • Egy dropship raktára (amit dropshippelnek)
  • Vagy mindkettő

4. Beszállítói katalógus (Supplier Catalog)

4.1. Beszállítók (Suppliers)

Beszállítók = nagykereskedők, gyártók, disztribútorok, akiktől terméket lehet rendelni.

MezőLeírás
nameBeszállító neve
codeRövid azonosító (pl. "TECHDATA", "OMEGA")
tax_numberAdószám
eu_vat_numberEU VAT szám (közösségi beszerzésnél)
contact_*Kapcsolattartó adatok
address_*Cím
currency_codeAlapértelmezett pénznem
payment_terms_daysFizetési határidő (nap)
lead_time_daysAlapértelmezett szállítási idő (nap)
procurement_typeDOMESTIC / EU_COMMUNITY / THIRD_COUNTRY
order_emailEmail cím ahova a rendelési PDF-et küldjük
order_methodRendelés módja: email / api / portal / manual
min_order_valueMinimum rendelési érték (ha van)

4.2. Termék-Beszállító kapcsolat (Supplier Products)

Egy terméknek több beszállítója lehet, mindegyiknek saját ára, MOQ-ja, cikkszáma.

supplier_products: melyik beszállítónál melyik termék elérhető
MezőLeírás
supplier_idFK → suppliers
product_idFK → products
variant_idFK → product_variants (nullable)
supplier_skuA beszállító saját cikkszáma (ami az ő rendszerében van)
unit_priceBeszerzési egységár
currency_codePénznem
moqMinimum Order Quantity (min. rendelési mennyiség)
order_unitRendelési egység (pl. 1 = darab, 10 = csomag, 100 = karton)
lead_time_daysSzállítási idő (felülírja a supplier szintű default-ot)
is_preferredElsődleges beszállító-e ehhez a termékhez
is_dropship_eligibleEz a beszállító tud dropshippelni ezzel a termékkel
supplier_stock_qtyBeszállítónál elérhető mennyiség (utolsó frissítés szerint)
stock_updated_atMikor frissült utoljára a beszállítói készlet
is_activeAktív-e ez a termék-beszállító kapcsolat
notesMegjegyzés

4.3. Beszállító kiválasztási logika

Ha egy terméknek több beszállítója van, a rendszer a következő sorrend szerint választ:

1. is_preferred = true → elsődleges beszállító
2. Ha az elsődlegesnél nincs elég készlet → következő, legolcsóbb aktív beszállító
3. Ha supplier_stock_qty megadott → csak onnan ahol van elég
4. Ha lead_time_days fontos → sürgős rendelésnél a leggyorsabb

Admin manuálisan felülírhatja a beszállító kiválasztást a PO létrehozásakor.

4.4. Beszállítói árlista import

Beszállítók rendszeresen küldenek frissített árlistát (CSV, Excel, API).

Import flow:
1. Admin feltölti az árlistát (CSV/Excel) vagy API-ból jön
2. Rendszer match-eli a supplier_sku alapján a meglévő supplier_products-hoz
3. Frissíti: unit_price, supplier_stock_qty, stock_updated_at
4. Új tételek → supplier_products rekord létrehozás (manuális jóváhagyás után)
5. Törölt tételek → is_active = false (de a rekord megmarad)

5. Lokáció menedzsment és Layout Editor

Csak fizikai raktárakra (physical) vonatkozik. Virtuális és dropship raktáraknak nincs lokációja.

5.1. Hierarchia: 4 szint

SHELF (salgó/állvány)
└── ROW (sor/polc)
└── SPACE (hely)
└── BOX (doboz)
  • SHELF: Egy fizikai állvány/salgó egység. Ez a legmagasabb szint.
  • ROW: Az állvány egy sora (polca). Egy shelf-en belül függőlegesen egymás felett.
  • SPACE: Egy hely a soron belül. Vízszintesen egymás mellett.
  • BOX: Egy doboz/rekesz a helyen belül. A legkisebb egység.

5.2. Helykód formátum

VECTON-{WAREHOUSE_CODE}-{SHELF}-{ROW}-{SPACE}-{BOX}

Példák:

KódJelentés
VECTON-W1-A-3-2-01W1 raktár, A salgó, 3. sor, 2. hely, 01 doboz
VECTON-W1-B-1-4-0W1 raktár, B salgó, 1. sor, 4. hely, nincs doboz
VECTON-W1-RECEIVING-1-0-0W1 raktár, RECEIVING terület
VECTON-W1-SHIPPING-1-0-0W1 raktár, SHIPPING terület
VECTON-W1-RMA-1-0-0W1 raktár, RMA karantén
VECTON-W1-SCRAP-1-0-0W1 raktár, selejt terület

Szabályok:

  • SHELF szint: string (betű vagy speciális név: A, B, RECEIVING, SHIPPING, RMA, SCRAP)
  • ROW, SPACE, BOX: számok (0 = nincs ilyen albontás)

5.3. Layout Editor = Lokáció CRUD

A layout editor közvetlenül a locations táblát kezeli. Két nézet:

Felülnézet (Top-down floor plan)

  • Node hozzáadása = locations rekord létrehozás (SHELF szint)
  • Node törlése = deaktiválás (ha üres) vagy TILTOTT (ha van készlet)
  • Node mozgatása = x, y frissítés
  • Link hozzáadása/törlése = location_links rekord

Elölnézet (Rack Detail View)

SHELF node-ra kattintva frontális 2D előnézet:

┌─────────────────────────────────────────────────────┐
│ VECTON-W1-A állvány │
│ Típus: Salgó │ Max terhelés: 2000 kg │
├─────────────────────────────────────────────────────┤
│ ┌────────┬────────┬────────┬────────┐ ← 4. sor │
│ │ A-4-1 │ A-4-2 │ A-4-3 │ A-4-4 │ h: 30cm │
│ │ ░░░░░░ │ │ ░░▓▓░░ │ ░░░░░░ │ max: 50kg│
│ │ 12 db │ üres │ 4 db │ 8 db │ │
│ └────────┴────────┴────────┴────────┘ │
│ ┌────────┬────────┬────────┬────────┐ ← 3. sor │
│ │ A-3-1 │ A-3-2 │ A-3-3 │ A-3-4 │ h: 40cm │
│ │ ▓▓▓▓▓▓ │ ▓▓▓▓▓▓ │ ░░░░░░ │ │ max: 80kg│
│ │ 24 db │ 30 db │ 6 db │ üres │ │
│ └────────┴────────┴────────┴────────┘ │
│ ┌────────┬────────┬────────┬────────┐ ← 2. sor │
│ │ A-2-1 │ A-2-2 │ A-2-3 │ A-2-4 │ h: 50cm │
│ │ ▓▓▓▓▓▓ │ ▓▓▓▓▓▓ │ ▓▓▓▓▓▓ │ ▓▓▓▓▓▓ │ max:120kg│
│ │ TELE │ TELE │ TELE │ 45 db │ │
│ └────────┴────────┴────────┴────────┘ │
│ ┌────────┬────────┬────────┬────────┐ ← 1. sor │
│ │ A-1-1 │ A-1-2 │ A-1-3 │ A-1-4 │ h: 60cm │
│ │ ▓▓▓▓▓▓ │ ░░▓▓▓▓ │ ▓▓▓▓▓▓ │ ▓▓▓▓▓▓ │ max:200kg│
│ │ TELE │ 15 db │ TELE │ TELE │ │
│ └────────┴────────┴────────┴────────┘ │
│ ══════════════════════════════════════ ← padló │
│ │
│ Összesen: 16 hely │ 12 foglalt │ 3 üres │ 1 tele │
│ Telítettség: 78% │ Súly: 1420/2000 kg │
└─────────────────────────────────────────────────────┘

Méretarányos a height_cm, width_cm alapján. Szín-kódolt telítettség (üres=fehér, részben=zöld, tele=narancs, túl=piros, zárolt=szürke, foglalt=kék csík). Kattintható helyek, drag & drop áthelyezés.

Shelf Properties panel

┌─────────────────────────────────┐
│ Shelf Properties │
├─────────────────────────────────┤
│ Kód: [A] │
│ Név: [A salgó] (opcionális)│
│ Max összterhelés: [2000] kg │
│ │
│ ── Sorok ── │
│ │ # │ Mag.(cm) │ Szél.(cm) │ Mély.(cm) │ Teher(kg) │ Helyek │
│ │ 4 │ [30] │ [120] │ [60] │ [50] │ [4] │
│ │ 3 │ [40] │ [120] │ [60] │ [80] │ [4] │
│ │ 2 │ [50] │ [120] │ [60] │ [120] │ [4] │
│ │ 1 │ [60] │ [120] │ [60] │ [200] │ [4] │
│ │
│ [+ Sor hozzáadása] │
│ [Elölnézet] [Címke generálás] │
└─────────────────────────────────┘

5.4. Lokáció törlés védelem

MűveletSzabályHibaüzenet
Shelf törlésMinden gyerek üres"Nem törölhető: {qty} db készlet van az állványon"
Row törlésMinden space/box üres"Nem törölhető: {qty} db készlet van a soron"
Space/Box törlésSUM(qty) > 0 → TILTOTT"Nem törölhető: {qty} db készlet van a helyen"
Warehouse törlésMinden location üres és inaktív"A raktárban még van készlet"

Törlés = deaktiválás (is_active = false). Lokáció rekord soha nem törlődik fizikailag.

5.5. Layout verziózás

A warehouse_layouts tábla snapshot-okat tárol (locations + links JSON dump). Restore = snapshot visszaállítás.


6. Készletkezelési modell

6.1. Készlet állapotok

┌─────────────────────────────────────────────────────────┐
│ PHYSICAL (fizikai raktárban van) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│ │ AVAILABLE│ │ RESERVED │ │ BLOCKED │ │ BUFFER │ │
│ │ (szabad) │ │(foglalt) │ │ (zárolt) │ │(tartalék)│ │
│ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ SUPPLIER_STOCK (beszállítónál van) │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ AVAILABLE │ │ RESERVED │ ← virtuális raktár │
│ │ (rendelhető) │ │ (PO-hoz kötve)│ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
┌─────────────────────┐
│ IN_TRANSIT (úton) │ ← beszállítótól felénk, vagy dropship esetén a vevőhöz
└─────────────────────┘
┌─────────────────────┐
│ UNDER_INVESTIGATION │ ← leltárhiány vizsgálat alatt
└─────────────────────┘
┌─────────────────────┐
│ SCRAPPED (selejtezett)│
└─────────────────────┘

6.2. Elérhető készlet számítás

Fizikai raktár:
Available = Physical - Reserved - Blocked - Buffer

Virtuális raktár:
Available = supplier_stock_qty - Reserved_for_pending_POs

Összesített elérhető (webshop felé):
Total_Available = SUM(fizikai) + SUM(virtuális * include_virtual_policy) + SUM(in_transit * include_transit_policy)

6.3. Készlet struktúra

MezőLeírás
product_idTermék FK
variant_idTermékvariáns FK (nullable)
location_idLokáció FK (NULL virtuális raktárnál)
warehouse_idRaktár FK (mindig kitöltve — fizikai ÉS virtuálisnál is)
qtyMennyiség
statusAVAILABLE / RESERVED / BLOCKED / UNDER_INVESTIGATION / SCRAPPED
stock_purposeSELLABLE / BUFFER_RMA / BUFFER_SAFETY
serial_numberEgyedi azonosító
batch_lot_numberSarzs szám
expiry_dateLejárat (FEFO)
received_atBevételezés dátuma (FIFO)
unit_costEgységár
procurement_item_idFK → procurement_items.id

7. Rendelés-routing (Order Fulfillment Routing)

7.1. A probléma

Egy beérkező rendelés tételeit különböző forrásokból kell teljesíteni:

  • Termék A → saját fizikai raktárban van → pick/pack/ship
  • Termék B → nincs saját készleten, de a beszállítónál van → PO létrehozás, összevárás, majd áruátvétel+ship
  • Termék C → dropship termék → PO a beszállítónak a vevő címével

7.2. Fulfillment Source meghatározás

Minden rendelési tételhez a rendszer meghatározza a fulfillment_source-t:

Order Item routing algorithm:

1. Van-e AVAILABLE készlet saját fizikai raktárban?
→ IGEN: source = PHYSICAL, warehouse_id = fizikai raktár
→ NEM: tovább

2. Van-e a terméknek dropship beszállítója (is_dropship_eligible = true)?
ÉS a rendelés típusa engedi a dropshippet?
→ IGEN: source = DROPSHIP, supplier_id = dropship beszállító
→ NEM: tovább

3. Van-e a terméknek virtuális raktárban készlete (supplier_stock_qty > 0)?
→ IGEN: source = SUPPLIER_ORDER, supplier_id = preferred/legolcsóbb
→ NEM: source = BACKORDER (nincs sehol készlet)

Admin manuálisan felülírhatja a routing-ot tétel szinten.

7.3. Fulfillment típusok

TípusKódLeírásFizikai mozgás
Saját raktárPHYSICALNormál pick/pack/shipPolcról szedés → csomagolás → szállítás
Beszállítói rendelésSUPPLIER_ORDERPO → áruátvétel → shipBeszállító → mi → vevő
DropshipDROPSHIPPO a vevő címévelBeszállító → vevő (mi nem nyúlunk hozzá)
BackorderBACKORDERNincs készlet seholVárakozás → értesítés amikor lesz

7.4. Összevárás (Batch Procurement / Order Batching)

Ha egy rendelési tétel SUPPLIER_ORDER forrású, a rendszer nem azonnal rendel a beszállítótól, hanem összevárja a rendeléseket:

Összevárás logika:

1. Rendelés beérkezik → tétel source = SUPPLIER_ORDER
2. Tétel bekerül a "procurement_queue"-ba (pending beszerzési sor)
3. Az ütemező (konfig alapján) rendszeresen generál PO-t:
- Ütemezés típusok:
a. DAILY: naponta egyszer (pl. 14:00-kor)
b. INTERVAL: X óránként
c. THRESHOLD: ha az összegyűlt tételek értéke eléri a minimum rendelési értéket
d. MANUAL: admin manuálisan indítja
4. PO generálás:
- Csoportosítás beszállítónként
- Összesítés: 3 rendelésben 5+3+5 db "Widget X" = 13 db a PO-n
- MOQ ellenőrzés (ha kevesebb mint MOQ → kitöltés MOQ-ra, vagy várakozás)
- Min. rendelési érték ellenőrzés
5. PO jóváhagyás (manuális vagy automatikus)
6. Beszállítói export PDF generálás és küldés

7.5. Beszállítói export PDF

A PO-ból generált PDF, amit a beszállítónak küldünk (email-ben vagy letölthető):

┌─────────────────────────────────────────────────┐
│ VECTON – Megrendelés │
│ │
│ PO szám: PO-2026-0342 │
│ Dátum: 2026-03-19 │
│ Beszállító: TechData Hungary Kft. │
│ │
│ ┌────┬──────────────┬────────┬──────┬──────────┐│
│ │ # │ Cikkszám │ Termék │ Menny│ Egységár ││
│ ├────┼──────────────┼────────┼──────┼──────────┤│
│ │ 1 │ TD-WDG-001 │ Widget │ 13 db│ 2.450 Ft ││
│ │ 2 │ TD-GAD-055 │ Gadget │ 7 db │ 8.900 Ft ││
│ │ 3 │ TD-SPR-012 │ Spring │ 25 db│ 340 Ft ││
│ ├────┼──────────────┼────────┼──────┼──────────┤│
│ │ │ │ Összesen│ │95.850 Ft ││
│ └────┴──────────────┴────────┴──────┴──────────┘│
│ │
│ Szállítási cím: [saját raktár címe] │
│ Fizetési mód: átutalás, 30 nap │
│ Megjegyzés: Kérjük a TD-WDG-001 tételt külön │
│ csomagolni. │
│ │
│ Megrendelő: VECTON Kft. │
│ Aláírás: ________________________ │
└─────────────────────────────────────────────────┘

A PDF-en a beszállító saját cikkszáma (supplier_sku) jelenik meg, nem a mi belső SKU-nk.

7.6. Rendelés-tétel állapotok (order items fulfillment lifecycle)

PENDING_ROUTING → ROUTED → AWAITING_PROCUREMENT → PO_CREATED → IN_TRANSIT → RECEIVED → PICKING → SHIPPED
│ │
│ └── (összevárás alatt)

├── PHYSICAL: → PICKING → SHIPPED
├── DROPSHIP: → PO_CREATED → IN_TRANSIT → DELIVERED
└── BACKORDER: → várakozás → újra routing amikor készlet lesz

8. Készletmozgások (Inventory Transactions)

8.1. Tranzakció típusok

TípusLeírásForrás → Cél
RECEIVEÁruátvétel (PO-ból)— → fizikai lokáció
PUTAWAYBetárolásRECEIVING → STORAGE
PICKKomissiózásSTORAGE → SHIPPING/PACK
PACKCsomagolásPICK → csomag
SHIPKiszállításSHIPPING → —
MOVEÁthelyezéslokáció A → lokáció B
ADJUST_UPKorrekció felfelé— → lokáció
ADJUST_DOWNKorrekció lefelélokáció → —
RESERVEFoglalásállapotváltás
UNRESERVEFoglalás feloldásállapotváltás
BLOCKZárolásállapotváltás
UNBLOCKFeloldásállapotváltás
RMA_RECEIVEVisszáru beérkezés— → RMA lokáció
RMA_RESTOCKVisszáru visszapolcozásRMA → STORAGE
SCRAPSelejtezéslokáció → SCRAP
CROSS_DOCKÁtrakóRECEIVING → SHIPPING
TRANSFERRaktárközi transzferW1 → W2
VIRTUAL_RESERVEVirtuális készlet foglalásvirtuális raktár állapotváltás
VIRTUAL_RELEASEVirtuális foglalás feloldásvirtuális raktár állapotváltás
DROPSHIP_ORDERDropship rendelés a beszállítónakvirtuális → in_transit
DROPSHIP_DELIVERDropship kiszállítva a vevőnekin_transit → —

8.2. Immutable Audit Log

Minden tranzakció egy inventory_transactions rekord. Nem törölhető, nem módosítható. Korrekció = új ellentétes tranzakció.


9. Áruátvétel (Receiving / Inbound)

9.1. Workflow

PO státusz: IN_TRANSIT → ARRIVED → RECEIVING → RECEIVED (partially/fully)

1. Beszállító megérkezik → PO kiválasztás
2. Tételes átvétel: scan + mennyiség beütés + eltérés rögzítés
3. Minőségellenőrzés (opcionális) → QUALITY-CONTROL lokáció
4. Betárolás (Putaway): rendszer javasol lokációt, raktáros megerősíti

9.2. Putaway stratégiák

StratégiaLogika
FIXEDTermékhez rögzített lokáció
CLOSEST_AVAILABLELegközelebbi szabad hely (Dijkstra)
ZONE_BASEDTermékkategória → shelf mapping
CONSOLIDATEOda, ahol már van ugyanabból
ABC_CLASSA-osztály közel a SHIPPING-hez

9.3. Részleges átvétel

Egy PO több alkalommal is átvehető. procurement_items.qty_received kumulatívan nő. Státuszok: PARTIALLY_RECEIVED → RECEIVED → CLOSED.

9.4. Összevárásból érkező áru kiosztása

Amikor egy összevárásból generált PO áruátvétele megtörténik:

1. PO tétel átvéve (pl. 13 db Widget)
2. Rendszer megkeresi az eredeti rendeléseket, amikből ez a PO jött:
- Rendelés #101: 5 db Widget
- Rendelés #105: 3 db Widget
- Rendelés #108: 5 db Widget
3. Automatikus foglalás (RESERVE) a rendelésekhez
4. Ha marad felesleg (MOQ kitöltés miatt): AVAILABLE készletbe kerül
5. A hozzárendelt rendelések automatikusan PICKING státuszba lépnek

10. Komissiózás és rendelés-teljesítés (Picking & Fulfillment)

10.1. Picking workflow

Order státusz: CONFIRMED → PICKING → PICKED → PACKING → SHIPPED

1. Készletfoglalás (RESERVE)
2. Pick list generálás + útvonal-optimalizálás (TSP)
3. Szedés: scan lokáció → scan termék → mennyiség
4. PICKED → packing station-re

10.2. Szedési stratégiák

StratégiaLeírásMikor
FIFOLegrégebben bevételezett előszörAlapértelmezett
FEFOLeghamarabb lejáró előszörLejáratos termék
LIFOLegutóbb bevételezett előszörSpeciális eset
NONEBármelyik lokációrólNem lejáratos

10.3. Picking módok

  • Single Order: Egy rendelés → egy szedés
  • Batch Picking: Több rendelés összevont szedése → sorting station
  • Wave Picking: Időablakos batch

10.4. Rendelés-foglalás (Reservation)

Foglalás + timeout (konfig: reservation_timeout_hours). Ha nincs elég → partial reservation + backorder.


11. Csomagolás és kiszállítás (Packing & Shipping)

11.1. Packing workflow

1. Szedett tételek a pack station-re
2. Scan rendelés → tartalom megjelenik
3. Scan tételek a csomagba → kipipálás
4. Csomagolóanyag kiválasztás
5. Csomag lezárás: shipping label + súly/méret rögzítés

11.2. Shipping integráció

FutárszolgálatTípusPrioritás
GLS HungaryCsomagküldésP1
MPL (Magyar Posta)CsomagküldésP1
DPDCsomagküldésP2
FoxPostCsomagautomataP2
PacketaCsomagpontP2
Saját futárLokális kiszállításP2

11.3. Multi-colli

Egy rendelés több csomagban szállítható. Rendelés csak akkor SHIPPED, ha minden csomag feladva.


12. Dropshipping

12.1. Dropship koncepció

A beszállító közvetlenül a vevőhöz szállít. Nálunk nincs fizikai készletmozgás, de az egész folyamatot mi menedzseljük:

Dropship flow:

1. Vevő rendelés beérkezik
2. Order routing: tétel source = DROPSHIP
3. Rendszer automatikusan (vagy admin manuálisan) PO-t hoz létre:
- Beszállító: a termék dropship beszállítója
- Tételek: a vevő rendeléséből
- Szállítási cím: a VEVŐ szállítási címe (nem a mi raktárunk!)
- A PO-n a supplier_sku jelenik meg
4. PO elküldése a beszállítónak (email PDF, API, portál)
5. Beszállító szállít közvetlenül a vevőnek
6. Beszállító visszajelzi a tracking számot (webhook, email, manuális)
7. Tracking szám átíródik a vevő rendeléséhez
8. Állapotkövetés: ORDERED → SHIPPED_BY_SUPPLIER → DELIVERED

12.2. Dropship PO sajátosságok

MezőNormál PODropship PO
Szállítási címSaját raktárVevő címe
CsomagolásMi csomagolunkBeszállító csomagol
Shipping labelMi generáljukBeszállító generálja (vagy mi, ha az ő rendszere engedi)
TrackingSaját futár trackingBeszállító tracking → passthrough a vevőnek
KészletmozgásRECEIVE → PUTAWAY → PICK → SHIPNincs fizikai mozgás (DROPSHIP_ORDER → DROPSHIP_DELIVER)
SzámlázásMi számlázunk a vevőnekMi számlázunk a vevőnek, beszállító nekünk

12.3. Dropship profitszámítás

Dropship profit = Vevő fizet (eladási ár) - Beszállító ár - Egyéb költségek

Egyéb költségek:
- Platform fee (ha marketplace)
- Payment processing fee
- Esetleges szállítási felár

12.4. Dropship + Normál vegyes rendelés

Egy rendelésben lehetnek dropship ÉS normál tételek:

Rendelés #201:
- Termék A: 2 db → PHYSICAL (saját raktár) → pick/pack/ship
- Termék B: 1 db → DROPSHIP (TechData) → PO a vevő címével

Eredmény: a vevő 2 csomagot kap:
1. Tőlünk: Termék A
2. TechData-tól: Termék B (dropship)

A rendelés csak akkor COMPLETED, ha mindkét csomag megérkezett.

12.5. Dropship visszáru

Ha a vevő visszaküldi a dropship terméket:

  • A vevő nekünk küldi vissza (mi vagyunk az eladó)
  • Mi fogadjuk be (RMA flow) — vagy ha a beszállítóval van megállapodás, közvetlenül nekik
  • A garancia és liability logika ugyanúgy működik mint normál RMA-nál

13. Beszerzés (Procurement)

13.1. PO Lifecycle

DRAFT → SUBMITTED → CONFIRMED → IN_TRANSIT → CUSTOMS_CLEARANCE* → ARRIVED → RECEIVING → RECEIVED → CLOSED

(csak EU-n kívüli import)

Dropship PO:

DRAFT → SUBMITTED → CONFIRMED → SHIPPED_BY_SUPPLIER → DELIVERED → CLOSED

13.2. PO típusok

TípusKódLeírásSzállítási cím
NormálSTANDARDHagyományos beszerzés → saját raktárbaSaját raktár
ÖsszevárásbólBATCHEDTöbb rendelésből összesítve generáltSaját raktár
DropshipDROPSHIPKözvetlen kiszállítás a vevőnekVevő címe

13.3. Összevárás (Procurement Batching)

A procurement_queue gyűjti az összevárásra váró tételeket:

-- Pending tételek (rendelésből jöttek, de még nincs PO)
procurement_queue:
id, order_id, order_item_id, product_id, variant_id,
supplier_id, qty, status (PENDING / ASSIGNED_TO_PO / CANCELLED),
procurement_id (NULL amíg nincs PO),
created_at

Ütemezési stratégiák (konfig: procurement.batch_strategy):

StratégiaLeírás
DAILYNaponta egyszer, beállított időpontban (pl. 14:00)
INTERVALX óránként (pl. 4 óránként)
THRESHOLDAmikor az összegyűlt érték eléri a supplier.min_order_value-t
MANUALCsak admin indításra

13.4. Batch PO generálás

Batch PO generálás flow:

1. Ütemező trigger (vagy admin gomb)
2. FOREACH beszállító WHERE van PENDING procurement_queue tétel:
a. Tételek összegyűjtése beszállítónként
b. Összesítés termék + variáns szinten: qty = SUM(queue.qty)
c. MOQ ellenőrzés:
- Ha összesített qty < MOQ → döntés:
i. Kitöltés MOQ-ra (extra készlet lesz)
ii. Várakozás (nem generálunk PO-t, marad a queue-ban)
→ Konfig: `procurement.moq_strategy` = 'fill' | 'wait'
d. Min. rendelési érték ellenőrzés:
- Ha total < supplier.min_order_value → várakozás
e. PO létrehozás (DRAFT státuszban)
f. procurement_queue tételek ASSIGNED_TO_PO + procurement_id kitöltve
3. PO-k listázása admin-nak → jóváhagyás
4. Jóváhagyás után: SUBMITTED + PDF generálás + email küldés beszállítónak

13.5. Adózási körök

TípusÁFADokumentumok
BelföldiMagyar ÁFA (27%)Számla
EU Közösségi0% (Reverse Charge)Számla + Intrastat
Harmadik országImport ÁFA + VámSzámla + Vámáru-nyilatkozat + CE tanúsítvány

13.6. Landed Cost (Bekerülési érték)

unit_landed_cost = unit_price + (allocated_shipping + allocated_duty + allocated_other) / qty

Allokációs módszerek: érték / súly / mennyiség alapú.

13.7. Beszerzési dokumentumok

Dinamikusan bővíthető (document_types szótártábla): Számla, Szállítólevél, Vámáru-nyilatkozat, CE tanúsítvány, Minőségi tanúsítvány, MSDS.


14. Visszáru kezelés (RMA)

14.1. RMA State Machine

REQUESTED → APPROVED → RECEIVED → INSPECTING → GRADED → RESOLVED
↓ ↓ ↓
REJECTED CANCELLED ┌───┴───┐
│ │
RESTOCKED SCRAPPED

14.2. Grading

GradeLeírásMűvelet
AÚjra eladhatóVisszapolcozás → AVAILABLE
BCsökkentett áron eladhatóVisszapolcozás → outlet
CJavítandóSzerviz → újra grading
SCRAPNem javíthatóSelejtezés

14.3. Fotó policy

products.min_rma_photos → kötelező kategóriák: PACKAGE_OUTER, PACKAGE_INNER, PRODUCT_DAMAGE, SERIAL_NUMBER.

14.4. Pénzügyi felelősség

warranty_liability: SUPPLIER / COMPANY / CUSTOMER — automatikus meghatározás a garanciális dátumok alapján.


15. Leltározás (Inventory Audit / Cycle Count)

Csak fizikai raktárakra vonatkozik.

15.1. Típusok

  • Full Inventory: Teljes raktár (éves)
  • Cycle Count: Forgó leltár (ABC osztályozás)
  • Spot Check: Eseti ellenőrzés

15.2. Workflow

  1. Lokációk zárolása → 2. Számolás (scan + beütés, opcionálisan blind count) → 3. Eltérés kezelés (recount / writeoff / surplus) → 4. Lezárás + riport

16. Termék életút-követés (Traceability)

  • Egyedi (S/N) vs Sarzs (Lot/Batch)products.is_unique
  • Garancia: supplier_warranty_until / customer_warranty_until → automatikus liability
  • Lejárat: FEFO szedés, automatikus BLOCKED lejárt terméknél

17. Teljesítmény és gyorsítótár

17.1. Inventory Summary

Termékenként és raktáranként aggregált készlet (fizikai ÉS virtuális raktárakra is).

17.2. Frissítés

  • Egyedi tranzakció: szinkron trigger (0ms)
  • Tömeges: aszinkron queue job (< 500ms)
  • Teljes újraépítés: artisan command

17.3. Overselling védelem

SELECT ... FOR UPDATE az inventory_summary soron foglalásnál.


18. Címke generálás (Label Generator)

Csak fizikai raktárakra vonatkozik.

18.1. Új működés (Location-driven)

A label generator kizárólag a locations táblából dolgozik. Szabad szöveges range/manual mód MEGSZŰNIK.

1. Raktár kiválasztás
2. Lokáció-fa betöltés (SHELF → ROW → SPACE → BOX)
3. Lokáció kiválasztás (checkbox fa, szintenként, szűréssel)
4. QR generálás: VECTON-{full_code}
5. label_printed_at = NOW()

18.2. API

POST /api/warehouse/warehouses/{id}/labels/preview
POST /api/warehouse/warehouses/{id}/labels/generate
body: { location_ids: [uuid, ...], design, orientation }

Régi range/manual paraméterek törlendők.


19. Integrációk

19.1. Webshop szinkron

IrányAdatTrigger
Webshop → WarehouseRendelésWebhook / RabbitMQ
Warehouse → WebshopKészlet szint (fizikai + virtuális)Inventory summary változás
Webshop → WarehouseTermék adatokSzinkron / webhook

19.2. Külső webshop platformok

Shopify, WooCommerce, Shoprenter, Unas: rendelés import, készlet push, tracking push.

19.3. Futárszolgálat API

interface ShippingProvider {
public function createShipment(Order $order, Package $package): ShipmentResult;
public function getLabel(string $shipmentId): LabelResult;
public function getTracking(string $shipmentId): TrackingResult;
public function cancelShipment(string $shipmentId): bool;
}

19.4. Beszállítói integráció

MódLeírás
Email PDFPO export PDF generálás + email küldés supplier.order_email-re
APIBeszállító REST API-ján keresztül PO beküldés (egyedi implementáció per beszállító)
PortálAdmin manuálisan rendel a beszállító webes felületén
EDIElektronikus adatcsere (nagy beszállítóknál, későbbi fázis)

19.5. Mérleg integráció (opcionális)

Pack station USB/soros mérleg, súly validáció.


20. Adatbázis séma

20.1. Raktárak (MÓDOSUL — type + supplier_id)

-- A meglévő warehouses tábla kiegészítése:
ALTER TABLE warehouses ADD COLUMN type ENUM('physical','virtual','dropship') DEFAULT 'physical';
ALTER TABLE warehouses ADD COLUMN supplier_id UUID NULL REFERENCES suppliers(id);
-- supplier_id: virtuális és dropship raktáraknál kötelező, fizikainál NULL

20.2. Beszállítók

CREATE TABLE suppliers (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
code VARCHAR(50),
tax_number VARCHAR(50) NULL,
eu_vat_number VARCHAR(50) NULL,
contact_name VARCHAR(255) NULL,
contact_email VARCHAR(255) NULL,
contact_phone VARCHAR(50) NULL,
address_line1 VARCHAR(255) NULL,
address_line2 VARCHAR(255) NULL,
address_city VARCHAR(100) NULL,
address_zip VARCHAR(20) NULL,
address_country VARCHAR(2) NULL,
currency_code CHAR(3) DEFAULT 'HUF',
payment_terms_days INT DEFAULT 30,
lead_time_days INT NULL,
procurement_type ENUM('DOMESTIC','EU_COMMUNITY','THIRD_COUNTRY') DEFAULT 'DOMESTIC',
order_email VARCHAR(255) NULL, -- PO PDF küldés ide
order_method ENUM('email','api','portal','manual') DEFAULT 'email',
min_order_value DECIMAL(18,4) NULL, -- minimum rendelési érték
notes TEXT NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP NULL
);

20.3. Beszállítói termék katalógus

CREATE TABLE supplier_products (
id UUID PRIMARY KEY,
supplier_id UUID NOT NULL REFERENCES suppliers(id),
product_id UUID NOT NULL,
variant_id UUID NULL,

supplier_sku VARCHAR(100) NOT NULL, -- beszállító saját cikkszáma
unit_price DECIMAL(18,4) NOT NULL,
currency_code CHAR(3) DEFAULT 'HUF',
moq INT DEFAULT 1, -- minimum order quantity
order_unit INT DEFAULT 1, -- rendelési egység (1=darab, 10=csomag)
lead_time_days INT NULL, -- NULL = supplier szintű default

is_preferred BOOLEAN DEFAULT FALSE, -- elsődleges beszállító-e
is_dropship_eligible BOOLEAN DEFAULT FALSE, -- tud dropshippelni?

supplier_stock_qty DECIMAL(12,4) NULL, -- beszállítónál elérhető mennyiség
stock_updated_at TIMESTAMP NULL,

is_active BOOLEAN DEFAULT TRUE,
notes TEXT NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP,

UNIQUE(supplier_id, product_id, variant_id),
INDEX(product_id, is_active),
INDEX(supplier_id, is_active),
INDEX(product_id, is_preferred)
);

20.4. Lokációk (csak fizikai raktárakhoz)

CREATE TABLE locations (
id UUID PRIMARY KEY,
warehouse_id UUID NOT NULL REFERENCES warehouses(id),
parent_id UUID NULL REFERENCES locations(id),

level_type ENUM('SHELF','ROW','SPACE','BOX') NOT NULL,

code VARCHAR(50) NOT NULL,
full_code VARCHAR(150) NOT NULL, -- VECTON-W1-A-3-2-01
name VARCHAR(255) NULL,

height_cm INT NULL,
width_cm INT NULL,
depth_cm INT NULL,
position_index INT DEFAULT 0,

max_items INT NULL,
max_weight DECIMAL(10,2) NULL,
max_volume DECIMAL(10,4) NULL,

x DECIMAL(10,2) NULL, -- felülnézeti pozíció (SHELF szint)
y DECIMAL(10,2) NULL,

is_active BOOLEAN DEFAULT TRUE,
is_locked_for_audit BOOLEAN DEFAULT FALSE,
locked_by_user_id UUID NULL,
locked_at TIMESTAMP NULL,

label_printed_at TIMESTAMP NULL,

created_at TIMESTAMP,
updated_at TIMESTAMP,
-- NINCS deleted_at — soha nem törlődik, csak is_active = false

UNIQUE(warehouse_id, full_code)
);
CREATE INDEX idx_locations_parent ON locations(parent_id);
CREATE INDEX idx_locations_warehouse ON locations(warehouse_id);
CREATE INDEX idx_locations_active ON locations(warehouse_id, is_active);

20.5. Lokáció linkek

CREATE TABLE location_links (
id UUID PRIMARY KEY,
warehouse_id UUID NOT NULL REFERENCES warehouses(id),
from_location_id UUID NOT NULL REFERENCES locations(id),
to_location_id UUID NOT NULL REFERENCES locations(id),
weight DECIMAL(10,2) DEFAULT 1,
is_bidirectional BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP,
updated_at TIMESTAMP,
UNIQUE(from_location_id, to_location_id)
);

20.6. Layout verziók

CREATE TABLE warehouse_layouts (
id UUID PRIMARY KEY,
warehouse_id UUID NOT NULL REFERENCES warehouses(id),
version INT NOT NULL,
name VARCHAR(255) NULL,
is_active BOOLEAN DEFAULT FALSE,
location_snapshot JSON NOT NULL,
link_snapshot JSON NOT NULL,
created_by UUID NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP NULL,
UNIQUE(warehouse_id, version)
);

20.7. Készlet

CREATE TABLE inventory (
id UUID PRIMARY KEY,
product_id UUID NOT NULL,
variant_id UUID NULL,
warehouse_id UUID NOT NULL REFERENCES warehouses(id),
location_id UUID NULL REFERENCES locations(id), -- NULL virtuális raktárnál

qty DECIMAL(12,4) NOT NULL DEFAULT 0,
status ENUM('AVAILABLE','RESERVED','BLOCKED','UNDER_INVESTIGATION','SCRAPPED'),
stock_purpose ENUM('SELLABLE','BUFFER_RMA','BUFFER_SAFETY') DEFAULT 'SELLABLE',

serial_number VARCHAR(255) NULL,
batch_lot_number VARCHAR(100) NULL,
expiry_date DATE NULL,
received_at TIMESTAMP NULL,

unit_cost DECIMAL(18,4) NULL,
currency_code CHAR(3) NULL,
procurement_item_id UUID NULL REFERENCES procurement_items(id),

reserved_order_id UUID NULL,
reserved_at TIMESTAMP NULL,
release_date DATE NULL,

created_at TIMESTAMP,
updated_at TIMESTAMP,

INDEX(product_id, status),
INDEX(warehouse_id, product_id),
INDEX(location_id),
INDEX(product_id, variant_id, status)
);

20.8. Készlet összesítő

CREATE TABLE inventory_summary (
id UUID PRIMARY KEY,
product_id UUID NOT NULL,
variant_id UUID NULL,
warehouse_id UUID NOT NULL, -- fizikai ÉS virtuális raktárakra is

physical_qty DECIMAL(12,4) DEFAULT 0,
reserved_qty DECIMAL(12,4) DEFAULT 0,
blocked_qty DECIMAL(12,4) DEFAULT 0,
buffer_qty DECIMAL(12,4) DEFAULT 0,
in_transit_qty DECIMAL(12,4) DEFAULT 0,
available_qty DECIMAL(12,4) DEFAULT 0,

last_movement_at TIMESTAMP NULL,
updated_at TIMESTAMP,

UNIQUE(product_id, variant_id, warehouse_id)
);

20.9. Készletmozgás napló

CREATE TABLE inventory_transactions (
id UUID PRIMARY KEY,

transaction_type ENUM('RECEIVE','PUTAWAY','PICK','PACK','SHIP','MOVE',
'ADJUST_UP','ADJUST_DOWN','RESERVE','UNRESERVE',
'BLOCK','UNBLOCK','RMA_RECEIVE','RMA_RESTOCK',
'SCRAP','CROSS_DOCK','TRANSFER',
'VIRTUAL_RESERVE','VIRTUAL_RELEASE',
'DROPSHIP_ORDER','DROPSHIP_DELIVER'),

product_id UUID NOT NULL,
variant_id UUID NULL,
warehouse_id UUID NULL,
inventory_id UUID NULL REFERENCES inventory(id),

from_location_id UUID NULL REFERENCES locations(id),
to_location_id UUID NULL REFERENCES locations(id),
from_location_code VARCHAR(150) NULL,
to_location_code VARCHAR(150) NULL,

qty DECIMAL(12,4) NOT NULL,

reference_type VARCHAR(50) NULL,
reference_id UUID NULL,
correlation_id VARCHAR(100) NULL,

user_id UUID NULL,
device_id VARCHAR(100) NULL,
notes TEXT NULL,

created_at TIMESTAMP NOT NULL,

INDEX(created_at),
INDEX(product_id, created_at),
INDEX(transaction_type, created_at),
INDEX(correlation_id),
INDEX(reference_type, reference_id),
INDEX(warehouse_id, created_at)
);
-- Immutable!

20.10. Beszerzés

CREATE TABLE procurements (
id UUID PRIMARY KEY,
supplier_id UUID NOT NULL REFERENCES suppliers(id),
warehouse_id UUID NOT NULL REFERENCES warehouses(id), -- célraktár (fizikai, vagy dropship-nél a dropship wh)

po_number VARCHAR(50) NOT NULL,
po_type ENUM('STANDARD','BATCHED','DROPSHIP') DEFAULT 'STANDARD',

status ENUM('DRAFT','SUBMITTED','CONFIRMED','IN_TRANSIT',
'CUSTOMS_CLEARANCE','ARRIVED','RECEIVING',
'PARTIALLY_RECEIVED','RECEIVED',
'SHIPPED_BY_SUPPLIER','DELIVERED', -- dropship státuszok
'CLOSED','CANCELLED'),

procurement_type ENUM('DOMESTIC','EU_COMMUNITY','THIRD_COUNTRY') NOT NULL,

currency_code CHAR(3) NOT NULL,
exchange_rate DECIMAL(12,6) NULL,

shipping_cost DECIMAL(18,4) DEFAULT 0,
customs_duty DECIMAL(18,4) DEFAULT 0,
other_costs DECIMAL(18,4) DEFAULT 0,
cost_allocation_method ENUM('VALUE','WEIGHT','QUANTITY') DEFAULT 'VALUE',
total_landed_cost DECIMAL(18,4) DEFAULT 0,

is_customs_cleared BOOLEAN DEFAULT FALSE,
customs_cleared_at TIMESTAMP NULL,

-- Dropship szállítási cím (vevő címe)
ship_to_name VARCHAR(255) NULL,
ship_to_address1 VARCHAR(255) NULL,
ship_to_address2 VARCHAR(255) NULL,
ship_to_city VARCHAR(100) NULL,
ship_to_zip VARCHAR(20) NULL,
ship_to_country VARCHAR(2) NULL,
ship_to_phone VARCHAR(50) NULL,

-- Dropship tracking
supplier_tracking_number VARCHAR(200) NULL,

-- Kapcsolat az eredeti rendeléshez (dropship)
order_id UUID NULL,

expected_delivery_at DATE NULL,
received_at TIMESTAMP NULL,

notes TEXT NULL,
created_by UUID NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP NULL,

UNIQUE(po_number)
);

CREATE TABLE procurement_items (
id UUID PRIMARY KEY,
procurement_id UUID NOT NULL REFERENCES procurements(id) ON DELETE CASCADE,
product_id UUID NOT NULL,
variant_id UUID NULL,
supplier_product_id UUID NULL REFERENCES supplier_products(id),

supplier_sku VARCHAR(100) NULL, -- befagyasztott beszállítói cikkszám
qty_ordered DECIMAL(12,4) NOT NULL,
qty_received DECIMAL(12,4) DEFAULT 0,
unit_price DECIMAL(18,4) NOT NULL,
unit_landed_cost DECIMAL(18,4) NULL,

supplier_warranty_until DATE NULL,
customer_warranty_until DATE NULL,
warranty_liability ENUM('SUPPLIER','COMPANY','CUSTOMER') NULL,

batch_lot_number VARCHAR(100) NULL,
expiry_date DATE NULL,

notes TEXT NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);

CREATE TABLE document_types (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
is_required BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP,
updated_at TIMESTAMP
);

CREATE TABLE procurement_documents (
id UUID PRIMARY KEY,
procurement_id UUID NOT NULL REFERENCES procurements(id) ON DELETE CASCADE,
document_type_id UUID NOT NULL REFERENCES document_types(id),
file_path VARCHAR(500) NOT NULL,
created_at TIMESTAMP
);

20.11. Összevárás sor (Procurement Queue)

CREATE TABLE procurement_queue (
id UUID PRIMARY KEY,

order_id UUID NOT NULL,
order_item_id UUID NOT NULL,

product_id UUID NOT NULL,
variant_id UUID NULL,
supplier_id UUID NOT NULL REFERENCES suppliers(id),
supplier_product_id UUID NULL REFERENCES supplier_products(id),

qty DECIMAL(12,4) NOT NULL,

status ENUM('PENDING','ASSIGNED_TO_PO','CANCELLED') DEFAULT 'PENDING',
procurement_id UUID NULL REFERENCES procurements(id), -- kitöltve ha ASSIGNED_TO_PO

created_at TIMESTAMP,
updated_at TIMESTAMP,

INDEX(status, supplier_id),
INDEX(order_id),
INDEX(supplier_id, status)
);

20.12. Rendelés-teljesítés (Fulfillment)

CREATE TABLE picking_tasks (
id UUID PRIMARY KEY,
warehouse_id UUID NOT NULL REFERENCES warehouses(id),
order_id UUID NULL,
picking_mode ENUM('SINGLE','BATCH','WAVE') DEFAULT 'SINGLE',
wave_id UUID NULL,
status ENUM('PENDING','ASSIGNED','IN_PROGRESS','COMPLETED',
'PARTIALLY_COMPLETED','CANCELLED'),
priority INT DEFAULT 0,
assigned_to UUID NULL,
assigned_at TIMESTAMP NULL,
started_at TIMESTAMP NULL,
completed_at TIMESTAMP NULL,
route_plan_id UUID NULL REFERENCES route_plans(id),
created_at TIMESTAMP,
updated_at TIMESTAMP
);

CREATE TABLE picking_task_items (
id UUID PRIMARY KEY,
picking_task_id UUID NOT NULL REFERENCES picking_tasks(id) ON DELETE CASCADE,
product_id UUID NOT NULL,
variant_id UUID NULL,
inventory_id UUID NOT NULL REFERENCES inventory(id),
location_id UUID NOT NULL REFERENCES locations(id),
qty_requested DECIMAL(12,4) NOT NULL,
qty_picked DECIMAL(12,4) DEFAULT 0,
pick_sequence INT NOT NULL,
status ENUM('PENDING','PICKED','SHORT_PICKED','SKIPPED'),
picked_at TIMESTAMP NULL,
picked_by UUID NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);

CREATE TABLE packages (
id UUID PRIMARY KEY,
order_id UUID NOT NULL,
package_number VARCHAR(50) NOT NULL,
status ENUM('PACKING','PACKED','LABELLED','SHIPPED','DELIVERED','RETURNED'),
weight DECIMAL(10,3) NULL,
width DECIMAL(10,2) NULL,
height DECIMAL(10,2) NULL,
depth DECIMAL(10,2) NULL,
shipping_provider VARCHAR(50) NULL,
tracking_number VARCHAR(100) NULL,
shipping_label_url VARCHAR(500) NULL,
shipping_cost DECIMAL(18,4) NULL,
packed_by UUID NULL,
packed_at TIMESTAMP NULL,
shipped_at TIMESTAMP NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);

CREATE TABLE package_items (
id UUID PRIMARY KEY,
package_id UUID NOT NULL REFERENCES packages(id) ON DELETE CASCADE,
product_id UUID NOT NULL,
variant_id UUID NULL,
inventory_id UUID NOT NULL,
qty DECIMAL(12,4) NOT NULL,
serial_number VARCHAR(255) NULL,
created_at TIMESTAMP
);

20.13. Visszáru (RMA)

CREATE TABLE rma_tickets (
id UUID PRIMARY KEY,
order_id UUID NULL,
order_item_id UUID NULL,
product_id UUID NOT NULL,
variant_id UUID NULL,
inventory_id UUID NULL,
status ENUM('REQUESTED','APPROVED','RECEIVED','INSPECTING',
'GRADED','RESOLVED','REJECTED','CANCELLED'),
reason_category ENUM('DEFECTIVE','WRONG_ITEM','DAMAGED_SHIPPING',
'CUSTOMER_REMORSE','WARRANTY','OTHER'),
reason_notes TEXT NULL,
grade_result ENUM('A','B','C','SCRAP') NULL,
resolution ENUM('RESTOCKED','SCRAPPED','REPAIRED','REFUNDED','REPLACED') NULL,
liability ENUM('SUPPLIER','COMPANY','CUSTOMER') NULL,
location_id UUID NULL REFERENCES locations(id),
is_dropship_origin BOOLEAN DEFAULT FALSE, -- dropship termék visszáruja?
received_at TIMESTAMP NULL,
inspected_at TIMESTAMP NULL,
resolved_at TIMESTAMP NULL,
resolved_by UUID NULL,
created_by UUID NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);

CREATE TABLE rma_photos (
id UUID PRIMARY KEY,
rma_ticket_id UUID NOT NULL REFERENCES rma_tickets(id) ON DELETE CASCADE,
photo_category ENUM('PACKAGE_OUTER','PACKAGE_INNER','PRODUCT_DAMAGE','SERIAL_NUMBER'),
file_path VARCHAR(500) NOT NULL,
uploaded_by UUID NULL,
created_at TIMESTAMP
);

20.14. Leltár

CREATE TABLE inventory_audits (
id UUID PRIMARY KEY,
warehouse_id UUID NOT NULL REFERENCES warehouses(id),
audit_type ENUM('FULL','CYCLE_COUNT','SPOT_CHECK'),
status ENUM('PLANNED','IN_PROGRESS','PENDING_REVIEW','COMPLETED','CANCELLED'),
name VARCHAR(255) NULL,
is_blind_count BOOLEAN DEFAULT FALSE,
started_at TIMESTAMP NULL,
completed_at TIMESTAMP NULL,
started_by UUID NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);

CREATE TABLE inventory_audit_items (
id UUID PRIMARY KEY,
audit_id UUID NOT NULL REFERENCES inventory_audits(id) ON DELETE CASCADE,
location_id UUID NOT NULL REFERENCES locations(id),
product_id UUID NOT NULL,
variant_id UUID NULL,
expected_qty DECIMAL(12,4) NOT NULL,
counted_qty DECIMAL(12,4) NULL,
variance_qty DECIMAL(12,4) NULL,
status ENUM('PENDING','COUNTED','PENDING_RECOUNT','RECOUNTED',
'PENDING_APPROVAL','APPROVED_WRITEOFF','APPROVED_SURPLUS','TRANSFERRED'),
counted_by UUID NULL,
counted_at TIMESTAMP NULL,
recounted_by UUID NULL,
recounted_at TIMESTAMP NULL,
approved_by UUID NULL,
approved_at TIMESTAMP NULL,
resolution_notes TEXT NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);

20.15. Konfiguráció

-- tenant_configs kulcsok:

wms.reservation_timeout_hours = 48
wms.backorder_policy = 'notify'
wms.virtual_stock_in_available = true -- virtuális készlet beleszámít a webshop available-ba?
wms.include_in_transit_in_available = false
wms.default_picking_mode = 'single'
wms.expiry_warning_days = 30
wms.auto_block_expired = true
wms.blind_count_default = false
wms.putaway_strategy = 'consolidate'
wms.cycle_count_a_frequency_days = 30
wms.cycle_count_b_frequency_days = 90
wms.cycle_count_c_frequency_days = 180

-- Beszerzés összevárás
procurement.batch_strategy = 'daily' -- daily | interval | threshold | manual
procurement.batch_time = '14:00' -- DAILY módnál: mikor fusson
procurement.batch_interval_hours = 4 -- INTERVAL módnál: hány óránként
procurement.moq_strategy = 'fill' -- fill | wait
procurement.auto_approve_po = false -- automatikus PO jóváhagyás?
procurement.auto_send_po = false -- automatikus email küldés?

-- Dropship
dropship.enabled = true
dropship.auto_create_po = true -- automatikus PO dropship rendelésnél

21. API végpontok

21.1. Meglévő (MÓDOSUL)

GET/POST/PUT/DELETE  /api/warehouse/warehouses[/{id}]
↑ type mező: 'physical' | 'virtual' | 'dropship'
↑ supplier_id mező virtuális/dropship-nél

POST /api/warehouse/warehouses/{id}/plan-route
POST /api/warehouse/plan-multi-route
POST /api/warehouse/warehouses/{id}/labels/preview
POST /api/warehouse/warehouses/{id}/labels/generate
↑ body: { location_ids, design, orientation }

21.2. Beszállítók & Katalógus

GET/POST        /api/warehouse/suppliers
GET/PUT/DELETE /api/warehouse/suppliers/{id}

GET/POST /api/warehouse/suppliers/{id}/products -- supplier_products CRUD
PUT/DELETE /api/warehouse/supplier-products/{id}
POST /api/warehouse/suppliers/{id}/products/import -- árlista CSV/Excel import
GET /api/warehouse/products/{productId}/suppliers -- termékhez tartozó beszállítók

21.3. Lokációk

GET     /api/warehouse/warehouses/{id}/locations
GET /api/warehouse/warehouses/{id}/locations/tree
GET /api/warehouse/warehouses/{id}/locations/flat
POST /api/warehouse/warehouses/{id}/locations
PUT /api/warehouse/locations/{id}
DELETE /api/warehouse/locations/{id} -- deaktiválás, csak ha üres
GET /api/warehouse/locations/{id}
GET /api/warehouse/locations/{id}/inventory
GET /api/warehouse/locations/{id}/children
GET /api/warehouse/locations/{id}/history
GET /api/warehouse/locations/{id}/rack-detail

POST /api/warehouse/locations/{id}/lock
POST /api/warehouse/locations/{id}/unlock

GET/POST/DELETE /api/warehouse/warehouses/{id}/location-links
GET/POST /api/warehouse/warehouses/{id}/layouts
POST /api/warehouse/warehouses/{id}/layouts/{id}/restore
DELETE /api/warehouse/warehouses/{id}/layouts/{id}

21.4. Készlet

GET     /api/warehouse/inventory
GET /api/warehouse/inventory/summary
GET /api/warehouse/inventory/summary/combined -- fizikai + virtuális összesítve (webshop felé)
GET /api/warehouse/inventory/{id}
POST /api/warehouse/inventory/move
POST /api/warehouse/inventory/adjust
POST /api/warehouse/inventory/reserve
POST /api/warehouse/inventory/unreserve
POST /api/warehouse/inventory/block
POST /api/warehouse/inventory/unblock

GET /api/warehouse/inventory/transactions
GET /api/warehouse/inventory/transactions/{id}

21.5. Rendelés-routing

POST    /api/warehouse/orders/{orderId}/route               -- order items routing (auto)
PUT /api/warehouse/orders/{orderId}/items/{itemId}/route -- manuális routing override
GET /api/warehouse/orders/{orderId}/fulfillment-status -- teljesítési állapot összesítő

21.6. Beszerzés & Összevárás

GET/POST        /api/warehouse/procurements
GET/PUT/DELETE /api/warehouse/procurements/{id}
POST /api/warehouse/procurements/{id}/submit
POST /api/warehouse/procurements/{id}/confirm
POST /api/warehouse/procurements/{id}/customs-clear
POST /api/warehouse/procurements/{id}/cancel
GET /api/warehouse/procurements/{id}/export-pdf -- beszállítói export PDF letöltés
POST /api/warehouse/procurements/{id}/send-to-supplier -- PDF email küldés

GET/POST /api/warehouse/procurements/{id}/items
PUT/DELETE /api/warehouse/procurements/{id}/items/{itemId}
POST /api/warehouse/procurements/{id}/documents
DELETE /api/warehouse/procurements/{id}/documents/{docId}

-- Összevárás
GET /api/warehouse/procurement-queue -- pending tételek
POST /api/warehouse/procurement-queue/generate-pos -- batch PO generálás (manuális trigger)
GET /api/warehouse/procurement-queue/preview -- preview: milyen PO-k jönnének létre
DELETE /api/warehouse/procurement-queue/{id} -- tétel törlése a sorból

21.7. Áruátvétel

POST    /api/warehouse/receiving/start
POST /api/warehouse/receiving/{sessionId}/scan
POST /api/warehouse/receiving/{sessionId}/confirm
POST /api/warehouse/receiving/{sessionId}/complete
POST /api/warehouse/receiving/{sessionId}/putaway
GET /api/warehouse/receiving/suggest-location

21.8. Komissiózás

GET/POST /api/warehouse/picking/tasks
GET /api/warehouse/picking/tasks/{id}
POST /api/warehouse/picking/tasks/{id}/assign
POST /api/warehouse/picking/tasks/{id}/start
POST /api/warehouse/picking/tasks/{id}/items/{itemId}/pick
POST /api/warehouse/picking/tasks/{id}/complete
POST /api/warehouse/picking/waves
GET /api/warehouse/picking/waves/{id}

21.9. Csomagolás & Szállítás

POST    /api/warehouse/packing/start
POST /api/warehouse/packing/{sessionId}/scan
POST /api/warehouse/packing/{sessionId}/close-package
GET /api/warehouse/packing/{sessionId}

POST /api/warehouse/shipping/create-shipment
GET /api/warehouse/shipping/label/{packageId}
POST /api/warehouse/shipping/ship/{packageId}
GET /api/warehouse/shipping/tracking/{packageId}

21.10. RMA & Leltár

GET/POST  /api/warehouse/rma
GET/PUT /api/warehouse/rma/{id}
POST /api/warehouse/rma/{id}/approve|receive|inspect|grade|resolve
POST /api/warehouse/rma/{id}/photos

GET/POST /api/warehouse/audits
GET/PUT /api/warehouse/audits/{id}
POST /api/warehouse/audits/{id}/start|complete
POST /api/warehouse/audits/{id}/items/{itemId}/count|recount|approve
GET /api/warehouse/audits/{id}/report

22. Megvalósítási fázisok

Fázis 1 — Lokációk, Layout Editor átdolgozás, Készlet mag ⏱️ ~5-7 hét

#FeladatPrioritás
1.1locations tábla (SHELF/ROW/SPACE/BOX) + CRUD APIP0
1.2location_links tábla + CRUD APIP0
1.3Layout Editor refactor: JSON → locations + location_linksP0
1.4Helykód: VECTON-{WAREHOUSE}-{SHELF}-{ROW}-{SPACE}-{BOX}P0
1.5Törlés védelem (inventory check)P0
1.6inventory + inventory_transactions + inventory_summaryP0
1.7Alapvető mozgások: MOVE, ADJUST_UP, ADJUST_DOWNP0
1.8Label generator: location_ids input, range/manual törlésP0
1.9Web UI: lokáció fa + készlet nézet + címke generátorP1
1.102D elölnézet (rack detail) + Shelf Properties panelP1
1.11Route planner átállítás location_links-reP1
1.12Layout verziózás (snapshot)P1

Fázis 2 — Beszállítók, Katalógus, Virtuális raktár ⏱️ ~4-5 hét

#FeladatPrioritás
2.1suppliers tábla + CRUDP0
2.2supplier_products tábla + CRUDP0
2.3Warehouses type mező: physical / virtual / dropshipP0
2.4Virtuális raktár koncepció: inventory_summary virtuális raktárakraP0
2.5Beszállítói árlista import (CSV/Excel)P1
2.6Összesített elérhető készlet (fizikai + virtuális)P1
2.7Web UI: beszállítók kezelése, termék-beszállító összerendelésP0

Fázis 3 — Beszerzés, Összevárás, Export PDF ⏱️ ~5-6 hét

#FeladatPrioritás
3.1procurements + procurement_items + PO lifecycleP0
3.2procurement_queue + összevárás logikaP0
3.3Batch PO generálás (daily/interval/threshold/manual)P0
3.4Beszállítói export PDF generálás (supplier_sku-val!)P0
3.5PO email küldés beszállítónakP1
3.6Áruátvételi workflow (RECEIVE → PUTAWAY)P0
3.7Összevárásból érkező áru automatikus kiosztás a rendelésekhezP1
3.8Landed cost kalkulációP2
3.9Web UI: PO kezelés, queue nézet, áruátvételP0

Fázis 4 — Rendelés-routing, Dropshipping ⏱️ ~4-5 hét

#FeladatPrioritás
4.1Order fulfillment routing logika (PHYSICAL / SUPPLIER_ORDER / DROPSHIP / BACKORDER)P0
4.2Dropship PO generálás (vevő címével)P0
4.3Dropship tracking passthroughP1
4.4Vegyes rendelés kezelés (dropship + fizikai)P1
4.5Dropship profit számításP2
4.6Web UI: routing nézet, dropship kezelésP0

Fázis 5 — Komissiózás, Csomagolás, Szállítás ⏱️ ~4-6 hét

#FeladatPrioritás
5.1RESERVE/UNRESERVE logika + timeoutP0
5.2picking_tasks + picking_task_itemsP0
5.3Pick list generálás (FIFO/FEFO) + route plannerP0
5.4packages + package_items (packing)P0
5.5ShippingProvider interface + GLS + MPLP0
5.6Shipping label + tracking visszaírásP0
5.7Batch/Wave pickingP2
5.8Web UI: picking, packing station, shippingP0

Fázis 6 — RMA, Leltár, Haladó ⏱️ ~3-4 hét + folyamatos

#FeladatPrioritás
6.1RMA state machine + grading + fotókP0
6.2Dropship visszáru kezelésP1
6.3Leltár (full / cycle count / spot check)P0
6.4Blind count módP2
6.5Vámkezelés workflowP2
6.6Raktárközi transzferP2
6.7Dashboard & riportokP1
6.8Beszállítói API integráció (EDI)P3
6.9Lejárat figyelő cron + auto zárolásP1

Összefoglaló

A rendszer kulcs tervezési döntései:

  • 3 raktár típus: Fizikai (saját), Virtuális (beszállítói készlet), Dropship (közvetlenül a vevőhöz)
  • Beszállítói katalógus: Termék-beszállító kapcsolat saját SKU-kkal, árakkal, MOQ-kkal
  • Összevárás: Rendelések gyűjtése → napi/időszakos batch PO generálás beszállítónként → export PDF
  • Order routing: Rendelési tételek automatikus routing-ja a legjobb forráshoz (saját készlet → beszállítói rendelés → dropship → backorder)
  • Dropshipping: Beszállító szállít a vevőnek, mi menedzseljük a folyamatot, tracking passthrough
  • Layout Editor = Lokáció kezelő: Közvetlenül a locations táblát kezeli, nincs szinkron
  • VECTON-{W}-{SHELF}-{ROW}-{SPACE}-{BOX}: Egységes hierarchia, minden hely regisztrált
  • Címke = regisztrált hely: QR generátor kizárólag locations táblából
  • Immutable audit trail: Minden mozgás naplózva, befagyasztott kódokkal
  • Tenant izoláció infrastruktúra szinten: Nincs tenant_id