100 lines
14 KiB
C#
100 lines
14 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using PowderCoating.Core.Entities;
|
|
using PowderCoating.Core.Enums;
|
|
|
|
namespace PowderCoating.Infrastructure.Services;
|
|
|
|
public partial class SeedDataService
|
|
{
|
|
/// <summary>
|
|
/// Seeds a default chart of accounts for a newly onboarded company, covering all five
|
|
/// standard double-entry categories: Assets, Liabilities, Equity, Revenue (with separate
|
|
/// powder coating and sandblasting lines), Cost of Goods Sold, and Expenses.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Idempotency: returns 0 immediately if any non-deleted accounts already exist for this
|
|
/// company, so re-running seed does not produce duplicate account numbers.
|
|
/// </para>
|
|
/// <para>
|
|
/// Several accounts are marked <c>IsSystem = true</c> (Checking, AR, AP, and main Powder
|
|
/// Coating Revenue). System accounts are referenced by account number in other seeders
|
|
/// (e.g. <c>SeedInvoicesAsync</c> looks up account "4000" for invoice line items) and
|
|
/// should not be renamed or deleted by end users.
|
|
/// </para>
|
|
/// <para>
|
|
/// Account numbers follow a conventional small-business numbering scheme:
|
|
/// 1xxx = Assets, 2xxx = Liabilities, 3xxx = Equity, 4xxx = Revenue,
|
|
/// 5xxx = Cost of Goods Sold, 6xxx = Expenses. This makes the chart immediately
|
|
/// recognisable to accountants without custom configuration.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="company">The tenant company to seed the chart of accounts for.</param>
|
|
/// <returns>Number of account records inserted, or 0 if already seeded.</returns>
|
|
private async Task<int> SeedDefaultChartOfAccountsAsync(Company company)
|
|
{
|
|
var existingCount = await _context.Set<Account>()
|
|
.IgnoreQueryFilters()
|
|
.CountAsync(a => a.CompanyId == company.Id && !a.IsDeleted);
|
|
|
|
if (existingCount > 0)
|
|
return 0; // Already seeded
|
|
|
|
var now = DateTime.UtcNow;
|
|
var accounts = new List<Account>
|
|
{
|
|
// ── ASSETS ────────────────────────────────────────────────────────
|
|
new Account { AccountNumber = "1000", Name = "Checking Account", AccountType = AccountType.Asset, AccountSubType = AccountSubType.Checking, IsSystem = true, IsActive = true, Description = "Primary business checking account", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "1010", Name = "Savings Account", AccountType = AccountType.Asset, AccountSubType = AccountSubType.Savings, IsSystem = false, IsActive = true, Description = "Business savings account", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "1100", Name = "Accounts Receivable", AccountType = AccountType.Asset, AccountSubType = AccountSubType.AccountsReceivable, IsSystem = true, IsActive = true, Description = "Amounts owed by customers for services", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "1200", Name = "Inventory - Powder", AccountType = AccountType.Asset, AccountSubType = AccountSubType.Inventory, IsSystem = false, IsActive = true, Description = "Powder coating materials in stock", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "1210", Name = "Inventory - Consumables", AccountType = AccountType.Asset, AccountSubType = AccountSubType.Inventory, IsSystem = false, IsActive = true, Description = "Masking, tape, and other consumables", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "1300", Name = "Equipment", AccountType = AccountType.Asset, AccountSubType = AccountSubType.FixedAsset, IsSystem = false, IsActive = true, Description = "Ovens, booths, sandblasters, and equipment", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "1310", Name = "Accumulated Depreciation", AccountType = AccountType.Asset, AccountSubType = AccountSubType.FixedAsset, IsSystem = false, IsActive = true, Description = "Accumulated depreciation on equipment", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "1400", Name = "Prepaid Expenses", AccountType = AccountType.Asset, AccountSubType = AccountSubType.OtherCurrentAsset, IsSystem = false, IsActive = true, Description = "Prepaid insurance, rent, and other items", CompanyId = company.Id, CreatedAt = now },
|
|
|
|
// ── LIABILITIES ───────────────────────────────────────────────────
|
|
new Account { AccountNumber = "2000", Name = "Accounts Payable", AccountType = AccountType.Liability, AccountSubType = AccountSubType.AccountsPayable, IsSystem = true, IsActive = true, Description = "Amounts owed to suppliers and vendors", CompanyId = company.Id, CreatedAt = now },
|
|
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 = "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 ────────────────────────────────────────────────────────
|
|
new Account { AccountNumber = "3000", Name = "Owner's Equity", AccountType = AccountType.Equity, AccountSubType = AccountSubType.OwnersEquity, IsSystem = false, IsActive = true, Description = "Owner's invested capital", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "3100", Name = "Retained Earnings", AccountType = AccountType.Equity, AccountSubType = AccountSubType.RetainedEarnings, IsSystem = false, IsActive = true, Description = "Cumulative net income retained in business", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "3200", Name = "Owner's Draw", AccountType = AccountType.Equity, AccountSubType = AccountSubType.OwnersEquity, IsSystem = false, IsActive = true, Description = "Withdrawals by owner", CompanyId = company.Id, CreatedAt = now },
|
|
|
|
// ── REVENUE ───────────────────────────────────────────────────────
|
|
new Account { AccountNumber = "4000", Name = "Powder Coating Revenue", AccountType = AccountType.Revenue, AccountSubType = AccountSubType.Sales, IsSystem = true, IsActive = true, Description = "Revenue from powder coating services", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "4100", Name = "Sandblasting Revenue", AccountType = AccountType.Revenue, AccountSubType = AccountSubType.ServiceRevenue, IsSystem = false, IsActive = true, Description = "Revenue from sandblasting services", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "4200", Name = "Other Service Revenue", AccountType = AccountType.Revenue, AccountSubType = AccountSubType.ServiceRevenue, IsSystem = false, IsActive = true, Description = "Revenue from other shop services", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "4900", Name = "Other Income", AccountType = AccountType.Revenue, AccountSubType = AccountSubType.OtherIncome, IsSystem = false, IsActive = true, Description = "Miscellaneous income", CompanyId = company.Id, CreatedAt = now },
|
|
|
|
// ── COST OF GOODS SOLD ────────────────────────────────────────────
|
|
new Account { AccountNumber = "5000", Name = "Cost of Goods Sold", AccountType = AccountType.CostOfGoods, AccountSubType = AccountSubType.CostOfGoodsSold, IsSystem = false, IsActive = true, Description = "Direct cost of services delivered", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "5100", Name = "Powder & Materials", AccountType = AccountType.CostOfGoods, AccountSubType = AccountSubType.CostOfGoodsSold, IsSystem = false, IsActive = true, Description = "Powder coatings and direct materials used", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "5200", Name = "Consumables & Shop Supplies", AccountType = AccountType.CostOfGoods, AccountSubType = AccountSubType.CostOfGoodsSold, IsSystem = false, IsActive = true, Description = "Masking, tape, and other job supplies", CompanyId = company.Id, CreatedAt = now },
|
|
|
|
// ── EXPENSES ──────────────────────────────────────────────────────
|
|
new Account { AccountNumber = "6000", Name = "Advertising & Marketing", AccountType = AccountType.Expense, AccountSubType = AccountSubType.Advertising, IsSystem = false, IsActive = true, Description = "Advertising, marketing, and promotions", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6100", Name = "Equipment & Repairs", AccountType = AccountType.Expense, AccountSubType = AccountSubType.Equipment, IsSystem = false, IsActive = true, Description = "Equipment maintenance and repair costs", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6200", Name = "Insurance", AccountType = AccountType.Expense, AccountSubType = AccountSubType.Insurance, IsSystem = false, IsActive = true, Description = "Business, liability, and equipment insurance", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6300", Name = "Payroll & Labor", AccountType = AccountType.Expense, AccountSubType = AccountSubType.Payroll, IsSystem = false, IsActive = true, Description = "Wages, salaries, and payroll taxes", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6400", Name = "Professional Fees", AccountType = AccountType.Expense, AccountSubType = AccountSubType.ProfessionalFees, IsSystem = false, IsActive = true, Description = "Accounting, legal, and consulting fees", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6500", Name = "Rent & Facilities", AccountType = AccountType.Expense, AccountSubType = AccountSubType.Rent, IsSystem = false, IsActive = true, Description = "Shop rent and facility costs", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6600", Name = "Utilities", AccountType = AccountType.Expense, AccountSubType = AccountSubType.Utilities, IsSystem = false, IsActive = true, Description = "Electric, gas, water, and internet", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6700", Name = "Vehicle & Transportation", AccountType = AccountType.Expense, AccountSubType = AccountSubType.Vehicle, IsSystem = false, IsActive = true, Description = "Fuel, vehicle maintenance, and transport", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6800", Name = "Office Supplies", AccountType = AccountType.Expense, AccountSubType = AccountSubType.OfficeSupplies, IsSystem = false, IsActive = true, Description = "General office and administrative supplies", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6900", Name = "Bank Charges & Fees", AccountType = AccountType.Expense, AccountSubType = AccountSubType.BankCharges, IsSystem = false, IsActive = true, Description = "Bank fees, merchant processing, and wire fees", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6950", Name = "Depreciation Expense", AccountType = AccountType.Expense, AccountSubType = AccountSubType.Depreciation, IsSystem = false, IsActive = true, Description = "Depreciation on fixed assets", CompanyId = company.Id, CreatedAt = now },
|
|
new Account { AccountNumber = "6990", Name = "Other Expenses", AccountType = AccountType.Expense, AccountSubType = AccountSubType.Other, IsSystem = false, IsActive = true, Description = "Miscellaneous business expenses", CompanyId = company.Id, CreatedAt = now },
|
|
};
|
|
|
|
await _context.Set<Account>().AddRangeAsync(accounts);
|
|
await _context.SaveChangesAsync();
|
|
|
|
return accounts.Count;
|
|
}
|
|
}
|