Refactor PreOrder and CargoTruck models, add ICargoTruck
Standardized PreOrder naming across classes, enums, and constants. Updated DB table name constants. Added IsTrailer, Created, and Modified properties to CargoTruck and linked to CargoPartner. Introduced ICargoTruck interface. Added SignalR support for fetching CargoTrucks by CargoPartnerId, with related service, interface, and test updates. Improved ToonDescription docs and updated UI components for new properties and naming. Refactored for clarity and consistency.
This commit is contained in:
parent
3e4d3260f0
commit
98799a79e1
|
|
@ -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.
|
||||
/// </summary>
|
||||
public const string PreorderWindowStart = "PreorderWindowStart";
|
||||
public const string PreOrderWindowStart = "PreOrderWindowStart";
|
||||
|
||||
/// <summary>
|
||||
/// DateTime generic attribute on Product.
|
||||
/// The end of the window during which this product is visible for preordering.
|
||||
/// </summary>
|
||||
public const string PreorderWindowEnd = "PreorderWindowEnd";
|
||||
public const string PreOrderWindowEnd = "PreOrderWindowEnd";
|
||||
|
||||
static FruitBankConst()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<PreorderItem> PreorderItems { get; set; } = new();
|
||||
public List<PreOrderItem> PreOrderItems { get; set; } = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace FruitBank.Common.Enums;
|
||||
|
||||
public enum PreorderItemStatus
|
||||
public enum PreOrderItemStatus
|
||||
{
|
||||
Pending = 0,
|
||||
Fulfilled = 10,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace FruitBank.Common.Enums;
|
||||
|
||||
public enum PreorderStatus
|
||||
public enum PreOrderStatus
|
||||
{
|
||||
Pending = 0,
|
||||
Confirmed = 10,
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
@ -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<List<CargoTruck>?> GetCargoTrucks();
|
||||
public Task<CargoTruck?> GetCargoTruckById(int id);
|
||||
public Task<List<CargoTruck>?> GetCargoTrucksByCargoPartnerId(int cargoPartnerId);
|
||||
public Task<CargoTruck?> AddCargoTruck(CargoTruck cargoTruck);
|
||||
public Task<CargoTruck?> UpdateCargoTruck(CargoTruck cargoTruck);
|
||||
#endregion CargoTruck
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using FruitBank.Common.Entities;
|
|||
|
||||
namespace FruitBank.Common.Interfaces;
|
||||
|
||||
|
||||
public interface ICargoPartner : IPartnerBase
|
||||
{
|
||||
List<CargoTruck>? CargoTrucks { get; set; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ namespace FruitBankHybrid.Shared.Tests
|
|||
Assert.IsNotNull(cargoTrucks);
|
||||
Assert.IsNotEmpty(cargoTrucks);
|
||||
}
|
||||
|
||||
//[TestMethod]
|
||||
//[DataRow(1)]
|
||||
public async Task<CargoTruck> 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)
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ public class FullProcessModel
|
|||
{
|
||||
public List<Shipping> Shippings { get; set; }
|
||||
public List<OrderDto> Orders { get; set; }
|
||||
public List<PreOrder> PreOrders { get; set; }
|
||||
public List<StockTaking> StockTakings { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,21 +44,21 @@
|
|||
<DetailRowTemplate>
|
||||
@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 ?? [];
|
||||
|
||||
<DxTabs>
|
||||
<DxTabPage Text="Kamionok">
|
||||
@{
|
||||
var observableShippingDocuments = new AcObservableCollection<CargoTruck>(cargoTrucks);
|
||||
<GridCargoTruck ParentDataItem="@partner" CargoTrucks="@observableShippingDocuments"></GridCargoTruck>
|
||||
var observableCargoTruck = new AcObservableCollection<CargoTruck>(cargoTrucks);
|
||||
<GridCargoTruck ParentDataItem="@cargoPartner" CargoTrucks="@observableCargoTruck"></GridCargoTruck>
|
||||
}
|
||||
</DxTabPage>
|
||||
|
||||
<DxTabPage Text="Szállítmányok">
|
||||
@{
|
||||
var observableShippings = new AcObservableCollection<Shipping>(shipping);
|
||||
var observableShippings = new AcObservableCollection<Shipping>(shippings);
|
||||
<GridShipping Shippings="@observableShippings" IsMasterGrid="false" />
|
||||
}
|
||||
</DxTabPage>
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
<DxGridDataColumn FieldName="@nameof(CargoTruck.LicencePlate)" />
|
||||
<DxGridDataColumn FieldName="@nameof(CargoTruck.CountryCode)" />
|
||||
<DxGridDataColumn FieldName="@nameof(CargoTruck.IsTrailer)" />
|
||||
|
||||
<DxGridDataColumn FieldName="Created" ReadOnly="true" />
|
||||
<DxGridDataColumn FieldName="Modified" ReadOnly="true" />
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public class GridCargoTruckBase: FruitBankGridBase<CargoTruck>, IGrid
|
|||
switch (ParentDataItem)
|
||||
{
|
||||
case ICargoPartner:
|
||||
GetAllMessageTag = SignalRTags.GetCargoTrucks;
|
||||
GetAllMessageTag = SignalRTags.GetCargoTrucksByCargoPartnerId;
|
||||
if (KeyFieldNameToParentId.IsNullOrWhiteSpace()) KeyFieldNameToParentId = nameof(CargoTruck.CargoPartnerId);
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
|
|||
#region CargoTruck
|
||||
public Task<List<CargoTruck>?> GetCargoTrucks() => GetAllAsync<List<CargoTruck>>(SignalRTags.GetCargoTrucks);
|
||||
public Task<CargoTruck?> GetCargoTruckById(int id) => GetByIdAsync<CargoTruck?>(SignalRTags.GetCargoTruckById, id);
|
||||
public Task<List<CargoTruck>?> GetCargoTrucksByCargoPartnerId(int cargoPartnerId) => GetAllAsync<List<CargoTruck>>(SignalRTags.GetCargoTrucksByCargoPartnerId, [cargoPartnerId]);
|
||||
public Task<CargoTruck?> AddCargoTruck(CargoTruck cargoTruck) => PostDataAsync(SignalRTags.AddCargoTruck, cargoTruck);
|
||||
public Task<CargoTruck?> UpdateCargoTruck(CargoTruck cargoTruck) => PostDataAsync(SignalRTags.UpdateCargoTruck, cargoTruck);
|
||||
#endregion CargoTruck
|
||||
|
|
|
|||
Loading…
Reference in New Issue