/** Yearly ER - Fetch SUB-groups **/
        public async Task <List <AccountYearViewModel> > FetchSubGroupsForYearlyEr(AccountYearViewModel ayear,
                                                                                   StructureType selectedType,
                                                                                   int mostRecentFinancialYear)
        {
            List <AccountYearViewModel> accountYearModel = null;

            // If user is in mixed-structureTypes mode:
            if (selectedType == StructureType.SubjectsThenFunctions || selectedType == StructureType.FunctionsThenSubjects)
            {
                // If user was on top-level when he clicked on account: IdOfParentInSuperordinateStructure == null
                // If user clicked on an account below the top-level-structure: IdOfParentInSuperordinateStructure will have a value
                string idOfParentInSuperordinateStructure = ayear.IdOfParentInSuperordinateStructure ?? ayear.AccountId;
                int    levelOfAccountsToFetch             = ayear.IdOfParentInSuperordinateStructure == null ? 1 : (ayear.AccountLevel + 1);

                List <int> years = new List <int> {
                    (ayear.Year - 1), ayear.Year
                };

                var query = GetQueryForErSubAccountsInMixedStructure(selectedType, ERAccountType.ExpensesAndIncomes, idOfParentInSuperordinateStructure, ayear.AccountId, levelOfAccountsToFetch, years);

                List <AccountYearViewModel> accountsForPreviousYear = await query.Where(a => a.Year == (ayear.Year - 1)).ToListAsync();

                List <AccountYearViewModel> accountsForSelectedYear = await query.Where(a => a.Year == ayear.Year).ToListAsync();

                SetPercentChangesBetweenTwoYears(accountsForPreviousYear,
                                                 accountsForSelectedYear,
                                                 mostRecentFinancialYear,
                                                 ayear.Year);

                // Add id of superordinate subject-account:
                foreach (var acc in accountsForSelectedYear)
                {
                    acc.IdOfParentInSuperordinateStructure = idOfParentInSuperordinateStructure;
                }
                accountYearModel = accountsForSelectedYear;
            }
            // If user is in subjects-mode or in functions-mode:
            else if (selectedType == StructureType.Functions || selectedType == StructureType.Subjects)
            {
                YearViewModel m = await FetchMainGroupsForYearlyER(selectedType,
                                                                   mostRecentFinancialYear,
                                                                   ayear.Year,
                                                                   (ayear.AccountLevel) + 1);

                accountYearModel = m.Accounts.Where(a => a.AccountId.Substring(0, ayear.AccountLevel) == ayear.AccountId).ToList();
            }
            return(accountYearModel);
        }
        /*******************************************
         * Helpers to assemble the final ViewModels
         ******************************************/

        private void SetPercentChangesBetweenTwoYears(List <AccountYearViewModel> accountsForPreviousYear,
                                                      List <AccountYearViewModel> accountsForSelectedYear,
                                                      int mostRecentFinancialYear,
                                                      int selectedYear)
        {
            foreach (AccountYearViewModel acc in accountsForSelectedYear)
            {
                // For account-group-items which had no partner in LEFT-JOIN the year was not yet set:
                acc.Year = selectedYear;

                AccountYearViewModel accInPrevYear = accountsForPreviousYear.FirstOrDefault(a => a.AccountId == acc.AccountId);

                if (accInPrevYear != null)
                {
                    SetPercentChangesBetweenTwoYears(accInPrevYear, acc, mostRecentFinancialYear, selectedYear);
                }
            }
        }
 private void SetPercentChangesBetweenTwoYears(AccountYearViewModel accPreviousYear,
                                               AccountYearViewModel accSelectedYear,
                                               int mostRecentFinancialYear,
                                               int selectedYear)
 {
     if (selectedYear <= mostRecentFinancialYear)
     {
         accSelectedYear.PercentageChangeExpensesActual = _helpers.GetPercentageChange(accPreviousYear.ExpensesActual, accSelectedYear.ExpensesActual);
         accSelectedYear.PercentageChangeIncomeActual   = _helpers.GetPercentageChange(accPreviousYear.IncomeActual, accSelectedYear.IncomeActual);
         accSelectedYear.PercentageChangeBalanceActual  = _helpers.GetPercentageChange(accPreviousYear.BalanceActual, accSelectedYear.BalanceActual);
     }
     else if (selectedYear == (mostRecentFinancialYear + 1))
     {
         accSelectedYear.PercentageChangeExpensesBudget = _helpers.GetPercentageChange(accPreviousYear.ExpensesActual, accSelectedYear.ExpensesBudget);
         accSelectedYear.PercentageChangeIncomeBudget   = _helpers.GetPercentageChange(accPreviousYear.IncomeActual, accSelectedYear.IncomeBudget);
         accSelectedYear.PercentageChangeBalanceBudget  = _helpers.GetPercentageChange(accPreviousYear.BalanceActual, accSelectedYear.BalanceBudget);
     }
     else if (selectedYear > (mostRecentFinancialYear + 1))
     {
         accSelectedYear.PercentageChangeExpensesBudget = _helpers.GetPercentageChange(accPreviousYear.ExpensesBudget, accSelectedYear.ExpensesBudget);
         accSelectedYear.PercentageChangeIncomeBudget   = _helpers.GetPercentageChange(accPreviousYear.IncomeBudget, accSelectedYear.IncomeBudget);
         accSelectedYear.PercentageChangeBalanceBudget  = _helpers.GetPercentageChange(accPreviousYear.BalanceBudget, accSelectedYear.BalanceBudget);
     }
 }
        /* Assembles models that contain the values of an account for multiple years. */
        internal MultipleYearsViewModel AssembleMultiYearsAccountModels(bool isFunctionGroups,
                                                                        ERAccountType erAccountType,
                                                                        List <int> selectedYears,
                                                                        int mostRecentFinancialYear,
                                                                        List <AccountYearViewModel> allAccounts)
        {
            List <string> accountIds = new List <string>();

            // In case the incoming accounts are function-groups
            if (isFunctionGroups)
            {
                accountIds = allAccounts.Select(a => a.AccountId)
                             .OrderBy(a => a)
                             .Distinct()
                             .ToList();
            }
            // In case the incoming accounts are subject-groups
            else
            {
                List <string> allowedFirstDigits = new List <string>();

                if (erAccountType == ERAccountType.Expenses || erAccountType == ERAccountType.Balances)
                {
                    allowedFirstDigits.Add(Const.FirstDigitOfExpenses);
                }
                if (erAccountType == ERAccountType.Income || erAccountType == ERAccountType.Balances)
                {
                    allowedFirstDigits.Add(Const.FirstDigitOfIncomes);
                }

                // all "Aufwand"-accounts resp. "Ertrag"-accounts start with the same number => use this fact for filtering:
                accountIds = allAccounts.Where(a => allowedFirstDigits.Contains(a.AccountId.Substring(0, 1)))
                             .Select(a => a.AccountId)
                             .OrderBy(a => a)
                             .Distinct()
                             .ToList();
            }

            List <YearTotalsViewModel> totalsForSelectedYears = GetTotalsForYears(selectedYears, allAccounts, mostRecentFinancialYear);

            var result = new MultipleYearsViewModel
            {
                SelectedYears             = selectedYears,
                ListOfAccountYearTotals   = totalsForSelectedYears,
                AccountsWithMultipleYears = new List <AccountMultipleYearsViewModel>()
            };

            /* There might be account-ids which are only available in certain years:
             * For these cases*/

            foreach (var id in accountIds)
            {
                var yearlyAccounts = new List <AccountYearViewModel>();
                for (int i = 0; i < selectedYears.Count; i++)
                {
                    // Check if an account for the given year / id is available
                    AccountYearViewModel yearlyAcc = allAccounts.FirstOrDefault(a => a.AccountId == id &&
                                                                                a.Year == selectedYears[i]);

                    if (yearlyAcc != null)
                    {
                        yearlyAccounts.Add(yearlyAcc);
                    }
                    // If for the given year no account with this id is available,
                    // create a new account-object based on the infos of another account with the same id (setting expenses and incomes == 0)
                    else
                    {
                        var ya = allAccounts.FirstOrDefault(a => a.AccountId == id);
                        if (ya != null)
                        {
                            yearlyAccounts.Add(new AccountYearViewModel
                            {
                                Year         = selectedYears[i],
                                AccountId    = ya.AccountId,
                                AccountName  = ya.AccountName,
                                AccountLevel = ya.AccountLevel,
                                ParentId     = ya.ParentId,
                                Type         = ya.Type
                            });
                        }
                    }

                    // Given there is a previous year,
                    // add percent change compared to previous year:
                    if (i > 0)
                    {
                        SetPercentChangesBetweenTwoYears(yearlyAccounts[i - 1], yearlyAccounts[i], mostRecentFinancialYear, selectedYears[i]);
                    }
                }

                result.AccountsWithMultipleYears.Add(new AccountMultipleYearsViewModel
                {
                    Type           = yearlyAccounts[0].Type,
                    AccountId      = yearlyAccounts[0].AccountId,
                    AccountName    = yearlyAccounts[0].AccountName,
                    AccountLevel   = yearlyAccounts[0].AccountLevel,
                    ParentId       = yearlyAccounts[0].ParentId,
                    SelectedYears  = selectedYears,
                    YearlyAccounts = yearlyAccounts
                });
            }
            return(result);
        }