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. |
||
|---|---|---|
| .. | ||
| EKAER_ISSUES.md | ||
| EKAER_TODO.md | ||
| README.md | ||
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.Corerepó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ésekrePendingEkaerHistorysorokat hoz létre, csak ha kötelező (lásd a kapu-szakaszt lentebb). Bejövőnél a(Shipping, Partner, PartnerDepot)csoport EGYEkaerHistory-t kap, a csoport dokumentumai pedigEkaerHistoryMappingsorokként kapcsolódnak; kimenőnél egy rendelés = egyEkaerHistory+ egy mapping.EkaerCreateResult-ot ad vissza (létrehozott szám + a kihagyott tételek üzenetei).GenerateEkaerXmlDocument(ekaerHistoryId)— egyEkaerHistory-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); aStatus/ErrorText/ConversionRatetö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— aShipping → tradeCardmapping 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) → Generate → Generated / 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ég — EkaerReportability.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 EGYEkaerHistory-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ásdEKAER_TODO.mdT-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>();