/*************************************************************/ /* Methods that enable the Views to fetch the desired accounts * /*************************************************************/ /** Timeline ER - Fetch main-groups **/ public MultipleYearsViewModel FetchMainGroupsForTimelineEr(Scenario scenario, StructureType selectedType, ERAccountType erAccountType, List <int> selectedYears, int selectedLevel) { if (scenario == null) { throw new Exception("No scenario defined!"); } bool isFunctionGroups = selectedType == StructureType.Functions || selectedType == StructureType.FunctionsThenSubjects; // Get all accounts of level 4 including changes based on scenario: List <AccountYearDto> allBaseAndScenarioAccounts = GetBaseAndScenarioYears(scenario); // accounts contains all accounts as a flat list: List <AccountYearViewModel> allAccounts = GroupAccountYearsAndJoinWithAccountGroups(isFunctionGroups, allBaseAndScenarioAccounts, selectedLevel) .ToList(); return(_dataSvc.AssembleMultiYearsAccountModels(isFunctionGroups, erAccountType, selectedYears, scenario.FinancialYear, allAccounts)); }
/** Timeline ER - Fetch SUB-groups **/ public List <AccountMultipleYearsViewModel> FetchSubGroupsForTimelineEr(Scenario scenario, AccountMultipleYearsViewModel accMultiYears, StructureType selectedType, ERAccountType selectedERAccountType) { List <AccountYearDto> allBaseAndScenarioAccounts = GetBaseAndScenarioYears(scenario); string selectedAccountId = accMultiYears.AccountId; List <AccountYearViewModel> allAccounts = null; bool isFunctionGroups = selectedType == StructureType.Functions || selectedType == StructureType.SubjectsThenFunctions; string idOfParentInSuperordinateStructure = null; if (selectedType == StructureType.SubjectsThenFunctions || selectedType == StructureType.FunctionsThenSubjects) { idOfParentInSuperordinateStructure = accMultiYears.IdOfParentInSuperordinateStructure ?? accMultiYears.AccountId; int levelOfSubordinatedAccounts = accMultiYears.IdOfParentInSuperordinateStructure == null ? 1 : (accMultiYears.AccountLevel + 1); allAccounts = GetEnumerableForErSubAccountsInMixedStructure(allBaseAndScenarioAccounts, selectedType, selectedERAccountType, idOfParentInSuperordinateStructure, accMultiYears.AccountId, levelOfSubordinatedAccounts, accMultiYears.SelectedYears) .ToList(); } else if (selectedType == StructureType.Functions || selectedType == StructureType.Subjects) { var query = GroupAccountYearsAndJoinWithAccountGroups(isFunctionGroups, allBaseAndScenarioAccounts, (accMultiYears.AccountLevel + 1)); // accounts contains all accounts as a flat list: // Pick all accounts, whose id starts with the clicked account's id allAccounts = query.Where(a => a.AccountId.Substring(0, accMultiYears.AccountLevel) == selectedAccountId) .ToList(); } MultipleYearsViewModel multiYearsModel = _dataSvc.AssembleMultiYearsAccountModels(isFunctionGroups, selectedERAccountType, accMultiYears.SelectedYears, scenario.FinancialYear, allAccounts); if (selectedType == StructureType.SubjectsThenFunctions || selectedType == StructureType.FunctionsThenSubjects) { foreach (AccountMultipleYearsViewModel acc in multiYearsModel.AccountsWithMultipleYears) { acc.IdOfParentInSuperordinateStructure = idOfParentInSuperordinateStructure; } } return(multiYearsModel?.AccountsWithMultipleYears ?? null); }
/** Timeline ER - Fetch main-groups **/ public async Task <MultipleYearsViewModel> FetchMainGroupsForTimelineEr(StructureType selectedType, ERAccountType erAccountType, List <int> selectedYears, int mostRecentFinancialYear, int selectedLevel) { bool isFunctionGroups = selectedType == StructureType.Functions || selectedType == StructureType.FunctionsThenSubjects; var query = GetQueryForErAccounts(isFunctionGroups, selectedYears, selectedLevel); // accounts contains all accounts as a flat list: List <AccountYearViewModel> allAccounts = await query.ToListAsync(); return(AssembleMultiYearsAccountModels(isFunctionGroups, erAccountType, selectedYears, mostRecentFinancialYear, allAccounts)); }
/************************************* * Helpers to assemble the Enumerables *************************************/ private IEnumerable <AccountYearViewModel> GetEnumerableForErSubAccountsInMixedStructure(List <AccountYearDto> allBaseAndScenarioAccounts, StructureType structureType, ERAccountType erAccountType, string idOfParentInSuperordinateStructure, string idOfSelectedAccount, int levelOfSubordinatedAccounts, List <int> years) { // Method accepts only mixed structure-types: if (structureType != StructureType.SubjectsThenFunctions && structureType != StructureType.FunctionsThenSubjects) { return(null); } string idOfSuperAcc = idOfParentInSuperordinateStructure; int levelOfSuperAcc = idOfParentInSuperordinateStructure.Length; bool isFunctionGroupSuperordinated = structureType == StructureType.FunctionsThenSubjects; IEnumerable <AccountYearDto> query = allBaseAndScenarioAccounts.Where(a => a.Type == "ER" && years.Contains(a.Year)); if (isFunctionGroupSuperordinated) { query = query.Where(a => a.IdOfParentFunctionGroup.Substring(0, levelOfSuperAcc) == idOfSuperAcc); // if subordinated subject-accounts are on level 1 => if all "Aufwände" or all "Erträge" have to be fetched: // => all subject-ids starting with 3 vs. all subject-ids starting with 4 if (levelOfSubordinatedAccounts == 1) { string firstDigit = erAccountType == ERAccountType.Expenses ? Const.FirstDigitOfExpenses : Const.FirstDigitOfIncomes; query = query.Where(a => a.SubjectId.Substring(0, 1) == firstDigit); } // if subordinated subject-accounts are on level 2, 3 or 4 (e.g. subject-groups: 42, 421, 4210) else { query = query.Where(a => a.SubjectId.Substring(0, (levelOfSubordinatedAccounts - 1)) == idOfSelectedAccount); } } // If subject-accounts represent the superordinated layer: else { query = query.Where(a => a.SubjectId.Substring(0, levelOfSuperAcc) == idOfSuperAcc); // if subordinated function-accounts are on level 2, 3 or 4 (e.g. function-groups: 10, 101, 1012) if (levelOfSubordinatedAccounts > 1) { query = query.Where(a => a.IdOfParentFunctionGroup.Substring(0, (levelOfSubordinatedAccounts - 1)) == idOfSelectedAccount); } } bool isFunctionGroup = structureType == StructureType.SubjectsThenFunctions; return(GroupAccountYearsAndJoinWithAccountGroups(isFunctionGroup, query, levelOfSubordinatedAccounts)); }
/* 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); }
/** Timeline ER - Fetch SUB-groups **/ public async Task <List <AccountMultipleYearsViewModel> > FetchSubGroupsForTimelineEr(AccountMultipleYearsViewModel accMultiYears, StructureType selectedType, ERAccountType selectedERAccountType, int mostRecentFinancialYear) { string selectedAccountId = accMultiYears.AccountId; List <AccountYearViewModel> allAccounts = null; bool isFunctionGroups = selectedType == StructureType.Functions || selectedType == StructureType.SubjectsThenFunctions; string idOfParentInSuperordinateStructure = null; if (selectedType == StructureType.SubjectsThenFunctions || selectedType == StructureType.FunctionsThenSubjects) { idOfParentInSuperordinateStructure = accMultiYears.IdOfParentInSuperordinateStructure ?? accMultiYears.AccountId; int levelOfSubordinatedAccounts = accMultiYears.IdOfParentInSuperordinateStructure == null ? 1 : (accMultiYears.AccountLevel + 1); allAccounts = await GetQueryForErSubAccountsInMixedStructure(selectedType, selectedERAccountType, idOfParentInSuperordinateStructure, accMultiYears.AccountId, levelOfSubordinatedAccounts, accMultiYears.SelectedYears) .ToListAsync(); } else if (selectedType == StructureType.Functions || selectedType == StructureType.Subjects) { var query = GetQueryForErAccounts(isFunctionGroups, accMultiYears.SelectedYears, (accMultiYears.AccountLevel + 1)); // accounts contains all accounts as a flat list: // Pick all accounts, whose id starts with the clicked account's id allAccounts = await query.Where(a => a.AccountId.Substring(0, accMultiYears.AccountLevel) == selectedAccountId) .ToListAsync(); } MultipleYearsViewModel multiYearsModel = AssembleMultiYearsAccountModels(isFunctionGroups, selectedERAccountType, accMultiYears.SelectedYears, mostRecentFinancialYear, allAccounts); if (selectedType == StructureType.SubjectsThenFunctions || selectedType == StructureType.FunctionsThenSubjects) { foreach (AccountMultipleYearsViewModel acc in multiYearsModel.AccountsWithMultipleYears) { acc.IdOfParentInSuperordinateStructure = idOfParentInSuperordinateStructure; } } return(multiYearsModel?.AccountsWithMultipleYears ?? null); }