FruitBankHybridApp/FruitBank.Common/Entities/Preorder.cs

54 lines
3.4 KiB
C#

using AyCode.Core.Serializers.Attributes;
using AyCode.Core.Serializers.Toons;
using FruitBank.Common.Enums;
using LinqToDB.Mapping;
using Mango.Nop.Core.Entities;
namespace FruitBank.Common.Entities;
[AcBinarySerializable(false, true, false, true, false, false)]
[Table(Name = FruitBankConstClient.PreOrderDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PreOrderDbTableName)]
[ToonDescription("Customer advance order placed before the goods physically arrive", Purpose = "Header of a customer pre-order against an upcoming inbound delivery. When a supplier shipping document confirms incoming stock, pending items are allocated first-come-first-served by PreOrderId (only within the conversion window — PreOrderConversionWindowDays, 4 days, of DateOfReceipt) and the preorder is converted into a real NopCommerce Order once any quantity is fulfilled. Preorders past DateOfReceipt are swept closed, dropping any still-Pending items.")]
public sealed class PreOrder : MgEntityBase
{
[ToonDescription(Purpose = "FK to the nopCommerce Customer who placed the preorder.")]
public int CustomerId { get; set; }
[ToonDescription(Purpose = "nopCommerce multi-store scope.")]
public int StoreId { get; set; }
[ToonDescription(Purpose = "Requested delivery date. Drives the conversion window (only preorders within PreOrderConversionWindowDays — 4 days — 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; }
// Persisted as an int column ("Status"). A raw enum property is NOT mapped/written by the
// nopCommerce LinqToDB stack (nop stores enums as int + a [NotMapped] wrapper — cf. Order.OrderStatusId),
// so writing the enum directly left the column stuck at 0. StatusId is the real mapped column;
// the Status wrapper below is the typed API.
[Column("Status")]
[ToonDescription(Purpose = "Header lifecycle status, stored as int. See the Status wrapper for the enum semantics.")]
public int StatusId { get; set; }
[NotColumn, System.ComponentModel.DataAnnotations.Schema.NotMapped]
[ToonDescription(Purpose = "Header lifecycle: Pending / Confirmed (all items Fulfilled) / PartiallyFulfilled (some Dropped or partial, none left Pending) / Cancelled.",
BusinessRule = "set by RefreshPreOrderStatusAsync from item states: items.All(Fulfilled) => Confirmed; (any Dropped or PartiallyFulfilled) && none Pending => PartiallyFulfilled; else Pending. Cancelled is set explicitly. Persisted via StatusId.")]
public PreOrderStatus Status
{
get => (PreOrderStatus)StatusId;
set => StatusId = (int)value;
}
[ToonDescription(Purpose = "Optional free-text note entered by the customer when placing the preorder.")]
public string? CustomerNote { get; set; }
public DateTime CreatedOnUtc { get; set; }
[ToonDescription(Purpose = "Bumped to UtcNow on every status / allocation change.")]
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; } = [];
}