Distribution_GL Initialization

This commit is contained in:
2026-10-20 13:07:07 +05:30
commit 3f16e0cb44
194 changed files with 35659 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
using General_Ledger_Service.Exceptions;
using General_Ledger_Service.Interfaces.Repositories;
using General_Ledger_Service.Models;
namespace General_Ledger_Service.Services
{
// Extracted from AccountService (2026-07-31) so BankService's auto-created "Bank"/"Cash" GL
// hierarchy (see BankService.CreateBankAccountAsync/CreateCashAccountAsync) can reuse the same
// Rule 8.1 code-generation scheme instead of duplicating it - same shared-static-helper shape
// as RecursiveTreeQueries/DepthGuard (CLAUDE.md Rule 11), not a base class.
public static class AccountCodeGenerator
{
private static readonly Dictionary<short, int> AccountTypeBlockStart = new()
{
[1] = 1000, // Asset
[2] = 2000, // Liability
[3] = 3000, // Equity
[4] = 4000, // Income
[5] = 5000 // Expense
};
public static async Task<string> GenerateAsync(IAccountRepository accountRepository, short accountTypeId, Account? parent)
{
if (parent != null)
{
for (var suffix = 1; suffix <= 99; suffix++)
{
var code = $"{parent.AccountCode}-{suffix:D2}";
if (code.Length > 20)
{
throw new BadRequestException("Cannot generate an account code: nesting is too deep for the 20-character account code column.");
}
if (await accountRepository.GetByCodeAsync(code) is null)
{
return code;
}
}
throw new BadRequestException("Maximum number of child accounts under this parent has been reached.");
}
if (!AccountTypeBlockStart.TryGetValue(accountTypeId, out var blockStart))
{
throw new BadRequestException(
$"Invalid accountTypeId '{accountTypeId}'. Must be one of: 1 (Asset), 2 (Liability), 3 (Equity), 4 (Income), 5 (Expense).");
}
// Probes each of the 10 designed slots directly rather than trusting a root count,
// since pre-existing accounts created before this generation scheme existed (manually
// coded, e.g. "5100") don't necessarily occupy slots in count order - a count-based
// guess can collide with one of those and crash on the DB's unique constraint instead
// of failing cleanly.
for (var slot = 0; slot < 10; slot++)
{
var code = (blockStart + slot * 100).ToString();
if (await accountRepository.GetByCodeAsync(code) is null)
{
return code;
}
}
throw new BadRequestException("Maximum number of root-level accounts for this account type has been reached.");
}
}
}