Track store credit as a Customer Credits liability (GL)
Audit finding 9b: store-credit refunds and credit memos posted nothing to the GL on issue (only a CreditMemo + Customer.CreditBalance), so outstanding store credit was invisible on the balance sheet and the contra-revenue was recognized only on apply. Introduces a 2350 "Customer Credits" liability so the credit is on the books from issue to apply. Model (chosen): lifecycle-equivalent to before, plus the liability is tracked. - Issue (credit memos, goodwill, and store-credit refunds): DR Sales Discounts (4950) / CR Customer Credits (2350). - Apply: DR Customer Credits / CR AR (was DR Sales Discounts / CR AR). - Void unapplied remainder: DR Customer Credits / CR Sales Discounts. Posting updated in all 8 sites: CreditMemosController Create/Apply/Void and InvoicesController IssueCreditMemo/IssueRefund(store credit)/ApplyCredit/ VoidCreditMemo/CancelRefund. New 2350 account (seed + self-heal). Reporting moved in lockstep so the books still balance: the 4950 contra-revenue shifts from applied -> issued (active memos in full + applied portion of voided), the 2350 liability = unapplied balance on active memos, AR still credited by applications. Updated in FinancialReportService (balance sheet retained earnings, trial balance, P&L) and LedgerService (per-account + prior-balance 2350 section). Verified the balance-sheet identity for active and voided memos by hand; new ledger test covers the 2350 lifecycle. Build clean; 284 unit tests pass. Note: pre-existing quirks left untouched (out of 9b scope) — account 2300 is seeded as "Payroll Liabilities" but resolved as Customer Deposits in code, and LedgerService doesn't recompute 4950 so RecalculateBalances understates it; both predate this change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -61,6 +61,7 @@ public partial class SeedDataService
|
||||
new Account { AccountNumber = "2100", Name = "Credit Card Payable", AccountType = AccountType.Liability, AccountSubType = AccountSubType.CreditCard, IsSystem = false, IsActive = true, Description = "Business credit card balance", CompanyId = company.Id, CreatedAt = now },
|
||||
new Account { AccountNumber = "2200", Name = "Sales Tax Payable", AccountType = AccountType.Liability, AccountSubType = AccountSubType.OtherCurrentLiability, IsSystem = false, IsActive = true, Description = "Sales tax collected and owed to government", CompanyId = company.Id, CreatedAt = now },
|
||||
new Account { AccountNumber = "2300", Name = "Payroll Liabilities", AccountType = AccountType.Liability, AccountSubType = AccountSubType.OtherCurrentLiability, IsSystem = false, IsActive = true, Description = "Payroll taxes and withholdings owed", CompanyId = company.Id, CreatedAt = now },
|
||||
new Account { AccountNumber = "2350", Name = "Customer Credits", AccountType = AccountType.Liability, AccountSubType = AccountSubType.OtherCurrentLiability, IsSystem = true, IsActive = true, Description = "Store credit owed to customers (credit memos not yet applied)", CompanyId = company.Id, CreatedAt = now },
|
||||
new Account { AccountNumber = "2900", Name = "Business Loan", AccountType = AccountType.Liability, AccountSubType = AccountSubType.LongTermLiability, IsSystem = false, IsActive = true, Description = "Long-term equipment or business loan", CompanyId = company.Id, CreatedAt = now },
|
||||
|
||||
// ── EQUITY ────────────────────────────────────────────────────────
|
||||
@@ -166,6 +167,30 @@ public partial class SeedDataService
|
||||
added++;
|
||||
}
|
||||
|
||||
// 2350 Customer Credits — liability for store credit owed to customers. Credited when a credit
|
||||
// memo (incl. store-credit refunds) is issued; debited when applied to an invoice.
|
||||
var has2350 = await _context.Set<Account>()
|
||||
.IgnoreQueryFilters()
|
||||
.AnyAsync(a => a.CompanyId == company.Id && a.AccountNumber == "2350" && !a.IsDeleted);
|
||||
|
||||
if (!has2350)
|
||||
{
|
||||
_context.Set<Account>().Add(new Account
|
||||
{
|
||||
AccountNumber = "2350",
|
||||
Name = "Customer Credits",
|
||||
AccountType = AccountType.Liability,
|
||||
AccountSubType = AccountSubType.OtherCurrentLiability,
|
||||
IsSystem = true,
|
||||
IsActive = true,
|
||||
Description = "Store credit owed to customers (credit memos not yet applied)",
|
||||
CompanyId = company.Id,
|
||||
CreatedAt = now
|
||||
});
|
||||
await _context.SaveChangesAsync();
|
||||
added++;
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user