AccountingNext/Schaad.Accounting.UI/Extensions.cs
Claudio Schaad 9f11f6490b PR A: correctness fixes and improvement plan
- Add IMPROVEMENT_PLAN.md with phased plan for follow-up work
- Consolidate DI registrations into a single AddAccounting() extension;
  drop the duplicate service registrations and the PdfParsingService
  self-registration
- TrySetYear: capture this.year before overwriting so rollback actually
  restores the previous value
- DummyFxService: check toCurrency (was checking fromCurrency twice)
- TransactionRepository.GetTransaction: return a copy instead of mutating
  the loaded entity, and guard against unknown ids
- ViewService.GetTransactionViewList(accountId): flip the sign on a copy
  rather than mutating the entity returned by the repository
- FileService.GetTransactionListCsv: same treatment; use a local
  signedValue instead of mutating trx.Value
- ProfitLossReport: use ClassIds.Income/Expenses instead of magic 3/4
- CLAUDE.md: correct the ClassIds documentation (1/2/3/4, not
  1000/2000/3000/4000)

SettingsService lifetime is intentionally left as Singleton for now;
making it Scoped requires persisting year/mandator selection across
page reloads first (tracked in the plan).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-02 20:37:03 +02:00

46 lines
2.1 KiB
C#

using System.Globalization;
using Schaad.Accounting.Interfaces;
using Schaad.Accounting.Repositories;
using Schaad.Accounting.Services;
using Schaad.Finance.Api;
using Schaad.Finance.Services;
namespace Schaad.Accounting.UI
{
public static class Extensions
{
public static string ToFormattedString(this decimal value)
{
var culture = new CultureInfo("de-CH");
culture.NumberFormat.NumberGroupSeparator = "'";
return value.ToString("#,0.00", culture);
}
public static IServiceCollection AddAccounting(this IServiceCollection services)
{
// Singleton because MyHeader triggers a full page reload (forceLoad: true) after
// changing year/mandator; a Scoped instance would be recreated on the new circuit
// and lose the selection. TODO: persist selection to a cookie/query string so this
// can safely become Scoped (see IMPROVEMENT_PLAN.md).
services.AddSingleton<ISettingsService, SettingsService>();
services.AddScoped<IAccountRepository, AccountRepository>();
services.AddScoped<IBankTransactionRepository, BankTransactionRepository>();
services.AddScoped<IBookingRuleRepository, BookingRuleRepository>();
services.AddScoped<IBookingTextRepository, BookingTextRepository>();
services.AddScoped<ISplitPredefinitonRepository, SplitPredefinitonRepository>();
services.AddScoped<ISubclassRepository, SubclassRepository>();
services.AddScoped<ITransactionRepository, TransactionRepository>();
services.AddScoped<IChartService, ChartService>();
services.AddScoped<IViewService, ViewService>();
services.AddScoped<IFileService, FileService>();
services.AddScoped<IAccountStatementService, AccountStatementService>();
services.AddScoped<ICreditCardStatementService, CreditCardStatementService>();
services.AddSingleton<IFxService, DummyFxService>();
services.AddSingleton<IPdfParsingService, PdfParsingService>();
return services;
}
}
}