feat: Add new services and interfaces for GRN, Purchase Return, Reason Code, Reorder, Stock, and Transfer functionalities
- Implemented IGrnService for managing goods receipts including retrieval, creation, and confirmation. - Created IPurchaseReturnService for handling purchase return operations. - Added IReasonCodeService for managing reason codes with listing and creation capabilities. - Developed IReorderService for fetching reorder alerts and creating suggested requisitions. - Introduced IStockMutator for applying stock changes and posting ledger entries. - Established IStockService for stock inquiries, ledger retrieval, and valuation. - Created ITransferService for managing inter-warehouse transfers including dispatch and receiving operations. - Implemented PurchaseReturnService to handle purchase return logic and stock adjustments. - Developed ReasonCodeService for listing and creating reason codes. - Created ReorderService for fetching reorder alerts and generating requisitions. - Implemented FifoCostingService for FIFO cost-layer management and ledger writing. - Developed StockMutator for applying stock deltas and posting ledger entries. - Created StockService for stock inquiries and ledger management. - Implemented TransferService for managing inter-warehouse transfers with dispatch and receive functionalities.
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable audit trail entry (FR-X-02) — the compensating control for the deferred
|
||||
/// RBAC (02-SECURITY AR-01/B.3). One row per create/update/delete of an audited
|
||||
/// entity, capturing who / when / what changed (old→new in <see cref="ChangeSet"/>).
|
||||
/// Written automatically by <c>ErpDbContext.SaveChangesAsync</c>. Append-only at the
|
||||
/// app level; DB-role revocation of UPDATE/DELETE is deferred hardening (B.3).
|
||||
/// Model: docs/10 Part C.7.
|
||||
/// </summary>
|
||||
public class AuditLog
|
||||
{
|
||||
public long AuditId { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string EntityType { get; set; } = string.Empty;
|
||||
public long EntityId { get; set; }
|
||||
public AuditAction Action { get; set; }
|
||||
/// <summary>JSON change set: field→value (create/delete) or field→{old,new} (update).</summary>
|
||||
public string ChangeSet { get; set; } = "{}";
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Batch/lot for a batch-tracked item (FR-GRN-04, FR-WH-03). Expiry drives FEFO
|
||||
/// picking of perishables. Model: docs/10 Part C.4.
|
||||
/// </summary>
|
||||
public class Batch
|
||||
{
|
||||
public long BatchId { get; set; }
|
||||
|
||||
public long ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
|
||||
public string BatchNo { get; set; } = string.Empty;
|
||||
public DateOnly? ExpiryDate { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Goods Receipt Note header (FR-GRN-01/02). Raised against a PO or direct
|
||||
/// (<see cref="PoId"/> null). On confirm each line creates a FIFO layer and posts
|
||||
/// an inbound ledger entry. Mutable aggregate with an <see cref="RowVersion"/>
|
||||
/// concurrency token (docs/10 C.10). Model: docs/10 Part C.3.
|
||||
/// </summary>
|
||||
public class Grn
|
||||
{
|
||||
public long GrnId { get; set; }
|
||||
public string DocNo { get; set; } = string.Empty;
|
||||
|
||||
public long? PoId { get; set; }
|
||||
public PurchaseOrder? PurchaseOrder { get; set; }
|
||||
|
||||
public long VendorId { get; set; }
|
||||
public Vendor? Vendor { get; set; }
|
||||
|
||||
public long WarehouseId { get; set; }
|
||||
public Warehouse? Warehouse { get; set; }
|
||||
|
||||
public GrnStatus Status { get; set; } = GrnStatus.Draft;
|
||||
|
||||
public long CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? PostedAt { get; set; }
|
||||
|
||||
/// <summary>PostgreSQL xmin-backed optimistic concurrency token.</summary>
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
public ICollection<GrnLine> Lines { get; set; } = new List<GrnLine>();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// GRN line (FR-GRN-04..08). <see cref="UnitCost"/> is the PO-derived cost for
|
||||
/// PO-based receipts (client cost ignored — 02-SECURITY C.3) or the entered cost
|
||||
/// for direct receipts. <see cref="ReceivedValue"/> = qty × unitCost.
|
||||
/// <see cref="HoldStatus"/> gates issuability. Model: docs/10 Part C.3.
|
||||
/// </summary>
|
||||
public class GrnLine
|
||||
{
|
||||
public long GrnLineId { get; set; }
|
||||
|
||||
public long GrnId { get; set; }
|
||||
public Grn? Grn { get; set; }
|
||||
|
||||
public long? PoLineId { get; set; }
|
||||
public PoLine? PoLine { get; set; }
|
||||
|
||||
public long ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
|
||||
public long UomId { get; set; }
|
||||
public Uom? Uom { get; set; }
|
||||
|
||||
public long? BinId { get; set; }
|
||||
public Bin? Bin { get; set; }
|
||||
|
||||
public long? BatchId { get; set; }
|
||||
public Batch? Batch { get; set; }
|
||||
|
||||
public decimal Qty { get; set; }
|
||||
public decimal UnitCost { get; set; }
|
||||
public decimal ReceivedValue { get; set; }
|
||||
public HoldStatus HoldStatus { get; set; } = HoldStatus.Available;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// GL-ready journal entry emitted per stock movement (FR-STK-13) — data only, no
|
||||
/// posting in Phase 1 (the Accounting module consumes these later). One row per
|
||||
/// ledger entry, referencing the same source document polymorphically. Account
|
||||
/// codes are Phase-1 placeholders until a chart of accounts exists.
|
||||
/// Model: docs/10 Part C.7.
|
||||
/// </summary>
|
||||
public class JournalEntryStub
|
||||
{
|
||||
public long JournalId { get; set; }
|
||||
public string SourceDocType { get; set; } = string.Empty;
|
||||
public long SourceDocId { get; set; }
|
||||
public string DebitAccount { get; set; } = string.Empty;
|
||||
public string CreditAccount { get; set; } = string.Empty;
|
||||
public decimal Amount { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Purchase return header (FR-PROC-08) — returns received goods to a vendor,
|
||||
/// generating an outbound stock movement. Auto-posts with a mandatory reason code.
|
||||
/// Model: docs/10 Part C.2.
|
||||
/// </summary>
|
||||
public class PurchaseReturn
|
||||
{
|
||||
public long ReturnId { get; set; }
|
||||
public string DocNo { get; set; } = string.Empty;
|
||||
|
||||
public long VendorId { get; set; }
|
||||
public Vendor? Vendor { get; set; }
|
||||
|
||||
public long WarehouseId { get; set; }
|
||||
public Warehouse? Warehouse { get; set; }
|
||||
|
||||
public long ReasonCodeId { get; set; }
|
||||
public ReasonCode? ReasonCode { get; set; }
|
||||
|
||||
public ReturnStatus Status { get; set; } = ReturnStatus.Posted;
|
||||
|
||||
public long CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public ICollection<PurchaseReturnLine> Lines { get; set; } = new List<PurchaseReturnLine>();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Purchase-return line (FR-PROC-08) referencing the original GRN line for
|
||||
/// traceability. <see cref="Qty"/> is in base UOM. Model: docs/10 Part C.2.
|
||||
/// </summary>
|
||||
public class PurchaseReturnLine
|
||||
{
|
||||
public long ReturnLineId { get; set; }
|
||||
|
||||
public long ReturnId { get; set; }
|
||||
public PurchaseReturn? Return { get; set; }
|
||||
|
||||
public long? GrnLineId { get; set; }
|
||||
public GrnLine? GrnLine { get; set; }
|
||||
|
||||
public long ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
|
||||
public decimal Qty { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Configurable reason code for adjustments, returns and count variances
|
||||
/// (FR-X-04). Model: docs/10 Part C.7.
|
||||
/// </summary>
|
||||
public class ReasonCode
|
||||
{
|
||||
public long ReasonCodeId { get; set; }
|
||||
public string Code { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public ReasonContext Context { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Serial number for a serial-tracked item across its lifecycle (FR-WH-04).
|
||||
/// Model: docs/10 Part C.4.
|
||||
/// </summary>
|
||||
public class Serial
|
||||
{
|
||||
public long SerialId { get; set; }
|
||||
|
||||
public long ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
|
||||
public string SerialNo { get; set; } = string.Empty;
|
||||
public string Status { get; set; } = "InStock";
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Stock adjustment header (FR-STK-07) — the highest-risk feature in the phase
|
||||
/// (02-SECURITY C.5). Auto-posts in Phase 1 with a mandatory reason code and user
|
||||
/// stamp. Mutable aggregate with an <see cref="RowVersion"/> token (docs/10 C.10).
|
||||
/// Model: docs/10 Part C.6.
|
||||
/// </summary>
|
||||
public class StockAdjustment
|
||||
{
|
||||
public long AdjustmentId { get; set; }
|
||||
public string DocNo { get; set; } = string.Empty;
|
||||
|
||||
public long WarehouseId { get; set; }
|
||||
public Warehouse? Warehouse { get; set; }
|
||||
|
||||
public long ReasonCodeId { get; set; }
|
||||
public ReasonCode? ReasonCode { get; set; }
|
||||
|
||||
public AdjustmentStatus Status { get; set; } = AdjustmentStatus.Posted;
|
||||
|
||||
public long CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
public ICollection<StockAdjustmentLine> Lines { get; set; } = new List<StockAdjustmentLine>();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Adjustment line (FR-STK-07). <see cref="QtyDelta"/> is a signed base-UOM
|
||||
/// quantity: negative consumes FIFO layers, positive creates a layer at last cost.
|
||||
/// Model: docs/10 Part C.6.
|
||||
/// </summary>
|
||||
public class StockAdjustmentLine
|
||||
{
|
||||
public long AdjLineId { get; set; }
|
||||
|
||||
public long AdjustmentId { get; set; }
|
||||
public StockAdjustment? Adjustment { get; set; }
|
||||
|
||||
public long ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
|
||||
public long? BinId { get; set; }
|
||||
public long? BatchId { get; set; }
|
||||
public long? SerialId { get; set; }
|
||||
|
||||
public decimal QtyDelta { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Cycle/full physical count header (FR-STK-08). System quantities are snapshotted
|
||||
/// at creation and are immutable once opened (02-SECURITY C.7); posting emits a
|
||||
/// variance adjustment. Mutable aggregate with an <see cref="RowVersion"/> token.
|
||||
/// Model: docs/10 Part C.6.
|
||||
/// </summary>
|
||||
public class StockCount
|
||||
{
|
||||
public long CountId { get; set; }
|
||||
public string DocNo { get; set; } = string.Empty;
|
||||
|
||||
public long WarehouseId { get; set; }
|
||||
public Warehouse? Warehouse { get; set; }
|
||||
|
||||
public CountType CountType { get; set; }
|
||||
public CountStatus Status { get; set; } = CountStatus.Draft;
|
||||
|
||||
public long CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
public ICollection<StockCountLine> Lines { get; set; } = new List<StockCountLine>();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Count line (FR-STK-08). <see cref="SystemQty"/> is the immutable snapshot;
|
||||
/// <see cref="Variance"/> = counted − system (in base UOM). Model: docs/10 Part C.6.
|
||||
/// </summary>
|
||||
public class StockCountLine
|
||||
{
|
||||
public long CountLineId { get; set; }
|
||||
|
||||
public long CountId { get; set; }
|
||||
public StockCount? Count { get; set; }
|
||||
|
||||
public long ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
|
||||
public long? BinId { get; set; }
|
||||
|
||||
public decimal SystemQty { get; set; }
|
||||
public decimal? CountedQty { get; set; }
|
||||
public decimal? Variance { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// FIFO cost layer — a quantity received at a specific unit cost, consumed
|
||||
/// oldest-first (FR-STK-02). Keyed per item **per warehouse**; quantities and
|
||||
/// <see cref="UnitCost"/> are in the item's base UOM. Answers valuation
|
||||
/// ("what's on hand and at what cost"). Model: docs/10 Part C.5.
|
||||
/// </summary>
|
||||
public class StockLayer
|
||||
{
|
||||
public long LayerId { get; set; }
|
||||
|
||||
public long ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
|
||||
public long WarehouseId { get; set; }
|
||||
public Warehouse? Warehouse { get; set; }
|
||||
|
||||
public long? BatchId { get; set; }
|
||||
public Batch? Batch { get; set; }
|
||||
|
||||
public long? SerialId { get; set; }
|
||||
public Serial? Serial { get; set; }
|
||||
|
||||
/// <summary>Originating GRN line — carries the inspection hold status for this stock.</summary>
|
||||
public long? GrnLineId { get; set; }
|
||||
public GrnLine? GrnLine { get; set; }
|
||||
|
||||
public decimal QtyReceived { get; set; }
|
||||
public decimal QtyRemaining { get; set; }
|
||||
public decimal UnitCost { get; set; }
|
||||
public DateTime ReceiptDate { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable, append-only stock ledger (FR-STK-01, FR-X-05). One row per costed
|
||||
/// movement; answers history ("what moved, when, by whom"). The originating
|
||||
/// document is referenced polymorphically via
|
||||
/// <see cref="SourceDocType"/>/<see cref="SourceDocId"/> (no hard FK per type) so
|
||||
/// new transaction types write here without a schema change. Model: docs/10 Part C.5.
|
||||
/// </summary>
|
||||
public class StockLedger
|
||||
{
|
||||
public long LedgerId { get; set; }
|
||||
|
||||
public long ItemId { get; set; }
|
||||
public long WarehouseId { get; set; }
|
||||
public long? BinId { get; set; }
|
||||
public long? BatchId { get; set; }
|
||||
public long? SerialId { get; set; }
|
||||
public long UserId { get; set; }
|
||||
|
||||
public Direction Direction { get; set; }
|
||||
public decimal QtyBase { get; set; }
|
||||
public decimal UnitCost { get; set; }
|
||||
public decimal Value { get; set; }
|
||||
public decimal RunningBalance { get; set; }
|
||||
|
||||
public string SourceDocType { get; set; } = string.Empty;
|
||||
public long SourceDocId { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Inter-warehouse stock transfer header (FR-STK-05/06). Dispatch consumes source
|
||||
/// FIFO layers into in-transit; receive creates the destination layer at the
|
||||
/// inherited cost (cost-preserving). Mutable aggregate with an
|
||||
/// <see cref="RowVersion"/> token (docs/10 C.10). Model: docs/10 Part C.6.
|
||||
/// </summary>
|
||||
public class StockTransfer
|
||||
{
|
||||
public long TransferId { get; set; }
|
||||
public string DocNo { get; set; } = string.Empty;
|
||||
|
||||
public long SrcWarehouseId { get; set; }
|
||||
public Warehouse? SrcWarehouse { get; set; }
|
||||
|
||||
public long DestWarehouseId { get; set; }
|
||||
public Warehouse? DestWarehouse { get; set; }
|
||||
|
||||
public TransferStatus Status { get; set; } = TransferStatus.Draft;
|
||||
|
||||
public long CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
public ICollection<StockTransferLine> Lines { get; set; } = new List<StockTransferLine>();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Transfer line (FR-STK-05/06). <see cref="Qty"/> is in base UOM.
|
||||
/// <para>
|
||||
/// Deviation note: <see cref="UnitCost"/> and <see cref="QtyReceived"/> extend
|
||||
/// docs/10 Part C.6's <c>STOCK_TRANSFER_LINE</c> to make the transfer
|
||||
/// cost-preserving: at dispatch the value-weighted cost of the consumed source
|
||||
/// layers is stored here, and receive recreates the destination layer at that cost
|
||||
/// (supports partial receive via <see cref="QtyReceived"/>).
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public class StockTransferLine
|
||||
{
|
||||
public long TransferLineId { get; set; }
|
||||
|
||||
public long TransferId { get; set; }
|
||||
public StockTransfer? Transfer { get; set; }
|
||||
|
||||
public long ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
|
||||
public long? SrcBinId { get; set; }
|
||||
public long? DestBinId { get; set; }
|
||||
public long? BatchId { get; set; }
|
||||
public long? SerialId { get; set; }
|
||||
|
||||
public decimal Qty { get; set; }
|
||||
|
||||
/// <summary>Value-weighted unit cost of the consumed source layers (set at dispatch).</summary>
|
||||
public decimal? UnitCost { get; set; }
|
||||
|
||||
/// <summary>Quantity already received at the destination (partial-receive support).</summary>
|
||||
public decimal QtyReceived { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Stock-adjustment lifecycle (docs/10 §B.8.1). Phase 1 auto-posts, so
|
||||
/// <see cref="PendingApproval"/> is reserved for the future threshold-approval
|
||||
/// workflow (FR-STK-07). Stored as a string.
|
||||
/// </summary>
|
||||
public enum AdjustmentStatus
|
||||
{
|
||||
Draft,
|
||||
PendingApproval,
|
||||
Posted
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>Kind of mutation recorded in the audit trail (FR-X-02). Stored as a string.</summary>
|
||||
public enum AuditAction
|
||||
{
|
||||
Create,
|
||||
Update,
|
||||
Delete
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>Stock-count lifecycle (docs/11 §8; docs/10 §B.8.1). Stored as a string.</summary>
|
||||
public enum CountStatus
|
||||
{
|
||||
Draft,
|
||||
Counted,
|
||||
Posted
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>Physical-count scope (docs/11 §8; FR-STK-08). Stored as a string.</summary>
|
||||
public enum CountType
|
||||
{
|
||||
Cycle,
|
||||
Full
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>Stock-ledger movement direction (docs/11 §8). Stored as a string.</summary>
|
||||
public enum Direction
|
||||
{
|
||||
In,
|
||||
Out
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>Goods-receipt-note lifecycle (docs/11 §8; docs/10 §B.8.1). Stored as a string.</summary>
|
||||
public enum GrnStatus
|
||||
{
|
||||
Draft,
|
||||
Confirmed,
|
||||
Closed
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Inspection-hold state of received stock (docs/11 §8; FR-GRN-05). <see cref="OnHold"/>
|
||||
/// stock is on-hand but not issuable until released (FR-WH-07). Stored as a string.
|
||||
/// </summary>
|
||||
public enum HoldStatus
|
||||
{
|
||||
Available,
|
||||
OnHold,
|
||||
Rejected
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>Where a reason code applies (FR-X-04; docs/10 §B.8.3). Stored as a string.</summary>
|
||||
public enum ReasonContext
|
||||
{
|
||||
Adjustment,
|
||||
Return,
|
||||
Count
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>Purchase-return lifecycle (docs/11 §3.4). Auto-posts in Phase 1. Stored as a string.</summary>
|
||||
public enum ReturnStatus
|
||||
{
|
||||
Draft,
|
||||
Posted
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>Stock-transfer lifecycle (docs/11 §8; docs/10 §B.8.1). Stored as a string.</summary>
|
||||
public enum TransferStatus
|
||||
{
|
||||
Draft,
|
||||
InTransit,
|
||||
Received,
|
||||
Closed
|
||||
}
|
||||
Reference in New Issue
Block a user