private Entities.Budget CloneBudget(Entities.Budget source, int workbookId, DateTime periodStartDate, DateTime periodEndDate) { // If there is no old budget (i.e. this is the first one we're creating), // then there's nothing to clone - create a new one. // if (source == null) { return(this.CreateNewBudget(workbookId, periodStartDate, periodEndDate)); } source.BudgetItemList = this.budgetItemRepository .GetList(q => q.Where(x => x.Budget.Id == source.Id)) .ToList(); // Generate actual amounts for the old budget - because we'll use those to // populate the budgeted amounts for the new budget. // var actualAmountDictionary = this.financeTransactionRepository .GetFor <IDictionary <int, decimal> >( q => q .Where(x => x.Workbook.Id == source.Workbook.Id && x.TransactionDate >= source.PeriodStartDate && x.TransactionDate <= source.PeriodEndDate) .Select(x => new { x.BudgetHeading.Id, x.Amount }) .ToList() .GroupBy(x => x.Id) .ToDictionary(x => x.Key, x => x.Select(y => y.Amount).Sum())); var budget = new Entities.Budget { Workbook = source.Workbook, PeriodStartDate = periodStartDate, PeriodEndDate = periodEndDate, BudgetItemList = source.BudgetItemList .Select(x => new Entities.BudgetItem { BudgetHeading = x.BudgetHeading, Amount = actualAmountDictionary.ContainsKey(x.BudgetHeading.Id) ? actualAmountDictionary[x.BudgetHeading.Id] : 0 }) .ToList() }; HandleAnnualizedAndSurplus(source, budget, actualAmountDictionary); return(budget); }
private static void HandleAnnualizedAndSurplus(Entities.Budget oldBudget, Entities.Budget newBudget, IDictionary <int, decimal> actualAmountDictionary) { // Annualized headings and surplus/deficit items need special care. // Surplus/deficit on annualized headings don't contribute to the overall surplus, they // are handled individually. var oldAnnualizedItems = oldBudget.BudgetItemList.Where(x => x.BudgetHeading.IsAnnualized); decimal overallSurplusToSubtract = 0; foreach (var oldAnnualizedItem in oldAnnualizedItems) { var actualAmount = actualAmountDictionary.ContainsKey(oldAnnualizedItem.BudgetHeading.Id) ? actualAmountDictionary[oldAnnualizedItem.BudgetHeading.Id] : 0; var surplus = oldAnnualizedItem.Amount - actualAmount; var newAnnualizedItem = newBudget.BudgetItemList.FirstOrDefault( x => x.BudgetHeading.Id == oldAnnualizedItem.BudgetHeading.Id); if (newAnnualizedItem == null) { continue; } newAnnualizedItem.Amount += surplus; overallSurplusToSubtract += surplus; } var oldEndingSurplus = oldBudget.BudgetItemList .Where(x => x.BudgetHeading.IsEndingSurplus) .Select(x => x.Amount) .Sum(); oldEndingSurplus -= overallSurplusToSubtract; var newBeginningSurplusItem = newBudget.BudgetItemList.FirstOrDefault(x => x.BudgetHeading.IsBeginningSurplus); if (newBeginningSurplusItem != null) { newBeginningSurplusItem.Amount = oldEndingSurplus; } newBudget.BudgetItemList .Where(x => x.BudgetHeading.IsEndingSurplus) .ForEach(x => x.Amount = 0); }
public Budget GetBudget(string userName, int id) { this.logger.Verbose(string.Format("Retrieving budget {0} for user {1}...", id, userName)); Entities.Budget budgetEntity = null; IDictionary <int, decimal> actualAmountDictionary = null; try { this.Database.With( this.budgetRepository, this.budgetItemRepository, this.financeTransactionRepository).Execute( unit => { budgetEntity = this.budgetRepository.Get(id); budgetEntity.BudgetItemList = this.budgetItemRepository .GetList(q => q.Where(x => x.Budget.Id == id).ToList()) .ToList(); // Actual amounts are calculated on the fly from transactions within the // same workbook that fall within the budget period. Each transaction has // a budget heading. // actualAmountDictionary = this.financeTransactionRepository .GetFor <IDictionary <int, decimal> >( q => q .Where(x => x.Workbook.Id == budgetEntity.Workbook.Id && x.TransactionDate >= budgetEntity.PeriodStartDate && x.TransactionDate <= budgetEntity.PeriodEndDate) .Select(x => new { x.BudgetHeading.Id, x.Amount }) .ToList() .GroupBy(x => x.Id) .ToDictionary(x => x.Key, x => x.Select(y => y.Amount).Sum())); }); } catch (Exception ex) { ex.WrapLogAndThrow <ServiceException, ServiceErrorCodes>(ServiceErrorCodes.GetBudgetError); } Debug.Assert(budgetEntity != null); this.authorizationService.Authorize(userName, budgetEntity.Workbook.Id); return(budgetEntity.ToDc(actualAmountDictionary)); }
public static Budget ToDc(this Entities.Budget entity, IDictionary <int, decimal> actualAmountDictionary) { var budget = new Budget { WorkbookId = entity.Workbook.Id, Id = entity.Id, BudgetName = entity.PeriodStartDate.ToString("MM/dd/yyyy") + " - " + entity.PeriodEndDate.ToString("MM/dd/yyyy"), BudgetItemList = entity.BudgetItemList .Select(x => new BudgetItem { Id = x.Id, IsMoneyComingIn = x.BudgetHeading.BudgetHeadingType.IsMoneyComingIn, BudgetHeading = x.BudgetHeading.Name, BudgetHeadingType = x.BudgetHeading.BudgetHeadingType.Name, BudgetAmount = x.Amount, ActualAmount = actualAmountDictionary.ContainsKey(x.BudgetHeading.Id) ? actualAmountDictionary[x.BudgetHeading.Id] : 0 }) .OrderBy(x => x.IsMoneyComingIn ? 1 : 2) .ThenBy(x => x.BudgetHeadingType) .ThenBy(x => x.BudgetHeading) .ToList() }; budget.BudgetHeadingList = budget.BudgetItemList .Select(x => x.BudgetHeading) .Distinct() .ToList(); budget.BudgetHeadingTypeList = budget.BudgetItemList .Select(x => x.BudgetHeadingType) .Distinct() .ToList(); return(budget); }