Phase C: Add Manual Journal Entries (double-entry GL)

- JournalEntry + JournalEntryLine entities with Draft/Posted/Reversed lifecycle
- JournalEntryStatus enum (Draft, Posted, Reversed)
- Migration AddJournalEntries: two new tables with self-referencing reversal FK
- IUnitOfWork/UnitOfWork wired with JournalEntries + JournalEntryLines repos
- ApplicationDbContext: DbSets, tenant query filters, reversal FK config
- LedgerService: JE lines added as 10th source in GetAccountLedgerAsync and ComputePriorBalanceAsync
- JournalEntriesController: Index (All/Draft/Posted tabs), Create, Details, Post, Reverse, Delete
- Views: Index, Create (dynamic balanced line grid with running debit/credit totals), Details
- journal-entry-create.js: dynamic line management with balance indicator
- Nav: Journal Entries added to Finance section in _Layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-09 23:56:03 -04:00
parent 0afb474c3e
commit a33687f7bd
15 changed files with 11017 additions and 3 deletions
@@ -142,6 +142,10 @@ public class UnitOfWork : IUnitOfWork
private IRepository<BillPayment>? _billPayments;
private IRepository<Expense>? _expenses;
// Manual Journal Entries
private IRepository<JournalEntry>? _journalEntries;
private IRepository<JournalEntryLine>? _journalEntryLines;
/// <summary>
/// Initialises the unit of work with the scoped <paramref name="context"/>.
/// The context is shared across all repositories created by this instance so that
@@ -513,6 +517,15 @@ public class UnitOfWork : IUnitOfWork
public IRepository<Expense> Expenses =>
_expenses ??= new Repository<Expense>(_context);
// Manual Journal Entries
/// <summary>Repository for <see cref="JournalEntry"/> double-entry manual journal entries; tenant-filtered with soft delete.</summary>
public IRepository<JournalEntry> JournalEntries =>
_journalEntries ??= new Repository<JournalEntry>(_context);
/// <summary>Repository for <see cref="JournalEntryLine"/> individual debit/credit lines within a journal entry.</summary>
public IRepository<JournalEntryLine> JournalEntryLines =>
_journalEntryLines ??= new Repository<JournalEntryLine>(_context);
/// <summary>
/// Flushes all pending changes in the EF Core change tracker to the database.
/// Returns the number of state entries written.