diff --git a/FruitBank.Common.Server/FruitBankConst.cs b/FruitBank.Common.Server/FruitBankConst.cs
index 4c4d2a9e..c60e6ca0 100644
--- a/FruitBank.Common.Server/FruitBankConst.cs
+++ b/FruitBank.Common.Server/FruitBankConst.cs
@@ -19,13 +19,13 @@ namespace FruitBank.Common.Server
/// DateTime generic attribute on Product.
/// The start of the window during which this product is visible for preordering.
///
- public const string PreorderWindowStart = "PreorderWindowStart";
+ public const string PreOrderWindowStart = "PreOrderWindowStart";
///
/// DateTime generic attribute on Product.
/// The end of the window during which this product is visible for preordering.
///
- public const string PreorderWindowEnd = "PreorderWindowEnd";
+ public const string PreOrderWindowEnd = "PreOrderWindowEnd";
static FruitBankConst()
{
diff --git a/FruitBank.Common/Entities/CargoTruck.cs b/FruitBank.Common/Entities/CargoTruck.cs
index bc4524ba..f9f791db 100644
--- a/FruitBank.Common/Entities/CargoTruck.cs
+++ b/FruitBank.Common/Entities/CargoTruck.cs
@@ -1,4 +1,5 @@
using AyCode.Core.Serializers.Attributes;
+using FruitBank.Common.Interfaces;
using LinqToDB.Mapping;
using Mango.Nop.Core.Entities;
@@ -8,10 +9,17 @@ namespace FruitBank.Common.Entities;
//[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")]
[Table(Name = FruitBankConstClient.CargoTruckDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.CargoTruckDbTableName)]
-public sealed class CargoTruck: MgEntityBase//, ICargoPartner
+public sealed class CargoTruck: MgEntityBase, ICargoTruck
{
public int CargoPartnerId { get; set; }
+
+ [Association(ThisKey = nameof(CargoPartnerId), OtherKey = nameof(CargoPartner.Id), CanBeNull = true)]
+ public CargoPartner CargoPartner { get; set; }
+
public string CountryCode { get; set; }
public string LicencePlate { get; set; }
+ public bool IsTrailer { get; set; }
+ public DateTime Created { get; set; }
+ public DateTime Modified { get; set; }
}
diff --git a/FruitBank.Common/Entities/Preorder.cs b/FruitBank.Common/Entities/Preorder.cs
index a9c987be..a16e9fa7 100644
--- a/FruitBank.Common/Entities/Preorder.cs
+++ b/FruitBank.Common/Entities/Preorder.cs
@@ -9,17 +9,26 @@ namespace FruitBank.Common.Entities;
[AcBinarySerializable(false, true, false, true, false, false)]
[Table(Name = FruitBankConstClient.PreOrderDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PreOrderDbTableName)]
-//[ToonDescription("Shipping document with partner, items and files", Purpose = "A digital representation of a supplier's delivery note or invoice associated with the shipment, used for reconciling paper-based data with measured reality")]
-public sealed class Preorder : MgEntityBase
+[ToonDescription("Customer advance order placed before the goods physically arrive", Purpose = "Header of a customer pre-order against an upcoming inbound delivery. Pending items are allocated from incoming stock first-come-first-served by PreOrderId when a shipping document confirms arrival, then converted into a real NopCommerce Order once any quantity is fulfilled.")]
+public sealed class PreOrder : MgEntityBase
{
public int CustomerId { get; set; }
public int StoreId { get; set; }
+
+ [ToonDescription(Purpose = "Requested delivery date. Drives the conversion window (only preorders within PreOrderConversionWindowDays of this date are eligible for allocation) and the expiry sweep — once this date is past, any still-Pending items are Dropped.")]
public DateTime DateOfReceipt { get; set; }
- public PreorderStatus Status { get; set; }
+
+ [ToonDescription(Purpose = "Header lifecycle: Pending -> Confirmed (all items Fulfilled) / PartiallyFulfilled (some Dropped or partial, none left Pending) / Cancelled.")]
+ public PreOrderStatus Status { get; set; }
+
+ [ToonDescription(Purpose = "Optional free-text note entered by the customer when placing the preorder.")]
public string? CustomerNote { get; set; }
+
public DateTime CreatedOnUtc { get; set; }
public DateTime UpdatedOnUtc { get; set; }
+
+ [ToonDescription(Purpose = "FK to the real NopCommerce Order created from this preorder. Null until the first item is fulfilled; set once on first conversion and reused so subsequent shipping documents append items to the same order.")]
public int? OrderId { get; set; }
- public List PreorderItems { get; set; } = new();
+ public List PreOrderItems { get; set; } = [];
}
diff --git a/FruitBank.Common/Entities/PreorderItem.cs b/FruitBank.Common/Entities/PreorderItem.cs
index 54829345..9f8f8756 100644
--- a/FruitBank.Common/Entities/PreorderItem.cs
+++ b/FruitBank.Common/Entities/PreorderItem.cs
@@ -9,13 +9,21 @@ namespace FruitBank.Common.Entities;
[AcBinarySerializable(false, true, false, true, false, false)]
[Table(Name = FruitBankConstClient.PreOrderItemDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PreOrderItemDbTableName)]
-//[ToonDescription("Shipping document with partner, items and files", Purpose = "A digital representation of a supplier's delivery note or invoice associated with the shipment, used for reconciling paper-based data with measured reality")]
-public sealed class PreorderItem : MgEntityBase
+[ToonDescription("Single product line of a customer preorder with fulfilment tracking", Purpose = "A requested product line within a PreOrder. Tracks requested versus cumulatively fulfilled quantity as incoming stock is allocated across one or more shipping-document conversion runs.")]
+public sealed class PreOrderItem : MgEntityBase
{
- public int PreorderId { get; set; }
+ public int PreOrderId { get; set; }
public int ProductId { get; set; }
+
+ [ToonDescription(Purpose = "Quantity of the product the customer requested.")]
public int RequestedQuantity { get; set; }
+
+ [ToonDescription(Purpose = "Quantity allocated from incoming stock so far; accumulates across conversion runs until it reaches RequestedQuantity.")]
public int FulfilledQuantity { get; set; }
+
+ [ToonDescription(Purpose = "Gross unit price locked at preorder time. Used as the order-item price on conversion for non-measurable products; measurable products are priced 0 at conversion and weighed afterwards.")]
public decimal UnitPriceInclTax { get; set; }
- public PreorderItemStatus Status { get; set; }
+
+ [ToonDescription(Purpose = "Item lifecycle: Pending -> Fulfilled (fully allocated) / PartiallyFulfilled (partly allocated) / Dropped (expired or no incoming stock).")]
+ public PreOrderItemStatus Status { get; set; }
}
diff --git a/FruitBank.Common/Enums/PreorderItemStatus.cs b/FruitBank.Common/Enums/PreorderItemStatus.cs
index 42d3a0de..009b67d6 100644
--- a/FruitBank.Common/Enums/PreorderItemStatus.cs
+++ b/FruitBank.Common/Enums/PreorderItemStatus.cs
@@ -1,6 +1,6 @@
namespace FruitBank.Common.Enums;
-public enum PreorderItemStatus
+public enum PreOrderItemStatus
{
Pending = 0,
Fulfilled = 10,
diff --git a/FruitBank.Common/Enums/PreorderStatus.cs b/FruitBank.Common/Enums/PreorderStatus.cs
index 2b01a9c5..27943ea7 100644
--- a/FruitBank.Common/Enums/PreorderStatus.cs
+++ b/FruitBank.Common/Enums/PreorderStatus.cs
@@ -2,7 +2,7 @@
namespace FruitBank.Common.Enums;
-public enum PreorderStatus
+public enum PreOrderStatus
{
Pending = 0,
Confirmed = 10,
diff --git a/FruitBank.Common/FruitBankConstClient.cs b/FruitBank.Common/FruitBankConstClient.cs
index a6e97f58..74958298 100644
--- a/FruitBank.Common/FruitBankConstClient.cs
+++ b/FruitBank.Common/FruitBankConstClient.cs
@@ -46,8 +46,8 @@ public static class FruitBankConstClient
public const string StockTakingItemPalletDbTableName = "fbStockTakingItemPallet";
public const string CustomerCreditDbTableName = "fbCustomerCredit";
- public const string PreOrderDbTableName = "fbPreorder";
- public const string PreOrderItemDbTableName = "fbPreorderItem";
+ public const string PreOrderDbTableName = "fbPreOrder";
+ public const string PreOrderItemDbTableName = "fbPreOrderItem";
public const string CargoPartnerDbTableName = "fbCargoPartner";
public const string CargoTruckDbTableName = "fbCargoTruck";
diff --git a/FruitBank.Common/Interfaces/ICargoTruck.cs b/FruitBank.Common/Interfaces/ICargoTruck.cs
new file mode 100644
index 00000000..538d8612
--- /dev/null
+++ b/FruitBank.Common/Interfaces/ICargoTruck.cs
@@ -0,0 +1,17 @@
+using AyCode.Interfaces.Entities;
+using AyCode.Interfaces.TimeStampInfo;
+using FruitBank.Common.Entities;
+
+namespace FruitBank.Common.Interfaces;
+
+public interface ICargoTruck : IEntityInt, ITimeStampInfo
+{
+ public int CargoPartnerId { get; set; }
+
+ public CargoPartner CargoPartner { get; set; }
+
+ public string CountryCode { get; set; }
+ public string LicencePlate { get; set; }
+
+ public bool IsTrailer { get; set; }
+}
\ No newline at end of file
diff --git a/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs b/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs
index 4af46ea9..39a8ae26 100644
--- a/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs
+++ b/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs
@@ -1,6 +1,7 @@
using FruitBank.Common.Dtos;
using FruitBank.Common.Entities;
using FruitBank.Common.Models;
+using FruitBank.Common.SignalRs;
using Mango.Nop.Core.Dtos;
using Mango.Nop.Core.Entities;
using Mango.Nop.Core.Models;
@@ -29,6 +30,7 @@ public interface IFruitBankDataControllerCommon
#region CargoTruck
public Task?> GetCargoTrucks();
public Task GetCargoTruckById(int id);
+ public Task?> GetCargoTrucksByCargoPartnerId(int cargoPartnerId);
public Task AddCargoTruck(CargoTruck cargoTruck);
public Task UpdateCargoTruck(CargoTruck cargoTruck);
#endregion CargoTruck
diff --git a/FruitBank.Common/Interfaces/IPartner.cs b/FruitBank.Common/Interfaces/IPartner.cs
index f5f53ab3..b757dc7e 100644
--- a/FruitBank.Common/Interfaces/IPartner.cs
+++ b/FruitBank.Common/Interfaces/IPartner.cs
@@ -4,7 +4,6 @@ using FruitBank.Common.Entities;
namespace FruitBank.Common.Interfaces;
-
public interface ICargoPartner : IPartnerBase
{
List? CargoTrucks { get; set; }
diff --git a/FruitBank.Common/SignalRs/SignalRTags.cs b/FruitBank.Common/SignalRs/SignalRTags.cs
index e57326f4..298ca2ef 100644
--- a/FruitBank.Common/SignalRs/SignalRTags.cs
+++ b/FruitBank.Common/SignalRs/SignalRTags.cs
@@ -21,9 +21,10 @@ public class SignalRTags : AcSignalRTags
public const int UpdateCargoPartner = 33;
public const int GetCargoTrucks = 35;
- public const int GetCargoTruckById = 36;
- public const int AddCargoTruck = 37;
- public const int UpdateCargoTruck = 38;
+ public const int GetCargoTrucksByCargoPartnerId = 36;
+ public const int GetCargoTruckById = 37;
+ public const int AddCargoTruck = 38;
+ public const int UpdateCargoTruck = 39;
public const int GetShippings = 40;
public const int GetNotMeasuredShippings = 41;
diff --git a/FruitBankHybrid.Shared.Tests/FruitBankClientTests.cs b/FruitBankHybrid.Shared.Tests/FruitBankClientTests.cs
index d18fc8a4..ed23b765 100644
--- a/FruitBankHybrid.Shared.Tests/FruitBankClientTests.cs
+++ b/FruitBankHybrid.Shared.Tests/FruitBankClientTests.cs
@@ -131,6 +131,7 @@ namespace FruitBankHybrid.Shared.Tests
Assert.IsNotNull(cargoTrucks);
Assert.IsNotEmpty(cargoTrucks);
}
+
//[TestMethod]
//[DataRow(1)]
public async Task GetCargoTruckByIdTest(int cargoTruckId)
@@ -143,6 +144,17 @@ namespace FruitBankHybrid.Shared.Tests
return cargoTruck;
}
+ [TestMethod]
+ [DataRow(1)]
+ public async Task GetCargoTrucksByCargoPartnerIdTest(int cargoPartnerId)
+ {
+ var cargoTrucks = await _signalRClient.GetCargoTrucksByCargoPartnerId(cargoPartnerId);
+
+ Assert.IsNotNull(cargoTrucks);
+ Assert.IsNotEmpty(cargoTrucks);
+ }
+
+
[TestMethod]
[DataRow(1)]
public async Task UpdateCargoTruckTest(int cargoTruckId)
diff --git a/FruitBankHybrid.Shared.Tests/ToonTests.cs b/FruitBankHybrid.Shared.Tests/ToonTests.cs
index 8f8b7576..fa8609e4 100644
--- a/FruitBankHybrid.Shared.Tests/ToonTests.cs
+++ b/FruitBankHybrid.Shared.Tests/ToonTests.cs
@@ -86,6 +86,7 @@ public class FullProcessModel
{
public List Shippings { get; set; }
public List Orders { get; set; }
+ public List PreOrders { get; set; }
public List StockTakings { get; set; }
}
diff --git a/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoPartner.razor b/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoPartner.razor
index 8c025799..1f0730c8 100644
--- a/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoPartner.razor
+++ b/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoPartner.razor
@@ -44,21 +44,21 @@
@if (IsMasterGrid)
{
- var partner = ((CargoPartner)context.DataItem);
- var shipping = partner?.Shippings ?? [];
- var cargoTrucks = partner?.CargoTrucks ?? [];
+ var cargoPartner = ((CargoPartner)context.DataItem);
+ var shippings = cargoPartner?.Shippings ?? [];
+ var cargoTrucks = cargoPartner?.CargoTrucks ?? [];
@{
- var observableShippingDocuments = new AcObservableCollection(cargoTrucks);
-
+ var observableCargoTruck = new AcObservableCollection(cargoTrucks);
+
}
@{
- var observableShippings = new AcObservableCollection(shipping);
+ var observableShippings = new AcObservableCollection(shippings);
}
diff --git a/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoTruck.razor b/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoTruck.razor
index c264877d..43f987bf 100644
--- a/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoTruck.razor
+++ b/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoTruck.razor
@@ -30,6 +30,7 @@
+
diff --git a/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoTruckBase.cs b/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoTruckBase.cs
index 2c1f1513..de1162ab 100644
--- a/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoTruckBase.cs
+++ b/FruitBankHybrid.Shared/Components/Grids/Cargos/GridCargoTruckBase.cs
@@ -35,7 +35,7 @@ public class GridCargoTruckBase: FruitBankGridBase, IGrid
switch (ParentDataItem)
{
case ICargoPartner:
- GetAllMessageTag = SignalRTags.GetCargoTrucks;
+ GetAllMessageTag = SignalRTags.GetCargoTrucksByCargoPartnerId;
if (KeyFieldNameToParentId.IsNullOrWhiteSpace()) KeyFieldNameToParentId = nameof(CargoTruck.CargoPartnerId);
break;
diff --git a/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs b/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs
index e9675de6..bf590cd1 100644
--- a/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs
+++ b/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs
@@ -76,6 +76,7 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
#region CargoTruck
public Task?> GetCargoTrucks() => GetAllAsync>(SignalRTags.GetCargoTrucks);
public Task GetCargoTruckById(int id) => GetByIdAsync(SignalRTags.GetCargoTruckById, id);
+ public Task?> GetCargoTrucksByCargoPartnerId(int cargoPartnerId) => GetAllAsync>(SignalRTags.GetCargoTrucksByCargoPartnerId, [cargoPartnerId]);
public Task AddCargoTruck(CargoTruck cargoTruck) => PostDataAsync(SignalRTags.AddCargoTruck, cargoTruck);
public Task UpdateCargoTruck(CargoTruck cargoTruck) => PostDataAsync(SignalRTags.UpdateCargoTruck, cargoTruck);
#endregion CargoTruck