diff --git a/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/CustomOrderController.cs b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/CustomOrderController.cs index 131e2ab..cc3a337 100644 --- a/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/CustomOrderController.cs +++ b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/CustomOrderController.cs @@ -969,8 +969,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers [CheckPermission(StandardPermission.Customers.CUSTOMERS_VIEW)] public virtual async Task CustomerSearchAutoComplete(string term) { - if (string.IsNullOrWhiteSpace(term) || term.Length < 2) - return Json(new List()); + if (string.IsNullOrWhiteSpace(term) || term.Length < 3) return Json(new List()); const int maxResults = 15; @@ -1037,38 +1036,28 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers [CheckPermission(StandardPermission.Catalog.PRODUCTS_VIEW)] public virtual async Task ProductSearchAutoComplete(string term) { - if (string.IsNullOrWhiteSpace(term) || term.Length < 2) - return Json(new List()); + if (string.IsNullOrWhiteSpace(term) || term.Length < 3) return Json(new List()); - const int maxResults = 30; + const int maxResults = 300; // Search products by name or SKU - var products = await _productService.SearchProductsAsync( - keywords: term, - pageIndex: 0, - pageSize: maxResults); + var products = await _productService.SearchProductsAsync(keywords: term, pageIndex: 0, pageSize: maxResults); var result = new List(); - var productDtosById = await _dbContext.ProductDtos.GetAllByIds(products.Select(p => p.Id)).ToDictionaryAsync(k => k.Id, v => v); + //var productDtosById = await _dbContext.ProductDtos.GetAllByIds(products.Select(p => p.Id)).Where(x => x.AvailableQuantity > 0).ToDictionaryAsync(k => k.Id, v => v); + var productDtos = await _dbContext.ProductDtos.GetAllByIds(products.Select(p => p.Id)).ToArrayAsync(); - foreach (var product in products) + foreach (var productDto in productDtos.Where(x => x.AvailableQuantity > 0)) { - var productDto = productDtosById[product.Id]; - if (productDto != null) + result.Add(new { - if (productDto.AvailableQuantity > 0) - { - result.Add(new - { - label = $"{product.Name} [RENDELHETŐ: {productDto.AvailableQuantity} (R:{productDto.StockQuantity}/K:{productDto.IncomingQuantity})] [ÁR: {product.Price}]", - value = product.Id, - sku = product.Sku, - price = product.Price, - stockQuantity = product.StockQuantity, - availableQuantity = productDto.AvailableQuantity, - }); - } - } + label = $"{productDto.Name} [RENDELHETŐ: {productDto.AvailableQuantity} (R:{productDto.StockQuantity}/K:{productDto.IncomingQuantity})] [ÁR: {productDto.Price}]", + value = productDto.Id, + sku = productDto.Sku, + price = productDto.Price, + stockQuantity = productDto.StockQuantity, + availableQuantity = productDto.AvailableQuantity, + }); } return Json(result); @@ -1078,8 +1067,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers [CheckPermission(StandardPermission.Catalog.PRODUCTS_VIEW)] public virtual async Task PreOrderProductSearchAutoComplete(string term) { - if (string.IsNullOrWhiteSpace(term) || term.Length < 2) - return Json(new List()); + if (string.IsNullOrWhiteSpace(term) || term.Length < 3) return Json(new List()); const int maxResults = 30; var today = DateTime.UtcNow.Date; @@ -1151,8 +1139,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers [CheckPermission(StandardPermission.Catalog.PRODUCTS_VIEW)] public virtual async Task ProductSearchUnfilteredAutoComplete(string term) { - if (string.IsNullOrWhiteSpace(term) || term.Length < 2) - return Json(new List()); + if (string.IsNullOrWhiteSpace(term) || term.Length < 3) return Json(new List()); const int maxResults = 30; diff --git a/Nop.Plugin.Misc.AIPlugin/Infrastructure/PluginNopStartup.cs b/Nop.Plugin.Misc.AIPlugin/Infrastructure/PluginNopStartup.cs index 28f1c89..9c11b76 100644 --- a/Nop.Plugin.Misc.AIPlugin/Infrastructure/PluginNopStartup.cs +++ b/Nop.Plugin.Misc.AIPlugin/Infrastructure/PluginNopStartup.cs @@ -41,6 +41,11 @@ using Nop.Web.Areas.Admin.Models.Catalog; using Nop.Web.Areas.Admin.Models.Orders; using System.Net.Http.Headers; using Mango.Nop.Core.Loggers; +using AyCode.Services.Nav; +using AyCode.Services.Nav.Ekaer; +using FruitBank.Common.Services.Ekaer; +using FruitBank.Common.Server.Services.Ekaer; +using System.Security.Authentication; namespace Nop.Plugin.Misc.FruitBankPlugin.Infrastructure; @@ -162,6 +167,44 @@ public class PluginNopStartup : INopStartup services.AddScoped(); services.AddScoped(); + // ── EKÁER (NAV közúti áruforgalom-bejelentés): map → validate → send ────────── + services.AddScoped(); // FruitBank.Common — leképezés + services.AddScoped(); // AyCode.Services — NAV-validáció + services.AddScoped(); // AyCode.Services — validate→send + services.AddScoped(); // FruitBank.Common.Server — fogyasztó + + services.AddHttpClient() // AyCode.Services — NAV HTTP + .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { SslProtocols = SslProtocols.Tls12 }); // a NAV TLS 1.2-t vár + + // A NAV-fiók hitelesítő adatai + a saját telephely/raktár — konfigurációból (appsettings "Ekaer" szekció). + // ⚠️ Titkos kulcsok: secret store / appsettings, SOHA NEM a forráskódba. + services.AddSingleton(sp => + { + var c = sp.GetRequiredService().GetSection("Ekaer:Credentials"); + return new NavCredentials + { + User = c["User"] ?? "", + Password = c["Password"] ?? "", + SigningKey = c["SigningKey"] ?? "", + TaxNumber = c["TaxNumber"] ?? "", + BaseUrl = c["BaseUrl"] ?? "https://import-test-b.ekaer.nav.gov.hu", // TEST; PROD: https://import.ekaer.nav.gov.hu + }; + }); + services.AddSingleton(sp => + { + var c = sp.GetRequiredService().GetSection("Ekaer:Company"); + return new EkaerCompanyInfo + { + Name = c["Name"], + TaxId = c["TaxId"], + CountryCode = c["CountryCode"] ?? "HU", // a NAV EKÁER magyar + PostalCode = c["PostalCode"], + City = c["City"], + Street = c["Street"], + // UnloadLocation (saját telephely): magyar címnél a NAV Name/VatNumber/Phone/Email-t is kér — TODO configból összeállítani. + }; + }); + services.AddControllersWithViews(options => { options.Filters.AddService(); diff --git a/Nop.Plugin.Misc.AIPlugin/docs/EKAER/EKAER_ISSUES.md b/Nop.Plugin.Misc.AIPlugin/docs/EKAER/EKAER_ISSUES.md index 8ac88ef..760715e 100644 --- a/Nop.Plugin.Misc.AIPlugin/docs/EKAER/EKAER_ISSUES.md +++ b/Nop.Plugin.Misc.AIPlugin/docs/EKAER/EKAER_ISSUES.md @@ -9,7 +9,10 @@ Scope: a FruitBank EKÁER-bejelentés szerver-oldali / nopCommerce-integrációs ## MGFBANKPLUG-EKAER-I-T3X8: A `Product.Gtin` átmenetileg a VTSZ-t tárolja — szétválasztandó -**Status:** Open · **Priority:** P3 · **Type:** I (adatmodell / átmeneti megoldás) +**Status:** Closed (2026-06-02) — superseded · **Priority:** P3 · **Type:** I (adatmodell / átmeneti megoldás) + +### Resolution +**Áthelyezve** az általános adatmodell-topicba: **`FBANKAPP-DMODEL-I-P6X4`** (`FruitBank.Common/docs/DATAMODEL/DATAMODEL_ISSUES.md#fbankapp-dmodel-i-p6x4`). Indok: a GTIN/VTSZ szétválasztás **általános** adatmodell-kérdés, nem EKÁER-specifikus — az EKÁER csak felhasználója. A követés ott folytatódik; az alábbi leírás referencia. Az EKÁER `tradeCardItem.productVtsz` (kötelező, 8 jegyű vámtarifaszám) forrása jelenleg a nopCommerce **`Product.Gtin`** oszlop (a `ProductDto.Gtin`-en keresztül). A GTIN és a VTSZ **fogalmilag különböző**: - **GTIN** — globális kereskedelmi cikkszám (vonalkód-azonosító, EAN/UPC). diff --git a/Nop.Plugin.Misc.AIPlugin/docs/SCHEMA.md b/Nop.Plugin.Misc.AIPlugin/docs/SCHEMA.md index 699b2c1..89a0e7b 100644 --- a/Nop.Plugin.Misc.AIPlugin/docs/SCHEMA.md +++ b/Nop.Plugin.Misc.AIPlugin/docs/SCHEMA.md @@ -1,3 +1,10 @@ +# Domain Model Schema (Toon Format) + +> Part of `Nop.Plugin.Misc.FruitBankPlugin`. See `README.md` for project overview. +> Full domain model in Toon (Token-Oriented Object Notation) format — see `AyCode.Core/Serializers/Toons/README.md` (in AyCode.Core solution). +> This is the authoritative schema for entities, DTOs, and enums in the FruitBank domain. +> For behavioral documentation (workflows, lifecycles, event cascades) see `docs/DOMAIN_MODEL.md`. + @meta { version = "1.0" format = "toon" @@ -313,6 +320,8 @@ CountryCode: string County: string Created: DateTime + Currency: string + purpose: "ISO 4217 currency code the company trades and settles in with this partner (e.g. EUR, HUF). For supplier partners it is the source currency for converting shipping-item values to example: HUF in NAV EKÁER reporting." Modified: DateTime Name: string PostalCode: string @@ -555,6 +564,8 @@ CountryCode: string County: string Created: DateTime + Currency: string + purpose: "ISO 4217 currency code the company trades and settles in with this partner (e.g. EUR, HUF). For supplier partners it is the source currency for converting shipping-item values to example: HUF in NAV EKÁER reporting." Modified: DateTime Name: string PostalCode: string