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

7.5 KiB

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 rekord nélküli szállítólevelekre/rendelésekre Pending EkaerHistory sorokat hoz létre, csak ha kötelező (lásd a kapu-szakaszt lentebb). EkaerCreateResult-ot ad vissza (létrehozott szám + a kihagyott tételek üzenetei).
  • GenerateEkaerXmlDocument(foreignKey, isOutgoing) — egy sorra 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; ForeignKey = bejövő ShippingDocument.Id / kimenő Order.Id + IsOutgoing; a Status int-oszlop + [NotColumn] enum-nézet): 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) csoport (= feladó→címzett→jármű) — a tömeg/érték a csoport ÖSSZES dokumentumára aggregálva (13/2020 PM rendelet); 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>();