Add PartnerDepot to ShippingDocument, EKÁER grid updates

- Introduced PartnerDepotId and PartnerDepot navigation to ShippingDocument and IShippingDocument, loaded only for EKÁER scenarios.
- Updated ShippingToEkaerMapper to leave CarrierName empty for outgoing shipments.
- Enhanced GridShippingDocument.razor: added PartnerDepot column with edit/display templates, improved Partner selection with cascade depot logic, and optimized partner lookup.
- Fixed Ekaer tab and count logic to use NeedsCompletion filter.
- Minor code and comment cleanups.
This commit is contained in:
Loretta 2026-06-16 12:02:24 +02:00
parent 47fd53cc4e
commit 2221d4a68e
7 changed files with 95 additions and 27 deletions

View File

@ -73,7 +73,8 @@
"WebFetch(domain:www.ekaer-feladas.hu)",
"WebFetch(domain:net.jogtar.hu)",
"WebFetch(domain:www.itrack.hu)",
"WebFetch(domain:docplayer.hu)"
"WebFetch(domain:docplayer.hu)",
"WebFetch(domain:supportcenter.devexpress.com)"
]
}
}

View File

@ -15,6 +15,7 @@ public sealed class ShippingDocument : MgEntityBase, IShippingDocument
{
public int PartnerId { get; set; }
public int? ShippingId { get; set; }
public int? PartnerDepotId { get; set; }
public string DocumentIdNumber { get; set; }
public string PdfFileName { get; set; }
@ -32,6 +33,12 @@ public sealed class ShippingDocument : MgEntityBase, IShippingDocument
[Association(ThisKey = nameof(PartnerId), OtherKey = nameof(Partner.Id), CanBeNull = true)]
public Partner? Partner { get; set; }
// Csak az EKÁER felrakodási címhez kell. SZÁNDÉKOSAN nincs benne semelyik alapértelmezett loadRelations-ben:
// kizárólag a generálás/reconciliation kéri explicit `LoadWith(sd => sd.PartnerDepot)`-tal, így a többi
// lekérdezést/sorosítást nem terheli (betöltetlenül null marad). Legacy szállítólevélnél PartnerDepotId = null.
[Association(ThisKey = nameof(PartnerDepotId), OtherKey = nameof(PartnerDepot.Id), CanBeNull = true)]
public PartnerDepot? PartnerDepot { get; set; }
[Association(ThisKey = nameof(Id), OtherKey = nameof(ShippingItem.ShippingDocumentId), CanBeNull = true)]
public List<ShippingItem>? ShippingItems { get; set; }

View File

@ -9,6 +9,7 @@ public interface IShippingDocument: IEntityInt, ITimeStampInfo//, IMeasured
{
public int PartnerId { get; set; }
public int? ShippingId { get; set; }
public int? PartnerDepotId { get; set; }
public string DocumentIdNumber { get; set; }
public string PdfFileName { get; set; }

View File

@ -147,8 +147,9 @@ public sealed class ShippingToEkaerMapper : IShippingToEkaerMapper
LoadLocation = company.Site,
UnloadLocation = BuildCustomerLocation(customer),
Lines = lines,
// Kimenőnél a VEVŐ veszi át / viszi el az árut → ő a fuvarozó.
CarrierName = customer?.Company,
// Kimenőnél NEM töltjük a szállítmányozót: a vevő maga viszi el, és a vevő MÁR a címzett (destinationName) —
// külön fuvarozót nem tartunk nyilván; a carrierText opcionális (a NAV nem követeli) → üresen hagyjuk.
CarrierName = null,
// A vonó jármű (rendszám) a customer-hez még nincs bekötve → üresen marad, a felrakodás megkezdéséig pótolandó
// (a validátor warningolja). Amint bekötik, a Vehicle is innen jön.
};

View File

@ -1,4 +1,4 @@
@using AyCode.Blazor.Components.Components.Grids
@using AyCode.Blazor.Components.Components.Grids
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@ -26,10 +26,23 @@
<Columns>
<MgGridDataColumn FieldName="Id" SortIndex="0" SortOrder="GridColumnSortOrder.Descending" ReadOnly="true"/>
<DxGridDataColumn FieldName="PartnerId" Caption="Partner" Visible="@(!ParentDataItemIsPartner)" ReadOnly="@ParentDataItemIsPartner">
<EditSettings>
<DxComboBoxSettings Data="Partners"
ValueFieldName="Id"
TextFieldName="Name"
<CellDisplayTemplate>
@{
var sdPd = (ShippingDocument)context.DataItem;
<text>@(PartnersDictById.GetValueOrDefault(sdPd.PartnerId)?.Name)</text>
}
</CellDisplayTemplate>
<CellEditTemplate>
@{
var sdPe = (ShippingDocument)context.EditModel;
}
<DxComboBox TData="Partner" TValue="int"
Data="@Partners"
Value="@sdPe.PartnerId"
ValueChanged="@((int v) => OnPartnerChanged(sdPe, v))"
ValueExpression="@(() => sdPe.PartnerId)"
ValueFieldName="@nameof(Partner.Id)"
TextFieldName="@nameof(Partner.Name)"
DropDownBodyCssClass="dd-body-class"
ListRenderMode="ListRenderMode.Entire"
SearchMode="ListSearchMode.AutoSearch"
@ -40,8 +53,36 @@
<DxListEditorColumn FieldName="@nameof(Partner.Name)" />
<DxListEditorColumn FieldName="@nameof(Partner.TaxId)" />
</Columns>
</DxComboBoxSettings>
</EditSettings>
</DxComboBox>
</CellEditTemplate>
</DxGridDataColumn>
<DxGridDataColumn FieldName="PartnerDepotId" Caption="Telephely">
<CellDisplayTemplate>
@{
var sdD = (ShippingDocument)context.DataItem;
var depotD = PartnersDictById.GetValueOrDefault(sdD.PartnerId)?.PartnerDepots?.FirstOrDefault(d => d.Id == sdD.PartnerDepotId);
<div style="text-align:left">@depotD?.Name</div>
}
</CellDisplayTemplate>
<CellEditTemplate>
@{
var sdE = (ShippingDocument)context.EditModel;
var depotsE = PartnersDictById.GetValueOrDefault(sdE.PartnerId)?.PartnerDepots ?? new List<PartnerDepot>();
}
<DxComboBox TData="PartnerDepot" TValue="int?"
Data="@depotsE"
@bind-Value="sdE.PartnerDepotId"
ValueFieldName="@nameof(PartnerDepot.Id)"
TextFieldName="@nameof(PartnerDepot.Name)"
NullText="(telephely…)"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
<Columns>
<DxListEditorColumn FieldName="@nameof(PartnerDepot.Name)" Caption="Név" />
<DxListEditorColumn FieldName="@nameof(PartnerDepot.FullAddress)" Caption="Cím" />
</Columns>
</DxComboBox>
</CellEditTemplate>
</DxGridDataColumn>
<DxGridDataColumn FieldName="Shipping.ShippingDate" Caption="Beérkezés" ReadOnly="true" />
<DxGridDataColumn FieldName="ShippingId" Caption="Shipping" Visible="@(!ParentDataItemIsShipping)" ReadOnly="@ParentDataItemIsShipping">
@ -185,6 +226,9 @@
private LoggerClient<GridShippingDocument> _logger = null!;
private int _activeTabIndex;
// Partner-lookup ID szerint a cella-templatekhez (a ReloadDataFromDb tölti) — renderenkénti lineáris keresés helyett.
private Dictionary<int, Partner> PartnersDictById = new();
protected override async Task OnInitializedAsync()
{
_logger = new LoggerClient<GridShippingDocument>(LogWriters.ToArray());
@ -223,9 +267,13 @@
{
if (Shippings == null && ParentDataItem is Shipping shippingParent) Shippings = [shippingParent];
if (Partners == null && ParentDataItem is Partner partnerParent) Partners = [partnerParent];
return;
}
// Partner-lookup ID szerint a cella-templatekhez (O(1) a renderenkénti FirstOrDefault helyett), a Partners véglegesülése után.
PartnersDictById = Partners?.ToDictionary(p => p.Id) ?? new();
if (!IsMasterGrid) return;
if (Grid == null) return;
using (await ObjectLock.GetSemaphore<ShippingDocument>().UseWaitAsync())
@ -269,6 +317,16 @@
EditItemsEnabled = true;
}
// Cascade: a Partner-combo ValueChanged-je. Beírjuk az új partnert; ha a partnernek PONTOSAN EGY telephelye van,
// arra auto-állunk, különben nullázzuk (a régi nem az új partneré); majd újrarenderelünk → a Telephely-combo frissül.
void OnPartnerChanged(ShippingDocument sd, int partnerId)
{
sd.PartnerId = partnerId;
var depots = PartnersDictById.GetValueOrDefault(partnerId)?.PartnerDepots;
sd.PartnerDepotId = depots?.Count == 1 ? depots[0].Id : null;
StateHasChanged();
}
protected async Task OnActiveTabChanged(int activeTabIndex)
{
_activeTabIndex = activeTabIndex;

View File

@ -20,7 +20,7 @@
<GridEkaerHistory @ref="gridEkaerHistoryPending" Filter="EkaerHistoryFilter.ToSubmit" OnDataChanged="RefreshNeedsCompletionCountAsync" OnBusyChanged="OnGridBusyChanged"></GridEkaerHistory>
</DxTabPage>
<DxTabPage Text="@NeedsCompletionTabText">
<GridEkaerHistory @ref="gridEkaerHistoryNeedsCompletion" Filter="EkaerHistoryFilter.ToSubmit" OnDataChanged="RefreshNeedsCompletionCountAsync" OnBusyChanged="OnGridBusyChanged"></GridEkaerHistory>
<GridEkaerHistory @ref="gridEkaerHistoryNeedsCompletion" Filter="EkaerHistoryFilter.NeedsCompletion" OnDataChanged="RefreshNeedsCompletionCountAsync" OnBusyChanged="OnGridBusyChanged"></GridEkaerHistory>
</DxTabPage>
<DxTabPage Text="Elküldött">
<GridEkaerHistory @ref="gridEkaerHistorySent" Filter="EkaerHistoryFilter.Sent" OnDataChanged="RefreshNeedsCompletionCountAsync" OnBusyChanged="OnGridBusyChanged"></GridEkaerHistory>

View File

@ -58,8 +58,8 @@ public partial class Ekaer : ComponentBase
{
try
{
//_needsCompletionCount = await FruitBankSignalRClient.GetEkaerHistoryCount(EkaerHistoryFilter.NeedsCompletion);
_needsCompletionCount = await FruitBankSignalRClient.GetEkaerHistoryCount(EkaerHistoryFilter.ToSubmit);
_needsCompletionCount = await FruitBankSignalRClient.GetEkaerHistoryCount(EkaerHistoryFilter.NeedsCompletion);
//_needsCompletionCount = await FruitBankSignalRClient.GetEkaerHistoryCount(EkaerHistoryFilter.ToSubmit);
StateHasChanged();
}
catch (Exception ex)