Add EKÁER history grid, detail view, and entity support

- Introduced `EkaerHistory` entity with status enum and new properties for EKÁER declaration lifecycle tracking.
- Added CRUD methods for `EkaerHistory` in controller interface and SignalR client.
- Implemented `GridEkaerHistory` and `GridEkaerDetail` components for displaying EKÁER records and trade card details.
- Enhanced `TradeCardItemType` with `IId<int>` for grid compatibility.
- Improved AcSignalRDataSource to skip server refresh for tagless/local data sources.
- Updated settings to include .NET 9 runtime install commands.
This commit is contained in:
Loretta 2026-06-10 16:24:54 +02:00
parent 735eabf008
commit 82f0f00196
10 changed files with 346 additions and 4 deletions

View File

@ -54,7 +54,10 @@
"Bash(rm -f H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Services/Ekaer/EkaerMappingOptions.cs H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Services/Ekaer/IShippingToEkaerMapper.cs H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Services/Ekaer/ShippingToEkaerMapper.cs)", "Bash(rm -f H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Services/Ekaer/EkaerMappingOptions.cs H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Services/Ekaer/IShippingToEkaerMapper.cs H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Services/Ekaer/ShippingToEkaerMapper.cs)",
"Bash(rmdir \"H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Services/Ekaer\")", "Bash(rmdir \"H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Services/Ekaer\")",
"Bash(rm -f \"H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Infrastructure/NavCredentials.cs\" *)", "Bash(rm -f \"H:/Applications/Mango/Source/NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/Infrastructure/NavCredentials.cs\" *)",
"Bash(rm -f \"H:/Applications/Aycode/Source/AyCode.Core/AyCode.Entities/IPostalParty.cs\" *)" "Bash(rm -f \"H:/Applications/Aycode/Source/AyCode.Core/AyCode.Entities/IPostalParty.cs\" *)",
"PowerShell(winget install Microsoft.DotNet.Runtime.9 --architecture x64 --accept-source-agreements --accept-package-agreements)",
"PowerShell($url = \"https://builds.dotnet.microsoft.com/dotnet/Runtime/9.0.17/dotnet-runtime-9.0.17-win-x64.exe\"; $dst = \"$env:TEMP\\\\dotnet-runtime-9.0.17-win-x64.exe\"; Invoke-WebRequest -Uri $url -OutFile $dst; Get-Item $dst | Select-Object Name, Length)",
"PowerShell($p = Start-Process \"$env:TEMP\\\\dotnet-runtime-9.0.17-win-x64.exe\" -ArgumentList \"/install\",\"/quiet\",\"/norestart\" -Wait -PassThru; \"ExitCode: $\\($p.ExitCode\\)\"; dotnet --list-runtimes | Select-String \"9\\\\.0\")"
] ]
} }
} }

View File

@ -7,19 +7,52 @@ using Mango.Nop.Core.Entities;
namespace FruitBank.Common.Entities; namespace FruitBank.Common.Entities;
[AcBinarySerializable(false, true, false, true, false, false)] [AcBinarySerializable(false, true, false, true, false, false)]
//[ToonDescription("Business partner with address and tax information", Purpose = "Represents an external legal entity, specifically a Supplier who provides goods or a business partner involved in the procurement chain")] [ToonDescription("NAV EKÁER declaration lifecycle record", Purpose = "Work-queue and audit row for one EKÁER road-freight declaration — one row per tradeCard: an incoming ShippingDocument (delivery note) or a completed outgoing Order. Tracks the declaration through generation, validation and submission to the Hungarian tax authority (NAV).")]
[Table(Name = FruitBankConstClient.EkaerHistoryDbTableName)] [Table(Name = FruitBankConstClient.EkaerHistoryDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.EkaerHistoryDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.EkaerHistoryDbTableName)]
public sealed class EkaerHistory: MgEntityBase, ITimeStampInfo public sealed class EkaerHistory: MgEntityBase, ITimeStampInfo
{ {
[ToonDescription(Purpose = "Id of the source entity the declaration belongs to: ShippingDocument.Id when IsOutgoing is false (one declaration per delivery note, matching NAV's one-TCN-per-tradeCard granularity), Order id when IsOutgoing is true.")]
public int ForeignKey { get; set; } public int ForeignKey { get; set; }
[ToonDescription(Purpose = "Direction of the goods movement: false = incoming shipment (Shipping), true = outgoing delivery (Order).")]
public bool IsOutgoing { get; set; } public bool IsOutgoing { get; set; }
[ToonDescription(Purpose = "Lifecycle state of the declaration: Pending (auto-created, not yet generated), Generated (tradeCard XML produced and valid), ValidationError (generation produced errors, see ErrorText), Sent (accepted by NAV, EkaerNumber filled), SendError (NAV call failed, see ErrorText).")]
public EkaerStatus Status { get; set; }
[ToonDescription(Purpose = "The generated NAV EKÁER tradeCard request XML exactly as it was (or will be) submitted — audit copy and source of the read-only detail view. Null until the first Generate.")]
public string? XmlDoc { get; set; }
[ToonDescription(Purpose = "The EKÁER number (TCN) assigned by NAV after a successful submission. Null until the declaration is accepted.")]
public string? EkaerNumber { get; set; }
[ToonDescription(Purpose = "When the declaration was successfully submitted to NAV. Null until sent.")]
public DateTime? SentDate { get; set; }
[ToonDescription(Purpose = "Validation or NAV submission error details for the ValidationError / SendError states. Null when the last operation succeeded.")]
public string? ErrorText { get; set; }
public DateTime Created { get; set; } public DateTime Created { get; set; }
public DateTime Modified { get; set; } public DateTime Modified { get; set; }
} }
/// <summary>Az EKÁER-bejelentés életciklus-állapota. Append-only: új érték a végére, meglévő értéke nem változhat (DB-ben int-ként tárolt).</summary>
public enum EkaerStatus
{
/// <summary>Automatikusan létrejött, még nem volt Generate.</summary>
Pending = 0,
/// <summary>A tradeCard XML legenerálva és valid — küldhető.</summary>
Generated = 1,
/// <summary>A Generate validációs hibákkal zárult (ErrorText) — a forrásadat javítandó.</summary>
ValidationError = 2,
/// <summary>NAV által befogadva (EkaerNumber + SentDate töltve).</summary>
Sent = 3,
/// <summary>A NAV-hívás hibával zárult (ErrorText) — újraküldhető.</summary>
SendError = 4,
}
//public sealed class EkaerHistoryShipping : EkaerHistoryBase //public sealed class EkaerHistoryShipping : EkaerHistoryBase
//{ //{
// public int ShippingId // public int ShippingId

View File

@ -28,6 +28,14 @@ public interface IFruitBankDataControllerCommon
public Task<PartnerDepot?> UpdatePartnerDepot(PartnerDepot partnerDepot); public Task<PartnerDepot?> UpdatePartnerDepot(PartnerDepot partnerDepot);
#endregion PartnerDepot #endregion PartnerDepot
#region EkaerHistory
public Task<List<EkaerHistory>?> GetEkaerHistories();
public Task<EkaerHistory?> GetEkaerHistoryById(int id);
public Task<List<EkaerHistory>?> GetEkaerHistoriesByForeignKey(int foreignKey);
public Task<EkaerHistory?> AddEkaerHistory(EkaerHistory ekaerHistory);
public Task<EkaerHistory?> UpdateEkaerHistory(EkaerHistory ekaerHistory);
#endregion EkaerHistory
#region CargoPartner #region CargoPartner
public Task<List<CargoPartner>?> GetCargoPartners(); public Task<List<CargoPartner>?> GetCargoPartners();
public Task<CargoPartner?> GetCargoPartnerById(int id); public Task<CargoPartner?> GetCargoPartnerById(int id);

View File

@ -0,0 +1,86 @@
@using AyCode.Blazor.Components.Components.Grids
@using AyCode.Core.Helpers
@using AyCode.Core.Interfaces
@using AyCode.Core.Loggers
@using AyCode.Services.Nav.Ekaer.Models
@using FruitBankHybrid.Shared.Services.Loggers
@using FruitBankHybrid.Shared.Services.SignalRs
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
@inject FruitBankSignalRClient FruitBankSignalRClient
@if (TradeCard != null)
{
@* Fejléc: csak a user-nek fontos, a mapper által ténylegesen töltött mezők. *@
<div style="display:grid; grid-template-columns:auto 1fr auto 1fr; gap:2px 12px; padding:8px 12px; font-size:0.85rem;">
<b>Irány:</b><span>@TradeCard.TradeType</span>
<b>Fuvarozó:</b><span>@TradeCard.CarrierText</span>
<b>Eladó:</b><span>@FormatParty(TradeCard.SellerName, TradeCard.SellerVatNumber, TradeCard.SellerAddress)</span>
<b>Címzett:</b><span>@FormatParty(TradeCard.DestinationName, TradeCard.DestinationVatNumber, TradeCard.DestinationAddress)</span>
<b>Felrakodás:</b><span>@FormatLocation(TradeCard.LoadLocation)</span>
<b>Lerakodás:</b><span>@FormatLocation(TradeCard.UnloadLocation)</span>
<b>Vontató:</b><span>@TradeCard.Vehicle?.PlateNumber</span>
<b>Pótkocsi:</b><span>@TradeCard.Vehicle2?.PlateNumber</span>
</div>
}
<MgGridWithInfoPanel ShowInfoPanel="false">
<GridContent>
<GridEkaerDetailBase @ref="Grid"
DataSource="TradeCardItems"
ParentDataItem="ParentDataItem"
SignalRClient="FruitBankSignalRClient"
AutoSaveLayoutName="GridEkaerDetail"
Logger="_logger"
CssClass="@GridCss"
ValidationEnabled="false">
<Columns>
<DxGridDataColumn FieldName="@nameof(TradeCardItemType.ItemExternalId)" Caption="Tétel az." ReadOnly="true" />
<DxGridDataColumn FieldName="@nameof(TradeCardItemType.TradeReason)" Caption="Jogcím" ReadOnly="true" />
<DxGridDataColumn FieldName="@nameof(TradeCardItemType.ProductVtsz)" Caption="VTSZ" ReadOnly="true" />
<DxGridDataColumn FieldName="@nameof(TradeCardItemType.ProductName)" Caption="Megnevezés" ReadOnly="true" />
<DxGridDataColumn FieldName="@nameof(TradeCardItemType.Weight)" Caption="Bruttó tömeg (kg)" ReadOnly="true" />
<DxGridDataColumn FieldName="@nameof(TradeCardItemType.Value)" Caption="Érték (HUF)" ReadOnly="true" />
</Columns>
</GridEkaerDetailBase>
</GridContent>
</MgGridWithInfoPanel>
@code {
[Parameter] public TradeCardType? TradeCard { get; set; }
[Parameter] public IId<int>? ParentDataItem { get; set; }
public GridEkaerDetailBase Grid { get; set; }
public bool IsMasterGrid => ParentDataItem == null;
string GridCss => !IsMasterGrid ? "hide-toolbar" : string.Empty;
private AcObservableCollection<TradeCardItemType> TradeCardItems = [];
private LoggerClient<GridEkaerDetail> _logger;
protected override void OnInitialized()
{
_logger = new LoggerClient<GridEkaerDetail>(LogWriters.ToArray());
}
protected override void OnParametersSet()
{
TradeCardItems = TradeCard?.Items is { } items ? new AcObservableCollection<TradeCardItemType>(items) : [];
}
private static string FormatParty(string? name, string? vatNumber, string? address)
{
var party = string.IsNullOrWhiteSpace(vatNumber) ? name : $"{name} ({vatNumber})";
return string.IsNullOrWhiteSpace(address) ? party ?? string.Empty : $"{party} — {address}";
}
private static string FormatLocation(LocationType? location)
{
if (location == null) return string.Empty;
return string.Join(" ", new[] { location.ZipCode, location.City, location.Street }.Where(p => !string.IsNullOrWhiteSpace(p)));
}
}

View File

@ -0,0 +1,19 @@
using AyCode.Services.Nav.Ekaer.Models;
using DevExpress.Blazor;
using FruitBankHybrid.Shared.Pages;
using Microsoft.AspNetCore.Components;
namespace FruitBankHybrid.Shared.Components.Grids.Ekaers;
/// <summary>
/// Readonly tétel-grid az EKÁER detail row-hoz: a generált tradeCard tételeit (<see cref="TradeCardItemType"/>)
/// mutatja, az <c>EkaerHistory.XmlDoc</c>-ból lokálisan deszerializálva. SZÁNDÉKOSAN nincs Get/Add/Update/Remove
/// tag — tag nélkül a grid readonly, a DataSource pedig lokális (nem SignalR-ből töltött).
/// A <see cref="TradeCardItemType"/> az IId&lt;int&gt;-et explicit partial-lal teljesíti (Id = ItemExternalId-ból számítva).
/// </summary>
public class GridEkaerDetailBase : FruitBankGridBase<TradeCardItemType>, IGrid
{
public GridEkaerDetailBase() : base()
{
}
}

View File

@ -0,0 +1,113 @@
@using AyCode.Blazor.Components.Components.Grids
@using AyCode.Core.Helpers
@using AyCode.Core.Interfaces
@using AyCode.Core.Loggers
@using AyCode.Services.Nav
@using AyCode.Services.Nav.Ekaer.Models
@using AyCode.Utils.Extensions
@using FruitBank.Common.Entities
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.Loggers
@using FruitBankHybrid.Shared.Services.SignalRs
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
@inject FruitBankSignalRClient FruitBankSignalRClient
<MgGridWithInfoPanel ShowInfoPanel="@IsMasterGrid">
<GridContent>
<GridEkaerHistoryBase @ref="Grid"
DataSource="EkaerHistories"
ParentDataItem="ParentDataItem"
AutoSaveLayoutName="GridEkaerHistory"
SignalRClient="FruitBankSignalRClient"
Logger="_logger"
CssClass="@GridCss"
ValidationEnabled="false"
OnGridFocusedRowChanged="Grid_FocusedRowChanged">
<Columns>
<DxGridDataColumn FieldName="Id" SortIndex="0" SortOrder="GridColumnSortOrder.Descending" ReadOnly="true" />
<DxGridDataColumn FieldName="@nameof(EkaerHistory.ForeignKey)" />
<DxGridDataColumn FieldName="@nameof(EkaerHistory.IsOutgoing)" />
<DxGridDataColumn FieldName="Created" ReadOnly="true" />
<DxGridDataColumn FieldName="Modified" ReadOnly="true" />
<DxGridCommandColumn Visible="!IsMasterGrid" Width="120"></DxGridCommandColumn>
</Columns>
<DetailRowTemplate>
@{
var ekaerHistory = (EkaerHistory)context.DataItem;
TradeCardType? tradeCard = null;
if (!string.IsNullOrWhiteSpace(ekaerHistory.XmlDoc))
{
try
{
tradeCard = NavXmlHelper.Deserialize<TradeCardType>(ekaerHistory.XmlDoc);
}
catch (Exception ex)
{
_logger.Error($"EkaerHistory XmlDoc deserialize error; id: {ekaerHistory.Id}", ex);
}
}
<GridEkaerDetail TradeCard="@tradeCard" ParentDataItem="@ekaerHistory"></GridEkaerDetail>
}
</DetailRowTemplate>
<ToolbarTemplate>
@if (IsMasterGrid)
{
@* EKÁER-rekordot a rendszer hoz létre (auto-rekord) — kézi new/edit/delete tiltva. *@
<MgGridToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" EnableNew="false" EnableEdit="false" EnableDelete="false" />
}
</ToolbarTemplate>
</GridEkaerHistoryBase>
</GridContent>
</MgGridWithInfoPanel>
@code {
[Inject] public required DatabaseClient Database { get; set; }
[Parameter] public AcObservableCollection<EkaerHistory>? EkaerHistories { get; set; }
const string ExportFileName = "ExportResult";
string GridSearchText = "";
bool EditItemsEnabled { get; set; }
int FocusedRowVisibleIndex { get; set; }
public GridEkaerHistoryBase Grid { get; set; }
string GridCss => !IsMasterGrid ? "hide-toolbar" : string.Empty;
[Parameter] public IId<int>? ParentDataItem { get; set; }
public bool IsMasterGrid => ParentDataItem == null;
private LoggerClient<GridEkaerHistory> _logger;
protected override async Task OnInitializedAsync()
{
_logger = new LoggerClient<GridEkaerHistory>(LogWriters.ToArray());
await ReloadDataFromDb(false);
}
private async Task ReloadDataFromDb(bool forceReload = false)
{
if (!IsMasterGrid) return;
if (Grid == null) return;
using (await ObjectLock.GetSemaphore<EkaerHistory>().UseWaitAsync())
if (forceReload) await Grid.ReloadDataSourceAsync();
if (forceReload) Grid.Reload();
}
async Task Grid_FocusedRowChanged(GridFocusedRowChangedEventArgs args)
{
if (Grid == null) return;
if (Grid.IsEditing() && !Grid.IsEditingNewRow())
await Grid.SaveChangesAsync();
FocusedRowVisibleIndex = args.VisibleIndex;
EditItemsEnabled = true;
}
}

View File

@ -0,0 +1,66 @@
using AyCode.Utils.Extensions;
using DevExpress.Blazor;
using FruitBank.Common.Entities;
using FruitBank.Common.SignalRs;
using FruitBankHybrid.Shared.Pages;
using Microsoft.AspNetCore.Components;
namespace FruitBankHybrid.Shared.Components.Grids.Ekaers;
public class GridEkaerHistoryBase : FruitBankGridBase<EkaerHistory>, IGrid
{
private bool _isFirstInitializeParameterCore;
private bool _isFirstInitializeParameters;
public GridEkaerHistoryBase() : base()
{
//GetAllMessageTag = SignalRTags.GetEkaerHistories;
AddMessageTag = SignalRTags.AddEkaerHistory;
UpdateMessageTag = SignalRTags.UpdateEkaerHistory;
//RemoveMessageTag = SignalRTags.;
}
protected override async Task OnInitializedAsync()
{
if (GetAllMessageTag > 0) return;
if (IsMasterGrid) GetAllMessageTag = SignalRTags.GetEkaerHistories;
else
{
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.
GetAllMessageTag = SignalRTags.GetEkaerHistoriesByForeignKey;
if (KeyFieldNameToParentId.IsNullOrWhiteSpace()) KeyFieldNameToParentId = nameof(EkaerHistory.ForeignKey);
}
await base.OnInitializedAsync();
}
protected override void OnParametersSet()
{
base.OnParametersSet();
if (!_isFirstInitializeParameters)
{
_isFirstInitializeParameters = false;
}
}
protected override async Task SetParametersAsyncCore(ParameterView parameters)
{
await base.SetParametersAsyncCore(parameters);
if (!_isFirstInitializeParameterCore)
{
//ShowFilterRow = true;
//ShowGroupPanel = true;
//AllowSort = false;
//etc...
_isFirstInitializeParameterCore = false;
}
}
}

View File

@ -1,5 +1,6 @@
@page "/Ekaer" @page "/Ekaer"
@using FruitBankHybrid.Shared.Components @using FruitBankHybrid.Shared.Components
@using FruitBankHybrid.Shared.Components.Grids.Ekaers
@using FruitBankHybrid.Shared.Databases @using FruitBankHybrid.Shared.Databases
<h3>EKÁER - Adminisztrátor</h3> <h3>EKÁER - Adminisztrátor</h3>
@ -15,10 +16,11 @@
<DxTabs ActiveTabIndexChanged="(i) => OnActiveTabChanged(i)" RenderMode="TabsRenderMode.OnDemand" AllowTabReorder="true"> <DxTabs ActiveTabIndexChanged="(i) => OnActiveTabChanged(i)" RenderMode="TabsRenderMode.OnDemand" AllowTabReorder="true">
<DxTabPage Text="Beküldésre váró"> <DxTabPage Text="Beküldésre váró">
@* A beküldésre váró EKÁER-ek grid-je ide kerül — külön feladat (kliens-metódus, szűrés). *@ @* TODO: "váró vs. elküldött" szűrés — az EkaerHistory-ban még nincs állapot-mező. *@
<GridEkaerHistory @ref="gridEkaerHistoryPending"></GridEkaerHistory>
</DxTabPage> </DxTabPage>
<DxTabPage Text="Elküldött"> <DxTabPage Text="Elküldött">
@* Az elküldött EKÁER-ek grid-je ide kerül — külön feladat (kliens-metódus, szűrés). *@ <GridEkaerHistory @ref="gridEkaerHistorySent"></GridEkaerHistory>
</DxTabPage> </DxTabPage>
</DxTabs> </DxTabs>
</DxLoadingPanel> </DxLoadingPanel>

View File

@ -1,5 +1,6 @@
using AyCode.Core.Loggers; using AyCode.Core.Loggers;
using FruitBank.Common.Models; using FruitBank.Common.Models;
using FruitBankHybrid.Shared.Components.Grids.Ekaers;
using FruitBankHybrid.Shared.Services.Loggers; using FruitBankHybrid.Shared.Services.Loggers;
using Mango.Nop.Core.Loggers; using Mango.Nop.Core.Loggers;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
@ -12,6 +13,9 @@ public partial class Ekaer : ComponentBase
[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; }
private GridEkaerHistory gridEkaerHistoryPending;
private GridEkaerHistory gridEkaerHistorySent;
private ILogger _logger = null!; private ILogger _logger = null!;
public int ActiveTabIndex; public int ActiveTabIndex;

View File

@ -73,6 +73,14 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
public Task<PartnerDepot?> UpdatePartnerDepot(PartnerDepot partnerDepot) => PostDataAsync(SignalRTags.UpdatePartnerDepot, partnerDepot); public Task<PartnerDepot?> UpdatePartnerDepot(PartnerDepot partnerDepot) => PostDataAsync(SignalRTags.UpdatePartnerDepot, partnerDepot);
#endregion PartnerDepot #endregion PartnerDepot
#region EkaerHistory
public Task<List<EkaerHistory>?> GetEkaerHistories() => GetAllAsync<List<EkaerHistory>>(SignalRTags.GetEkaerHistories);
public Task<EkaerHistory?> GetEkaerHistoryById(int id) => GetByIdAsync<EkaerHistory?>(SignalRTags.GetEkaerHistoryById, id);
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);
#endregion EkaerHistory
#region CargoPartner #region CargoPartner
public Task<List<CargoPartner>?> GetCargoPartners() => GetAllAsync<List<CargoPartner>>(SignalRTags.GetCargoPartners); public Task<List<CargoPartner>?> GetCargoPartners() => GetAllAsync<List<CargoPartner>>(SignalRTags.GetCargoPartners);
public Task<CargoPartner?> GetCargoPartnerById(int id) => GetByIdAsync<CargoPartner?>(SignalRTags.GetCargoPartnerById, id); public Task<CargoPartner?> GetCargoPartnerById(int id) => GetByIdAsync<CargoPartner?>(SignalRTags.GetCargoPartnerById, id);