Phase G: Add Budgeting and Year-End Close
Budgeting: - Budget + BudgetLine entities with Jan–Dec monthly columns per GL account - BudgetsController: Index, Create, Edit, SetDefault, Copy, Delete - Copy action rolls a budget forward to a new fiscal year - Budget vs. Actual report (BudgetVsActual): compares monthly budget amounts to real P&L by calling GetProfitAndLossAsync once per month; variance shown as favorable/unfavorable; year + budget selectors in header - Views: Budgets/Index, Create, Edit with inline annual totals via budget-edit.js - Nav link + report card on Landing Year-End Close: - YearEndClose entity records each closed year + JE reference for audit trail - AccountsController.YearEndClose GET (history + form) + CloseYear POST - Close zeroes all Revenue and Expense/COGS account balances into Retained Earnings via IAccountBalanceService and posts a supporting JE dated Dec 31 - Idempotency: rejects attempt to close an already-closed year - Pre-close checklist in view to guide the workflow - Nav link under Finance Migration AddBudgetsAndYearEndClose applied Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -395,3 +395,62 @@ public class FixedAssetDepreciationEntry : BaseEntity
|
||||
public virtual FixedAsset FixedAsset { get; set; } = null!;
|
||||
public virtual JournalEntry? JournalEntry { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A named annual budget. Contains one BudgetLine per account per month. Supports
|
||||
/// multiple budgets per fiscal year (e.g. "Conservative" vs "Optimistic") but only
|
||||
/// one is marked IsDefault for the Budget vs. Actual report.
|
||||
/// </summary>
|
||||
public class Budget : BaseEntity
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public int FiscalYear { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
public bool IsDefault { get; set; } = false;
|
||||
|
||||
public virtual ICollection<BudgetLine> Lines { get; set; } = new List<BudgetLine>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Monthly budget amount for one account within a Budget. Jan–Dec stored as separate
|
||||
/// columns so the grid editor can write them in a single POST without a line-item loop.
|
||||
/// Annual is a computed property summing all twelve months.
|
||||
/// </summary>
|
||||
public class BudgetLine : BaseEntity
|
||||
{
|
||||
public int BudgetId { get; set; }
|
||||
public int AccountId { get; set; }
|
||||
|
||||
public decimal Jan { get; set; }
|
||||
public decimal Feb { get; set; }
|
||||
public decimal Mar { get; set; }
|
||||
public decimal Apr { get; set; }
|
||||
public decimal May { get; set; }
|
||||
public decimal Jun { get; set; }
|
||||
public decimal Jul { get; set; }
|
||||
public decimal Aug { get; set; }
|
||||
public decimal Sep { get; set; }
|
||||
public decimal Oct { get; set; }
|
||||
public decimal Nov { get; set; }
|
||||
public decimal Dec { get; set; }
|
||||
|
||||
public decimal Annual => Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec;
|
||||
|
||||
public virtual Budget Budget { get; set; } = null!;
|
||||
public virtual Account Account { get; set; } = null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Records a completed year-end close. The close posts a JE that zeroes all
|
||||
/// Revenue and Expense account balances into Retained Earnings, and marks
|
||||
/// the year as closed so it cannot be closed again.
|
||||
/// </summary>
|
||||
public class YearEndClose : BaseEntity
|
||||
{
|
||||
public int ClosedYear { get; set; }
|
||||
public DateTime ClosedAt { get; set; } = DateTime.UtcNow;
|
||||
public string? ClosedBy { get; set; }
|
||||
public int JournalEntryId { get; set; }
|
||||
|
||||
public virtual JournalEntry JournalEntry { get; set; } = null!;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user