Mango.Nop.Plugins/Nop.Plugin.Misc.AIPlugin/docs/PREORDER/PREORDER_ISSUES.md

7.7 KiB

PRE-ORDER — Known Issues

Companion to README.md. Topic PREO, prefix MGFBANKPLUG → entry IDs MGFBANKPLUG-PREO-I-<RAND> (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) 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 InsertOrderItemsAsyncAdjustInventoryAsync(-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 = 6pool = 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) ú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.csBuildIncomingQuantityPoolAsync (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.csConvertPreOrdersForProductsAsync (jogosultsági szűrő alsó korlát), SweepExpiredPreOrdersAsync (dátum-szintű lejárat + PartiallyFulfilled maradék véglegesítése + rendelés-jegyzet).