257 lines
9.8 KiB
Plaintext
257 lines
9.8 KiB
Plaintext
@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
|
|
@inject IJSRuntime JS
|
|
|
|
<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)" ReadOnly="true" />
|
|
<DxGridDataColumn FieldName="@nameof(EkaerHistory.IsOutgoing)" 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" />
|
|
<DxGridDataColumn FieldName="@nameof(EkaerHistory.SentDate)" DisplayFormat="yyyy.MM.dd HH:mm" />
|
|
@* Audit: a value-számításhoz alkalmazott árfolyam (HUF feladónál 1). ReadOnly — generáláskor töltődik. *@
|
|
<DxGridDataColumn FieldName="@nameof(EkaerHistory.ConversionRate)" Caption="Árfolyam" ReadOnly="true" DisplayFormat="0.00##" />
|
|
<DxGridDataColumn FieldName="@nameof(EkaerHistory.ErrorText)" Caption="Hiba" ReadOnly="true">
|
|
<CellDisplayTemplate>
|
|
@if (!string.IsNullOrWhiteSpace(context.DisplayText))
|
|
{
|
|
<span title="@context.DisplayText">
|
|
<span aria-hidden="true" style="font-size:1.2em; margin-right:3px;">⚠️</span>@context.DisplayText
|
|
</span>
|
|
}
|
|
</CellDisplayTemplate>
|
|
</DxGridDataColumn>
|
|
|
|
<DxGridDataColumn FieldName="Created" ReadOnly="true" DisplayFormat="yyyy.MM.dd HH:mm" />
|
|
<DxGridDataColumn FieldName="Modified" ReadOnly="true" DisplayFormat="yyyy.MM.dd HH:mm" />
|
|
<DxGridDataColumn Caption="Műveletek" Width="200" AllowSort="false" AllowGroup="false">
|
|
<CellDisplayTemplate>
|
|
@{
|
|
var row = (EkaerHistory)context.DataItem;
|
|
<DxButton Text="Generate"
|
|
SizeMode="SizeMode.Small"
|
|
RenderStyle="ButtonRenderStyle.Primary"
|
|
Enabled="@(CanGenerate(row))"
|
|
Attributes="@(new Dictionary<string, object> { ["title"] = row.ErrorText ?? "EKÁER XML generálása és validálása" })"
|
|
Click="async () => await OnGenerateClick(row)" />
|
|
<DxButton Text="Copy"
|
|
SizeMode="SizeMode.Small"
|
|
RenderStyle="ButtonRenderStyle.Secondary"
|
|
Enabled="@(CanCopy(row))"
|
|
Attributes="@(new Dictionary<string, object> { ["title"] = CanCopy(row) ? "A generált XML vágólapra másolása (kézi NAV-beadáshoz)" : "Hibás bejelentés nem másolható — javítsd az adatokat és generáld újra." })"
|
|
Click="async () => await OnCopyClick(row)" />
|
|
}
|
|
</CellDisplayTemplate>
|
|
</DxGridDataColumn>
|
|
<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-rekord a toolbar "sorok létrehozása" gombbal készül (new/delete tiltva — nincs automata
|
|
érzékelés, a létrehozás explicit és idempotens). Az Edit a kézi NAV-beadás fázisában
|
|
engedélyezett: Status / EKÁER szám / SentDate kézi rögzítéséhez. *@
|
|
<MgGridToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" EnableNew="false" EnableEdit="true" EnableDelete="false">
|
|
<ToolbarItemsExtended>
|
|
@* A dátumválasztó editor csak Template-ben mehet toolbarba; a gomb natív DxToolbarItem,
|
|
hogy a toolbar stílusát/igazítását kapja (lásd: "Ai process..." minta a GridShippingDocument-ben). *@
|
|
@* dxbl-toolbar-edit: a DevExpress téma saját opt-in osztálya editor-t hordozó toolbar-itemre —
|
|
ettől kapja a beépített középre igazítást és a toolbarba simuló editor-stílust. *@
|
|
<DxToolbarItem BeginGroup="true" CssClass="dxbl-toolbar-edit ekaer-create-from-date-item">
|
|
<Template Context="toolbarItemContext">
|
|
<DxDateEdit @bind-Date="CreateFromDate"
|
|
Format="yyyy.MM.dd"
|
|
MinDate="@DateTime.Today.AddDays(-7)"
|
|
MaxDate="@DateTime.Today"
|
|
CssClass="ekaer-create-from-date" />
|
|
</Template>
|
|
</DxToolbarItem>
|
|
<DxToolbarItem Text="EKÁER sorok létrehozása"
|
|
Enabled="@(!_creatingMissing)"
|
|
Tooltip="A választott dátumtól kezdődő, rekord nélküli szállítólevelekre/rendelésekre Pending sort hoz létre (idempotens)."
|
|
Click="OnCreateMissingClick">
|
|
</DxToolbarItem>
|
|
</ToolbarItemsExtended>
|
|
</MgGridToolbarTemplate>
|
|
}
|
|
</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;
|
|
}
|
|
|
|
private readonly HashSet<int> _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).
|
|
// 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 && !_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)
|
|
=> !string.IsNullOrWhiteSpace(ekaerHistory.XmlDoc) && string.IsNullOrWhiteSpace(ekaerHistory.ErrorText);
|
|
|
|
private async Task OnGenerateClick(EkaerHistory ekaerHistory)
|
|
{
|
|
if (!_generatingIds.Add(ekaerHistory.Id)) return;
|
|
|
|
try
|
|
{
|
|
var updated = await FruitBankSignalRClient.GenerateEkaerXmlDocument(ekaerHistory.ForeignKey, ekaerHistory.IsOutgoing);
|
|
|
|
if (updated == null)
|
|
{
|
|
_logger.Error($"GenerateEkaerXmlDocument null választ adott; ForeignKey: {ekaerHistory.ForeignKey}");
|
|
return;
|
|
}
|
|
|
|
// A sor frissítése helyben — a grid ugyanazt a példányt mutatja.
|
|
ekaerHistory.Status = updated.Status;
|
|
ekaerHistory.XmlDoc = updated.XmlDoc;
|
|
ekaerHistory.ConversionRate = updated.ConversionRate;
|
|
ekaerHistory.ErrorText = updated.ErrorText;
|
|
ekaerHistory.EkaerNumber = updated.EkaerNumber;
|
|
ekaerHistory.SentDate = updated.SentDate;
|
|
ekaerHistory.Modified = updated.Modified;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error($"GenerateEkaerXmlDocument hiba; ForeignKey: {ekaerHistory.ForeignKey}", ex);
|
|
}
|
|
finally
|
|
{
|
|
_generatingIds.Remove(ekaerHistory.Id);
|
|
Grid?.Reload();
|
|
}
|
|
}
|
|
|
|
DateTime CreateFromDate { get; set; } = DateTime.Today.AddDays(-3);
|
|
private bool _creatingMissing;
|
|
|
|
private async Task OnCreateMissingClick()
|
|
{
|
|
if (_creatingMissing) return;
|
|
_creatingMissing = true;
|
|
|
|
try
|
|
{
|
|
var createdCount = await FruitBankSignalRClient.CreateMissingEkaerHistories(CreateFromDate);
|
|
_logger.Info($"CreateMissingEkaerHistories; created: {createdCount}; fromDate: {CreateFromDate:yyyy.MM.dd}");
|
|
|
|
if (createdCount > 0) await ReloadDataFromDb(true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error($"CreateMissingEkaerHistories hiba; fromDate: {CreateFromDate:yyyy.MM.dd}", ex);
|
|
}
|
|
finally
|
|
{
|
|
_creatingMissing = false;
|
|
}
|
|
}
|
|
|
|
private async Task OnCopyClick(EkaerHistory ekaerHistory)
|
|
{
|
|
if (!CanCopy(ekaerHistory)) return;
|
|
|
|
try
|
|
{
|
|
await JS.InvokeVoidAsync("navigator.clipboard.writeText", ekaerHistory.XmlDoc);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error($"XmlDoc vágólapra másolása sikertelen; EkaerHistory.Id: {ekaerHistory.Id}", ex);
|
|
}
|
|
}
|
|
}
|