A transient wrapper class to indicate a budget's active state in relation to other budgets in the collection. This class will tell you if a budget is active, future dated, or has past and is archived.
        public void ShouldIndicateFutureBudgetWhenOneIsGiven()
        {
            var budget3 = new BudgetModel { EffectiveFrom = new DateTime(2020, 01, 30) };
            var subject = new BudgetCurrencyContext(
                new BudgetCollection(new[]
                {
                    BudgetModelTestData.CreateTestData1(),
                    BudgetModelTestData.CreateTestData2(),
                    budget3
                }),
                budget3
           );

            Assert.IsFalse(subject.BudgetActive);
            Assert.IsFalse(subject.BudgetArchived);
            Assert.IsTrue(subject.BudgetInFuture);
        }
        public BudgetController(
            [NotNull] UiContext uiContext,
            [NotNull] IBudgetMaintenanceService maintenanceService,
            [NotNull] IApplicationDatabaseService applicationDatabaseService)
        {
            if (uiContext == null)
            {
                throw new ArgumentNullException(nameof(uiContext));
            }

            if (maintenanceService == null)
            {
                throw new ArgumentNullException(nameof(maintenanceService));
            }

            if (applicationDatabaseService == null)
            {
                throw new ArgumentNullException(nameof(applicationDatabaseService));
            }

            this.maintenanceService = maintenanceService;
            this.applicationDatabaseService = applicationDatabaseService;
            this.questionBox = uiContext.UserPrompts.YesNoBox;
            this.messageBox = uiContext.UserPrompts.MessageBox;
            this.inputBox = uiContext.UserPrompts.InputBox;
            BudgetPieController = uiContext.BudgetPieController;
            NewBudgetController = uiContext.NewBudgetModelController;
            NewBudgetController.Ready += OnAddNewBudgetReady;
            Shown = false;

            MessengerInstance = uiContext.Messenger;
            MessengerInstance.Register<ShellDialogResponseMessage>(this, OnPopUpResponseReceived);
            this.maintenanceService.Closed += OnClosedNotificationReceived;
            this.maintenanceService.NewDataSourceAvailable += OnNewDataSourceAvailableNotificationReceived;
            this.maintenanceService.Saving += OnSavingNotificationReceived;
            this.maintenanceService.Validating += OnValidatingNotificationReceived;
            this.maintenanceService.Saved += OnSavedNotificationReceived;

            CurrentBudget = new BudgetCurrencyContext(this.maintenanceService.Budgets, this.maintenanceService.Budgets.CurrentActiveBudget);
        }
 public BudgetReadyMessage(BudgetCurrencyContext activeBudget, BudgetCollection budgets = null)
 {
     ActiveBudget = activeBudget;
     Budgets = budgets;
 }
 private void SyncDataFromBudgetService()
 {
     Budgets = this.maintenanceService.Budgets;
     CurrentBudget = new BudgetCurrencyContext(Budgets, Budgets.CurrentActiveBudget);
     BudgetBucketBindingSource.BucketRepository = this.maintenanceService.BudgetBucketRepository;
     RaisePropertyChanged(() => TruncatedFileName);
     if (CurrentBudget != null)
     {
         MessengerInstance.Send(new BudgetReadyMessage(CurrentBudget, Budgets));
     }
 }
 private void ShowOtherBudget(BudgetModel budgetToShow)
 {
     CurrentBudget = new BudgetCurrencyContext(Budgets, budgetToShow);
     Shown = true;
     Dirty = false; // Need to reset this because events fire needlessly (in this case) as a result of setting the CurrentBudget.
 }
 private void OnClosedNotificationReceived(object sender, EventArgs eventArgs)
 {
     CurrentBudget = new BudgetCurrencyContext(this.maintenanceService.Budgets, this.maintenanceService.Budgets.CurrentActiveBudget);
     Budgets = CurrentBudget.BudgetCollection;
     BudgetBucketBindingSource.BucketRepository = this.maintenanceService.BudgetBucketRepository;
     RaisePropertyChanged(() => TruncatedFileName);
     MessengerInstance.Send(new BudgetReadyMessage(CurrentBudget, Budgets));
 }
        private void ValidateAndClose()
        {
            if (CurrentBudget == null)
            {
                // No budget loaded yet
                return;
            }

            bool valid = ValidateAndSaveIfRequired();
            if (valid)
            {
                if (CurrentBudget.Model != Budgets.CurrentActiveBudget)
                {
                    // Were viewing a different budget other than the current active budget for today's date.  Reset back to active budget.
                    CurrentBudget = new BudgetCurrencyContext(Budgets, Budgets.CurrentActiveBudget);
                    this.dirty = false;
                }

                MessengerInstance.Send(new BudgetReadyMessage(CurrentBudget, Budgets));
            }
        }
        public BudgetController(
            [NotNull] IBudgetRepository budgetRepository,
            [NotNull] UiContext uiContext,
            [NotNull] DemoFileHelper demoFileHelper,
            [NotNull] IBudgetBucketRepository bucketRepo)
        {
            if (budgetRepository == null)
            {
                throw new ArgumentNullException("budgetRepository");
            }

            if (uiContext == null)
            {
                throw new ArgumentNullException("uiContext");
            }

            if (demoFileHelper == null)
            {
                throw new ArgumentNullException("demoFileHelper");
            }

            if (bucketRepo == null)
            {
                throw new ArgumentNullException("bucketRepo");
            }

            this.demoFileHelper = demoFileHelper;
            this.bucketRepo = bucketRepo;
            this.budgetRepository = budgetRepository;
            this.questionBox = uiContext.UserPrompts.YesNoBox;
            this.messageBox = uiContext.UserPrompts.MessageBox;
            this.fileOpenDialogFactory = uiContext.UserPrompts.OpenFileFactory;
            this.fileSaveDialogFactory = uiContext.UserPrompts.SaveFileFactory;
            this.inputBox = uiContext.UserPrompts.InputBox;
            BudgetPieController = uiContext.BudgetPieController;
            Shown = false;

            MessengerInstance = uiContext.Messenger;
            MessengerInstance.Register<ApplicationStateRequestedMessage>(this, OnApplicationStateRequested);
            MessengerInstance.Register<ApplicationStateLoadedMessage>(this, OnApplicationStateLoaded);
            MessengerInstance.Register<ShellDialogResponseMessage>(this, OnPopUpResponseReceived);

            var budget = new BudgetModel();
            CurrentBudget = new BudgetCurrencyContext(new BudgetCollection(new[] { budget }), budget);
        }
 private void LoadBudget(string fileName)
 {
     try
     {
         this.loading = true;
         Budgets = this.budgetRepository.Load(fileName);
         BudgetBucketBindingSource.BucketRepository = this.budgetRepository.BudgetBucketRepository;
         CurrentBudget = new BudgetCurrencyContext(Budgets, Budgets.CurrentActiveBudget);
         RaisePropertyChanged(() => TruncatedFileName);
         if (CurrentBudget != null)
         {
             MessengerInstance.Send(new BudgetReadyMessage(CurrentBudget, Budgets));
         }
     }
     finally
     {
         this.loading = false;
     }
 }
        private void SearchForOverspentLedgers(StatementModel statement, GlobalFilterCriteria filter, BudgetCurrencyContext budget, IDictionary<BudgetBucket, decimal> overspendingSummary, int warnings)
        {
            List<Transaction> transactions = statement.Transactions.Where(t => t.Date < filter.BeginDate.Value.AddMonths(1)).ToList();
            foreach (Expense expense in budget.Model.Expenses.Where(e => e.Bucket is BillToPayExpenseBucket))
            {
                if (overspendingSummary.ContainsKey(expense.Bucket))
                {
                    continue;
                }

                decimal bucketBalance = expense.Amount + transactions.Where(t => t.BudgetBucket == expense.Bucket).Sum(t => t.Amount);
                overspendingSummary.Add(expense.Bucket, bucketBalance);
                if (bucketBalance < -this.Tolerance)
                {
                    warnings++;
                }
            }
        }
 private static BudgetCurrencyContext CreateSubject2()
 {
     BudgetModel budget2 = BudgetModelTestData.CreateTestData2();
     var subject = new BudgetCurrencyContext(new BudgetCollection(new[] { BudgetModelTestData.CreateTestData1(), budget2 }), budget2);
     return subject;
 }
        public override void Update([NotNull] params object[] input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (!ValidateUpdateInput(input))
            {
                ToolTip = this.disabledToolTip;
                Enabled = false;
                return;
            }

            this.budget = (BudgetCurrencyContext)input[0];
            this.statement = (StatementModel)input[1];
            this.filter = (GlobalFilterCriteria)input[2];
            this.bucketRepository = (IBudgetBucketRepository)input[3];
            this.ledgerBook = (LedgerBook)input[4];

            if (!this.bucketRepository.IsValidCode(BucketCode))
            {
                ToolTip = this.disabledToolTip;
                Enabled = false;
                return;
            }

            if (this.statement == null || this.budget == null || this.filter == null || this.filter.Cleared || this.filter.BeginDate == null || this.filter.EndDate == null)
            {
                ToolTip = this.disabledToolTip;
                Enabled = false;
                return;
            }

            if (this.filter.BeginDate.Value.DurationInMonths(this.filter.EndDate.Value) != 1)
            {
                Enabled = false;
                ToolTip = DesignedForOneMonthOnly;
                return;
            }

            Enabled = true;
            decimal totalBudget = MonthlyBudgetAmount();
            Maximum = Convert.ToDouble(totalBudget);

            // Debit transactions are negative so normally the total spend will be a negative number.
            decimal remainingBudget = totalBudget + this.statement.Transactions.Where(t => t.BudgetBucket != null && t.BudgetBucket.Code == BucketCode).Sum(t => t.Amount);
            if (remainingBudget < 0)
            {
                remainingBudget = 0;
            }

            Value = Convert.ToDouble(remainingBudget);
            ToolTip = string.Format(CultureInfo.CurrentCulture, this.remainingBudgetToolTip, remainingBudget);

            if (remainingBudget < 0.2M * totalBudget)
            {
                ColourStyleName = WidgetWarningStyle;
            }
            else
            {
                ColourStyleName = this.standardStyle;
            }
        }