Add CargoPartner/CargoTruck entities and logistics links
Introduced CargoPartner and CargoTruck entities for logistics, updated Shipping and IShipping to link to carrier and vehicles, and enhanced UI grids for selection and validation. Updated documentation and glossary to reflect new logistics model and terminology. Removed obsolete Shippings navigation from CargoPartner.
This commit is contained in:
parent
c9b0bf8334
commit
3cb5efe2d2
|
|
@ -7,7 +7,7 @@ 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("Transport / haulage company (carrier) with its vehicle fleet", Purpose = "A carrier that delivers goods to the warehouse and owns the CargoTrucks (both trucks and trailers). Distinct from Partner, which is the goods supplier. Name, address and tax fields are inherited from PartnerBase.")]
|
||||||
[Table(Name = FruitBankConstClient.CargoPartnerDbTableName)]
|
[Table(Name = FruitBankConstClient.CargoPartnerDbTableName)]
|
||||||
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.CargoPartnerDbTableName)]
|
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.CargoPartnerDbTableName)]
|
||||||
public sealed class CargoPartner : PartnerBase, ICargoPartner
|
public sealed class CargoPartner : PartnerBase, ICargoPartner
|
||||||
|
|
@ -16,6 +16,5 @@ public sealed class CargoPartner : PartnerBase, ICargoPartner
|
||||||
public List<CargoTruck>? CargoTrucks { get; set; }
|
public List<CargoTruck>? CargoTrucks { get; set; }
|
||||||
|
|
||||||
//[Association(ThisKey = nameof(Id), OtherKey = nameof(Shipping.CargoPartnerId), CanBeNull = true)]
|
//[Association(ThisKey = nameof(Id), OtherKey = nameof(Shipping.CargoPartnerId), CanBeNull = true)]
|
||||||
public List<Shipping>? Shippings { get; set; }
|
//public List<Shipping>? Shippings { get; set; }
|
||||||
//public decimal DecProp{get; set; }
|
|
||||||
}
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -11,6 +11,11 @@ Domain entities for inbound/outbound goods tracking and inventory. All map to `f
|
||||||
- **`ShippingDocumentToFiles.cs`** — Many-to-many link: document ↔ file with DocumentType. Table: `fbShippingDocumentToFiles`.
|
- **`ShippingDocumentToFiles.cs`** — Many-to-many link: document ↔ file with DocumentType. Table: `fbShippingDocumentToFiles`.
|
||||||
- **`Partner.cs`** — External supplier with address and tax info. Table: `fbPartner`.
|
- **`Partner.cs`** — External supplier with address and tax info. Table: `fbPartner`.
|
||||||
|
|
||||||
|
## Cargo / Logistics
|
||||||
|
|
||||||
|
- **`CargoPartner.cs`** — Freight/haulage partner (carrier). Distinct from `Partner` (supplier) — this is the transport side. Has `CargoTrucks` and `Shippings` collections. Table: `fbCargoPartner`.
|
||||||
|
- **`CargoTruck.cs`** — Individual truck belonging to a `CargoPartner` (`LicencePlate`, `CountryCode`, `IsTrailer` for trailers). Table: `fbCargoTruck`.
|
||||||
|
|
||||||
## Order (Outbound)
|
## Order (Outbound)
|
||||||
|
|
||||||
- **`OrderItemPallet.cs`** — Measurement record for outgoing goods with RevisorId for audit. Table: `fbOrderItemPallet`.
|
- **`OrderItemPallet.cs`** — Measurement record for outgoing goods with RevisorId for audit. Table: `fbOrderItemPallet`.
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ namespace FruitBank.Common.Entities;
|
||||||
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingDbTableName)]
|
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingDbTableName)]
|
||||||
public sealed class Shipping : MgEntityBase, IShipping, IEntityComment
|
public sealed class Shipping : MgEntityBase, IShipping, IEntityComment
|
||||||
{
|
{
|
||||||
|
public int CargoPartnerId { get; set; }
|
||||||
|
public int? CargoTruckId { get; set; }
|
||||||
|
public int? CargoTrailerId { get; set; }
|
||||||
|
|
||||||
public DateTime ShippingDate { get; set; } = DateTime.Now;
|
public DateTime ShippingDate { get; set; } = DateTime.Now;
|
||||||
public string LicencePlate { get; set; }
|
public string LicencePlate { get; set; }
|
||||||
public bool IsAllMeasured { get; set; }
|
public bool IsAllMeasured { get; set; }
|
||||||
|
|
@ -21,6 +25,18 @@ public sealed class Shipping : MgEntityBase, IShipping, IEntityComment
|
||||||
|
|
||||||
public DateTime? MeasuredDate { get; set; }
|
public DateTime? MeasuredDate { get; set; }
|
||||||
|
|
||||||
|
[ToonDescription(Purpose = "The transport company (carrier) that hauled this delivery — distinct from the goods supplier, which is reached via ShippingDocument.Partner.")]
|
||||||
|
[Association(ThisKey = nameof(CargoPartnerId), OtherKey = nameof(CargoPartner.Id), CanBeNull = true)]
|
||||||
|
public CargoPartner CargoPartner { get; set; }
|
||||||
|
|
||||||
|
[ToonDescription(Purpose = "The tractor/truck unit — a CargoTruck row with IsTrailer=false.")]
|
||||||
|
[Association(ThisKey = nameof(CargoTruckId), OtherKey = nameof(CargoTruck.Id), CanBeNull = true)]
|
||||||
|
public CargoTruck CargoTruck { get; set; }
|
||||||
|
|
||||||
|
[ToonDescription(Purpose = "The trailer — the SAME CargoTruck table as CargoTruck, but the row with IsTrailer=true (CargoTrailerId → CargoTruck.Id).")]
|
||||||
|
[Association(ThisKey = nameof(CargoTrailerId), OtherKey = nameof(CargoTruck.Id), CanBeNull = true)]
|
||||||
|
public CargoTruck CargoTrailer { get; set; }
|
||||||
|
|
||||||
[Association(ThisKey = nameof(Id), OtherKey = nameof(ShippingDocument.ShippingId), CanBeNull = true)]
|
[Association(ThisKey = nameof(Id), OtherKey = nameof(ShippingDocument.ShippingId), CanBeNull = true)]
|
||||||
public List<ShippingDocument>? ShippingDocuments { get; set; }
|
public List<ShippingDocument>? ShippingDocuments { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,6 @@ public interface ICargoTruck : IEntityInt, ITimeStampInfo
|
||||||
public string LicencePlate { get; set; }
|
public string LicencePlate { get; set; }
|
||||||
|
|
||||||
public bool IsTrailer { get; set; }
|
public bool IsTrailer { get; set; }
|
||||||
|
|
||||||
|
public string? CargoPartnerName { get; }
|
||||||
}
|
}
|
||||||
|
|
@ -6,6 +6,10 @@ namespace FruitBank.Common.Interfaces;
|
||||||
|
|
||||||
public interface IShipping : IEntityInt, ITimeStampInfo//, IMeasured
|
public interface IShipping : IEntityInt, ITimeStampInfo//, IMeasured
|
||||||
{
|
{
|
||||||
|
public int CargoPartnerId { get; set; }
|
||||||
|
public int? CargoTruckId { get; set; }
|
||||||
|
public int? CargoTrailerId { get; set; }
|
||||||
|
|
||||||
DateTime ShippingDate { get; set; }
|
DateTime ShippingDate { get; set; }
|
||||||
string LicencePlate { get; set; }
|
string LicencePlate { get; set; }
|
||||||
bool IsAllMeasured { get; set; }
|
bool IsAllMeasured { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
@if (IsMasterGrid)
|
@if (IsMasterGrid)
|
||||||
{
|
{
|
||||||
var cargoPartner = ((CargoPartner)context.DataItem);
|
var cargoPartner = ((CargoPartner)context.DataItem);
|
||||||
var shippings = cargoPartner?.Shippings ?? [];
|
var shippings = new AcObservableCollection<Shipping>(); //cargoPartner?.Shippings ?? [];
|
||||||
var cargoTrucks = cargoPartner?.CargoTrucks ?? [];
|
var cargoTrucks = cargoPartner?.CargoTrucks ?? [];
|
||||||
|
|
||||||
<DxTabs>
|
<DxTabs>
|
||||||
|
|
@ -56,13 +56,13 @@
|
||||||
}
|
}
|
||||||
</DxTabPage>
|
</DxTabPage>
|
||||||
|
|
||||||
<DxTabPage Text="Szállítmányok">
|
@* <DxTabPage Text="Szállítmányok">
|
||||||
@{
|
@{
|
||||||
var observableShippings = new AcObservableCollection<Shipping>(shippings);
|
//var observableShippings = new AcObservableCollection<Shipping>(shippings);
|
||||||
<GridShipping Shippings="@observableShippings" IsMasterGrid="false" />
|
<GridShipping Shippings="@shippings" IsMasterGrid="false" />
|
||||||
}
|
}
|
||||||
</DxTabPage>
|
</DxTabPage>
|
||||||
</DxTabs>
|
*@ </DxTabs>
|
||||||
}
|
}
|
||||||
</DetailRowTemplate>
|
</DetailRowTemplate>
|
||||||
<ToolbarTemplate>
|
<ToolbarTemplate>
|
||||||
|
|
@ -83,6 +83,7 @@
|
||||||
[Parameter] public AcObservableCollection<CargoPartner>? CargoPartners { get; set; }
|
[Parameter] public AcObservableCollection<CargoPartner>? CargoPartners { get; set; }
|
||||||
[Parameter] public AcObservableCollection<Shipping>? Shippings { get; set; }
|
[Parameter] public AcObservableCollection<Shipping>? Shippings { get; set; }
|
||||||
|
|
||||||
|
|
||||||
const string ExportFileName = "ExportResult";
|
const string ExportFileName = "ExportResult";
|
||||||
string GridSearchText = "";
|
string GridSearchText = "";
|
||||||
bool EditItemsEnabled { get; set; }
|
bool EditItemsEnabled { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
@using FruitBank.Common.Entities
|
@using FruitBank.Common.Entities
|
||||||
@using FruitBankHybrid.Shared.Components.Grids.Shippings
|
@using FruitBankHybrid.Shared.Components.Grids.Shippings
|
||||||
@using FruitBankHybrid.Shared.Databases
|
@using FruitBankHybrid.Shared.Databases
|
||||||
|
@using FruitBankHybrid.Shared.Extensions
|
||||||
@using FruitBankHybrid.Shared.Services.Loggers
|
@using FruitBankHybrid.Shared.Services.Loggers
|
||||||
@using FruitBankHybrid.Shared.Services.SignalRs
|
@using FruitBankHybrid.Shared.Services.SignalRs
|
||||||
|
|
||||||
|
|
@ -19,11 +20,68 @@
|
||||||
<GridContent>
|
<GridContent>
|
||||||
<GridShippingBase @ref="Grid" DataSource="Shippings" AutoSaveLayoutName="GridShipping" SignalRClient="FruitBankSignalRClient" Logger="_logger"
|
<GridShippingBase @ref="Grid" DataSource="Shippings" AutoSaveLayoutName="GridShipping" SignalRClient="FruitBankSignalRClient" Logger="_logger"
|
||||||
CssClass="@GridCss" ValidationEnabled="false"
|
CssClass="@GridCss" ValidationEnabled="false"
|
||||||
|
OnGridEditModelSaving="Grid_EditModelSaving"
|
||||||
OnGridFocusedRowChanged="Grid_FocusedRowChanged">
|
OnGridFocusedRowChanged="Grid_FocusedRowChanged">
|
||||||
<Columns>
|
<Columns>
|
||||||
<DxGridDataColumn FieldName="Id" SortIndex="0" SortOrder="GridColumnSortOrder.Descending" ReadOnly="true" />
|
<DxGridDataColumn FieldName="Id" SortIndex="0" SortOrder="GridColumnSortOrder.Descending" ReadOnly="true" />
|
||||||
|
<DxGridDataColumn FieldName="ShippingDate" Caption="Beérkezés" />
|
||||||
|
<DxGridDataColumn FieldName="CargoPartnerId" Caption="Fuvarozó">
|
||||||
|
<EditSettings>
|
||||||
|
<DxComboBoxSettings Data="CargoPartners"
|
||||||
|
ValueFieldName="Id"
|
||||||
|
TextFieldName="Name"
|
||||||
|
DropDownBodyCssClass="dd-body-class"
|
||||||
|
ListRenderMode="ListRenderMode.Entire"
|
||||||
|
SearchMode="ListSearchMode.AutoSearch"
|
||||||
|
SearchFilterCondition="ListSearchFilterCondition.Contains"
|
||||||
|
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
|
||||||
|
<Columns>
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoPartner.Id)" />
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoPartner.Name)" />
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoPartner.TaxId)" />
|
||||||
|
</Columns>
|
||||||
|
</DxComboBoxSettings>
|
||||||
|
</EditSettings>
|
||||||
|
</DxGridDataColumn>
|
||||||
|
<DxGridDataColumn FieldName="CargoTruckId" Caption="Vontató">
|
||||||
|
<EditSettings>
|
||||||
|
<DxComboBoxSettings Data="CargoTrucks.Where(x => !x.IsTrailer)"
|
||||||
|
ValueFieldName="Id"
|
||||||
|
TextFieldName="LicencePlate"
|
||||||
|
DropDownBodyCssClass="dd-body-class"
|
||||||
|
ListRenderMode="ListRenderMode.Entire"
|
||||||
|
SearchMode="ListSearchMode.AutoSearch"
|
||||||
|
SearchFilterCondition="ListSearchFilterCondition.Contains"
|
||||||
|
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
|
||||||
|
<Columns>
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoTruck.Id)" />
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoTruck.CargoPartnerName)" />
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoTruck.LicencePlate)" />
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoTruck.IsTrailer)" />
|
||||||
|
</Columns>
|
||||||
|
</DxComboBoxSettings>
|
||||||
|
</EditSettings>
|
||||||
|
</DxGridDataColumn>
|
||||||
|
<DxGridDataColumn FieldName="CargoTrailerId" Caption="Utánfutó">
|
||||||
|
<EditSettings>
|
||||||
|
<DxComboBoxSettings Data="CargoTrucks.Where(x => x.IsTrailer)"
|
||||||
|
ValueFieldName="Id"
|
||||||
|
TextFieldName="LicencePlate"
|
||||||
|
DropDownBodyCssClass="dd-body-class"
|
||||||
|
ListRenderMode="ListRenderMode.Entire"
|
||||||
|
SearchMode="ListSearchMode.AutoSearch"
|
||||||
|
SearchFilterCondition="ListSearchFilterCondition.Contains"
|
||||||
|
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
|
||||||
|
<Columns>
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoTruck.Id)" />
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoTruck.CargoPartnerName)" />
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoTruck.LicencePlate)" />
|
||||||
|
<DxListEditorColumn FieldName="@nameof(CargoTruck.IsTrailer)" />
|
||||||
|
</Columns>
|
||||||
|
</DxComboBoxSettings>
|
||||||
|
</EditSettings>
|
||||||
|
</DxGridDataColumn>
|
||||||
|
|
||||||
<DxGridDataColumn FieldName="ShippingDate" Caption="Beérkezés"/>
|
|
||||||
<DxGridDataColumn FieldName="LicencePlate" Caption="Rendszám" />
|
<DxGridDataColumn FieldName="LicencePlate" Caption="Rendszám" />
|
||||||
<DxGridDataColumn FieldName="Comment" Caption="Megjegyzés" ReadOnly="false" />
|
<DxGridDataColumn FieldName="Comment" Caption="Megjegyzés" ReadOnly="false" />
|
||||||
<DxGridDataColumn FieldName="CargoCompany" Caption="Fuvarozó" ReadOnly="false" />
|
<DxGridDataColumn FieldName="CargoCompany" Caption="Fuvarozó" ReadOnly="false" />
|
||||||
|
|
@ -71,7 +129,11 @@
|
||||||
|
|
||||||
[Parameter] public bool IsMasterGrid { get; set; } = false;
|
[Parameter] public bool IsMasterGrid { get; set; } = false;
|
||||||
[Parameter] public AcObservableCollection<Partner>? Partners { get; set; }
|
[Parameter] public AcObservableCollection<Partner>? Partners { get; set; }
|
||||||
|
[Parameter] public AcObservableCollection<CargoPartner>? CargoPartners { get; set; }
|
||||||
[Parameter] public AcObservableCollection<Shipping>? Shippings { get; set; }
|
[Parameter] public AcObservableCollection<Shipping>? Shippings { get; set; }
|
||||||
|
[Inject] public required IDialogService DialogService { get; set; } = null!;
|
||||||
|
|
||||||
|
public List<CargoTruck> CargoTrucks { get; set; } = [];
|
||||||
|
|
||||||
const string ExportFileName = "ExportResult";
|
const string ExportFileName = "ExportResult";
|
||||||
string GridSearchText = "";
|
string GridSearchText = "";
|
||||||
|
|
@ -91,6 +153,23 @@
|
||||||
|
|
||||||
private async Task ReloadDataFromDb(bool forceReload = false)
|
private async Task ReloadDataFromDb(bool forceReload = false)
|
||||||
{
|
{
|
||||||
|
using (await ObjectLock.GetSemaphore<CargoPartner>().UseWaitAsync())
|
||||||
|
{
|
||||||
|
if (CargoPartners == null) CargoPartners = new AcObservableCollection<CargoPartner>(await FruitBankSignalRClient.GetCargoPartners() ?? []);
|
||||||
|
else if (CargoPartners.Count == 0 || forceReload)
|
||||||
|
{
|
||||||
|
CargoPartners.Replace(await FruitBankSignalRClient.GetCargoPartners() ?? []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CargoTrucks = CargoPartners.Where(x => x.CargoTrucks != null).SelectMany(x =>
|
||||||
|
{
|
||||||
|
if (x.CargoTrucks == null) return null;
|
||||||
|
|
||||||
|
foreach (var cargoTruck in x.CargoTrucks) cargoTruck.CargoPartner = x;
|
||||||
|
return x.CargoTrucks;
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
if (!IsMasterGrid) return;
|
if (!IsMasterGrid) return;
|
||||||
|
|
||||||
using (await ObjectLock.GetSemaphore<Partner>().UseWaitAsync())
|
using (await ObjectLock.GetSemaphore<Partner>().UseWaitAsync())
|
||||||
|
|
@ -121,7 +200,23 @@
|
||||||
EditItemsEnabled = true;
|
EditItemsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task OnActiveTabChanged(int activeTabIndex)
|
async Task Grid_EditModelSaving(GridEditModelSavingEventArgs e)
|
||||||
|
{
|
||||||
|
var shipping = (Shipping)e.EditModel; // a szerkesztett sor
|
||||||
|
|
||||||
|
if (ValidateCargoConsistency(shipping, out string error)) return;
|
||||||
|
|
||||||
|
e.Cancel = true;
|
||||||
|
await DialogService.ShowMessageBoxAsync("Hibás adat", error, MessageBoxRenderStyle.Danger);
|
||||||
|
// e.IsNew → add vs update
|
||||||
|
|
||||||
|
// ... before-save logika (validáció, számított mezők, CargoTrailer beállítás stb.)
|
||||||
|
|
||||||
|
// megszakítás, ha kell:
|
||||||
|
// e.Cancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async protected Task OnActiveTabChanged(int activeTabIndex)
|
||||||
{
|
{
|
||||||
_activeTabIndex = activeTabIndex;
|
_activeTabIndex = activeTabIndex;
|
||||||
return;
|
return;
|
||||||
|
|
@ -142,5 +237,29 @@
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ValidateCargoConsistency(Shipping shipping, out string? error)
|
||||||
|
{
|
||||||
|
error = null;
|
||||||
|
|
||||||
|
if (shipping.CargoTruckId != null)
|
||||||
|
{
|
||||||
|
var truck = CargoTrucks.FirstOrDefault(t => t.Id == shipping.CargoTruckId);
|
||||||
|
if (truck == null || truck.CargoPartnerId != shipping.CargoPartnerId)
|
||||||
|
{
|
||||||
|
error = $"A vontató ({truck?.LicencePlate}) nem a kiválasztott fuvarozóhoz tartozik!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shipping.CargoTrailerId == null) return true;
|
||||||
|
|
||||||
|
var trailer = CargoTrucks.FirstOrDefault(t => t.Id == shipping.CargoTrailerId);
|
||||||
|
if (trailer != null && trailer.CargoPartnerId == shipping.CargoPartnerId) return true;
|
||||||
|
|
||||||
|
error = $"Az utánfutó ({trailer?.LicencePlate}) nem a kiválasztott fuvarozóhoz tartozik!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ Domain terminology for the FruitBank system. **Read this before making changes.*
|
||||||
| **Order** | Megrendelés | **OUTBOUND** delivery: warehouse → customer. |
|
| **Order** | Megrendelés | **OUTBOUND** delivery: warehouse → customer. |
|
||||||
| **Pallet** (XxxItemPallet) | Mérési rekord | A **measurement record**, NOT a physical pallet. Always created, even for non-measurable products. |
|
| **Pallet** (XxxItemPallet) | Mérési rekord | A **measurement record**, NOT a physical pallet. Always created, even for non-measurable products. |
|
||||||
| **Partner** | Partner / Beszállító | External supplier providing goods. |
|
| **Partner** | Partner / Beszállító | External supplier providing goods. |
|
||||||
|
| **CargoPartner** | Fuvarozó | Freight carrier company that transports goods. **Distinct from Partner** (supplier). |
|
||||||
|
| **CargoTruck** | Kamion | A specific truck belonging to a CargoPartner (licence plate, trailer flag). |
|
||||||
| **ShippingDocument** | Szállítólevél | Supplier's delivery note or invoice, linked to a Shipping. |
|
| **ShippingDocument** | Szállítólevél | Supplier's delivery note or invoice, linked to a Shipping. |
|
||||||
| **ShippingItem** | Szállítólevél tétel | Product line on a shipping document. Tracks declared vs measured discrepancies. |
|
| **ShippingItem** | Szállítólevél tétel | Product line on a shipping document. Tracks declared vs measured discrepancies. |
|
||||||
| **StockTaking** | Leltározás | Inventory session that freezes logical stock and reconciles with physical count. |
|
| **StockTaking** | Leltározás | Inventory session that freezes logical stock and reconciles with physical count. |
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue