# PRE-ORDER — Known Issues > Companion to [`README.md`](README.md). Topic `PREO`, prefix `MGFBANKPLUG` → entry IDs `MGFBANKPLUG-PREO-I-` (issue) / `-B-` (confirmed bug). > ID format, Status vocabulary, type codes and archival are **not restated here** — see `../../.github/TOPIC_CODES.md` (which points to the framework registry). Entry template: follow `AyCode.Core/.github/META_ISSUES.md`. Scope: bugs / inconsistent or observable edge-case behaviour in the pre-order subsystem — placement, allocation/conversion, conversion window, expiry sweep, order create/append, product replacement, status derivation, pricing. ## Active entries ## MGFBANKPLUG-PREO-B-K7M2: A konverziós pool dupla-számolja a már teljesített foglalásokat — alul-allokáció **Status:** Closed (2026-06-29) — javítva · **Priority:** P2 · **Type:** B (megerősített bug) ### Resolution (2026-06-29) Kijavítva a `PreOrderConversionService`-ben, három összefüggő lépéssel (mind a `Services/PreorderConversionService.cs`-ben): 1. **Konvertálhatósági előszűrés** a `ConvertPreOrdersForProductsAsync`-ben: csak az a preorder kap teljesítést, ami tényleg rendelést tud létrehozni (van `OrderId` = append-út, vagy feloldható customer + számlázási cím = új-rendelés-út, az új `ResolveBillingAddressIdAsync` helperrel). Ezzel garantált az invariáns: **`Fulfilled ⇒ rendelés létrejön ⇒ készlet levonva`**. A nem konvertálható preorderek tételei `Pending`-ben maradnak. 2. **Delta-alapú order-item**: az `InsertOrderItemsAsync` mostantól a futásban szerzett mennyiséget (`gainedByItemId` delta) viszi a tételbe / vonja le a készletből, nem a kumulatív `FulfilledQuantity`-t. Ez javítja a **vele összefonódó, korábban elfedett második hibát**: részleges utántöltésnél (multi-dokumentum) az append a *teljes* mennyiséget vonta le → dupla-levonás + duplikált order-item. 3. A garantált invariáns mellett a `BuildIncomingQuantityPoolAsync` dupláló `alreadyAllocated` levonása **eltávolítva**: `pool = AvailableQuantity` (ami az `AdjustInventoryAsync` miatt már tartalmazza a korábbi foglalásokat). **Eredmény:** a reprodukciós eset (`Stock=0, Incoming=10`, A 6-ot kap, B 6-ot kér) most helyesen B-nek 4-et ad; a részleges utántöltés is helyesen a deltát viszi. **Maradék (elhanyagolható) él:** ha a customer/cím a futás közben (előszűrés után, rendeléslétrehozás előtt) törlődne — extrém versenyhelyzet —, az item `Fulfilled` maradhatna rendelés nélkül. A `CreateOrderAsync` korai return-jei safety netként megmaradtak; a teljes védelemhez a státusz-mentést a rendeléslétrehozás *után* kellene végezni (külön, nem szükséges most). --- #### Eredeti leírás **Type:** B (megerősített bug) `PreOrderConversionService.BuildIncomingQuantityPoolAsync` ([`Services/PreorderConversionService.cs`](../../Services/PreorderConversionService.cs)) a rendelkezésre álló mennyiségből **kétszer** vonja le a korábbi futásokban már teljesített (`Fulfilled`/`PartiallyFulfilled`) preorder-tételeket. - `AvailableQuantity = StockQuantity + IncomingQuantity` (SCHEMA.md), az élő `Product.StockQuantity`-ből. - Teljesítéskor `InsertOrderItemsAsync` → `AdjustInventoryAsync(-FulfilledQuantity)` **már csökkenti** a `StockQuantity`-t, így a következő futás `AvailableQuantity`-je **már tartalmazza** a foglalást. - A pool ezen felül **még levonja** az `alreadyAllocated`-et (a `Fulfilled`/`PartiallyFulfilled` itemek `FulfilledQuantity` összegét) → **futások közötti dupla-levonás**. **Reprodukció:** `Stock=0, Incoming=10`. „A" preorder 6-ot teljesít (run 1) → `Stock=-6`, allocated=6. „B" preorder 6-ot kér (run 2): `available = -6+10 = 4`, `committed = 6` → `pool = max(0, 4-6) = 0`. **B nem kap semmit, pedig fizikailag 4 jár neki.** Az alul-allokáció a „még nincs beérkezve" eset — az előrendelés tipikus forgatókönyve. **Miért nem puszta törlés a fix:** a `CreateOrderAsync` korai `return`-jei (nincs `Customer` / nincs számlázási cím, [sorok ~300-319](../../Services/PreorderConversionService.cs)) úgy lépnek ki, hogy az item a fő ciklusban (sor ~153) **már `Fulfilled`-re lett állítva és elmentve**, de a készletlevonás nem futott le. Ezeken a hibautakon az `alreadyAllocated` levonás *helyesen* kompenzál; a levonás puszta törlése **túl-allokációt (overselling)** okozna. **Javítási irány (ajánlott):** az item csak akkor legyen `Fulfilled`, ha a rendelés + készletlevonás ténylegesen sikerült (korai return esetén maradjon `Pending`/visszaállítás), majd ezután eltávolítható a dupláló `alreadyAllocated` levonás. Így megszűnik az alul-allokáció túl-allokációs kockázat nélkül. **Affected:** - `Services/PreorderConversionService.cs` → `BuildIncomingQuantityPoolAsync` (a `alreadyAllocated` levonás), `ConvertPreOrdersForProductsAsync` fő ciklusa (státusz-mutáció sorrendje), `CreateOrderAsync` korai return ágai. ## MGFBANKPLUG-PREO-B-M4T9: Lejárt előrendeléseket kielégít a rendszer friss szállítmányból **Status:** Closed (2026-07-08) — javítva · **Priority:** P1 · **Type:** B (megerősített bug, éles jelzés) Admin-jelzés: hosszú ideje **lejárt** előrendeléseket a rendszer friss szállítmányból kielégít, holott a lejárt előrendelésnek lezártnak kellene lennie és soha többé nem konvertálódnia. **Gyökérok — két hiba játszik össze:** 1. A `ConvertPreOrdersForProductsAsync` jogosultsági szűrőjének **csak felső korlátja volt** (`DateOfReceipt.Date <= ma + PreOrderConversionWindowDays`), **alsó korlátja nem** — így egy tetszőleges múltbeli dátumú előrendelés is átment (múltbeli dátum ≤ ma+4 mindig igaz). 2. A `SweepExpiredPreOrdersAsync` **csak a `Pending` tételeket ejti**; a `PartiallyFulfilled` tételeket érintetlenül hagyja (mert azok már valós rendelésen vannak). Ezek `OrderId`-vel rendelkeznek → az `AppendItemsToOrderAsync` a maradék mennyiséget **minden későbbi szállítmányból utántölti**, korlátlan ideig a lejárat után. **Tipikus eset:** vevő 100-at rendel, 60 megjön (`PartiallyFulfilled`), a dátum lejár → a maradék 40-et a rendszer örökké tölti a friss szállítmányokból. ### Resolution (2026-07-08) `Services/PreorderConversionService.cs`: - **Alsó korlát** a jogosultsági szűrőben: `DateOfReceipt.Date >= ma` — lejárt (múltbeli) előrendelés **soha** nem kap allokációt (sem új rendelést, sem utántöltést). Ez az egyetlen konverziós kapu, minden trigger ezen megy át. - A **sweep** lejárat-határa dátum-szintre igazítva (`DateOfReceipt < ma-éjfél`, kliens-oldali konstans → SQL-biztos), hogy egy **aznapi** előrendelés a teljes szállítási napon aktív maradjon, és ne legyen „félig lezárva" (Pending ejtve, de PartiallyFulfilled még tölthető). Így a sweep (dátum < ma) és a szűrő (dátum ≥ ma) pontos komplementerek, nincs rés. **Maradék-véglegesítés (2026-07-08, riport-tisztaság):** a `SweepExpiredPreOrdersAsync` mostantól a lejárt előrendelések `PartiallyFulfilled` tételeit is lezárja: a tétel a teljesített mennyiségen záródik (`RequestedQuantity ← FulfilledQuantity`, státusz `Fulfilled`), így a maradék ejtve — nem mutatkozik többé nyitott igényként (pl. DemandList). A shortfall (eredeti igény vs. teljesített) a kapcsolt **rendeléshez jegyzetként** rögzül, tehát nem vész el. A soha nem teljesített tételeket mennyiség-alapon (`FulfilledQuantity == 0`) ejti, robusztusan a bizonytalan enum-olvasás ellen. **Affected:** - `Services/PreorderConversionService.cs` → `ConvertPreOrdersForProductsAsync` (jogosultsági szűrő alsó korlát), `SweepExpiredPreOrdersAsync` (dátum-szintű lejárat + `PartiallyFulfilled` maradék véglegesítése + rendelés-jegyzet).