EkaerHistoryFilter: add [Flags], tab count refresh, API

- Refactored EkaerHistoryFilter as a [Flags] enum for combinable filters and improved docs.
- Added GetEkaerHistoryCount SignalR API and client method.
- GridEkaerHistory now notifies parent on data changes via OnDataChanged callback.
- Ekaer.razor tabs now show live "NeedsCompletion" counts and refresh on tab/data changes.
- Updated tab order, filter assignments, and disabled tab reordering.
This commit is contained in:
Loretta 2026-06-12 18:45:58 +02:00
parent 1e41632599
commit 6f46aaebb0
7 changed files with 57 additions and 17 deletions

View File

@ -92,18 +92,21 @@ public static class EkaerStatusExtensions
public static bool NeedsCompletion(this EkaerStatus status) => status is EkaerStatus.SentWithMissingData; public static bool NeedsCompletion(this EkaerStatus status) => status is EkaerStatus.SentWithMissingData;
} }
/// <summary>EkaerHistory-lekérdezés szűrő a tabokhoz. <see cref="All"/> = 0 (minden) — szándékosan explicit, NEM nullable, /// <summary>EkaerHistory-lekérdezés szűrő a tabokhoz, <see cref="FlagsAttribute"/>. A kategóriák diszjunkt
/// hogy ne kelljen null-t kezelni sehol; a default érték (0) automatikusan „minden", ami biztonságos.</summary> /// StatusId-partíciók, ezért kombinálhatók (pl. <c>ToSubmit | NeedsCompletion</c> = minden, ami még nincs lezárva).
/// <see cref="All"/> = 0 (nincs bit = nincs szűrő → minden), egyúttal a biztonságos default; szándékosan NEM nullable.
/// Vigyázat: <c>HasFlag(All)</c> mindig true (0 bit), ezért a szerver előbb a <c>== All</c> ágat nézi.</summary>
[Flags]
public enum EkaerHistoryFilter public enum EkaerHistoryFilter
{ {
/// <summary>Minden rekord (nincs szűrés).</summary> /// <summary>Minden rekord (nincs szűrés). 0 = nincs bit → minden; egyúttal a biztonságos default.</summary>
All = 0, All = 0,
/// <summary>Beküldésre váró: minden, ami még NINCS a NAV-nál (Pending/Generated/GeneratedWithWarning/ValidationError/SendError).</summary> /// <summary>Beküldésre váró: minden, ami még NINCS a NAV-nál (Pending/Generated/GeneratedWithWarning/ValidationError/SendError).</summary>
ToSubmit, ToSubmit = 1,
/// <summary>Elküldött és hiánytalan (<see cref="EkaerStatus.Sent"/>).</summary> /// <summary>Elküldött és hiánytalan (<see cref="EkaerStatus.Sent"/>).</summary>
Sent, Sent = 2,
/// <summary>Elküldve, de pótlásra vár (<see cref="EkaerStatus.SentWithMissingData"/>).</summary> /// <summary>Elküldve, de pótlásra vár (<see cref="EkaerStatus.SentWithMissingData"/>).</summary>
NeedsCompletion, NeedsCompletion = 4,
} }
//public sealed class EkaerHistoryShipping : EkaerHistoryBase //public sealed class EkaerHistoryShipping : EkaerHistoryBase

View File

@ -37,6 +37,7 @@ public interface IFruitBankDataControllerCommon
public Task<EkaerHistory?> GenerateEkaerXmlDocument(int foreignKey, bool isOutgoing); public Task<EkaerHistory?> GenerateEkaerXmlDocument(int foreignKey, bool isOutgoing);
public Task<EkaerHistory?> CreateEkaerHistory(int foreignKey, bool isOutgoing); public Task<EkaerHistory?> CreateEkaerHistory(int foreignKey, bool isOutgoing);
public Task<int> CreateMissingEkaerHistories(DateTime fromDate); public Task<int> CreateMissingEkaerHistories(DateTime fromDate);
public Task<int> GetEkaerHistoryCount(EkaerHistoryFilter filter);
#endregion EkaerHistory #endregion EkaerHistory
#region CargoPartner #region CargoPartner

View File

@ -126,6 +126,7 @@ public class SignalRTags : AcSignalRTags
public const int GenerateEkaerXmlDocument = 190; public const int GenerateEkaerXmlDocument = 190;
public const int CreateEkaerHistory = 191; public const int CreateEkaerHistory = 191;
public const int CreateMissingEkaerHistories = 192; public const int CreateMissingEkaerHistories = 192;
public const int GetEkaerHistoryCount = 193;
public const int AuthenticateUser = 195; public const int AuthenticateUser = 195;
public const int RefreshToken = 200; public const int RefreshToken = 200;

View File

@ -143,6 +143,10 @@
/// <summary>Szerver-oldali szűrő (a tabok adják): ToSubmit / Sent / NeedsCompletion. Default All = minden.</summary> /// <summary>Szerver-oldali szűrő (a tabok adják): ToSubmit / Sent / NeedsCompletion. Default All = minden.</summary>
[Parameter] public EkaerHistoryFilter Filter { get; set; } = EkaerHistoryFilter.All; [Parameter] public EkaerHistoryFilter Filter { get; set; } = EkaerHistoryFilter.All;
/// <summary>A szülő (oldal) értesítése, ha egy művelet státuszt válthatott (generálás / kézi mentés / jövőbeni beküldés) —
/// hogy a fül-számlálók azonnal frissüljenek, mert a sor átkerülhet másik tabra.</summary>
[Parameter] public EventCallback OnDataChanged { get; set; }
public bool IsMasterGrid => ParentDataItem == null; public bool IsMasterGrid => ParentDataItem == null;
private LoggerClient<GridEkaerHistory> _logger; private LoggerClient<GridEkaerHistory> _logger;
@ -170,7 +174,10 @@
if (Grid == null) return; if (Grid == null) return;
if (Grid.IsEditing() && !Grid.IsEditingNewRow()) if (Grid.IsEditing() && !Grid.IsEditingNewRow())
{
await Grid.SaveChangesAsync(); await Grid.SaveChangesAsync();
await NotifyDataChanged(); // kézi szerkesztés (pl. Status → SentWithMissingData) → fül-szám frissítése
}
FocusedRowVisibleIndex = args.VisibleIndex; FocusedRowVisibleIndex = args.VisibleIndex;
EditItemsEnabled = true; EditItemsEnabled = true;
@ -186,6 +193,9 @@
private static bool CanCopy(EkaerHistory ekaerHistory) private static bool CanCopy(EkaerHistory ekaerHistory)
=> ekaerHistory.Status.IsSubmittable() && !string.IsNullOrWhiteSpace(ekaerHistory.XmlDoc); => ekaerHistory.Status.IsSubmittable() && !string.IsNullOrWhiteSpace(ekaerHistory.XmlDoc);
// A szülő-oldal (fül-számlálók) értesítése egy státuszt érintő művelet után. Üres delegáltnál no-op.
private Task NotifyDataChanged() => OnDataChanged.HasDelegate ? OnDataChanged.InvokeAsync() : Task.CompletedTask;
private async Task OnGenerateClick(EkaerHistory ekaerHistory) private async Task OnGenerateClick(EkaerHistory ekaerHistory)
{ {
if (!_generatingIds.Add(ekaerHistory.Id)) return; if (!_generatingIds.Add(ekaerHistory.Id)) return;
@ -217,6 +227,7 @@
{ {
_generatingIds.Remove(ekaerHistory.Id); _generatingIds.Remove(ekaerHistory.Id);
Grid?.Reload(); Grid?.Reload();
await NotifyDataChanged();
} }
} }

View File

@ -15,15 +15,15 @@
IndicatorAreaVisible="false" IndicatorAreaVisible="false"
Text="Adatok szinkronizálása folyamatban..."> Text="Adatok szinkronizálása folyamatban...">
<DxTabs ActiveTabIndexChanged="(i) => OnActiveTabChanged(i)" RenderMode="TabsRenderMode.OnDemand" AllowTabReorder="true"> <DxTabs ActiveTabIndexChanged="(i) => OnActiveTabChanged(i)" RenderMode="TabsRenderMode.OnDemand" AllowTabReorder="false">
<DxTabPage Text="Beküldésre váró"> <DxTabPage Text="Beküldésre váró">
<GridEkaerHistory @ref="gridEkaerHistoryPending" Filter="EkaerHistoryFilter.ToSubmit"></GridEkaerHistory> <GridEkaerHistory @ref="gridEkaerHistoryPending" Filter="EkaerHistoryFilter.ToSubmit" OnDataChanged="RefreshNeedsCompletionCountAsync"></GridEkaerHistory>
</DxTabPage>
<DxTabPage Text="@NeedsCompletionTabText">
<GridEkaerHistory @ref="gridEkaerHistoryNeedsCompletion" Filter="EkaerHistoryFilter.ToSubmit" OnDataChanged="RefreshNeedsCompletionCountAsync"></GridEkaerHistory>
</DxTabPage> </DxTabPage>
<DxTabPage Text="Elküldött"> <DxTabPage Text="Elküldött">
<GridEkaerHistory @ref="gridEkaerHistorySent" Filter="EkaerHistoryFilter.Sent"></GridEkaerHistory> <GridEkaerHistory @ref="gridEkaerHistorySent" Filter="EkaerHistoryFilter.Sent" OnDataChanged="RefreshNeedsCompletionCountAsync"></GridEkaerHistory>
</DxTabPage>
<DxTabPage Text="Pótlásra váró">
<GridEkaerHistory @ref="gridEkaerHistoryNeedsCompletion" Filter="EkaerHistoryFilter.NeedsCompletion"></GridEkaerHistory>
</DxTabPage> </DxTabPage>
</DxTabs> </DxTabs>
</DxLoadingPanel> </DxLoadingPanel>

View File

@ -1,7 +1,9 @@
using AyCode.Core.Loggers; using AyCode.Core.Loggers;
using FruitBank.Common.Entities;
using FruitBank.Common.Models; using FruitBank.Common.Models;
using FruitBankHybrid.Shared.Components.Grids.Ekaers; using FruitBankHybrid.Shared.Components.Grids.Ekaers;
using FruitBankHybrid.Shared.Services.Loggers; using FruitBankHybrid.Shared.Services.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs;
using Mango.Nop.Core.Loggers; using Mango.Nop.Core.Loggers;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
@ -12,6 +14,7 @@ public partial class Ekaer : ComponentBase
[Inject] public required IEnumerable<IAcLogWriterClientBase> LogWriters { get; set; } [Inject] public required IEnumerable<IAcLogWriterClientBase> LogWriters { get; set; }
[Inject] public required NavigationManager NavManager { get; set; } [Inject] public required NavigationManager NavManager { get; set; }
[Inject] public required LoggedInModel LoggedInModel { get; set; } [Inject] public required LoggedInModel LoggedInModel { get; set; }
[Inject] public required FruitBankSignalRClient FruitBankSignalRClient { get; set; }
private GridEkaerHistory gridEkaerHistoryPending; private GridEkaerHistory gridEkaerHistoryPending;
private GridEkaerHistory gridEkaerHistorySent; private GridEkaerHistory gridEkaerHistorySent;
@ -20,20 +23,40 @@ public partial class Ekaer : ComponentBase
private ILogger _logger = null!; private ILogger _logger = null!;
public int ActiveTabIndex; public int ActiveTabIndex;
protected override Task OnInitializedAsync() /// <summary>Pótlásra váró (SentWithMissingData) rekordok száma a fül feliratához — hogy ránézésre látsszon, ha van pótolnivaló.</summary>
private int _needsCompletionCount;
public string NeedsCompletionTabText => _needsCompletionCount > 0 ? $"Pótlásra váró ({_needsCompletionCount})" : "Pótlásra váró";
protected override async Task OnInitializedAsync()
{ {
if (!LoggedInModel.IsRevisor) NavManager.NavigateTo("/Login"); if (!LoggedInModel.IsRevisor) NavManager.NavigateTo("/Login");
_logger = new LoggerClient<Ekaer>(LogWriters.ToArray()); _logger = new LoggerClient<Ekaer>(LogWriters.ToArray());
_logger.Info("OnInitializedAsync"); _logger.Info("OnInitializedAsync");
return base.OnInitializedAsync(); await base.OnInitializedAsync();
await RefreshNeedsCompletionCountAsync();
} }
protected Task OnActiveTabChanged(int activeTabIndex) protected async Task OnActiveTabChanged(int activeTabIndex)
{ {
ActiveTabIndex = activeTabIndex; ActiveTabIndex = activeTabIndex;
// A fülek tartalma (EKÁER-grid) külön feladat — több előfeltétele van (kliens-metódus, szűrés). // Fülváltáskor frissítjük a számlálót — a gridben végzett művelet (generálás/státusz-állítás) megváltoztathatta.
return Task.CompletedTask; await RefreshNeedsCompletionCountAsync();
}
/// <summary>A „Pótlásra váró" rekordok számának frissítése a fül feliratához (a count endpointról, flag-szűrővel).</summary>
private async Task RefreshNeedsCompletionCountAsync()
{
try
{
//_needsCompletionCount = await FruitBankSignalRClient.GetEkaerHistoryCount(EkaerHistoryFilter.NeedsCompletion);
_needsCompletionCount = await FruitBankSignalRClient.GetEkaerHistoryCount(EkaerHistoryFilter.ToSubmit);
StateHasChanged();
}
catch (Exception ex)
{
_logger.Error($"GetEkaerHistoryCount hiba: {ex.Message}");
}
} }
} }

View File

@ -82,6 +82,7 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
public Task<EkaerHistory?> GenerateEkaerXmlDocument(int foreignKey, bool isOutgoing) => GetByIdAsync<EkaerHistory?>(SignalRTags.GenerateEkaerXmlDocument, [foreignKey, isOutgoing]); public Task<EkaerHistory?> GenerateEkaerXmlDocument(int foreignKey, bool isOutgoing) => GetByIdAsync<EkaerHistory?>(SignalRTags.GenerateEkaerXmlDocument, [foreignKey, isOutgoing]);
public Task<EkaerHistory?> CreateEkaerHistory(int foreignKey, bool isOutgoing) => GetByIdAsync<EkaerHistory?>(SignalRTags.CreateEkaerHistory, [foreignKey, isOutgoing]); public Task<EkaerHistory?> CreateEkaerHistory(int foreignKey, bool isOutgoing) => GetByIdAsync<EkaerHistory?>(SignalRTags.CreateEkaerHistory, [foreignKey, isOutgoing]);
public Task<int> CreateMissingEkaerHistories(DateTime fromDate) => GetByIdAsync<int>(SignalRTags.CreateMissingEkaerHistories, fromDate); public Task<int> CreateMissingEkaerHistories(DateTime fromDate) => GetByIdAsync<int>(SignalRTags.CreateMissingEkaerHistories, fromDate);
public Task<int> GetEkaerHistoryCount(EkaerHistoryFilter filter) => GetByIdAsync<int>(SignalRTags.GetEkaerHistoryCount, filter);
#endregion EkaerHistory #endregion EkaerHistory
#region CargoPartner #region CargoPartner