public void TotalAmount_ChangingItemAmounts_ExpectTotalAmountChangedEvent()
        {
            var items = new List <BudgetItem>
            {
                new BudgetItem("1", "item 1"),
                new BudgetItem("2", "item 2"),
                new BudgetItem("3", "item 3"),
            };

            var  group      = new BudgetGroup("1", "group 1", budgetItems: items);
            var  viewModel  = new BudgetGroupViewModel(group);
            bool wasChanged = false;

            viewModel.PropertyChanged += (o, e) =>
            {
                if (e.PropertyName == nameof(viewModel.TotalAmount))
                {
                    wasChanged = true;
                }
            };

            group.BudgetItems[1].Amount = 234.56m;
            wasChanged.Should().BeTrue();
            viewModel.TotalAmount.Should().Be(group.TotalAmount.ToCurrencyString());
        }
        internal Budget(
            BudgetGroup incomeGroup,
            BudgetGroup housingGroup,
            BudgetGroup transportationGroup,
            BudgetGroup foodGroup,
            BudgetGroup personalGroup,
            BudgetGroup givingGroup,
            BudgetGroup debtGroup,
            BudgetGroup basicExpensesDisplayGroup)
        {
            IncomeGroup               = incomeGroup ?? throw new ArgumentNullException(nameof(incomeGroup));
            HousingGroup              = housingGroup ?? throw new ArgumentNullException(nameof(housingGroup));
            TransportationGroup       = transportationGroup ?? throw new ArgumentNullException(nameof(transportationGroup));
            FoodGroup                 = foodGroup ?? throw new ArgumentNullException(nameof(foodGroup));
            PersonalGroup             = personalGroup ?? throw new ArgumentNullException(nameof(personalGroup));
            GivingGroup               = givingGroup ?? throw new ArgumentNullException(nameof(givingGroup));
            DebtGroup                 = debtGroup ?? throw new ArgumentNullException(nameof(debtGroup));
            BasicExpensesDisplayGroup = basicExpensesDisplayGroup ?? throw new ArgumentNullException(nameof(basicExpensesDisplayGroup));

            void InitializeBudgetGroupChangeListeners()
            {
                IncomeGroup.PropertyChanged         += GroupPropertyChanged;
                HousingGroup.PropertyChanged        += GroupPropertyChanged;
                TransportationGroup.PropertyChanged += GroupPropertyChanged;
                FoodGroup.PropertyChanged           += GroupPropertyChanged;
                PersonalGroup.PropertyChanged       += GroupPropertyChanged;
                GivingGroup.PropertyChanged         += GroupPropertyChanged;
                DebtGroup.PropertyChanged           += GroupPropertyChanged;
                GivingGroup.PropertyChanged         += GroupPropertyChanged;
            }

            void GroupPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                if (e.PropertyName == nameof(BudgetGroup.TotalAmount))
                {
                    RecalculateTotals();
                }
            }

            void RecalculateTotals()
            {
                IncomeRemaining =
                    IncomeGroup.TotalAmount
                    - HousingGroup.TotalAmount
                    - TransportationGroup.TotalAmount
                    - FoodGroup.TotalAmount
                    - PersonalGroup.TotalAmount
                    - GivingGroup.TotalAmount
                    - DebtGroup.TotalAmount;

                BasicExpensesDisplayGroup.BudgetItems[0].Amount =
                    HousingGroup.TotalAmount
                    + TransportationGroup.TotalAmount
                    + FoodGroup.TotalAmount
                    + PersonalGroup.TotalAmount;
            }
        }
        public void IsTotalAmountZero_NonZeroItemAmounts_ExpectFalse()
        {
            var items = new List <BudgetItem>
            {
                new BudgetItem("1", "test 1"),
                new BudgetItem("2", "test 2", 100m),
                new BudgetItem("3", "test 3")
            };

            var group     = new BudgetGroup("1", "name", budgetItems: items);
            var viewModel = new BudgetGroupViewModel(group);

            viewModel.IsTotalAmountZero.Should().BeFalse();
        }
        public void IsTotalAmountZero_AllZeroItemsAmount_ExpectTrue()
        {
            var items = new List <BudgetItem>
            {
                new BudgetItem("1", "test 1"),
                new BudgetItem("2", "test 2"),
                new BudgetItem("3", "test 3")
            };

            var group     = new BudgetGroup("1", "name", budgetItems: items);
            var viewModel = new BudgetGroupViewModel(group);

            viewModel.IsTotalAmountZero.Should().BeTrue();
        }
        double CalculateGroupRatio(BudgetGroup group)
        {
            if (budget.IncomeGroup.TotalAmount <= 0)
            {
                return(1);
            }

            var ratio = (double)(group.TotalAmount / budget.IncomeGroup.TotalAmount);

            ratio = Math.Max(0, ratio);
            ratio = Math.Min(1, ratio);

            return(ratio);
        }
        public void BudgetItems_DeleteItemGroup_ViewModelDeleted()
        {
            var items = new List <BudgetItem>
            {
                new BudgetItem("id1", "name1"),
                new BudgetItem("id2", "name2", 12.34m, BudgetItemType.Debt),
            };

            var group = new BudgetGroup("id", "group name", budgetItems: items);
            var budgetGroupViewModel = new BudgetGroupViewModel(group);

            var itemDeleted = group.BudgetItems[0];

            group.BudgetItems.RemoveAt(0);
            budgetGroupViewModel.BudgetItems.Count.Should().Be(1);
            budgetGroupViewModel.BudgetItems.Any(item => item.BudgetItem == itemDeleted).Should().BeFalse();
        }
        public void IsTotalAmountZero_ChangingItemAmounts_ExpectChangingTrueFalse()
        {
            var items = new List <BudgetItem>
            {
                new BudgetItem("1", "item 1"),
                new BudgetItem("2", "item 2"),
                new BudgetItem("3", "item 3"),
            };
            var group     = new BudgetGroup("1", "group 1", budgetItems: items);
            var viewModel = new BudgetGroupViewModel(group);

            viewModel.IsTotalAmountZero.Should().BeTrue();
            group.BudgetItems[1].Amount = 234.56m;
            viewModel.IsTotalAmountZero.Should().BeFalse();
            group.BudgetItems[1].Amount = 0;
            viewModel.IsTotalAmountZero.Should().BeTrue();
        }
        public void Constructor_DefaultBudgetGroupPresentation_PresentsDefaultValues()
        {
            var name  = "group";
            var group = new BudgetGroup("group1", name);

            BudgetGroupViewModel viewModel = new BudgetGroupViewModel(group);

            viewModel.BudgetItems.Should().BeEmpty();
            viewModel.ColorKey.Should().Be(BudgetGroupPresentation.DefaultColorKey);
            viewModel.IconSource.Should().Be("");
            viewModel.Description.Should().Be("");
            viewModel.Subtitle.Should().Be(BudgetGroupPresentation.DefaultSubtitle);
            viewModel.AddItemText.Should().Be(BudgetGroupPresentation.DefaultAddItemText);
            viewModel.CustomTitle.Should().Be("");
            viewModel.IsTitleVisible.Should().BeTrue("a custom title is not provided");
            viewModel.IsCustomTitleVisible.Should().BeFalse("a custom title is not provided");
            viewModel.HasSecondaryHeader.Should().BeFalse();
            viewModel.HeaderTextWithoutDate.Should().Be(name.ToUpper());
            viewModel.HeaderText.Should().Be(viewModel.HeaderTextWithoutDate, "hasDateOnHeader is false");
        }
        internal Budget(
            BudgetGroup incomeGroup,
            BudgetGroup housingGroup,
            BudgetGroup transportationGroup,
            BudgetGroup foodGroup,
            BudgetGroup personalGroup,
            BudgetGroup givingGroup,
            BudgetGroup debtGroup,
            BudgetGroup basicExpensesDisplayGroup)
        {
            IncomeGroup               = incomeGroup ?? throw new ArgumentNullException(nameof(incomeGroup));
            HousingGroup              = housingGroup ?? throw new ArgumentNullException(nameof(housingGroup));
            TransportationGroup       = transportationGroup ?? throw new ArgumentNullException(nameof(transportationGroup));
            FoodGroup                 = foodGroup ?? throw new ArgumentNullException(nameof(foodGroup));
            PersonalGroup             = personalGroup ?? throw new ArgumentNullException(nameof(personalGroup));
            GivingGroup               = givingGroup ?? throw new ArgumentNullException(nameof(givingGroup));
            DebtGroup                 = debtGroup ?? throw new ArgumentNullException(nameof(debtGroup));
            BasicExpensesDisplayGroup = basicExpensesDisplayGroup ?? throw new ArgumentNullException(nameof(basicExpensesDisplayGroup));

            InitializeBudgetGroupChangeListeners();
        }
        public void Constructor_ModelWithBudgetItems_PresentsGroupAndItems()
        {
            string name  = "test group name";
            var    items = new List <BudgetItem>
            {
                new BudgetItem("id1", "group1"),
                new BudgetItem("id2", "group2", 12.34m),
            };

            var group     = new BudgetGroup("id3", name, budgetItems: items);
            var viewModel = new BudgetGroupViewModel(group);

            viewModel.Name.Should().Be(group.Name);
            viewModel.NameLower.Should().Be(group.Name.ToLower());
            viewModel.TotalAmount.Should().Be(group.TotalAmount.ToCurrencyString());
            viewModel.BudgetItems.Count.Should().Be(items.Count);

            for (int i = 0; i < items.Count; i++)
            {
                viewModel.BudgetItems[i].BudgetItem.Should().Be(items[i]);
            }
        }