Add item tracking migrations

This commit is contained in:
2026-10-06 13:30:12 +05:30
parent 92f1aadb81
commit c358764f4e
11 changed files with 9799 additions and 12 deletions
+2
View File
@@ -44,4 +44,6 @@ namespace Distribution.Models
/// ModeB: Invoice created as a separate explicit step.
/// </summary>
public enum InvoiceCreationMode { ModeA, ModeB }
public enum SerialStatus { InStock, Sold, Returned, Damaged }
}
+7
View File
@@ -32,6 +32,13 @@ namespace Distribution.Models
/// <summary>Cost/purchase price, used to value free-goods scheme redemptions for getSchemeROI.</summary>
public decimal? CostPrice { get; set; }
public bool TracksSerialNumbers { get; set; } = false;
public bool TracksBatches { get; set; } = false;
public bool TracksExpiryDate { get; set; } = false;
public bool HasWarranty { get; set; } = false;
public int? WarrantyPeriodDays { get; set; }
public bool AllowCustomWarrantyPeriod { get; set; } = false;
public SyncSource SyncSource { get; set; } = SyncSource.Manual;
public int? ExternalErpItemId { get; set; }
public DateTime? LastSyncedAt { get; set; }
+20
View File
@@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Distribution.Models
{
/// <summary>
/// Backs both batch/lot tracking and expiry-only tracking for an item. BatchNumber is null
/// when the item tracks an expiry date but not a batch number (TracksExpiryDate without
/// TracksBatches).
/// </summary>
public class ItemBatch : Template
{
public Guid FK_ItemId { get; set; }
[ForeignKey("FK_ItemId")]
public Item Item { get; set; }
public string? BatchNumber { get; set; }
public DateTime? ManufactureDate { get; set; }
public DateTime? ExpiryDate { get; set; }
}
}
+26
View File
@@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Distribution.Models
{
/// <summary>One row per physical serial-tracked unit. Quantity is always 1.</summary>
public class ItemSerialNumber : Template
{
public Guid FK_ItemId { get; set; }
[ForeignKey("FK_ItemId")]
public Item Item { get; set; }
public string SerialNumber { get; set; }
public SerialStatus Status { get; set; } = SerialStatus.InStock;
public Guid? CurrentLocationId { get; set; }
public LocationType? CurrentLocationType { get; set; }
public DateTime ReceivedAt { get; set; }
/// <summary>Snapshotted at receipt when Item.AllowCustomWarrantyPeriod is true; otherwise null and the system default applies when the warranty starts.</summary>
public int? WarrantyPeriodDaysOverride { get; set; }
/// <summary>Set when the serial is sold/delivered: sale date + (override ?? system default). Null while in stock or if Item.HasWarranty is false.</summary>
public DateTime? WarrantyExpiresAt { get; set; }
}
}
+10
View File
@@ -13,6 +13,16 @@ namespace Distribution.Models
public Guid LocationId { get; set; }
public LocationType LocationType { get; set; }
/// <summary>Null for items that don't track batches/expiry — no behavior change for existing items.</summary>
public Guid? FK_ItemBatchId { get; set; }
[ForeignKey("FK_ItemBatchId")]
public ItemBatch? ItemBatch { get; set; }
/// <summary>Null for items that don't track serial numbers.</summary>
public Guid? FK_ItemSerialNumberId { get; set; }
[ForeignKey("FK_ItemSerialNumberId")]
public ItemSerialNumber? ItemSerialNumber { get; set; }
public decimal Quantity { get; set; }
public DateTime UpdatedAt { get; set; } = DateTime.Now;
}
+10
View File
@@ -16,6 +16,16 @@ namespace Distribution.Models
public Guid? ToLocationId { get; set; }
public LocationType? ToLocationType { get; set; }
/// <summary>Null for items that don't track batches/expiry — no behavior change for existing items.</summary>
public Guid? FK_ItemBatchId { get; set; }
[ForeignKey("FK_ItemBatchId")]
public ItemBatch? ItemBatch { get; set; }
/// <summary>Null for items that don't track serial numbers. Quantity is always 1 when set.</summary>
public Guid? FK_ItemSerialNumberId { get; set; }
[ForeignKey("FK_ItemSerialNumberId")]
public ItemSerialNumber? ItemSerialNumber { get; set; }
public decimal Quantity { get; set; }
public MovementType Type { get; set; }