From 93830415040d697fe993f7c980745cdad3a45a58 Mon Sep 17 00:00:00 2001 From: Loretta Date: Fri, 12 Jun 2026 07:54:38 +0200 Subject: [PATCH] =?UTF-8?q?Add=20EK=C3=81ER=20XML=20support=20for=20outgoi?= =?UTF-8?q?ng=20orders,=20refactor=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduced IEkaerSettings interface and refactored code to use it for DI/testability - Added support for generating EKÁER XML from outgoing orders (OrderDto) - Extended service and mapper interfaces for outgoing order handling - Implemented MapOrder and value calculation for order items - Replaced UnloadLocation with Site in EkaerCompanyInfo for general site usage - Updated tests, SignalR/controller interfaces, and UI to support new features and signatures - Improved documentation and code clarity throughout --- .claude/settings.local.json | 3 +- .../Services/Ekaer/FruitBankEkaerService.cs | 56 +++++++----- .../Services/Ekaer/IFruitBankEkaerService.cs | 8 ++ .../IFruitBankDataControllerCommon.cs | 2 +- .../Services/Ekaer/EkaerSettings.cs | 7 +- .../Services/Ekaer/EkaerValueCalculator.cs | 14 +++ .../Services/Ekaer/IShippingToEkaerMapper.cs | 8 ++ .../Services/Ekaer/ShippingToEkaerMapper.cs | 87 ++++++++++++++++++- .../Ekaer/ShippingToEkaerMapperTests.cs | 16 ++-- .../FruitBankEkaerTests.cs | 6 +- .../Grids/Ekaers/GridEkaerHistory.razor | 8 +- .../SignalRs/FruitBankSignalRClient.cs | 2 +- 12 files changed, 172 insertions(+), 45 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 3d148c8f..85101802 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -67,7 +67,8 @@ "Bash(grep -c -a \"ConversionRate\" FruitBank.Common.dll)", "Bash(grep -c -a \"ConversionRate\" FruitBank.Common.Server.dll)", "Bash(grep -c -a \"EurHufRate\" FruitBank.Common.dll FruitBank.Common.Server.dll)", - "Bash(ls -la --time-style=+%H:%M FruitBank.Common.dll FruitBank.Common.Server.dll)" + "Bash(ls -la --time-style=+%H:%M FruitBank.Common.dll FruitBank.Common.Server.dll)", + "Bash(find \"H:\\\\\\\\Applications\\\\\\\\Mango\" -name \"Order.cs\" -path \"*/Domain/Orders/*\" 2>&1 | head -3)" ] } } diff --git a/FruitBank.Common.Server/Services/Ekaer/FruitBankEkaerService.cs b/FruitBank.Common.Server/Services/Ekaer/FruitBankEkaerService.cs index 9e21f0b8..3c1004e3 100644 --- a/FruitBank.Common.Server/Services/Ekaer/FruitBankEkaerService.cs +++ b/FruitBank.Common.Server/Services/Ekaer/FruitBankEkaerService.cs @@ -1,6 +1,7 @@ using AyCode.Services.Nav; using AyCode.Services.Nav.Ekaer; using AyCode.Services.Nav.Ekaer.Models; +using FruitBank.Common.Dtos; using FruitBank.Common.Entities; using FruitBank.Common.Services.Ekaer; @@ -17,9 +18,9 @@ public sealed class FruitBankEkaerService : IFruitBankEkaerService private readonly IShippingToEkaerMapper _mapper; private readonly IEkaerSubmitService _submitService; private readonly IEkaerTradeCardValidator _validator; - private readonly EkaerSettings _settings; + private readonly IEkaerSettings _settings; - public FruitBankEkaerService(IShippingToEkaerMapper mapper, IEkaerSubmitService submitService, IEkaerTradeCardValidator validator, EkaerSettings settings) + public FruitBankEkaerService(IShippingToEkaerMapper mapper, IEkaerSubmitService submitService, IEkaerTradeCardValidator validator, IEkaerSettings settings) { _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); _submitService = submitService ?? throw new ArgumentNullException(nameof(submitService)); @@ -39,35 +40,44 @@ public sealed class FruitBankEkaerService : IFruitBankEkaerService public EkaerHistory GenerateEkaerXmlDocument(ShippingDocument document, EkaerHistory? ekaerHistory = null) { ArgumentNullException.ThrowIfNull(document); - ekaerHistory ??= new EkaerHistory { ForeignKey = document.Id, IsOutgoing = false }; - // Config-ellenőrzés a leképezés ELŐTT: külföldi (nem HUF) feladónál az árfolyam kötelező — különben a - // value csendben 0 lenne. Hibás configgal nem generálunk félrevezető XML-t, hanem jelezzük a hibát. - if (!EkaerValueCalculator.IsHuf(document.Partner?.Currency) && _settings.EurHufRate <= 0) - { - ekaerHistory.Status = EkaerStatus.ValidationError; - ekaerHistory.ErrorText = "EKÁER EUR-HUF árfolyam nincs konfigurálva (appsettings Ekaer:ExchangeRate:EurHuf) — a tétel-érték nem számolható."; - return ekaerHistory; - } + var currency = document.Partner?.Currency; + return TryConfigError(ekaerHistory, currency) ?? Finalize(ekaerHistory, _mapper.MapDocument(document, _settings.Company), currency); + } - var operation = new TradeCardOperationType - { - Index = 1, - Operation = OperationType.Create, - TradeCard = _mapper.MapDocument(document, _settings.Company), - }; + public EkaerHistory GenerateEkaerXmlDocument(OrderDto order, EkaerHistory? ekaerHistory = null) + { + ArgumentNullException.ThrowIfNull(order); + ekaerHistory ??= new EkaerHistory { ForeignKey = order.Id, IsOutgoing = true }; + // Kimenő pénznem: jelenleg minden HUF (a deviza az OrderDto-ba kerül, amint bekötik) → ConversionRate = 1. + const string currency = "HUF"; + return TryConfigError(ekaerHistory, currency) ?? Finalize(ekaerHistory, _mapper.MapOrder(order, _settings.Company), currency); + } + + /// Config-kapu: külföldi (nem HUF) feladónál az árfolyam kötelező — különben a leképezés ELŐTT + /// ValidationError (nincs félrevezető XML). null = rendben, mehet a generálás. + private EkaerHistory? TryConfigError(EkaerHistory ekaerHistory, string? currency) + { + if (EkaerValueCalculator.IsHuf(currency) || _settings.EurHufRate > 0) return null; + + ekaerHistory.Status = EkaerStatus.ValidationError; + ekaerHistory.ErrorText = "EKÁER EUR-HUF árfolyam nincs konfigurálva (appsettings Ekaer:ExchangeRate:EurHuf) — a tétel-érték nem számolható."; + return ekaerHistory; + } + + /// Közös befejezés (bejövő/kimenő): validál, szerializál; az XML validációs hibánál IS tárolódik + /// (a detail-nézethez), és rögzíti a ténylegesen alkalmazott árfolyamot (HUF → 1, külföldi → FX-ráta). + private EkaerHistory Finalize(EkaerHistory ekaerHistory, TradeCardType tradeCard, string? currency) + { + var operation = new TradeCardOperationType { Index = 1, Operation = OperationType.Create, TradeCard = tradeCard }; var errors = _validator.Validate(operation); - // Az XML validációs hibánál IS tárolódik — a detail-nézetben így látszik, mi hiányzik. - ekaerHistory.XmlDoc = NavXmlHelper.Serialize(operation.TradeCard); - // Audit: a value-számításhoz TÉNYLEGESEN alkalmazott árfolyam (HUF → 1, külföldi → FX-ráta) — pont az, - // amivel a value készült. A NAV-sémában nincs árfolyam-mező, csak a HUF value; ez az oszlop őrzi meg, hogyan. - ekaerHistory.ConversionRate = EkaerValueCalculator.ResolveRateToHuf(document.Partner?.Currency, _settings.EurHufRate); + ekaerHistory.XmlDoc = NavXmlHelper.Serialize(tradeCard); + ekaerHistory.ConversionRate = EkaerValueCalculator.ResolveRateToHuf(currency, _settings.EurHufRate); ekaerHistory.Status = errors.Count == 0 ? EkaerStatus.Generated : EkaerStatus.ValidationError; ekaerHistory.ErrorText = errors.Count == 0 ? null : string.Join(Environment.NewLine, errors.Select(e => e.ErrorMessage)); - return ekaerHistory; } } diff --git a/FruitBank.Common.Server/Services/Ekaer/IFruitBankEkaerService.cs b/FruitBank.Common.Server/Services/Ekaer/IFruitBankEkaerService.cs index 244bbf3a..22113025 100644 --- a/FruitBank.Common.Server/Services/Ekaer/IFruitBankEkaerService.cs +++ b/FruitBank.Common.Server/Services/Ekaer/IFruitBankEkaerService.cs @@ -1,5 +1,6 @@ using AyCode.Services.Nav.Ekaer; using AyCode.Services.Nav.Ekaer.Models; +using FruitBank.Common.Dtos; using FruitBank.Common.Entities; namespace FruitBank.Common.Server.Services.Ekaer; @@ -26,4 +27,11 @@ public interface IFruitBankEkaerService /// A szállítólevél a betöltött gráffal (Partner, Items+ProductDto, Shipping→járművek). /// A dokumentum meglévő rekordja (újrageneráláskor); null → új rekord készül. EkaerHistory GenerateEkaerXmlDocument(ShippingDocument document, EkaerHistory? ekaerHistory = null); + + /// + /// Egy kimenő rendelésből () legenerálja az EKÁER tradeCard XML-t és validálja — + /// a (meglévő vagy új) rekordot tölti (IsOutgoing = true). Mi vagyunk az + /// ELADÓ, a vevő a CÍMZETT (belföldi értékesítés). NEM perzisztál és NEM hív NAV-ot — a mentés a hívó dolga. + /// + EkaerHistory GenerateEkaerXmlDocument(OrderDto order, EkaerHistory? ekaerHistory = null); } diff --git a/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs b/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs index 74463d40..9c7f89bc 100644 --- a/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs +++ b/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs @@ -34,7 +34,7 @@ public interface IFruitBankDataControllerCommon public Task?> GetEkaerHistoriesByForeignKey(int foreignKey); public Task AddEkaerHistory(EkaerHistory ekaerHistory); public Task UpdateEkaerHistory(EkaerHistory ekaerHistory); - public Task GenerateEkaerXmlDocument(int shippingDocumentId); + public Task GenerateEkaerXmlDocument(int foreignKey, bool isOutgoing); public Task CreateEkaerHistory(int foreignKey, bool isOutgoing); public Task CreateMissingEkaerHistories(DateTime fromDate); #endregion EkaerHistory diff --git a/FruitBank.Common/Services/Ekaer/EkaerSettings.cs b/FruitBank.Common/Services/Ekaer/EkaerSettings.cs index 94d7b5e4..9b04665c 100644 --- a/FruitBank.Common/Services/Ekaer/EkaerSettings.cs +++ b/FruitBank.Common/Services/Ekaer/EkaerSettings.cs @@ -7,7 +7,7 @@ namespace FruitBank.Common.Services.Ekaer; /// cégadata + a küszöbök + az árfolyam. A küszöbök és az árfolyam évente / jogszabály szerint változhatnak, /// ezért configban élnek — nem a kódban beégetve. /// -public sealed class EkaerSettings +public sealed class EkaerSettings : IEkaerSettings { /// A bejelentő saját cégadatai (címzett a bejövő relációban) + a lerakodási hely. public EkaerCompanyInfo Company { get; set; } = new(); @@ -23,6 +23,7 @@ public sealed class EkaerSettings public double ThresholdWeightKg { get; set; } /// Érték-küszöb HUF-ban (nettó): e felett (vagy a tömeg-küszöb felett) kell EKÁER. Kockázatos élelmiszer: 250 000 Ft. - /// Default nélkül: be nem töltött config → 0 → minden szállítmány „átlépi" (mindent jelentünk, a biztonság felé). - public long ThresholdValueHuf { get; set; } + /// Default nélkül: be nem töltött config → 0 → minden szállítmány „átlépi" (mindent jelentünk, a biztonság felé). + /// int: a legmagasabb küszöb 5 millió Ft, bőven belefér. + public int ThresholdValueHuf { get; set; } } diff --git a/FruitBank.Common/Services/Ekaer/EkaerValueCalculator.cs b/FruitBank.Common/Services/Ekaer/EkaerValueCalculator.cs index d028f688..3a674f9f 100644 --- a/FruitBank.Common/Services/Ekaer/EkaerValueCalculator.cs +++ b/FruitBank.Common/Services/Ekaer/EkaerValueCalculator.cs @@ -1,3 +1,4 @@ +using FruitBank.Common.Dtos; using FruitBank.Common.Entities; namespace FruitBank.Common.Services.Ekaer; @@ -37,4 +38,17 @@ public static class EkaerValueCalculator var huf = Math.Round(ItemLineValue(item) * rateToHuf, MidpointRounding.AwayFromZero); return huf > 0 ? (long)huf : null; } + + // ── Kimenő (Order) változatok ──────────────────────────────────────────── + // Az érték a NETTÓ (ÁFA nélküli) egységár × mennyiség — az EKÁER „nettó érték"-et vár. + + /// Egy rendelés-tétel nettó értéke a számla pénznemében (UnitPriceExclTax × mennyiség), átváltás előtt. + public static double ItemLineValue(OrderItemDto item) => (double)item.UnitPriceExclTax * item.Quantity; + + /// Egy rendelés-tétel értéke HUF-ban, egészre kerekítve. 0/ismeretlen → null (lásd a bejövő párját). + public static long? ItemValueHuf(OrderItemDto item, double rateToHuf) + { + var huf = Math.Round(ItemLineValue(item) * rateToHuf, MidpointRounding.AwayFromZero); + return huf > 0 ? (long)huf : null; + } } diff --git a/FruitBank.Common/Services/Ekaer/IShippingToEkaerMapper.cs b/FruitBank.Common/Services/Ekaer/IShippingToEkaerMapper.cs index 31b2b70b..85b6aacb 100644 --- a/FruitBank.Common/Services/Ekaer/IShippingToEkaerMapper.cs +++ b/FruitBank.Common/Services/Ekaer/IShippingToEkaerMapper.cs @@ -1,5 +1,6 @@ using AyCode.Services.Nav.Ekaer; using AyCode.Services.Nav.Ekaer.Models; +using FruitBank.Common.Dtos; using FruitBank.Common.Entities; namespace FruitBank.Common.Services.Ekaer; @@ -29,4 +30,11 @@ public interface IShippingToEkaerMapper /// document.Shipping-ből jönnek; ha az nincs betöltve, ezek üresen maradnak (a validátor jelzi). /// TradeCardType MapDocument(ShippingDocument document, EkaerCompanyInfo company); + + /// + /// EGY kimenő rendelést () képez le egy tradeCard-dá: a bejelentő + /// (mi) az ELADÓ, a vevő a CÍMZETT, az irány belföldi értékesítés (D/S). A vonó jármű forrása + /// a kimenő fuvar-adat (OrderDto) — amíg az nincs bekötve, üresen marad (a validátor jelzi). + /// + TradeCardType MapOrder(OrderDto order, EkaerCompanyInfo company); } diff --git a/FruitBank.Common/Services/Ekaer/ShippingToEkaerMapper.cs b/FruitBank.Common/Services/Ekaer/ShippingToEkaerMapper.cs index f2230597..6fbaa96c 100644 --- a/FruitBank.Common/Services/Ekaer/ShippingToEkaerMapper.cs +++ b/FruitBank.Common/Services/Ekaer/ShippingToEkaerMapper.cs @@ -2,7 +2,9 @@ using AyCode.Core.Interfaces; using AyCode.Entities; using AyCode.Services.Nav.Ekaer; using AyCode.Services.Nav.Ekaer.Models; +using FruitBank.Common.Dtos; using FruitBank.Common.Entities; +using Nop.Core.Domain.Customers; using TradeReasonType = AyCode.Services.Nav.Ekaer.Models.Common.TradeReasonType; using TradeType = AyCode.Services.Nav.Ekaer.Models.Common.TradeType; @@ -19,9 +21,13 @@ public sealed class ShippingToEkaerMapper : IShippingToEkaerMapper /// A NAV EKÁER magyar rendszer — a „belföld" mindig HU; minden más feladó-ország import. private const string HomeCountry = "HU"; - private readonly EkaerSettings _settings; + /// Kimenő pénznem — jelenleg minden HUF (a vevő/rendelés devizája az OrderDto-ban még nincs leképezve; + /// bekötéskor innen jön). HUF → nincs átváltás (rate 1). + private const string OutboundCurrency = "HUF"; - public ShippingToEkaerMapper(EkaerSettings settings) + private readonly IEkaerSettings _settings; + + public ShippingToEkaerMapper(IEkaerSettings settings) => _settings = settings ?? throw new ArgumentNullException(nameof(settings)); public IReadOnlyList MapShipping(Shipping shipping, EkaerCompanyInfo company, OperationType operation = OperationType.Create) @@ -57,6 +63,45 @@ public sealed class ShippingToEkaerMapper : IShippingToEkaerMapper return BuildTradeCard(document.Shipping, document, company, rateToHuf); } + /// + public TradeCardType MapOrder(OrderDto order, EkaerCompanyInfo company) + { + ArgumentNullException.ThrowIfNull(order); + ArgumentNullException.ThrowIfNull(company); + + var customer = order.Customer; + var rateToHuf = EkaerValueCalculator.ResolveRateToHuf(OutboundCurrency, _settings.EurHufRate); + + var tradeCard = new TradeCardType + { + // Kimenő belföldi értékesítés. (Export `E` + külföldi deviza: későbbi — jelenleg minden HUF/belföld.) + TradeType = TradeType.D, + ModByCarrierEnabled = false, + + // Eladó = mi (kimenő relációban) + SellerName = company.Name, + SellerVatNumber = NormalizeVatNumber(company.TaxId), + SellerCountry = NormalizeCountryCode(company.CountryCode, 2), + SellerAddress = Truncate(company.FullAddress, 200), + + // Címzett = a vevő. Ország jelenleg HU (belföld); a Customer.CountryId-feloldás + export: későbbi. + DestinationName = customer?.Company, + DestinationVatNumber = NormalizeVatNumber(customer?.VatNumber), + DestinationCountry = HomeCountry, + DestinationAddress = Truncate(ComposeCustomerAddress(customer), 200), + + // Felrakodás = a mi telephelyünk; lerakodás = a vevő. + LoadLocation = company.Site, + UnloadLocation = BuildCustomerLocation(customer), + + // Vonó jármű / fuvarozó: a kimenő fuvar-adat (OrderDto) bekötéséig nincs forrás — üresen marad, + // a validátor jelzi (mint a bejövőnél kezdetben). TODO: order. → Vehicle / CarrierText. + }; + + foreach (var item in order.OrderItemDtos ?? []) tradeCard.Items.Add(BuildOutboundItem(item, rateToHuf)); + return tradeCard; + } + private static TradeCardType BuildTradeCard(Shipping? shipping, ShippingDocument document, EkaerCompanyInfo company, double rateToHuf) { var seller = document.Partner; // a beszállító (feladó) — ICompanyInfoBase @@ -82,7 +127,7 @@ public sealed class ShippingToEkaerMapper : IShippingToEkaerMapper CarrierText = shipping?.CargoPartner?.Name, // Lerakodás = saját telephely (a cégadatból); felrakodás = a beszállító telephelye. - UnloadLocation = company.UnloadLocation, + UnloadLocation = company.Site, LoadLocation = BuildLoadLocation(seller), }; @@ -114,6 +159,18 @@ public sealed class ShippingToEkaerMapper : IShippingToEkaerMapper Value = EkaerValueCalculator.ItemValueHuf(item, rateToHuf), // beszerzési érték HUF-ban (Partner.Currency → árfolyam); 0/ismeretlen → null }; + /// Kimenő (Order) tétel → tradeCardItem. Értékesítés (S); bruttó tömeg a palettákból; nettó érték HUF-ban. + private static TradeCardItemType BuildOutboundItem(OrderItemDto item, double rateToHuf) => new() + { + ItemExternalId = item.Id.ToString(), + // Kimenő áru = értékesítés → S. (Enum: S=értékesítés, A=beszerzés, W=bérmunka, O=egyéb.) + TradeReason = TradeReasonType.S, + ProductVtsz = NormalizeVtsz(item.ProductDto?.Gtin), // VTSZ — átmenetileg a Gtin oszlopban (FBANKAPP-DMODEL-I-P6X4) + ProductName = item.ProductDto?.Name, + Weight = (decimal)item.GrossWeight, // bruttó tömeg kg-ban (OrderItemPallets összegéből) + Value = EkaerValueCalculator.ItemValueHuf(item, rateToHuf), // nettó értékesítési érték HUF-ban; 0/ismeretlen → null + }; + private static BasicVehicleDetailType BuildVehicle(CargoTruck truck) => new() { PlateNumber = NormalizePlateNumber(truck.LicencePlate), @@ -138,6 +195,30 @@ public sealed class ShippingToEkaerMapper : IShippingToEkaerMapper }; } + /// A vevő egysoros címe (irsz + város + utca) a NAV destinationAddress-hez. + private static string? ComposeCustomerAddress(Customer? customer) + { + if (customer is null) return null; + var parts = new[] { customer.ZipPostalCode, customer.City, customer.StreetAddress, customer.StreetAddress2 } + .Where(p => !string.IsNullOrWhiteSpace(p)); + return EmptyToNull(string.Join(" ", parts).Trim()); + } + + /// Lerakodási hely a vevő adataiból (kimenő reláció). Ország jelenleg HU (belföld). + private static LocationType? BuildCustomerLocation(Customer? customer) + { + if (customer is null) return null; + return new LocationType + { + Name = customer.Company, + VatNumber = NormalizeVatNumber(customer.VatNumber), + Country = HomeCountry, + ZipCode = NormalizeZipCode(customer.ZipPostalCode), + City = customer.City, + Street = customer.StreetAddress, + }; + } + /// Adószám normalizálása. Pattern: [0-9A-Z-]{1,15}. private static string? NormalizeVatNumber(string? value) { diff --git a/FruitBankHybrid.Shared.Tests/Ekaer/ShippingToEkaerMapperTests.cs b/FruitBankHybrid.Shared.Tests/Ekaer/ShippingToEkaerMapperTests.cs index 461ab4c9..be7ac26c 100644 --- a/FruitBankHybrid.Shared.Tests/Ekaer/ShippingToEkaerMapperTests.cs +++ b/FruitBankHybrid.Shared.Tests/Ekaer/ShippingToEkaerMapperTests.cs @@ -15,7 +15,9 @@ namespace FruitBankHybrid.Shared.Tests.Ekaer; [TestClass] public sealed class ShippingToEkaerMapperTests { - private static readonly ShippingToEkaerMapper Mapper = new(new EkaerSettings()); + // EurHufRate > 0 kell: a teszt-partnernek nincs Currency-je (null → külföldiként kezelt), és árfolyam nélkül + // a value-számítás ResolveRateToHuf-ja dobna. A value-t a tesztek nem ellenőrzik; ez csak az átváltáshoz kell. + private static readonly ShippingToEkaerMapper Mapper = new(new EkaerSettings { EurHufRate = 356 }); // ---- Helpers ------------------------------------------------------------ @@ -67,15 +69,17 @@ public sealed class ShippingToEkaerMapperTests PostalCode = "1102", City = "Budapest", Street = "Raktar utca 5", - UnloadLocation = new LocationType + Site = new LocationType { Name = "FruitBank Raktár", VatNumber = "98765432-2-41", + Phone = "+36301234567", // NAV-formátum: + / 06 prefix kötelező + Email = "raktar@fruitbank.hu", Country = "HU", - ZipCode = "1102", + ZipCode = "1239", City = "Budapest", - Street = "Raktar utca", - StreetNumber = "5", + Street = "Nagykőrösi út", + StreetNumber = "353", }, }; @@ -166,7 +170,7 @@ public sealed class ShippingToEkaerMapperTests Assert.AreEqual("FruitBank Kft", tradeCard.DestinationName); Assert.AreEqual("HU", tradeCard.DestinationCountry); StringAssert.Contains(tradeCard.DestinationAddress, "Budapest", "a destinationAddress a company FullAddress-éből jön"); - Assert.AreSame(company.UnloadLocation, tradeCard.UnloadLocation, "a lerakodási hely a cégadatból jön"); + Assert.AreSame(company.Site, tradeCard.UnloadLocation, "a lerakodási hely a cég telephelyéből jön"); } [TestMethod] diff --git a/FruitBankHybrid.Shared.Tests/FruitBankEkaerTests.cs b/FruitBankHybrid.Shared.Tests/FruitBankEkaerTests.cs index 12bbe5e9..c8e8c716 100644 --- a/FruitBankHybrid.Shared.Tests/FruitBankEkaerTests.cs +++ b/FruitBankHybrid.Shared.Tests/FruitBankEkaerTests.cs @@ -73,7 +73,7 @@ namespace FruitBankHybrid.Shared.Tests foreach (var shippingDocument in shippingDocuments) { - var ekaerHistory = await _signalRClient.GenerateEkaerXmlDocument(shippingDocument.Id); + var ekaerHistory = await _signalRClient.GenerateEkaerXmlDocument(shippingDocument.Id, false); // A szerver által visszaadott állapot/hibalista logolása — az assertek ELŐTT, hogy hibánál is látsszon. Console.WriteLine($"doc#{shippingDocument.Id}: Status: {(ekaerHistory == null ? "NULL VÁLASZ!" : ekaerHistory.Status.ToString())}"); @@ -105,8 +105,8 @@ namespace FruitBankHybrid.Shared.Tests var shippingDocumentId = shippingDocuments[0].Id; - var first = await _signalRClient.GenerateEkaerXmlDocument(shippingDocumentId); - var second = await _signalRClient.GenerateEkaerXmlDocument(shippingDocumentId); + var first = await _signalRClient.GenerateEkaerXmlDocument(shippingDocumentId, false); + var second = await _signalRClient.GenerateEkaerXmlDocument(shippingDocumentId, false); Assert.IsNotNull(first); Assert.IsNotNull(second); diff --git a/FruitBankHybrid.Shared/Components/Grids/Ekaers/GridEkaerHistory.razor b/FruitBankHybrid.Shared/Components/Grids/Ekaers/GridEkaerHistory.razor index de00d48b..0d67a925 100644 --- a/FruitBankHybrid.Shared/Components/Grids/Ekaers/GridEkaerHistory.razor +++ b/FruitBankHybrid.Shared/Components/Grids/Ekaers/GridEkaerHistory.razor @@ -172,10 +172,10 @@ private readonly HashSet _generatingIds = []; - // Elküldött bejelentést nem generálunk újra némán (az már a NAV-nál van — módosítás külön művelet lesz); - // kimenő (Order) generálás még nincs implementálva. + // Elküldött bejelentést nem generálunk újra némán (az már a NAV-nál van — módosítás külön művelet lesz). + // Bejövő és kimenő (Order) is generálható; a kimenőnél a fuvar-adat bekötéséig a validátor jelzi a hiányt. private bool CanGenerate(EkaerHistory ekaerHistory) - => ekaerHistory.Status != EkaerStatus.Sent && !ekaerHistory.IsOutgoing && !_generatingIds.Contains(ekaerHistory.Id); + => ekaerHistory.Status != EkaerStatus.Sent && !_generatingIds.Contains(ekaerHistory.Id); // Hibás (validációs hibás) bejelentés XML-jét nem adjuk a user kezébe — ne kerülhessen kézzel a NAV-hoz. private static bool CanCopy(EkaerHistory ekaerHistory) @@ -187,7 +187,7 @@ try { - var updated = await FruitBankSignalRClient.GenerateEkaerXmlDocument(ekaerHistory.ForeignKey); + var updated = await FruitBankSignalRClient.GenerateEkaerXmlDocument(ekaerHistory.ForeignKey, ekaerHistory.IsOutgoing); if (updated == null) { diff --git a/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs b/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs index 7bad3074..2f85f620 100644 --- a/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs +++ b/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs @@ -79,7 +79,7 @@ namespace FruitBankHybrid.Shared.Services.SignalRs public Task?> GetEkaerHistoriesByForeignKey(int foreignKey) => GetAllAsync>(SignalRTags.GetEkaerHistoriesByForeignKey, [foreignKey]); public Task AddEkaerHistory(EkaerHistory ekaerHistory) => PostDataAsync(SignalRTags.AddEkaerHistory, ekaerHistory); public Task UpdateEkaerHistory(EkaerHistory ekaerHistory) => PostDataAsync(SignalRTags.UpdateEkaerHistory, ekaerHistory); - public Task GenerateEkaerXmlDocument(int shippingDocumentId) => GetByIdAsync(SignalRTags.GenerateEkaerXmlDocument, shippingDocumentId); + public Task GenerateEkaerXmlDocument(int foreignKey, bool isOutgoing) => GetByIdAsync(SignalRTags.GenerateEkaerXmlDocument, [foreignKey, isOutgoing]); public Task CreateEkaerHistory(int foreignKey, bool isOutgoing) => GetByIdAsync(SignalRTags.CreateEkaerHistory, [foreignKey, isOutgoing]); public Task CreateMissingEkaerHistories(DateTime fromDate) => GetByIdAsync(SignalRTags.CreateMissingEkaerHistories, fromDate); #endregion EkaerHistory