A set of criteria for filtering all budget data.
Inheritance: INotifyPropertyChanged, IModelValidate, IDataChangeDetection
        public GlobalFilterController(
            [NotNull] UiContext uiContext,
            [NotNull] IAccountTypeRepository accountTypeRepository)
        {
            if (uiContext == null)
            {
                throw new ArgumentNullException("uiContext");
            }

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

            this.accountTypeRepository = accountTypeRepository;
            this.userMessageBox = uiContext.UserPrompts.MessageBox;
            this.doNotUseCriteria = new GlobalFilterCriteria();

            MessengerInstance = uiContext.Messenger;
            MessengerInstance.Register<ApplicationStateLoadedMessage>(this, OnApplicationStateLoaded);
            MessengerInstance.Register<ApplicationStateLoadFinishedMessage>(this, OnApplicationStateLoadFinished);
            MessengerInstance.Register<ApplicationStateRequestedMessage>(this, OnApplicationStateRequested);
            MessengerInstance.Register<RequestFilterMessage>(this, OnGlobalFilterRequested);
            MessengerInstance.Register<WidgetActivatedMessage>(this, OnWidgetActivatedMessageReceived);
            MessengerInstance.Register<ShellDialogResponseMessage>(this, OnShellDialogResponseReceived);
            MessengerInstance.Register<RequestFilterChangeMessage>(this, OnGlobalFilterChangeRequested);
        }
        private bool NavigateToTransactionOutsideOfFilter(Guid transactionId)
        {
            Transaction foundTransaction = ViewModel.Statement.AllTransactions.FirstOrDefault(t => t.Id == transactionId);
            if (foundTransaction != null)
            {
                bool? result = this.questionBox.Show("The transaction falls outside the current filter. Do you wish to adjust the filter to show the transaction?", "Navigate to Transaction");
                if (result == null || !result.Value)
                {
                    return false;
                }

                GlobalFilterCriteria newCriteria;
                var requestCurrentFilter = new RequestFilterMessage(this);
                MessengerInstance.Send(requestCurrentFilter);

                if (foundTransaction.Date < requestCurrentFilter.Criteria.BeginDate)
                {
                    newCriteria = new GlobalFilterCriteria { BeginDate = foundTransaction.Date, EndDate = requestCurrentFilter.Criteria.EndDate };
                }
                else
                {
                    newCriteria = new GlobalFilterCriteria { BeginDate = requestCurrentFilter.Criteria.BeginDate, EndDate = foundTransaction.Date };
                }

                MessengerInstance.Send(new RequestFilterChangeMessage(this) { Criteria = newCriteria });

                return NavigateToVisibleTransaction(transactionId);
            }

            return false;
        }
        public void Load(StatementModel statementModel, BudgetCollection budgets, GlobalFilterCriteria criteria)
        {
            Analysis = new OverallPerformanceBudgetAnalyser(statementModel, budgets, this.bucketRepository);
            Analysis.Analyse(criteria);
            OverallPerformance = (double)Analysis.OverallPerformance;
            ExpenseFilter = true;
            IncomeFilter = false;

            RaisePropertyChanged(() => Analysis);
            ICollectionView view = CollectionViewSource.GetDefaultView(Analysis.Analyses);
            view.Filter = x =>
            {
                var bucketAnalysis = x as BucketPerformanceAnalyser;
                if (bucketAnalysis == null)
                {
                    return true;
                }

                if (IncomeFilter)
                {
                    return bucketAnalysis.Bucket is IncomeBudgetBucket;
                }

                bool result = !(bucketAnalysis.Bucket is IncomeBudgetBucket);
                return result;
            };
        }
        public void UsingTestData1_LocateApplicableLedgerBalance_ShouldReturn64()
        {
            var ledgerBook = LedgerBookTestData.TestData1();
            var filter = new GlobalFilterCriteria { BeginDate = new DateTime(2013, 04, 15), EndDate = new DateTime(2013, 05, 15) };

            var result = LedgerCalculation.LocateApplicableLedgerBalance(ledgerBook, filter, StatementModelTestData.PhoneBucket.Code);
            Assert.AreEqual(0M, result);
        }
        public void MinDateShouldGetTransalatedToNull()
        {
            var subject = new GlobalFilterCriteria
            {
                BeginDate = DateTime.MinValue,
                EndDate = DateTime.MinValue,
            };

            Assert.IsNull(subject.BeginDate);
            Assert.IsNull(subject.EndDate);
        }
        public void NotValidForBeginDateToBeAfterEndDate()
        {
            var invalidEndDate = new DateTime(2014, 3, 1);
            var subject = new GlobalFilterCriteria
            {
                BeginDate = new DateTime(2014, 5, 1),
                EndDate = invalidEndDate,
            };

            Assert.AreNotEqual(invalidEndDate, subject.EndDate);
            Assert.IsTrue(subject.BeginDate < subject.EndDate);
        }
        public void EndDateShouldAutoAdjustGivenDateAfterStartDate()
        {
            var invalidEndDate = new DateTime(2014, 3, 1);
            var subject = new GlobalFilterCriteria
            {
                BeginDate = new DateTime(2014, 5, 1),
                EndDate = invalidEndDate
            };

            Assert.AreNotEqual(invalidEndDate, subject.EndDate);
            Assert.IsTrue(subject.BeginDate < subject.EndDate);
        }
        private static DateTime CalculateBeginDate(GlobalFilterCriteria criteria)
        {
            if (criteria.Cleared)
            {
                return DateTime.Today.AddMonths(-1);
            }

            if (criteria.BeginDate != null)
            {
                return criteria.BeginDate.Value;
            }

            if (criteria.EndDate == null)
            {
                return DateTime.Today.AddMonths(-1);
            }

            return criteria.EndDate.Value.AddMonths(-1);
        }
        public void TestInitialise()
        {
            this.bucketRepo = new BucketBucketRepoAlwaysFind();
            this.subject = new RemainingSurplusWidget();
            this.criteriaTestData = new GlobalFilterCriteria
            {
                BeginDate = new DateTime(2015, 10, 20),
                EndDate = new DateTime(2015, 11, 19)
            };

            StatementModelTestDataForThisTest.AccountTypeRepo = new InMemoryAccountTypeRepository();
            StatementModelTestDataForThisTest.BudgetBucketRepo = this.bucketRepo;
            this.statementTestData = StatementModelTestDataForThisTest.TestDataGenerated();

            BudgetModel budgetModel = BudgetModelTestData.CreateTestData1();
            this.budgetTestData = new BudgetCurrencyContext(new BudgetCollection(budgetModel), budgetModel);

            this.ledgerBookTestData = new LedgerBookBuilder
            {
                StorageKey = "RemainingSurplusWidgetTest.xml",
                Modified = new DateTime(2015, 11, 23),
                Name = "Smith Budget 2015"
            }
                .IncludeLedger(LedgerBookTestData.PhoneLedger, 130M)
                .IncludeLedger(LedgerBookTestData.CarMtcLedger, 90M)
                .IncludeLedger(LedgerBookTestData.PowerLedger)
                .AppendReconciliation(
                    new DateTime(2015, 10, 20),
                    new BankBalance(LedgerBookTestData.ChequeAccount, 4502.75M))
                .WithReconciliationEntries(
                    entryBuilder =>
                    {
                        entryBuilder.WithLedger(LedgerBookTestData.PhoneLedger).HasNoTransactions();
                        entryBuilder.WithLedger(LedgerBookTestData.CarMtcLedger).HasNoTransactions();
                        entryBuilder.WithLedger(LedgerBookTestData.PowerLedger)
                            .AppendTransactions(txnBuilder => { txnBuilder.WithCredit(3000M, "Oct Savings", new DateTime(2015, 10, 20), "automatchref12"); });
                    })
                .Build();

            this.ledgerCalculation = new LedgerCalculation(new FakeLogger());
        }
        public void Build(GlobalFilterCriteria criteria,
            StatementModel statementModel,
            BudgetModel budgetModel,
            Engine.Ledger.LedgerBook ledgerBookModel)
        {
            var beginDate = CalculateBeginDate(criteria);
            var dateRangeDescription = String.Format(CultureInfo.CurrentCulture, "For the month starting {0:D} to {1:D} inclusive.", beginDate, beginDate.AddMonths(1).AddDays(-1));

            var listOfCharts = new List<BucketBurnDownController>(this.budgetBucketRepository.Buckets.Count());

            foreach (BudgetBucket bucket in this.budgetBucketRepository.Buckets
                .Where(b => b is ExpenseBucket)
                .OrderBy(b => b.Code))
            {
                BucketBurnDownController chartController = this.bucketSpendingFactory();
                chartController.Load(statementModel, budgetModel, bucket, beginDate, ledgerBookModel);
                listOfCharts.Add(chartController);
            }

            listOfCharts = listOfCharts.OrderBy(x => x.Bucket).ToList();

            // Put surplus at the top.
            listOfCharts.Insert(
                0,
                this.bucketSpendingFactory().Load(statementModel, budgetModel, this.budgetBucketRepository.SurplusBucket, beginDate, ledgerBookModel));

            // Put any custom charts on top.
            foreach (CustomAggregateBurnDownGraph customChart in this.CustomCharts)
            {
                BucketBurnDownController chartController = this.bucketSpendingFactory();
                IEnumerable<BudgetBucket> buckets = this.budgetBucketRepository.Buckets
                    .Join(customChart.BucketIds, bucket => bucket.Code, code => code, (bucket, code) => bucket);
                chartController.LoadCustomChart(statementModel, budgetModel, buckets, beginDate, ledgerBookModel, customChart.Name);
                listOfCharts.Insert(0, chartController);
            }

            this.Results = new BurnDownChartBuilderResults(beginDate, dateRangeDescription, listOfCharts);
        }
 public FilterAppliedMessage(object sender, GlobalFilterCriteria criteria)
 {
     Criteria = criteria;
     Sender = sender;
 }
        private void OnApplicationStateLoaded(ApplicationStateLoadedMessage message)
        {
            var filterState = message.ElementOfType<PersistentFiltersApplicationState>();
            if (filterState == null)
            {
                return;
            }

            Criteria = new GlobalFilterCriteria
            {
                BeginDate = filterState.BeginDate,
                EndDate = filterState.EndDate
            };

            SendFilterAppliedMessage();
        }
 public void ValidateShouldThrowGivenNullValidationMessages()
 {
     var subject = new GlobalFilterCriteria { BeginDate = new DateTime(), EndDate = DateTime.Now };
     Assert.IsFalse(subject.Validate(null));
 }
 public void ValidateShouldReturnTrueGivenDatesButNoAccount()
 {
     var subject = new GlobalFilterCriteria { BeginDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Now };
     Assert.IsFalse(subject.Cleared);
     Assert.IsTrue(subject.Validate(this.validationMessages));
 }
 public void ValidateShouldReturnTrueGivenCleared()
 {
     var subject = new GlobalFilterCriteria();
     Assert.IsTrue(subject.Cleared);
     Assert.IsTrue(subject.Validate(this.validationMessages));
 }
 public void ValidateShouldReturnFalseGivenEndDateIsNull()
 {
     var subject = new GlobalFilterCriteria { BeginDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Now };
     subject.EndDate = null;
     Assert.IsFalse(subject.Validate(this.validationMessages));
 }
        private void OnApplicationStateLoaded(ApplicationStateLoadedMessage message)
        {
            if (!message.RehydratedModels.ContainsKey(typeof(PersistentFiltersV1)))
            {
                return;
            }

            var rehydratedFilters = message.RehydratedModels[typeof(PersistentFiltersV1)].AdaptModel<FilterStateV1>();
            Criteria = new GlobalFilterCriteria
            {
                AccountType = rehydratedFilters.AccountType,
                BeginDate = rehydratedFilters.BeginDate,
                EndDate = rehydratedFilters.EndDate,
            };

            SendFilterAppliedMessage();
        }
 public void Load(StatementModel statementModel, GlobalFilterCriteria criteria)
 {
     this.analyser.Analyse(statementModel, criteria);
     GraphMaximumValue = Graph.Series.Max(s => s.Plots.Max(p => p.Amount));
     GraphMinimumValue = Graph.Series.Min(s => s.MinimumValue);
 }
 public void Load(StatementModel statementModel, GlobalFilterCriteria criteria)
 {
     try
     {
         Graph = this.chartService.BuildChart(statementModel, criteria);
         GraphMaximumValue = Graph.Series.Max(s => s.Plots.Max(p => p.Amount));
         GraphMinimumValue = Graph.Series.Min(s => s.MinimumValue);
     }
     catch (ArgumentException ex)
     {
         Graph = null;
         this.messageService.Show($"Unable to compile data for this report.\n{ex.Message}", "Data Validation");
     }
 }
        public void UsingTestData1WithAugust15_LocateApplicableLedgerBalance_ShouldReturn64()
        {
            var filter = new GlobalFilterCriteria { BeginDate = new DateTime(2013, 07, 15), EndDate = new DateTime(2013, 08, 15) };

            decimal result = Subject.LocateApplicableLedgerBalance(TestData, filter, StatementModelTestData.PhoneBucket.Code);
            TestData.Output();
            Assert.AreEqual(64.71M, result);
        }
 internal override void Filter(GlobalFilterCriteria criteria)
 {
     FilterByCriteriaWasCalled++;
 }