Initial commit

This commit is contained in:
2026-04-23 21:38:24 -04:00
commit 63e12a9636
1762 changed files with 1672620 additions and 0 deletions
@@ -0,0 +1,158 @@
using PowderCoating.Core.Enums;
namespace PowderCoating.Core.Entities;
/// <summary>
/// Chart of Accounts entry. Supports a flat or one-level hierarchy via ParentAccountId.
/// </summary>
public class Account : BaseEntity
{
public string AccountNumber { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public AccountType AccountType { get; set; }
public AccountSubType AccountSubType { get; set; }
public string? Description { get; set; }
/// <summary>Nullable FK for sub-accounts (one level deep).</summary>
public int? ParentAccountId { get; set; }
/// <summary>System accounts cannot be deleted (seeded defaults).</summary>
public bool IsSystem { get; set; } = false;
public bool IsActive { get; set; } = true;
/// <summary>Starting balance when the account was first set up in this system.</summary>
public decimal OpeningBalance { get; set; } = 0;
/// <summary>The date the opening balance is as-of. Null means it pre-dates all transactions.</summary>
public DateTime? OpeningBalanceDate { get; set; }
/// <summary>
/// Denormalized running balance kept in sync with each transaction. Positive = normal-balance direction
/// (debit-normal for Assets/Expenses/COGS; credit-normal for Liabilities/Equity/Revenue).
/// Use AccountsController.RecalculateBalances to rebuild from scratch if needed.
/// </summary>
public decimal CurrentBalance { get; set; } = 0;
// Navigation
public virtual Account? ParentAccount { get; set; }
public virtual ICollection<Account> SubAccounts { get; set; } = new List<Account>();
public virtual ICollection<BillLineItem> BillLineItems { get; set; } = new List<BillLineItem>();
public virtual ICollection<Bill> Bills { get; set; } = new List<Bill>();
public virtual ICollection<BillPayment> BillPayments { get; set; } = new List<BillPayment>();
public virtual ICollection<Expense> Expenses { get; set; } = new List<Expense>();
public virtual ICollection<Expense> ExpensePaymentAccounts { get; set; } = new List<Expense>();
}
/// <summary>
/// Vendor bill (accounts payable). Represents money owed to a supplier.
/// </summary>
public class Bill : BaseEntity
{
public string BillNumber { get; set; } = string.Empty;
/// <summary>Vendor's own invoice/reference number.</summary>
public string? VendorInvoiceNumber { get; set; }
public int VendorId { get; set; }
/// <summary>Which AP account this bill posts to (default: Accounts Payable 2000).</summary>
public int APAccountId { get; set; }
public DateTime BillDate { get; set; } = DateTime.UtcNow;
public DateTime? DueDate { get; set; }
public BillStatus Status { get; set; } = BillStatus.Draft;
public string? Terms { get; set; }
public string? Memo { get; set; }
// Financials
public decimal SubTotal { get; set; }
public decimal TaxPercent { get; set; }
public decimal TaxAmount { get; set; }
public decimal Total { get; set; }
public decimal AmountPaid { get; set; }
[System.ComponentModel.DataAnnotations.Schema.NotMapped]
public decimal BalanceDue => Total - AmountPaid;
/// <summary>Blob path to an attached receipt/invoice document (PDF or image).</summary>
public string? ReceiptFilePath { get; set; }
// Navigation
public virtual Vendor Vendor { get; set; } = null!;
public virtual Account APAccount { get; set; } = null!;
public virtual ICollection<BillLineItem> LineItems { get; set; } = new List<BillLineItem>();
public virtual ICollection<BillPayment> Payments { get; set; } = new List<BillPayment>();
}
/// <summary>
/// A single line on a vendor bill, posted to an expense or asset account.
/// </summary>
public class BillLineItem : BaseEntity
{
public int BillId { get; set; }
/// <summary>Expense/asset account this line item is categorized under. Nullable for QB-imported bills where account is unknown.</summary>
public int? AccountId { get; set; }
/// <summary>Optional job costing link.</summary>
public int? JobId { get; set; }
public string Description { get; set; } = string.Empty;
public decimal Quantity { get; set; } = 1;
public decimal UnitPrice { get; set; }
public decimal Amount { get; set; }
public int DisplayOrder { get; set; }
// Navigation
public virtual Bill Bill { get; set; } = null!;
public virtual Account? Account { get; set; }
public virtual Job? Job { get; set; }
}
/// <summary>
/// A payment made against a vendor bill.
/// </summary>
public class BillPayment : BaseEntity
{
public string PaymentNumber { get; set; } = string.Empty;
public int BillId { get; set; }
/// <summary>Denormalized for AP reporting without joining through Bill.</summary>
public int VendorId { get; set; }
/// <summary>Bank/cash account the payment came out of.</summary>
public int BankAccountId { get; set; }
public DateTime PaymentDate { get; set; } = DateTime.UtcNow;
public decimal Amount { get; set; }
public PaymentMethod PaymentMethod { get; set; }
public string? CheckNumber { get; set; }
public string? Memo { get; set; }
// Navigation
public virtual Bill Bill { get; set; } = null!;
public virtual Vendor Vendor { get; set; } = null!;
public virtual Account BankAccount { get; set; } = null!;
}
/// <summary>
/// A direct expense paid immediately (not via a bill). Covers cash/card purchases.
/// </summary>
public class Expense : BaseEntity
{
public string ExpenseNumber { get; set; } = string.Empty;
public DateTime Date { get; set; } = DateTime.UtcNow;
/// <summary>Optional vendor the expense was paid to.</summary>
public int? VendorId { get; set; }
/// <summary>Expense category account (e.g. 6200 Powder & Materials).</summary>
public int ExpenseAccountId { get; set; }
/// <summary>Account money came out of (e.g. 1000 Checking, 2100 Credit Card).</summary>
public int PaymentAccountId { get; set; }
/// <summary>Optional job costing link.</summary>
public int? JobId { get; set; }
public PaymentMethod PaymentMethod { get; set; }
public decimal Amount { get; set; }
public string? Memo { get; set; }
public string? ReceiptFilePath { get; set; }
// Navigation
public virtual Vendor? Vendor { get; set; }
public virtual Account ExpenseAccount { get; set; } = null!;
public virtual Account PaymentAccount { get; set; } = null!;
public virtual Job? Job { get; set; }
}