Mango.Nop.Plugins/Nop.Plugin.Misc.AIPlugin/docs/EKAER
Loretta c71bf2fcd8 EKÁER: add mapping table, group logic, atomic ops
Refactored EKÁER logic to use EkaerHistoryMapping junction table, decoupling EkaerHistory from direct foreign keys. Grouped inbound declarations by (ShippingId, PartnerId, PartnerDepotId) and enabled atomic creation of histories with mappings. Updated controller endpoints, DI registration, and documentation. Improved error handling, logging, and adjusted method signatures for the new mapping-based approach.
2026-06-16 21:45:49 +02:00
..
EKAER_ISSUES.md EKÁER docs: VTSZ grouping, archive rules, reopened issue 2026-06-15 18:01:48 +02:00
EKAER_TODO.md EKÁER: add mapping table, group logic, atomic ops 2026-06-16 21:45:49 +02:00
README.md EKÁER: add mapping table, group logic, atomic ops 2026-06-16 21:45:49 +02:00

README.md

EKÁER — NAV közúti áruforgalom-bejelentés (FruitBank áttekintő)

Topic EKAER, prefix MGFBANKPLUG → entry ID-k MGFBANKPLUG-EKAER-I-<RAND> (issue) / -T- (TODO) / -B- (bug).

A FruitBank EKÁER-bejelentés szerver-oldali (a kliens már standalone WASM, böngészőből CORS miatt nem hívhat NAV-ot — a kliens SignalR-en triggerel). A tényleges logika viszont rétegekre bontva él, nem ebben a pluginban; ez a folder a belépő/áttekintő + a FruitBank-/nopCommerce-specifikus nyitott döntések.

A NAV-protokoll részletei (transport, auth, üzenet-szerkezet) az AyCode.Core repóban: AyCode.Services/Nav/docs/EKAER_*.md. Itt nem ismételjük.

A teljes EKÁER-kép (4 réteg)

Réteg Hol Mit ad
NAV/EKÁER framework AyCode.Services/Nav/ + Nav/Ekaer/ (AyCode.Core) transport, auth (SHA-512), generált modellek, EkaerTradeCardValidator (NAV-séma + üzleti szabályok), EkaerSubmitService (validate→send), EkaerManageService (HTTP). Általános — nem FruitBank-specifikus.
FruitBank leképezés FruitBank.Common/Services/Ekaer/ ShippingToEkaerMapper — a forrást (bejövő ShippingDocument-csoport / kimenő OrderDto) egy irány-független EkaerConsignment-re képezi (ToConsignment), abból épül a tradeCard (BuildTradeCard). EkaerReportability — bejelentés-kötelezettség (küszöb/külföld). EkaerValueCalculator — tétel-érték HUF-ban.
FruitBank fogyasztó FruitBank.Common.Server/Services/Ekaer/ FruitBankEkaerService — szerver-oldali orchestráció: credentials/options + map → submit
nopCommerce-integráció (ez a plugin) ez a folder + a plugin kód DI-bekötés, NAV-fiók settings, a VTSZ-forrás (Product.Gtin), SignalR-trigger a kliens felől, és ez a doksi

A beküldési lánc

FruitBankEkaerService.SubmitShippingAsync(shipping)        // FruitBank.Common.Server
   → ShippingToEkaerMapper.MapShipping(...)                // FruitBank.Common      (map)
   → EkaerSubmitService.SubmitAsync(ops)                   // AyCode.Services       (validate → send)
        → EkaerTradeCardValidator.Validate(ops)            //   hibalista → ha nem üres: NEM küld
        → EkaerManageService.ManageAsync(request)          //   auth + HTTP POST a NAV-nak

Validációs hiba → hibalista (EkaerSubmitResult.Invalid), nem megy ki kérés. NAV-oldali hiba → NavReportException propagál.

További belépési pontok (a kézi NAV-beadás munkafolyamathoz — FruitBankDataController SignalR-endpointok, kliens felől triggerelve):

  • CreateMissingEkaerHistories(fromDate) — reconciliation-kapu: a dátumtól még le nem fedett szállítólevelekre/rendelésekre Pending EkaerHistory sorokat hoz létre, csak ha kötelező (lásd a kapu-szakaszt lentebb). Bejövőnél a (Shipping, Partner, PartnerDepot) csoport EGY EkaerHistory-t kap, a csoport dokumentumai pedig EkaerHistoryMapping sorokként kapcsolódnak; kimenőnél egy rendelés = egy EkaerHistory + egy mapping. EkaerCreateResult-ot ad vissza (létrehozott szám + a kihagyott tételek üzenetei).
  • GenerateEkaerXmlDocument(ekaerHistoryId) — egy EkaerHistory-deklarációra (a mappingben rögzített forrás-dokumentumok ÖSSZES tételét egy tradeCard-ba vonva) legenerálja + validálja a tradeCard XML-t (NEM küld NAV-ot); a Status / ErrorText / ConversionRate töltődik, az XML vágólapra másolható a kézi beadáshoz.

Companion fájlok

  • EKAER_ISSUES.md — ismert problémák (pl. MGFBANKPLUG-EKAER-I-T3X8: GTIN≠VTSZ).
  • EKAER_TODO.md — a Shipping → tradeCard mapping nyitott üzleti döntései.

A leképezés (tisztázott pontok)

EKÁER FruitBank forrás
seller* (feladó) ShippingDocument.Partner (a beszállító)
carrierText (szállítmányozó — opcionális, NAV nem követeli) bejövő: Shipping.CargoPartner.Name (valós, külön fuvarozó); kimenő:üres (a vevő maga viszi el, ő már a címzett; nincs külön fuvarozónk)
vehicle / vehicle2 Shipping.CargoTruck / CargoTrailer (LicencePlate + CountryCode, normalizálva)
tétel productVtsz ShippingItem.ProductDto.Gtin (átmenetileg — lásd EKAER_ISSUES.md)
tétel productName ShippingItem.ProductName (a VTSZ-szerinti csoportosítás + a csoport-név Category-ből: TODO T-V9G3)
tétel weight ShippingItem.MeasuredGrossWeight (bruttó)
tétel tradeReason A (beszerzés — bejövő áru). ⚠️ Az enum: S=értékesítés, A=beszerzés, W=bérmunka, O=egyéb.

A nyitott pontok (tradeType, destination, value/deviza, granularitás, kimenő irány): EKAER_TODO.md.

Reconciliation-kapu, kötelezettség, életciklus (2026-06)

A kézi NAV-beadás munkafolyamat: a kapu létrehozza a sorokat → a user generál + másol/beküld → kézzel rögzíti a NAV-választ.

EkaerHistory életciklus (egy sor = egy tradeCard; a forrás-rekordok az EkaerHistoryMapping junctionön át kapcsolódnak — bejövő: a (Shipping, Partner, PartnerDepot) csoport N ShippingDocument-je, kimenő: 1 Order —, az EkaerHistory maga nem hordoz forrás-kulcsot, az irány az IsOutgoing; a Status int-oszlop + [NotColumn] enum-nézet; a mapping a GetAll(loadRelations: true)-zal töltődik a Mappings asszociációba): Pending (a kapu hozta létre) → GenerateGenerated / GeneratedWithWarning (küldhető, de pótlandó — pl. hiányzó rendszám) / ValidationError (blokkoló) → kézi NAV-beadás után Sent / SentWithMissingData (pótlásra vár). A grid 3 tabja ezekre szűr (szerver-oldali EkaerHistoryFilter), a warning ⚠️ / error ikonnal megkülönböztetve.

Bejelentés-kötelezettségEkaerReportability.Evaluate(consignment, settings), a kapu hívja egységenként:

  • egység: bejövőnél a (Shipping, Partner, PartnerDepot) csoport (= feladó+telephely→címzett→jármű) — a tömeg/érték a csoport ÖSSZES dokumentumára aggregálva (13/2020 PM rendelet), és a csoport EGY EkaerHistory-t kap; kimenőnél egy rendelés;
  • küszöb felett → kötelező, az országkódtól függetlenül (az országkód-hibát a generate-validálás jelzi);
  • küszöb alatt → csak a külföldi reláció kötelező (a feladó és a címzett országkódja eltér); belföld → nem; hiányzó/érvénytelen (nem ISO-2) országkód → DataError (a sor kimarad + üzenet a popupban);
  • mentesség: Partner.IsEkaer = false, és a Partner nélküli (félkész) szállítólevél — csendben kimaradnak.

A küszöb configból jön (Ekaer:Thresholds:WeightKg / :ValueHuf) — a kódba NINCS drótozva, mert a NAV-jogszabály és a beállítás szerint változhat. A konkrét, dátumozott értékeket és a termékkategóriákat lásd EKAER_TODO.md T-W3R8. A NAV mindkét irányban büntet (alul- ÉS túljelentés), ezért a küszöbnek pontosnak kell lennie.

Egyesített leképezés: a bejövő/kimenő forrás egy EkaerConsignment köztes modellre képződik (két adapter), és abból épül MIND a tradeCard (BuildTradeCard), MIND a kötelezettség-döntés — így az irányfüggő rész két adapterre szorul, a közös logika egy helyen van. A MapDocument / MapOrder / MapShipping ennek vékony wrappere.

Bekötés a szerveren (DI)

A plugin (vagy a szerver-startup) köti be a láncot — a NAV-fiók titkos adatai a szerver config/secret store-jából:

services.AddSingleton<INavCredentials>(/* NAV-fiók: User/Password/SigningKey/TaxNumber/BaseUrl */);
services.AddHttpClient<EkaerManageService>(/* NAV TLS 1.2 */);
services.AddScoped<IEkaerTradeCardValidator, EkaerTradeCardValidator>();
services.AddScoped<IEkaerSubmitService, EkaerSubmitService>();
services.AddScoped<IShippingToEkaerMapper, ShippingToEkaerMapper>();
services.AddSingleton<IEkaerSettings>(/* EkaerSettings: Ekaer:Company + Site + küszöbök + EUR-HUF árfolyam — configból */);
services.AddScoped<IFruitBankEkaerService, FruitBankEkaerService>();