new updates
This commit is contained in:
@@ -13,4 +13,7 @@ public class Batch
|
||||
|
||||
public string BatchNo { get; set; } = string.Empty;
|
||||
public DateOnly? ExpiryDate { get; set; }
|
||||
|
||||
/// <summary>Optional scan code for barcode/RFID lookup (unique when set).</summary>
|
||||
public string? Barcode { get; set; }
|
||||
}
|
||||
|
||||
@@ -17,6 +17,12 @@ public class BranchConfig
|
||||
|
||||
public bool BranchingEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>Independent sub-toggle: when the global <see cref="BranchingEnabled"/> is on
|
||||
/// but this is off, Warehouses stop asking for/showing a branch while Employees etc.
|
||||
/// still do. Meaningless when <see cref="BranchingEnabled"/> is off (everything is
|
||||
/// single-branch already).</summary>
|
||||
public bool WarehouseBranchingEnabled { get; set; } = true;
|
||||
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
public int? UpdatedBy { get; set; }
|
||||
|
||||
@@ -29,6 +29,9 @@ public class Customer
|
||||
public int? DefaultWarehouseId { get; set; }
|
||||
public Warehouse? DefaultWarehouse { get; set; }
|
||||
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
|
||||
public EntityStatus Status { get; set; } = EntityStatus.Active;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
@@ -14,6 +14,9 @@ public class Item
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>Optional scan code for barcode/RFID lookup (unique when set).</summary>
|
||||
public string? Barcode { get; set; }
|
||||
|
||||
public int CategoryId { get; set; }
|
||||
public Category? Category { get; set; }
|
||||
|
||||
@@ -41,7 +44,14 @@ public class Item
|
||||
public Warranty Warranty { get; set; } = Warranty.NonWarranty;
|
||||
/// <summary>Coverage length in months (see <see cref="Enums.WarrantyPeriods.AllowedMonths"/>) when <see cref="Warranty"/> is Warranty; null otherwise.</summary>
|
||||
public int? WarrantyPeriodMonths { get; set; }
|
||||
public string? TaxClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The tax rate a sales/purchase line for this item defaults to (see
|
||||
/// <see cref="TaxRate"/>) — replaces the old free-text "tax class" label that nothing
|
||||
/// ever read. Null means no default; a line must be given an explicit tax percentage.
|
||||
/// </summary>
|
||||
public int? TaxRateId { get; set; }
|
||||
public TaxRate? TaxRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional selling price range and flat price used by Sales only.
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// A single raised notification event (e.g. "GRN Confirmed"). Broadcast to
|
||||
/// active users via <see cref="NotificationRecipient"/> rows, gated by
|
||||
/// whether the module's InApp channel is enabled in <see cref="NotificationConfig"/>.
|
||||
/// </summary>
|
||||
public class Notification
|
||||
{
|
||||
public int NotificationId { get; set; }
|
||||
|
||||
public string ModuleKey { get; set; } = string.Empty;
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
||||
public string? RelatedEntityType { get; set; }
|
||||
public int? RelatedEntityId { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public ICollection<NotificationRecipient> Recipients { get; set; } = new List<NotificationRecipient>();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Per-user read state for a broadcast <see cref="Notification"/>.
|
||||
/// </summary>
|
||||
public class NotificationRecipient
|
||||
{
|
||||
public int NotificationRecipientId { get; set; }
|
||||
|
||||
public int NotificationId { get; set; }
|
||||
public Notification? Notification { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
public User? User { get; set; }
|
||||
|
||||
public bool IsRead { get; set; }
|
||||
public DateTime? ReadAt { get; set; }
|
||||
}
|
||||
@@ -10,6 +10,10 @@ public class NumberSequence
|
||||
{
|
||||
public int SequenceId { get; set; }
|
||||
public string DocType { get; set; } = string.Empty;
|
||||
/// <summary>Per-branch counter key (docs/BRANCH_ISOLATION_PLAN.md §5) — backfilled to the
|
||||
/// deployment's default branch for rows that predate per-branch numbering.</summary>
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
public int Year { get; set; }
|
||||
public int LastNumber { get; set; }
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ public class PurchaseInvoice
|
||||
public int VendorId { get; set; }
|
||||
public Vendor? Vendor { get; set; }
|
||||
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
|
||||
public string VendorSnapshotName { get; set; } = string.Empty;
|
||||
public string? VendorSnapshotTaxNo { get; set; }
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@ namespace ERPCore.Domain.Entities;
|
||||
/// <summary>
|
||||
/// Purchase order header (FR-PROC-03..06). Mutable aggregate with a
|
||||
/// <see cref="RowVersion"/> ETag token; editable while open (FR-PROC-05).
|
||||
/// Phase 1 auto-approves on creation; <see cref="ApprovalRequired"/> is retained
|
||||
/// for the future approval workflow. Totals are computed server-side from lines
|
||||
/// (not stored). Model: docs/10 Part C.2.
|
||||
/// A submitted/issued PO goes to <see cref="PurchaseOrderStatus.PendingApproval"/> and
|
||||
/// needs a separate Approve action (an Admin who isn't <see cref="CreatedBy"/>) before it
|
||||
/// reaches <see cref="PurchaseOrderStatus.Approved"/>. Totals are computed server-side
|
||||
/// from lines (not stored). Model: docs/10 Part C.2.
|
||||
/// </summary>
|
||||
public class PurchaseOrder
|
||||
{
|
||||
@@ -17,15 +18,25 @@ public class PurchaseOrder
|
||||
public int VendorId { get; set; }
|
||||
public Vendor? Vendor { get; set; }
|
||||
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
|
||||
public int? RequisitionId { get; set; }
|
||||
public Requisition? Requisition { get; set; }
|
||||
|
||||
public PurchaseOrderStatus Status { get; set; } = PurchaseOrderStatus.Draft;
|
||||
/// <summary>True once the PO has been (or needs to be) routed through approval —
|
||||
/// i.e. it is not a still-editable Draft.</summary>
|
||||
public bool ApprovalRequired { get; set; }
|
||||
|
||||
public int CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
|
||||
/// <summary>Who approved this PO — set only when <see cref="Status"/> reaches Approved.</summary>
|
||||
public int? ApprovedBy { get; set; }
|
||||
public User? Approver { get; set; }
|
||||
public DateTime? ApprovedAt { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ public class Requisition
|
||||
public int RequestedBy { get; set; }
|
||||
public User? Requester { get; set; }
|
||||
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
|
||||
public RequisitionStatus Status { get; set; } = RequisitionStatus.Draft;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ public class Rfq
|
||||
public int RequisitionId { get; set; }
|
||||
public Requisition? Requisition { get; set; }
|
||||
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
|
||||
public RfqStatus Status { get; set; } = RfqStatus.Open;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>Join row granting a <see cref="Role"/> visibility of a <see cref="Permission"/> (nav node).</summary>
|
||||
@@ -6,6 +8,13 @@ public class RolePermission
|
||||
public int RoleId { get; set; }
|
||||
public int PermissionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Which mutating actions the role may perform within this permission's module
|
||||
/// (see <see cref="RolePermissionAction"/>); defaults to <see cref="RolePermissionAction.All"/>
|
||||
/// so existing grants keep today's behavior until an admin narrows them.
|
||||
/// </summary>
|
||||
public RolePermissionAction Actions { get; set; } = RolePermissionAction.All;
|
||||
|
||||
public Role? Role { get; set; }
|
||||
public Permission? Permission { get; set; }
|
||||
}
|
||||
|
||||
@@ -27,6 +27,16 @@ public class SalesDayEnd
|
||||
public decimal TaxTotal { get; set; }
|
||||
public decimal GrandTotal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sum of <see cref="SalesSlip.PaidAmount"/> across the day's slips (bundle sales have no
|
||||
/// partial-payment field and are always counted as fully paid) — what actually gets debited
|
||||
/// to Cash on close. <see cref="BalanceTotal"/> is the rest (<c>GrandTotal - PaidTotal</c>),
|
||||
/// debited to Accounts Receivable instead. Before partial payments existed these were always
|
||||
/// equal to GrandTotal/0 respectively (every sale was assumed fully cash).
|
||||
/// </summary>
|
||||
public decimal PaidTotal { get; set; }
|
||||
public decimal BalanceTotal { get; set; }
|
||||
|
||||
/// <summary>Sum of the FIFO cost consumed for these slips (from <see cref="StockLedger"/>), for the COGS GL lines.</summary>
|
||||
public decimal CostOfGoodsSold { get; set; }
|
||||
|
||||
|
||||
@@ -19,6 +19,12 @@ public class SalesSlipLine
|
||||
public int WarehouseId { get; set; }
|
||||
public Warehouse? Warehouse { get; set; }
|
||||
|
||||
public int? BatchId { get; set; }
|
||||
public Batch? Batch { get; set; }
|
||||
|
||||
public int? SerialId { get; set; }
|
||||
public Serial? Serial { get; set; }
|
||||
|
||||
public decimal UnitPrice { get; set; }
|
||||
public decimal BaseCost { get; set; }
|
||||
public string PriceSource { get; set; } = string.Empty;
|
||||
|
||||
@@ -13,4 +13,7 @@ public class Serial
|
||||
|
||||
public string SerialNo { get; set; } = string.Empty;
|
||||
public string Status { get; set; } = "InStock";
|
||||
|
||||
/// <summary>Optional scan code for barcode/RFID lookup (unique when set).</summary>
|
||||
public string? Barcode { get; set; }
|
||||
}
|
||||
|
||||
@@ -16,6 +16,12 @@ public class StockCountLine
|
||||
|
||||
public int? BinId { get; set; }
|
||||
|
||||
public int? BatchId { get; set; }
|
||||
public Batch? Batch { get; set; }
|
||||
|
||||
public int? SerialId { get; set; }
|
||||
public Serial? Serial { get; set; }
|
||||
|
||||
public decimal SystemQty { get; set; }
|
||||
public decimal? CountedQty { get; set; }
|
||||
public decimal? Variance { get; set; }
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// A help-desk ticket raised by a user from the Help page. Status is
|
||||
/// admin-managed; the conversation is a flat thread of <see cref="SupportTicketMessage"/> rows.
|
||||
/// Field/concurrency shape follows the same conventions as <see cref="Employee"/>
|
||||
/// (CreatedBy/UpdatedBy actor stamps, RowVersion for optimistic concurrency).
|
||||
/// </summary>
|
||||
public class SupportTicket
|
||||
{
|
||||
public int TicketId { get; set; }
|
||||
|
||||
public string Subject { get; set; } = string.Empty;
|
||||
public TicketStatus Status { get; set; } = TicketStatus.Open;
|
||||
|
||||
public int CreatedBy { get; set; }
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
public int? UpdatedBy { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
public ICollection<SupportTicketMessage> Messages { get; set; } = new List<SupportTicketMessage>();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>One message in a <see cref="SupportTicket"/> thread — from the submitter or an admin.</summary>
|
||||
public class SupportTicketMessage
|
||||
{
|
||||
public int MessageId { get; set; }
|
||||
|
||||
public int TicketId { get; set; }
|
||||
public SupportTicket? Ticket { get; set; }
|
||||
|
||||
public int SenderUserId { get; set; }
|
||||
public bool IsFromAdmin { get; set; }
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// A named tax rate (e.g. "Standard" 15%, "Zero-Rated" 0%, "Exempt" 0%) — the real backing
|
||||
/// for <see cref="Item.TaxRateId"/>. Before this existed, <c>Item.TaxClass</c> was a free-text
|
||||
/// label nothing ever read, and every sales/purchase line carried its own hand-typed tax
|
||||
/// percentage with no link back to the item at all. Now a line's tax defaults to whatever
|
||||
/// percentage the item's assigned TaxRate carries at the moment the line is created — change
|
||||
/// the rate here and every new document picks it up; a line already created keeps the percentage
|
||||
/// it was given (SalesSlipLine.TaxPct etc. are snapshots, never recomputed from this table).
|
||||
/// </summary>
|
||||
public class TaxRate
|
||||
{
|
||||
public int TaxRateId { get; set; }
|
||||
public string Code { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public decimal Percentage { get; set; }
|
||||
public EntityStatus Status { get; set; } = EntityStatus.Active;
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
/// <summary>PostgreSQL xmin-backed optimistic concurrency token (ETag source).</summary>
|
||||
public uint RowVersion { get; set; }
|
||||
}
|
||||
@@ -17,6 +17,9 @@ public class Vendor
|
||||
public string Currency { get; set; } = "LKR";
|
||||
public EntityStatus Status { get; set; } = EntityStatus.Active;
|
||||
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ public class Warehouse
|
||||
public int WarehouseId { get; set; }
|
||||
public string Code { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Address { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Purchase-order lifecycle (docs/11 §8; docs/10 §B.8.1). Phase 1 auto-approves on
|
||||
/// creation, so <see cref="PendingApproval"/> is reserved (not entered) until the
|
||||
/// approval workflow is enabled (FR-PROC-04). Stored as a string.
|
||||
/// Purchase-order lifecycle (docs/11 §8; docs/10 §B.8.1). Issuing a PO (create
|
||||
/// non-draft, or submit a Draft) enters <see cref="PendingApproval"/>; an Admin who
|
||||
/// isn't the creator must Approve it to reach <see cref="Approved"/>, or Reject it back
|
||||
/// to <see cref="Draft"/> (FR-PROC-04). Stored as a string.
|
||||
/// </summary>
|
||||
public enum PurchaseOrderStatus
|
||||
{
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Fine-grained actions a <see cref="Entities.RolePermission"/> can grant within a module
|
||||
/// it already has nav-level access to (see <see cref="Infra.Auth.NavPolicies"/>). Nav-level
|
||||
/// access answers "can this role reach this module"; this answers "which mutations within
|
||||
/// it can this role actually perform" — e.g. a role that can see Procurement but should not
|
||||
/// be able to delete or approve purchase orders.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum RolePermissionAction
|
||||
{
|
||||
None = 0,
|
||||
View = 1,
|
||||
Create = 2,
|
||||
Edit = 4,
|
||||
Delete = 8,
|
||||
Approve = 16,
|
||||
|
||||
All = View | Create | Edit | Delete | Approve
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
public enum TicketStatus
|
||||
{
|
||||
Open,
|
||||
InProgress,
|
||||
Resolved
|
||||
}
|
||||
Reference in New Issue
Block a user