diff --git a/Distribution/Models/Enums.cs b/Distribution/Models/Enums.cs
index cb588a3..311200e 100644
--- a/Distribution/Models/Enums.cs
+++ b/Distribution/Models/Enums.cs
@@ -19,7 +19,9 @@ namespace Distribution.Models
Transfer,
Damage,
Adjustment,
- Load
+ Load,
+ PurchaseReceipt,
+ PurchaseReturn
}
public enum LoadingSheetStatus
@@ -38,4 +40,6 @@ namespace Distribution.Models
public enum CancelRequestType { VehicleBreakdown, DriverUnavailable, RouteIssue, Other }
public enum CancelRequestStatus { Pending, Approved, Rejected }
+
+ public enum PurchaseOrderStatus { Issued, PartiallyReceived, Received, Closed, Cancelled }
}
diff --git a/Distribution/Models/GoodsReceipt.cs b/Distribution/Models/GoodsReceipt.cs
new file mode 100644
index 0000000..4ce1368
--- /dev/null
+++ b/Distribution/Models/GoodsReceipt.cs
@@ -0,0 +1,26 @@
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Distribution.Models
+{
+ public class GoodsReceipt : Template
+ {
+ public Guid FK_PurchaseOrderId { get; set; }
+ [ForeignKey("FK_PurchaseOrderId")]
+ public PurchaseOrder PurchaseOrder { get; set; }
+
+ public Guid FK_ReceivedByUserId { get; set; }
+
+ ///
+ /// Warehouse the accepted quantities are received into. Not listed as a field in
+ /// docs/15_procurement.md's GoodsReceipt table, but required to write StockBalance/
+ /// StockMovement rows (both keyed by LocationId+LocationType) for the accepted quantities.
+ ///
+ public Guid FK_WarehouseId { get; set; }
+ [ForeignKey("FK_WarehouseId")]
+ public Warehouse Warehouse { get; set; }
+
+ public DateTime ReceivedAt { get; set; } = DateTime.Now;
+
+ public ICollection Items { get; set; } = [];
+ }
+}
diff --git a/Distribution/Models/GoodsReceiptItem.cs b/Distribution/Models/GoodsReceiptItem.cs
new file mode 100644
index 0000000..7a04ebb
--- /dev/null
+++ b/Distribution/Models/GoodsReceiptItem.cs
@@ -0,0 +1,21 @@
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Distribution.Models
+{
+ public class GoodsReceiptItem : Template
+ {
+ public Guid FK_GoodsReceiptId { get; set; }
+ [ForeignKey("FK_GoodsReceiptId")]
+ public GoodsReceipt GoodsReceipt { get; set; }
+
+ public Guid FK_PurchaseOrderItemId { get; set; }
+ [ForeignKey("FK_PurchaseOrderItemId")]
+ public PurchaseOrderItem PurchaseOrderItem { get; set; }
+
+ /// Added to warehouse stock.
+ public int AcceptedQuantity { get; set; }
+
+ /// Damaged/short at receipt, not added to stock.
+ public int RejectedQuantity { get; set; } = 0;
+ }
+}
diff --git a/Distribution/Models/PurchaseOrder.cs b/Distribution/Models/PurchaseOrder.cs
new file mode 100644
index 0000000..e785d6a
--- /dev/null
+++ b/Distribution/Models/PurchaseOrder.cs
@@ -0,0 +1,19 @@
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Distribution.Models
+{
+ public class PurchaseOrder : Template
+ {
+ public Guid FK_SupplierId { get; set; }
+ [ForeignKey("FK_SupplierId")]
+ public Supplier Supplier { get; set; }
+
+ public Guid FK_CreatedByUserId { get; set; }
+
+ public PurchaseOrderStatus Status { get; set; } = PurchaseOrderStatus.Issued;
+
+ public string? CancelReason { get; set; }
+
+ public ICollection Items { get; set; } = [];
+ }
+}
diff --git a/Distribution/Models/PurchaseOrderItem.cs b/Distribution/Models/PurchaseOrderItem.cs
new file mode 100644
index 0000000..5ad9954
--- /dev/null
+++ b/Distribution/Models/PurchaseOrderItem.cs
@@ -0,0 +1,32 @@
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Distribution.Models
+{
+ public class PurchaseOrderItem : Template
+ {
+ public Guid FK_PurchaseOrderId { get; set; }
+ [ForeignKey("FK_PurchaseOrderId")]
+ public PurchaseOrder PurchaseOrder { get; set; }
+
+ public Guid FK_ItemId { get; set; }
+ [ForeignKey("FK_ItemId")]
+ public Item Item { get; set; }
+
+ public int Quantity { get; set; }
+
+ /// Agreed cost per unit at the time the PO was issued.
+ public decimal UnitCost { get; set; }
+
+ /// Running total, incremented by createGoodsReceipt; drives PurchaseOrder.Status.
+ public int ReceivedQuantity { get; set; } = 0;
+
+ ///
+ /// Set by cancelPurchaseOrderLine. Outstanding qty for receiving purposes is
+ /// Quantity - ReceivedQuantity - CancelledQuantity.
+ ///
+ public int CancelledQuantity { get; set; } = 0;
+
+ /// True once this line is individually cancelled.
+ public bool IsCancelled { get; set; } = false;
+ }
+}
diff --git a/Distribution/Models/PurchaseReturn.cs b/Distribution/Models/PurchaseReturn.cs
new file mode 100644
index 0000000..4f487bd
--- /dev/null
+++ b/Distribution/Models/PurchaseReturn.cs
@@ -0,0 +1,15 @@
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Distribution.Models
+{
+ public class PurchaseReturn : Template
+ {
+ public Guid FK_PurchaseOrderId { get; set; }
+ [ForeignKey("FK_PurchaseOrderId")]
+ public PurchaseOrder PurchaseOrder { get; set; }
+
+ public string Reason { get; set; }
+
+ public ICollection Items { get; set; } = [];
+ }
+}
diff --git a/Distribution/Models/PurchaseReturnItem.cs b/Distribution/Models/PurchaseReturnItem.cs
new file mode 100644
index 0000000..54a4620
--- /dev/null
+++ b/Distribution/Models/PurchaseReturnItem.cs
@@ -0,0 +1,18 @@
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Distribution.Models
+{
+ public class PurchaseReturnItem : Template
+ {
+ public Guid FK_PurchaseReturnId { get; set; }
+ [ForeignKey("FK_PurchaseReturnId")]
+ public PurchaseReturn PurchaseReturn { get; set; }
+
+ public Guid FK_ItemId { get; set; }
+ [ForeignKey("FK_ItemId")]
+ public Item Item { get; set; }
+
+ /// Returned quantity, decremented from warehouse stock.
+ public int Quantity { get; set; }
+ }
+}