Mango.Nop.Plugins/Nop.Plugin.Misc.AIPlugin/docs/EKAER/EKAER_TODO.md

22 KiB
Raw Blame History

EKÁER — TODO / nyitott döntések

Companion to README.md. Topic EKAER, prefix MGFBANKPLUG → entry IDs MGFBANKPLUG-EKAER-T-<RAND>. ID format, Status vocabulary, type codes, archival → ../../.github/TOPIC_CODES.md (→ framework registry).

Scope: a Shipping / ShippingDocument → NAV tradeCard leképezés (ShippingToEkaerMapper, FruitBank.Common/Services/Ekaer/) nyitott üzleti/technikai döntései. A tisztázott megfeleltetést lásd README.md.

Active entries

MGFBANKPLUG-EKAER-T-K7Q2: Shipping → tradeCard mapping — nyitott döntések

Status: Open · Priority: P2 · Type: T (mapping-tervezés)

A ShippingToEkaerMapper megírása előtt tisztázandó pontok. Minden sor a jelenlegi (alapértelmezett) feltételezést és a nyitott kérdést rögzíti.

# Téma Jelenlegi feltételezés Nyitott kérdés
1 tradeType (E/I/D irány) Frissítve (2026-06): a feladó és a címzett országkódjának összevetése dönt: egyezik → D (belföld); eltér → kimenőnél E (export), bejövőnél I (import). (Korábban: HU ↔ nem-HU.) A Customer.CountryId → ISO-feloldás kimenőnél még TODO (#7) → addig a vevő HU, ezért a kimenő ténylegesen D marad.
2 Célhely / telephely Megoldva: configból (Ekaer:Company + Site al-szekció) → IEkaerSettings.Company + EkaerCompanyInfo.Site (LocationType, fel-/lerakodás). Nincs hardcode. Több telephely (mint a PartnerDepot) — későbbi, ha kell.
3 Érték (value, HUF) Megoldva: UnitPriceOnDocument × QuantityOnDocument × árfolyam (EkaerValueCalculator). Pénznem a Partner.Currency-ből; EUR-HUF árfolyam configból (Ekaer:ExchangeRate:EurHuf, MNB középárfolyam). Árfolyam dinamizálása (jelenleg „drót" config-érték) — későbbi.
4 Tömeg (weight) Frissítve (2026-07): GrossWeightOnDocument — a szállítólevélen szereplő bruttó (a value-hoz hasonlóan minden adat a kísérő dokumentumról; a bejelentés nem függ a későbbi mérlegeléstől). Korábban: MeasuredGrossWeight. Megoldva (2026-07): a validátor tételenként blokkoló weight > 0 szabályt kényszerít (0 = a doksiról hiányzó súly → ValidationError). A kapu tételenkénti súly-előfeltétele külön teendő: #12.
5 Granularitás Frissítve (2026-06/07): a kézi út CSOPORT-alapú — bejövő: a (Shipping, Partner, PartnerDepot) csoport ÖSSZES dokumentuma = 1 tradeCard (1 EkaerHistory + N mapping); kimenő: 1 rendelés = 1 tradeCard. ⚠️ A MapShipping (automata SubmitShippingAsync-út) még dokumentumonként gyárt tradeCard-ot — a granularitás ELTÉR a kézi úttól; az automata beadás bekötése ELŐTT a kézi (csoport-alapú) granularitásra egységesítendő.
6 Eladó (seller*) mezők ShippingDocument.Partner-ből: Name, TaxId (első 8 jegy = adószám-törzs), CountryCode, City, Street, PostalCode. A Partner (PartnerBase) pontos mezőnevei/forrásai — megerősíteni. Továbbá: a NAV magyar felrakodási helynél phone/email mezőt is kér — a Partner/PartnerDepot entitásban nincs ilyen (entitás+DB bővítés kell; importnál — külföldi feladó — nem játszik).
7 Kimenő irány (Order → EKÁER) Implementálva (ToConsignment(OrderDto)): mi=eladó, vevő=címzett; tömeg OrderItemDto.GrossWeight, érték nettó (UnitPriceExclTax × qty), jelenleg minden HUF (rate 1). carrierText kimenőnél NEM töltve (üres) — a vevő maga viszi el, ő már a címzett; a carrierText opcionális (2026-06). Nyitott: a vonó jármű (rendszám) forrása — a Customer-hez még nincs bekötve (üres → warning, a felrakodás megkezdéséig pótolandó). Külföldi deviza + Customer.CountryId ISO-feloldás (export E): későbbi.
8 productVtsz forrás ProductDto.Gtin (átmeneti). GTIN ≠ VTSZ — lásd MGFBANKPLUG-EKAER-I-T3X8; hosszú távon külön Vtsz mező. A VTSZ-csoportosítás + productName külön kérdés: T-V9G3.
9 tétel tradeReason Megoldva (2026-07-10, common.xsd-ből ellenőrizve): MINDKÉT irány S-t küld (= „Termék értékesítés / beszerzés" — egy kód). A korábbi bejövő A HIBÁS volt: az A = „Saját tulajdonú termék — törvényváltozás miatt KIVEZETVE" (nem „beszerzés"!), és belföldön (D) csak S adható. Lásd AyCode EKAER_TRADECARD.md → tradeReason.
10 value mező Megoldva: a value most töltve (lásd #3); 0 / ismeretlen ár esetén null marad. Megoldva (2026-07): a validátor tételenként blokkoló value > 0 szabályt kényszerít (hiányzó/0 érték → ValidationError).
11 Külföldi reláció a küszöb-kapuban Lezárva — kimondottan az ügyfél kérése (megerősítve 2026-07-10): az EkaerReportability küszöb alatt is kötelezőnek veszi a külföldi relációt; a hatályos jog ennél kevesebbet követel (13/2020 PM 4.§ i — a mentesség irány-független). A lehetséges jövőbeni átírás (jogszabályi szabályra) követése: EKAER_ISSUES.md I-F5D9.
12 Kapu: tételenkénti bruttó súly-előfeltétel Megoldva (2026-07-10): az EkaerReportability.Evaluate (0). lépése MINDEN ág előtt — bármely tétel WeightKg <= 0DataError tételes üzenettel (a sor nem jön létre; pótlás után a következő futás felveszi). Korábban a 0 súlyú tétel (kitöltetlen GrossWeightOnDocument / méretlen rendelés) csendben alul-számolta a küszöb-summát → alul-jelentési kockázat volt.

Affected:

  • ShippingToEkaerMapper (FruitBank.Common/Services/Ekaer/) — a leképezés
  • EkaerTradeCardValidator / EkaerSubmitService / EkaerManageService (AyCode.Services/Nav/Ekaer/) — validáció + beküldés + HTTP (általános NAV-réteg)
  • FruitBankEkaerService (FruitBank.Common.Server/Services/Ekaer/) — a szerver-oldali fogyasztó (map → submit)
  • Forrás-entitások (FruitBank.Common): Shipping, ShippingDocument, ShippingItem, ProductDto.Gtin

MGFBANKPLUG-EKAER-T-W3R8: Termék-szintű EKÁER-besorolás (kockázatos-lista tagság) + hatályos küszöb

Status: Open · Priority: P2 · Type: T (adatmodell + mapping + config)

⚠️ ÚJRAÍRVA (2026-07-10, webről ellenőrizve — net.jogtar 13/2020 PM + 51/2014 NGM): a korábban itt szereplő 3-kategóriás küszöb-tábla (200 kg/250 eFt élelmiszer · 500 kg/1 MFt egyéb · 2500 kg/5 MFt nem-kockázatos) a 2021 ELŐTTI rezsim (5/2015 NGM) volt — NEM hatályos.

Hatályos szabály (2021-01-01 óta, 13/2020. (XII. 23.) PM rendelet):

  • CSAK a kockázatos (bejelentésköteles) termék EKÁER-köteles — a lista az 51/2014. (XII. 31.) NGM rendelet 1. melléklete (VTSZ-alapú). A listán NEM szereplő termék egyáltalán nem jelentendő.
  • Egyetlen, egységes küszöb (4. § i): mentes a fuvarozás, ha az 500 kg bruttó tömeget ÉS az 1 000 000 Ft adó nélküli értéket sem haladja meg → kötelező, ha bármelyik átlépi (a feladó→címzett→jármű relációra aggregálva).
  • Lista-módosítás — 25/2025. (VIII. 18.) NGM (2025-08-18-tól): egyes kertészeti termékek KIKERÜLTEK a kockázatos-listából: vöröshagyma-dughagyma (07031011), friss borsó (07081000), friss bab (07082000), csemegekukorica (07099960), egyes vetőmagok (07129011, 07131010, 07133310). Ha ilyet forgalmazunk, rá bejelentés sem kell.

Jelenlegi állapot — CONFIG RENDBEN (2026-07-10, user megerősítve): a CreateMissingEkaerHistories globális küszöbe a configból (Ekaer:Thresholds) jön, és a hatályos 500 kg / 1 000 000 Ft van beállítva az appsettings-ben. A kapu aggregálási/irány-szabályainak ismert nyitott pontjai: K7Q2 #11 (külföldi küszöb nélkül — túljelent), #12 (0-súlyú tétel), T-H7F2 (depot-szintű summa — alul-jelenthet).

Cél (a per-termék rész): NEM küszöb-kategória-enum kell (az a régi jogszabályhoz készült terv), hanem termék-szintű „kockázatos-e" besorolás — a termék rajta van-e az 51/2014-es VTSZ-listán —, DB-ben tárolva (Product oszlop / GenericAttribute), kézzel karbantartva. A kapu a NEM kockázatos terméket a küszöb-summából (és a bejelentésből) teljesen kihagyja. (Későbbi lépés: automatikus levezetés a VTSZ-listából — a lista-módosításokat, mint a 25/2025 NGM, követni kell.)

Affected:

  • FruitBank.Common/Dtos/ProductDto.cs — küszöb-kategória mező (enum, DB-ben)
  • EkaerSettings / EkaerValueCalculator (FruitBank.Common/Services/Ekaer/) — kategória → küszöbérték leképezés
  • FruitBankDataController.CreateMissingEkaerHistories — a kapu a tételek kategóriái szerint

MGFBANKPLUG-EKAER-T-V9G3: tradeCardItem-ek csoportosítása VTSZ szerint + productName Category-ből

Status: Open · Priority: P2 · Type: T (mapping) · 2026-06

A NAV felé egy VTSZ-re egy tradeCardItem kell — több azonos-VTSZ-ű termék (pl. kajszibarack/nektarin/őszibarack, mind 08093000) egy tételbe vonva, összegzett tömeggel/értékkel. Jelenleg a mapper terméktételenként ad egy tradeCardItem-et → azonos VTSZ-nél több sor (a NAV felé nem jó). A nehézség a productName (a csoport tagjainak más a neve).

Ez NEM a VTSZ/GTIN-szétválasztás — az külön nyitott kérdés: MGFBANKPLUG-EKAER-I-T3X8 (lásd #8). A T-V9G3 csak a csoportosítást és a csoport-nevet oldja meg, a VTSZ tárolási helyétől (jelenleg Product.Gtin) függetlenül.

Eldöntött terv (2026-06):

  • productName (a csoport neve): egy nopCommerce Category-ből, ami VTSZ→név helper: a Category.MetaKeywords első 8 karaktere = a VTSZ, a Category.Name = a productName. A kategóriát a termék VTSZ-e (jelenleg a Gtin-ben — I-T3X8) = MetaKeywords[0..8] match azonosítja → a termék kategória-tagsága lényegtelen (több kategóriából csak az egyező számít). A kategóriák a weben is pontosak maradnak.
  • itemExternalId: sorszám (1, 2, …) a VTSZ-csoportok fölött — a séma szerint „bejelentésen belüli tetszőleges azonosító a kérés↔válasz párosításhoz" (max 50), NEM kell stabilnak / forrás-Id-nek lennie; int-parse-olható.
  • Csoportosítás helye: BuildTradeCard (VTSZ szerint group → Σtömeg, Σérték, név a lookupból). A kapu (EvaluateObligation) NEM érintett (csak Σ-t számol → nincs plusz query a reconciliation-nél).
  • Név-feloldás: csak generáláskor, szerver-oldalon — a ProductDto-t NEM szennyezzük EKÁER-only mezővel. A termék-query (productId, categoryId) tuple-t ad (a VTSZ↔MetaKeywords joinból), majd egy batch Category-load ToDictionary-be → productId → categoryName.
  • Fallback: ha egy VTSZ-hez nincs kategória → a productName üres marad → a generate-validátor jelzi (mint a value > 0).

Üzemeltetési feltétel: a VTSZ-forrás (jelenleg Gtin) és a kategória MetaKeywords-VTSZ-e legyen szinkronban (FruitBank-felelősség; a beírásnál a VTSZ-t elöl).

Affected:

  • FruitBank.Common/Services/Ekaer/ShippingToEkaerMapper.csBuildTradeCard VTSZ-group + vtszNames lookup
  • FruitBank.Common.Server/Services/Ekaer/{IFruitBankEkaerService,FruitBankEkaerService}.cs — a vtszNames átadása a generate-en
  • FruitBankDataController.GenerateEkaerXmlDocument (plugin) — (productId, categoryId) tuple + batch Category-load → Dictionary<vtsz, name>
  • nopCommerce Category (MetaKeywords = VTSZ, Name = productName) — adat/üzemeltetés

MGFBANKPLUG-EKAER-T-D8R4: Kapu-csoportosítás (Shipping, PartnerDepot)-re; a PartnerDepotId kötelező

Status: Closed (2026-07-10) · Priority: P2 · Type: T (kapu) · 2026-06

A CreateMissingEkaerHistories bejövő kapuja jelenleg (ShippingId, PartnerId, PartnerDepotId)-re csoportosít. Mivel a PartnerDepot egyértelműen egy Partner-hez tartozik (a depó implikálja a feladót), a PartnerId a kulcsban redundáns → elég a (ShippingId, PartnerDepotId) csoportosítás.

Cél:

  • A csoportosítási kulcs (ShippingId, PartnerDepotId) (a PartnerId kivehető).
  • A PartnerDepotId kötelező az EKÁER-hez: ha egy szállítólevélen nincs PartnerDepotIdhiba, és NE generálódjon rá deklaráció. A kapu a hiányzó-telephelyű dokumentumokat kihagyja + üzenettel jelzi (mint a DataError-nál); a generate ValidationError-t ad (nem küldhető), nem üres/téves tradeCard-ot.

Megj.: szigorítás a jelenlegihez képest, ahol a null PartnerDepotId még külön (null-telephelyű) csoportként kezelődik. Bevezetés előtt a meglévő szállítólevelek PartnerDepotId-ját pótolni kell, különben a kapu kihagyja őket.

Affected:

  • FruitBankDataController.CreateMissingEkaerHistories (plugin) — a GroupBy kulcs (ShippingId, PartnerDepotId)-re + a hiányzó-PartnerDepotId hiba-ág (kihagyás + üzenet)
  • FruitBankDataController.GenerateEkaerXmlDocument / FruitBankEkaerService — hiányzó telephelynél ValidationError, nincs generálás
  • ShippingToEkaerMapper / EkaerReportability (FruitBank.Common/Services/Ekaer/) — ha a feladó-cím a PartnerDepot-ból jön, a hiányzó telephely validációs hiba

Resolution (2026-07-10)

Implementálva, EGY tudatos eltéréssel: a kulcs-egyszerűsítés NEM készült el — a csoportkulcs szándékosan (ShippingId, PartnerId, PartnerDepotId) maradt, mert null PartnerDepotId-nál a (ShippingId, PartnerDepotId) kulcs KÜLÖNBÖZŐ partnerek dokumentumait vonná egy csoportba (null == null), és a kötelezettség-aggregátum partnerek közt keveredne; nem-null depotnál a PartnerId redundáns, de ártalmatlan (ugyanazt a csoportosítást adja).

  • Kapu: kötelező bejelentésnél hiányzó PartnerDepotId → üzenet a popupba, sor NEM jön létre. A depot-check a kötelezettség-döntés UTÁN fut — küszöb alatti belföldi csoportra nem szól feleslegesen.
  • Generate: LoadWith(sd => sd.PartnerDepot) (a lazy asszociáció csak itt töltve) + FruitBankEkaerService.TryDepotError guard → hiányzó/betöltetlen depotnál ValidationError, XML nem generálódik.
  • Mapper: LoadLocation = BuildLocation(PartnerDepot ?? partner) — a felrakodási hely a depot címe; a TaxId Partner-passthrough (depot.Partner ??= partner). A kapu-útvonalon a depot nincs betöltve → partner-cím, ami ott nem számít (a kötelezettség-döntés címet nem használ).

MGFBANKPLUG-EKAER-T-H7F2: Küszöb-aggregálás szintje: (Shipping, Partner) — a depot-bontás küszöb-rést nyit

Status: Open (parkolva — vállalt kockázat, ügyfél-döntés 2026-07-10; az I-F5D9-cel együtt kezelendő) · Priority: P3 · Type: T (kapu) · 2026-07-10

A T-D8R4 óta a kapu (ShippingId, PartnerId, PartnerDepotId)-re csoportosít, és a küszöb-summa is ezen a csoporton fut. A jogszabályi aggregálási egység viszont a feladó→címzett→jármű reláció, telephelytől FÜGGETLENÜL — a 13/2020 PM §12 (4) szó szerint: „Egy EKAER számot kell megállapítani akkor is, ha egy gépjárművel egy feladó több felrakodási címéről, egy címzett több kirakodási címére történik a közúti fuvarozás."

A rés (alul-jelentés!): ugyanaz a Partner két telephelyről 300300 kg-ot ad fel ugyanarra a kamionra → a kapu két külön 300 kg-os csoportot lát → mindkettő „küszöb alatt, nem kell" — pedig jogilag 600 kg = kötelező. (A gyűjtőfuvar KÜLÖNBÖZŐ feladókkal viszont jogszerűen mentes relációnként — az egység nem a kamion.)

Döntés (2026-07-10, ügyfél): MARAD ÍGY — vállalt kockázat, az entry NYITVA tartva. Indoklás: (1) nagyon ritkán fordulhat elő; (2) az érintett tételek egyenként definíció szerint küszöb alattiak, így a kitettség kicsi; (3) a loadDate csak nap-pontosságú (időpont nélküli, opcionális) — a bejelentési adatokból két azonos napi külön fuvar megkülönböztethetetlen, így a NAV felé „két külön alkalommal vitte el" magyarázat adható. Egyben kezelendő az I-F5D9-cel (bejövő külföldi szabály): ha az ügyfél a hatályos jogszabályi szabályra váltat, a kapu+UI úgyis átírandó — AKKOR ezt is meg kell oldani az alábbi opciók egyikével; addig parkolva.

Döntési opciók (a jövőbeni átíráskor):

  • (a) Jogilag tiszta: kötelezettség (Shipping, Partner)-szinten; EGY EkaerHistory/tradeCard partnerenként, a telephelyek külön deliveryPlan-ekként. Séma-oldalról megerősítve (2026-07-10, ekaermanagement.xsd): a deliveryPlans 1..N deliveryPlan-t enged, mindegyik saját loadLocation+unloadLocation+tételekkel; a loadDate viszont EGY van (fejrész-szintű, opcionális) — „több loadDate" sémaszinten nem létezik, a NAV az egész túrát egy fuvarnak modellezi (érkezés a finalize-nál). Mapper-bővítés kell — most csak 1 fel-/lerakodási helyet képezünk, deliveryPlan nélkül.
  • (b) Pragmatikus: a kötelezettség-summa (Shipping, Partner)-szinten fut (ha átlépi, a partner MINDEN depot-csoportja sort kap); a deklaráció marad depot-onként. A küszöb-rés eltűnik; formailag több EKÁER-szám lesz ott, ahol a §12 (4) egyet mond — kockázata tisztázandó.

Affected:

  • FruitBankDataController.CreateMissingEkaerHistories (plugin) — a kötelezettség-kiértékelés szintje vs a csoport/EkaerHistory-képzés szétválasztása
  • ShippingToEkaerMapper (FruitBank.Common/Services/Ekaer/) — (a) opciónál deliveryPlan-többes leképezés
  • Kapcsolódik: T-D8R4 (Closed — a depot-csoportosítás bevezetése), K7Q2 #11/#12 (küszöb-szabályok)

MGFBANKPLUG-EKAER-T-C3M8: Customer isEkaer mentesség a kimenő kapuban + null-szemantika

Status: Closed (2026-07-10) · Priority: P2 · Type: T (kapu + admin-widget) · 2026-07

A vevő-oldali EKÁER-mentesség attribútum létezik (GenericAttribute: Key="isEkaer", KeyGroup="Customer", StoreId=0; admin CustomerCredit-widget checkbox „Ekáer köteles", SetEkaer endpoint menti), de a kimenő kapu (CreateMissingEkaerHistories) nem nézi — a nagybani piacos (közúti fuvar nélküli) vevők rendelései is tévesen kapnak Pending sort. Bejövő oldalon a Partner.IsEkaer mentesség működik (csendes kihagyás).

Blokkoló döntés — mi legyen a SOHA be nem állított vevővel (nincs attribútum-sora)? A csapda: az olvasó (GetGenericAttributeValueAsync<Customer,bool>) hiányzó sornál false-t ad, így a widgetben a „be nem állított" és az „explicit mentesített" vevő megkülönböztethetetlen (mindkettő üres checkbox); a Partner-oldalon a default fordított (IsEkaer = true, csak explicit false mentesít).

Opció Kapu-viselkedés Kockázat Plusz teendő
A) hiányzó = KÖTELES (Partner-konzisztens, fail-safe) csak az explicit false sor mentesít felesleges Pending az új vevőknél (látható, törölhető) a widget default-ját igazítani (hiányzó → pipált), különben félrevezet
B) hiányzó = MENTES (a mostani widget-megjelenítés) csak explicit true-ra jön létre sor új/be-nem-állított vevő csendben kimarad → alul-jelentés minden köteles vevőt pipálni kell

Implementáció (a döntés után): a kimenő ágban csendes kihagyás (mint a Partner.IsEkaer), az attribútum StoreId=0-val olvasva; a rendelés-lista kicsi (dátum-szűrt), per-customer olvasás vagy batch GenericAttribute-query.

Affected:

  • FruitBankDataController.CreateMissingEkaerHistories (plugin) — kimenő ág: isEkaer-szűrés
  • CustomerCreditWidgetViewComponent + CustomerCreditWidget.cshtml (plugin) — A) opciónál a hiányzó-attribútum default igazítása
  • docs/EKAER/README.md — kapu-szakasz mentesség-bullet kiegészítése a döntés után

Resolution (2026-07-10)

Az A) szemantika valósult meg, bool?-olvasással (a user javaslata — a tri-state az adatszinten explicit, a UI kétállapotú maradt):

  • Kapu (kimenő ág): az érintett vevők isEkaer attribútumai EGY batch-queryvel a ciklus előtt dictionary-be (ctx.GenericAttributes.Table, KeyGroup="Customer", StoreId=0, a CustomerId-kra szűrve — nincs ciklusonkénti DB-hívás); a ciklusban TryGetValue: hiányzó kulcs = nincs beállítva = köteles (fail-safe, Partner-konzisztens), explicit false → csendes kihagyás (mint a Partner.IsEkaer).
  • Widget: az olvasó bool? + ?? true — a soha be nem állított vevőnél a checkbox pipáltat mutat, pontosan azt, amit a kapu csinál; tri-state UI nem készült (a null a felületen nem külön állapot).
  • CommonHelper.To<bool?> forrásból ellenőrizve: NullableConverter kezeli a "True"/"False" konverziót; hiányzó sor → null.

MGFBANKPLUG-EKAER-T-N4E7: EkaerHistory delete/újragenerálás végpont

Status: Open · Priority: P2 · Type: T (folyamat) · 2026-07

A dizájn-cél a „törölhető + újragenerálható" deklaráció (az EKÁER-kapcsolat az EkaerHistoryMapping junctionben él, a core adatokat nem érinti), de törlő végpont NINCS — a grid delete tiltva, a hibásan/elavultan létrejött sorok (pl. a T-D8R4 szigorítás ELŐTT létrejött, null-depotos Pending-ek) csak kézzel, DB-ből takaríthatók.

Cél: SignalR-endpoint az EkaerHistory + mapping sorok atomikus törlésére; a grid delete engedélyezése. Üzletileg tisztázandó: Sent státuszú (a NAV-nál már bejelentett) sor törölhető-e (valószínűleg csak Pending / Generated* / ValidationError).

Affected:

  • FruitBankDataController (plugin) — delete endpoint (EkaerHistory + mappingek atomikusan)
  • EkaerHistory grid (kliens) — delete gomb engedélyezése