Add a Scoped RepositoryCache that memoizes deserialized XML lists, keyed by absolute file path. Each XML file is loaded at most once per SignalR circuit; Save invalidates the corresponding entry so subsequent reads reload from disk. BaseRepository gains a LoadList<T>(fileName) helper; each of the seven repositories now defines Get*List() as a one-liner over that helper and takes RepositoryCache via the constructor. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
115 lines
No EOL
3.6 KiB
C#
115 lines
No EOL
3.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Schaad.Accounting.Interfaces;
|
|
using Schaad.Accounting.Models;
|
|
|
|
namespace Schaad.Accounting.Repositories
|
|
{
|
|
public class AccountRepository : BaseRepository, IAccountRepository
|
|
{
|
|
private readonly string ACCOUNTS = "Accounts.xml";
|
|
|
|
public AccountRepository(ISettingsService settingsService, RepositoryCache cache)
|
|
: base(settingsService, cache)
|
|
{
|
|
EnsureAccountsFile();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load accounts
|
|
/// </summary>
|
|
public List<Account> GetAccountList() => LoadList<Account>(ACCOUNTS);
|
|
|
|
/// <summary>
|
|
/// Save an account (insert/update)
|
|
/// </summary>
|
|
public void SaveAccount(Account account)
|
|
{
|
|
var accounts = GetAccountList();
|
|
var existingAccount = accounts.FirstOrDefault(a => a.Id == account.Id);
|
|
|
|
if (existingAccount == null)
|
|
{
|
|
existingAccount = new Account();
|
|
accounts.Add(existingAccount);
|
|
account.Id = Guid.NewGuid().ToString();
|
|
}
|
|
account.Copy(existingAccount);
|
|
Save(accounts, ACCOUNTS);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get account
|
|
/// </summary>
|
|
public Account GetAccount(string id)
|
|
{
|
|
var accounts = GetAccountList();
|
|
return accounts.FirstOrDefault(t => t.Id == id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete account
|
|
/// </summary>
|
|
public void DeleteAccount(string id)
|
|
{
|
|
var accounts = GetAccountList();
|
|
accounts.RemoveAll(t => t.Id == id);
|
|
Save(accounts, ACCOUNTS);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get account
|
|
/// </summary>
|
|
public Account GetAccountForBankAccountNumber(string bankAccountNumber)
|
|
{
|
|
var accounts = GetAccountList();
|
|
return accounts.SingleOrDefault(t => t.BankAccountNumber == bankAccountNumber);
|
|
}
|
|
|
|
public void SaveBankAccountBalance(string bankAccountNumber, decimal accountBalance)
|
|
{
|
|
var account = GetAccountForBankAccountNumber(bankAccountNumber);
|
|
account.LastBankBalance = accountBalance;
|
|
SaveAccount(account);
|
|
}
|
|
|
|
private void EnsureAccountsFile()
|
|
{
|
|
string filePath = Path.Combine(settingsService.GetDbPath(), ACCOUNTS);
|
|
if (File.Exists(filePath))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var lastYearFile = Path.Combine(settingsService.GetLastYearDbPath(), ACCOUNTS);
|
|
if (File.Exists(lastYearFile))
|
|
{
|
|
File.Copy(lastYearFile, filePath);
|
|
}
|
|
|
|
// Year rollover: seed start balances from the previous year's closing values.
|
|
// Bank accounts start at the last known bank balance; cash accounts start at zero.
|
|
var accounts = GetAccountList();
|
|
var modified = false;
|
|
foreach (var account in accounts.Where(a => a.Class == ClassIds.Activa))
|
|
{
|
|
if (account.LastBankBalance > 0)
|
|
{
|
|
account.StartBalance = account.LastBankBalance;
|
|
modified = true;
|
|
}
|
|
else if (account.Number < 1010)
|
|
{
|
|
account.StartBalance = 0;
|
|
modified = true;
|
|
}
|
|
}
|
|
if (modified)
|
|
{
|
|
Save(accounts, ACCOUNTS);
|
|
}
|
|
}
|
|
}
|
|
} |