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;
namespace FruitBank.Common.Server.Services.Ekaer;
///
///
/// A teljes lánc: map (, FruitBank.Common) →
/// validate → send (, AyCode.Services). A saját cégadatot
/// () és a NAV-fiók hitelesítő adatait a DI szolgáltatja.
///
public sealed class FruitBankEkaerService : IFruitBankEkaerService
{
private readonly IShippingToEkaerMapper _mapper;
private readonly IEkaerSubmitService _submitService;
private readonly IEkaerTradeCardValidator _validator;
private readonly IEkaerSettings _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));
_validator = validator ?? throw new ArgumentNullException(nameof(validator));
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
}
public Task SubmitShippingAsync(Shipping shipping, OperationType operation = OperationType.Create, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(shipping);
// map (FruitBank.Common) → submit: validate → send (AyCode.Services)
var operations = _mapper.MapShipping(shipping, _settings.Company, operation);
return _submitService.SubmitAsync(operations, cancellationToken);
}
public EkaerHistory GenerateEkaerXmlDocument(IReadOnlyCollection documents, EkaerHistory? ekaerHistory = null)
{
ArgumentNullException.ThrowIfNull(documents);
if (documents.Count == 0) throw new ArgumentException("documents is empty", nameof(documents));
ekaerHistory ??= new EkaerHistory { IsOutgoing = false };
// A csoport azonos Partneré (a kapu így csoportosít) → az első dokumentum pénzneme a mérvadó.
var currency = documents.First().Partner?.Currency;
// A csoport ÖSSZES dokumentuma EGY tradeCard-dá (összevont tömeg/érték): ToConsignment → BuildTradeCard.
var tradeCard = _mapper.BuildTradeCard(_mapper.ToConsignment(documents, _settings.Company));
return TryConfigError(ekaerHistory, currency) ?? Finalize(ekaerHistory, tradeCard, currency);
}
public EkaerHistory GenerateEkaerXmlDocument(OrderDto order, EkaerHistory? ekaerHistory = null)
{
ArgumentNullException.ThrowIfNull(order);
ekaerHistory ??= new EkaerHistory { 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);
}
public EkaerObligationResult EvaluateObligation(IReadOnlyCollection documents)
=> EkaerReportability.Evaluate(_mapper.ToConsignment(documents, _settings.Company), _settings);
public EkaerObligationResult EvaluateObligation(OrderDto order)
=> EkaerReportability.Evaluate(_mapper.ToConsignment(order, _settings.Company), _settings);
/// 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 messages = _validator.Validate(operation);
ekaerHistory.XmlDoc = NavXmlHelper.Serialize(tradeCard);
ekaerHistory.ConversionRate = EkaerValueCalculator.ResolveRateToHuf(currency, _settings.EurHufRate);
// Blokkoló hiba → ValidationError (nem küldhető); csak warning → GeneratedWithWarning (küldhető, de pótlandó);
// semmi → Generated. Az üzeneteket súlyossággal prefixeljük, hogy a detail-nézet megkülönböztesse őket.
ekaerHistory.Status = messages.HasErrors() ? EkaerStatus.ValidationError
: messages.HasWarnings() ? EkaerStatus.GeneratedWithWarning
: EkaerStatus.Generated;
// Error-ok elöl, warningok hátul (a detail-nézet soronként színez); a prefix [Error]/[Warning] hordozza a szintet.
ekaerHistory.ErrorText = messages.Count == 0 ? null
: string.Join(Environment.NewLine, messages
.OrderByDescending(m => m.GetSeverity())
.Select(m => $"[{m.GetSeverity()}] {m.ErrorMessage}"));
return ekaerHistory;
}
}