using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Schaad.Accounting.Datasets; using Schaad.Accounting.Datasets.Charts; using Schaad.Accounting.Interfaces; namespace Schaad.Accounting.Services { public class ChartService : IChartService { private readonly ISettingsService settingsService; private readonly IViewService viewService; public ChartService(ISettingsService settingsService, IViewService viewService) { this.settingsService = settingsService; this.viewService = viewService; } public async Task> GetExpensesPerMonthAsync() { var expenseTransactions = (await viewService.GetTransactionViewListAsync()) .Where(t => t.TargetAccount.Class == ClassIds.Expenses) .ToList(); var distinctSubClasses = expenseTransactions .Select(t => t.TargetAccount.SubClass) .Distinct() .Count(); return distinctSubClasses > 1 ? await GetSubClassExpensesPerMonthAsync(expenseTransactions) : await GetAccountExpensesPerMonthAsync(); } private async Task> GetSubClassExpensesPerMonthAsync(List expenseTransactions) { var year = settingsService.GetYear(); var maxMonth = expenseTransactions .OrderByDescending(t => t.ValueDate) .FirstOrDefault()?.ValueDate.Month ?? 12; var subClassNameByNumber = (await viewService.GetAccountViewListAsync()) .GroupBy(a => a.SubClass) .ToDictionary(g => g.Key, g => g.First().SubClassName); var list = new List(); foreach (var grp in expenseTransactions.GroupBy(t => t.TargetAccount.SubClass)) { var groupedByMonth = grp .GroupBy(t => t.ValueDate.Month) .ToDictionary(g => g.Key, g => g.Sum(t => t.GetValue(t.TargetAccount.IsFxAccount))); EnsureEntryForEveryMonth(groupedByMonth, maxMonth); list.Add(new DataSerie( Id: grp.Key.ToString(), Name: subClassNameByNumber[grp.Key], X: groupedByMonth.OrderBy(g => g.Key).Select(g => new DateOnly(year, g.Key, 1)).ToList(), Y: groupedByMonth.OrderBy(g => g.Key).Select(g => g.Value).ToList() )); } return list; } private async Task> GetAccountExpensesPerMonthAsync() { var year = settingsService.GetYear(); var allTransactions = await viewService.GetTransactionViewListAsync(); var expenseAccounts = (await viewService.GetAccountViewListAsync()).Where(a => a.Class == ClassIds.Expenses); var list = new List(); foreach (var account in expenseAccounts) { var transactions = allTransactions.Where(t => t.TargetAccountId == account.Id).ToList(); if (transactions.Count == 0) { continue; } var maxMonth = transactions.Max(t => t.ValueDate.Month); var groupedByMonth = transactions .GroupBy(t => t.ValueDate.Month) .ToDictionary(g => g.Key, g => g.Sum(t => t.GetValue(account.IsFxAccount))); EnsureEntryForEveryMonth(groupedByMonth, maxMonth); list.Add(new DataSerie( Id: account.Id, Name: account.Name, X: groupedByMonth.OrderBy(g => g.Key).Select(g => new DateOnly(year, g.Key, 1)).ToList(), Y: groupedByMonth.OrderBy(g => g.Key).Select(g => g.Value).ToList() )); } return list; } public async Task> GetBookingTextExpensesPerMonthAsync(string accountId) { var account = await viewService.GetAccountViewAsync(accountId); var transactions = await viewService.GetTransactionViewListAsync(accountId); if (transactions.Count == 0) { return new List(); } var year = settingsService.GetYear(); var maxMonth = transactions.Max(t => t.ValueDate.Month); var list = new List(); foreach (var grp in transactions.GroupBy(t => t.GetTextGroup())) { var groupedByMonth = grp .GroupBy(t => t.ValueDate.Month) .ToDictionary(g => g.Key, g => g.Sum(t => t.GetValue(account.IsFxAccount, accountId))); EnsureEntryForEveryMonth(groupedByMonth, maxMonth); list.Add(new DataSerie( Id: grp.Key, Name: grp.Key, X: groupedByMonth.OrderBy(g => g.Key).Select(g => new DateOnly(year, g.Key, 1)).ToList(), Y: groupedByMonth.OrderBy(g => g.Key).Select(g => g.Value).ToList() )); } return list; } public async Task> GetBookingTextTotalsAsync(string accountId) { var account = await viewService.GetAccountViewAsync(accountId); var transactions = await viewService.GetTransactionViewListAsync(accountId); return transactions .Where(t => t.TargetAccountId == accountId) .GroupBy(t => t.GetTextGroup()) .Select(g => new CategoryTotal(g.Key, g.Sum(t => t.GetValue(account.IsFxAccount, accountId)))) .Where(c => c.Value != 0) .ToList(); } private static void EnsureEntryForEveryMonth(Dictionary values, int maxMonth = 12) { for (int i = 1; i <= maxMonth; i++) { if (values.ContainsKey(i) == false) { values.Add(i, 0); } } } } }