Compare commits
2 Commits
2221d4a68e
...
3cf18efd99
| Author | SHA1 | Date |
|---|---|---|
|
|
3cf18efd99 | |
|
|
973c8030d2 |
|
|
@ -74,7 +74,8 @@
|
|||
"WebFetch(domain:net.jogtar.hu)",
|
||||
"WebFetch(domain:www.itrack.hu)",
|
||||
"WebFetch(domain:docplayer.hu)",
|
||||
"WebFetch(domain:supportcenter.devexpress.com)"
|
||||
"WebFetch(domain:supportcenter.devexpress.com)",
|
||||
"PowerShell($c = Get-Command claude -ErrorAction SilentlyContinue; if \\($c\\) { $c.Source; & claude --help 2>&1 | Select-Object -First 90 } else { \"claude not on PATH\" })"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,19 +37,23 @@ public sealed class FruitBankEkaerService : IFruitBankEkaerService
|
|||
return _submitService.SubmitAsync(operations, cancellationToken);
|
||||
}
|
||||
|
||||
public EkaerHistory GenerateEkaerXmlDocument(ShippingDocument document, EkaerHistory? ekaerHistory = null)
|
||||
public EkaerHistory GenerateEkaerXmlDocument(IReadOnlyCollection<ShippingDocument> documents, EkaerHistory? ekaerHistory = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(document);
|
||||
ekaerHistory ??= new EkaerHistory { ForeignKey = document.Id, IsOutgoing = false };
|
||||
ArgumentNullException.ThrowIfNull(documents);
|
||||
if (documents.Count == 0) throw new ArgumentException("documents is empty", nameof(documents));
|
||||
ekaerHistory ??= new EkaerHistory { IsOutgoing = false };
|
||||
|
||||
var currency = document.Partner?.Currency;
|
||||
return TryConfigError(ekaerHistory, currency) ?? Finalize(ekaerHistory, _mapper.MapDocument(document, _settings.Company), currency);
|
||||
// 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 { ForeignKey = order.Id, IsOutgoing = true };
|
||||
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";
|
||||
|
|
@ -62,6 +66,12 @@ public sealed class FruitBankEkaerService : IFruitBankEkaerService
|
|||
public EkaerObligationResult EvaluateObligation(OrderDto order)
|
||||
=> EkaerReportability.Evaluate(_mapper.ToConsignment(order, _settings.Company), _settings);
|
||||
|
||||
public void SetSummary(EkaerHistory history, DateTime? shippingDate, string? partner)
|
||||
{
|
||||
history.ShippingDate = shippingDate;
|
||||
history.Partner = partner;
|
||||
}
|
||||
|
||||
/// <summary>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). <c>null</c> = rendben, mehet a generálás.</summary>
|
||||
private EkaerHistory? TryConfigError(EkaerHistory ekaerHistory, string? currency)
|
||||
|
|
|
|||
|
|
@ -20,14 +20,14 @@ public interface IFruitBankEkaerService
|
|||
Task<EkaerSubmitResult> SubmitShippingAsync(Shipping shipping, OperationType operation = OperationType.Create, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Egy szállítólevélből legenerálja az EKÁER tradeCard XML-t és validálja — a (meglévő vagy új)
|
||||
/// Egy szállítólevél-CSOPORTBÓL (egy EKÁER-egység dokumentumai) legenerálja az EKÁER tradeCard XML-t és validálja — a (meglévő vagy új)
|
||||
/// <see cref="EkaerHistory"/> rekordot tölti: <c>XmlDoc</c> + <c>Status</c>
|
||||
/// (<see cref="EkaerStatus.Generated"/> / <see cref="EkaerStatus.ValidationError"/>) + <c>ErrorText</c>.
|
||||
/// NEM perzisztál és NEM hív NAV-ot — a mentés (upsert) a hívó SignalR endpoint dolga.
|
||||
/// </summary>
|
||||
/// <param name="document">A szállítólevél a betöltött gráffal (Partner, Items+ProductDto, Shipping→járművek).</param>
|
||||
/// <param name="ekaerHistory">A dokumentum meglévő rekordja (újrageneráláskor); <c>null</c> → új rekord készül.</param>
|
||||
EkaerHistory GenerateEkaerXmlDocument(ShippingDocument document, EkaerHistory? ekaerHistory = null);
|
||||
/// <param name="documents">A deklarációhoz tartozó szállítólevél-CSOPORT (egy (Shipping, Partner, PartnerDepot) egység) a betöltött gráffal (Partner, Items+ProductDto, Shipping→járművek) — összevont tömeggel/értékkel EGY tradeCard.</param>
|
||||
/// <param name="ekaerHistory">A csoport meglévő rekordja (újrageneráláskor); <c>null</c> → új rekord készül.</param>
|
||||
EkaerHistory GenerateEkaerXmlDocument(IReadOnlyCollection<ShippingDocument> documents, EkaerHistory? ekaerHistory = null);
|
||||
|
||||
/// <summary>
|
||||
/// Egy kimenő rendelésből (<see cref="OrderDto"/>) legenerálja az EKÁER tradeCard XML-t és validálja —
|
||||
|
|
@ -45,4 +45,9 @@ public interface IFruitBankEkaerService
|
|||
|
||||
/// <summary>Eldönti egy kimenő rendelés EKÁER-kötelezettségét (ugyanaz a logika, a rendelés tételeire).</summary>
|
||||
EkaerObligationResult EvaluateObligation(OrderDto order);
|
||||
|
||||
/// <summary>Beállítja a deklaráció (<see cref="EkaerHistory"/>) összegző mezőit (DB-mentes): <c>ShippingDate</c> + <c>Partner</c>.
|
||||
/// A csoporton belül invariánsak; a forrás-kinyerés (bejövő: doc.ShippingDate + Partner.Name; kimenő: order.DateOfReceipt +
|
||||
/// Customer.Company) a hívóé. Fallback NINCS — null/üres marad, ha hiányzik.</summary>
|
||||
void SetSummary(EkaerHistory history, DateTime? shippingDate, string? partner);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -33,6 +33,7 @@ public static class FruitBankConstClient
|
|||
public const string PartnerDepotDbTableName = "fbPartnerDepot";
|
||||
|
||||
public const string EkaerHistoryDbTableName = "fbEkaerHistory";
|
||||
public const string EkaerHistoryMappingDbTableName = "fbEkaerHistoryMapping";
|
||||
|
||||
public const string OrderItemPalletDbTableName = "fbOrderItemPallet";
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public interface IFruitBankDataControllerCommon
|
|||
public Task<List<EkaerHistory>?> GetEkaerHistoriesByForeignKey(int foreignKey);
|
||||
public Task<EkaerHistory?> AddEkaerHistory(EkaerHistory ekaerHistory);
|
||||
public Task<EkaerHistory?> UpdateEkaerHistory(EkaerHistory ekaerHistory);
|
||||
public Task<EkaerHistory?> GenerateEkaerXmlDocument(int foreignKey, bool isOutgoing);
|
||||
public Task<EkaerHistory?> GenerateEkaerXmlDocument(int ekaerHistoryId);
|
||||
public Task<EkaerHistory?> CreateEkaerHistory(int foreignKey, bool isOutgoing);
|
||||
public Task<EkaerCreateResult?> CreateMissingEkaerHistories(DateTime fromDate);
|
||||
public Task<int> GetEkaerHistoryCount(EkaerHistoryFilter filter);
|
||||
|
|
|
|||
|
|
@ -41,8 +41,9 @@ namespace FruitBankHybrid.Shared.Tests
|
|||
|
||||
Assert.IsNotNull(ekaerHistory, $"shippingDocument.Id: {shippingDocument.Id}");
|
||||
Assert.IsGreaterThan(0, ekaerHistory.Id, $"shippingDocument.Id: {shippingDocument.Id}");
|
||||
Assert.AreEqual(shippingDocument.Id, ekaerHistory.ForeignKey);
|
||||
Assert.IsFalse(ekaerHistory.IsOutgoing);
|
||||
Assert.IsNotNull(ekaerHistory.Mappings, $"Mappings null (loadRelations?); shippingDocument.Id: {shippingDocument.Id}");
|
||||
Assert.AreEqual(shippingDocument.Id, ekaerHistory.Mappings.Single().ForeignKey, $"A mapping nem a forrás-dokumentumra mutat; shippingDocument.Id: {shippingDocument.Id}");
|
||||
}
|
||||
|
||||
// Idempotencia: a második hívás a meglévőt adja vissza, nem duplikál.
|
||||
|
|
@ -73,15 +74,18 @@ namespace FruitBankHybrid.Shared.Tests
|
|||
|
||||
foreach (var shippingDocument in shippingDocuments)
|
||||
{
|
||||
var ekaerHistory = await _signalRClient.GenerateEkaerXmlDocument(shippingDocument.Id, false);
|
||||
// A generálás mostantól EkaerHistory-Id alapú → előbb a (mapping-elt) rekordot hozzuk létre.
|
||||
var created = await _signalRClient.CreateEkaerHistory(shippingDocument.Id, false);
|
||||
Assert.IsNotNull(created, $"CreateEkaerHistory null; shippingDocument.Id: {shippingDocument.Id}");
|
||||
var ekaerHistory = await _signalRClient.GenerateEkaerXmlDocument(created.Id);
|
||||
|
||||
// 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())}");
|
||||
if (!string.IsNullOrWhiteSpace(ekaerHistory?.ErrorText)) Console.WriteLine($" ErrorText: {ekaerHistory.ErrorText}");
|
||||
|
||||
Assert.IsNotNull(ekaerHistory, $"shippingDocument.Id: {shippingDocument.Id}");
|
||||
Assert.AreEqual(shippingDocument.Id, ekaerHistory.ForeignKey);
|
||||
Assert.IsFalse(ekaerHistory.IsOutgoing);
|
||||
Assert.AreEqual(shippingDocument.Id, ekaerHistory.Mappings!.Single().ForeignKey, $"A mapping nem a forrás-dokumentumra mutat; shippingDocument.Id: {shippingDocument.Id}");
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(ekaerHistory.XmlDoc), $"XmlDoc üres; shippingDocument.Id: {shippingDocument.Id}");
|
||||
Assert.IsTrue(ekaerHistory.Status is EkaerStatus.Generated or EkaerStatus.ValidationError,
|
||||
$"Status: {ekaerHistory.Status}; shippingDocument.Id: {shippingDocument.Id}; ErrorText: {ekaerHistory.ErrorText}");
|
||||
|
|
@ -105,8 +109,12 @@ namespace FruitBankHybrid.Shared.Tests
|
|||
|
||||
var shippingDocumentId = shippingDocuments[0].Id;
|
||||
|
||||
var first = await _signalRClient.GenerateEkaerXmlDocument(shippingDocumentId, false);
|
||||
var second = await _signalRClient.GenerateEkaerXmlDocument(shippingDocumentId, false);
|
||||
// Generálás EkaerHistory-Id alapján → előbb a rekord (mapping-gel), majd kétszeri generálás ugyanarra az Id-ra.
|
||||
var created = await _signalRClient.CreateEkaerHistory(shippingDocumentId, false);
|
||||
Assert.IsNotNull(created);
|
||||
|
||||
var first = await _signalRClient.GenerateEkaerXmlDocument(created.Id);
|
||||
var second = await _signalRClient.GenerateEkaerXmlDocument(created.Id);
|
||||
|
||||
Assert.IsNotNull(first);
|
||||
Assert.IsNotNull(second);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ public class FullProcessModel
|
|||
public List<OrderDto> Orders { get; set; }
|
||||
public List<PreOrder> PreOrders { get; set; }
|
||||
public List<StockTaking> StockTakings { get; set; }
|
||||
public List<EkaerHistory> EkaerHistories { get; set; }
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
|
|
|
|||
|
|
@ -31,8 +31,27 @@
|
|||
OnGridFocusedRowChanged="Grid_FocusedRowChanged">
|
||||
<Columns>
|
||||
<DxGridDataColumn FieldName="Id" SortIndex="0" SortOrder="GridColumnSortOrder.Descending" ReadOnly="true" />
|
||||
<DxGridDataColumn FieldName="@nameof(EkaerHistory.ForeignKey)" ReadOnly="true" />
|
||||
<DxGridDataColumn FieldName="@nameof(EkaerHistory.IsOutgoing)" ReadOnly="true" />
|
||||
<DxGridDataColumn Caption="ForeignKey(s)" AllowSort="false" AllowGroup="false">
|
||||
@* A lefedett forrás-rekordok (ShippingDocument/Order Id-k) a betöltött Mappings-ből összefűzve —
|
||||
egyből látszik, ha több dokumentum van egy EKÁER-deklaráció alá vonva. *@
|
||||
<CellDisplayTemplate>
|
||||
@{
|
||||
var row = (EkaerHistory)context.DataItem;
|
||||
}
|
||||
@if (row.Mappings is { Count: > 0 } maps)
|
||||
{
|
||||
var noun = row.IsOutgoing ? "rendelés" : "szállítólevél";
|
||||
<span title="@(maps.Count > 1 ? $"{maps.Count} {noun} egy EKÁER alá vonva" : $"1 {noun}")">@string.Join(", ", maps.Select(m => $"#{m.ForeignKey}"))</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>—</span>
|
||||
}
|
||||
</CellDisplayTemplate>
|
||||
</DxGridDataColumn>
|
||||
<DxGridDataColumn FieldName="@nameof(EkaerHistory.ShippingDate)" Caption="Dátum" DisplayFormat="yyyy.MM.dd" ReadOnly="true" />
|
||||
<DxGridDataColumn FieldName="@nameof(EkaerHistory.Partner)" Caption="Partner" ReadOnly="true" />
|
||||
<DxGridDataColumn FieldName="@nameof(EkaerHistory.IsOutgoing)" Caption="Kimenő?" ReadOnly="true" />
|
||||
@* A kézi NAV-beadás fázisában a Status / EKÁER szám / SentDate kézzel szerkeszthető. *@
|
||||
<DxGridDataColumn FieldName="@nameof(EkaerHistory.Status)" />
|
||||
<DxGridDataColumn FieldName="@nameof(EkaerHistory.EkaerNumber)" Caption="EKÁER szám" />
|
||||
|
|
@ -209,11 +228,11 @@
|
|||
|
||||
try
|
||||
{
|
||||
var updated = await FruitBankSignalRClient.GenerateEkaerXmlDocument(ekaerHistory.ForeignKey, ekaerHistory.IsOutgoing);
|
||||
var updated = await FruitBankSignalRClient.GenerateEkaerXmlDocument(ekaerHistory.Id);
|
||||
|
||||
if (updated == null)
|
||||
{
|
||||
_logger.Error($"GenerateEkaerXmlDocument null választ adott; ForeignKey: {ekaerHistory.ForeignKey}");
|
||||
_logger.Error($"GenerateEkaerXmlDocument null választ adott; EkaerHistory #{ekaerHistory.Id}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -228,7 +247,7 @@
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"GenerateEkaerXmlDocument hiba; ForeignKey: {ekaerHistory.ForeignKey}", ex);
|
||||
_logger.Error($"GenerateEkaerXmlDocument hiba; EkaerHistory #{ekaerHistory.Id}", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,9 +37,11 @@ public class GridEkaerHistoryBase : FruitBankGridBase<EkaerHistory>, IGrid
|
|||
{
|
||||
if (ContextIds == null || ContextIds.Length == 0) ContextIds = [ParentDataItem!.Id];
|
||||
|
||||
// A ForeignKey általános (Shipping/Order stb.) — bármely szülőnél a ForeignKey-re szűrünk.
|
||||
// Detail-mód: a forrás-rekord (Shipping/Order/ShippingDocument) EKÁER-deklarációi a mappingen át.
|
||||
// Megj.: az EkaerHistory már NEM hordoz per-szülő mezőt (a kapcsolat az EkaerHistoryMapping junctionben él),
|
||||
// ezért a kliens-oldali KeyFieldNameToParentId itt nem alkalmazható — a szerver-oldali szűrés
|
||||
// (GetEkaerHistoriesByForeignKey → mapping) adja a szülőhöz tartozó sorokat. (Jelenleg nincs detail-használat.)
|
||||
GetAllMessageTag = SignalRTags.GetEkaerHistoriesByForeignKey;
|
||||
if (KeyFieldNameToParentId.IsNullOrWhiteSpace()) KeyFieldNameToParentId = nameof(EkaerHistory.ForeignKey);
|
||||
}
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
|
|||
public Task<List<EkaerHistory>?> GetEkaerHistoriesByForeignKey(int foreignKey) => GetAllAsync<List<EkaerHistory>>(SignalRTags.GetEkaerHistoriesByForeignKey, [foreignKey]);
|
||||
public Task<EkaerHistory?> AddEkaerHistory(EkaerHistory ekaerHistory) => PostDataAsync(SignalRTags.AddEkaerHistory, ekaerHistory);
|
||||
public Task<EkaerHistory?> UpdateEkaerHistory(EkaerHistory ekaerHistory) => PostDataAsync(SignalRTags.UpdateEkaerHistory, ekaerHistory);
|
||||
public Task<EkaerHistory?> GenerateEkaerXmlDocument(int foreignKey, bool isOutgoing) => GetByIdAsync<EkaerHistory?>(SignalRTags.GenerateEkaerXmlDocument, [foreignKey, isOutgoing]);
|
||||
public Task<EkaerHistory?> GenerateEkaerXmlDocument(int ekaerHistoryId) => GetByIdAsync<EkaerHistory?>(SignalRTags.GenerateEkaerXmlDocument, ekaerHistoryId);
|
||||
public Task<EkaerHistory?> CreateEkaerHistory(int foreignKey, bool isOutgoing) => GetByIdAsync<EkaerHistory?>(SignalRTags.CreateEkaerHistory, [foreignKey, isOutgoing]);
|
||||
public Task<EkaerCreateResult?> CreateMissingEkaerHistories(DateTime fromDate) => GetByIdAsync<EkaerCreateResult?>(SignalRTags.CreateMissingEkaerHistories, fromDate);
|
||||
public Task<int> GetEkaerHistoryCount(EkaerHistoryFilter filter) => GetByIdAsync<int>(SignalRTags.GetEkaerHistoryCount, filter);
|
||||
|
|
|
|||
Loading…
Reference in New Issue