예제 #1
0
        /// <summary>
        /// Called when the group collection is changed. Used to add/remove Totals rows.
        /// </summary>
        /// <param name="sender">The modified collection</param>
        /// <param name="e">The arguments</param>
        private void GroupsCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
        {
            //Adds Totals rows
            if (e.NewItems != null && e.Action != NotifyCollectionChangedAction.Move)
            {
                foreach (Group newGroup in e.NewItems)
                {
                    Category newCategory = new Category(newGroup.Name);
                    try
                    {
                        Group totalGroup;
                        //Gets the income state
                        if (newGroup.IsIncome)
                        {
                            totalGroup = columnIncomeTotalsGroup;
                        }
                        else
                        {
                            totalGroup = columnExpendituresTotalsGroup;
                        }
                        this.BudgetTotals.Add(new MoneyGridRow(totalGroup, newCategory));
                        this.SpendingTotals.Add(new MoneyGridRow(totalGroup, newCategory));
                        this.ComparisonTotals.Add(new MoneyGridRow(totalGroup, newCategory));
                    }
                    catch (ArgumentException ex)
                    {
                        this._errorhandler.DisplayError($"Could not match group to category {newCategory.Name}").Wait();
                        throw new ArgumentException("Could not match group to category " + newGroup.Name, ex);
                    }
                }
            }

            //Removes totals rows
            if (e.OldItems != null && e.Action != NotifyCollectionChangedAction.Move)
            {
                foreach (Group oldGroup in e.OldItems)
                {
                    MoneyGridRow oldRow = this.BudgetTotals.Where(row => row.Category.Name.Equals(oldGroup.Name)).ElementAt(0);
                    if (oldRow == null)
                    {
                        throw new ArgumentException("Cannot locate deleted row");
                    }
                    this.BudgetTotals.Remove(oldRow);

                    oldRow = this.SpendingTotals.Where(row => row.Category.Name.Equals(oldGroup.Name)).ElementAt(0);
                    if (oldRow == null)
                    {
                        throw new ArgumentException("Cannot locate deleted row");
                    }
                    this.SpendingTotals.Remove(oldRow);

                    oldRow = this.ComparisonTotals.Where(row => row.Category.Name.Equals(oldGroup.Name)).ElementAt(0);
                    if (oldRow == null)
                    {
                        throw new ArgumentException("Cannot locate deleted row");
                    }
                    this.ComparisonTotals.Remove(oldRow);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Move a category closer to the back (N-index) of its group's collection
        /// </summary>
        /// <param name="category">The category to move up</param>
        private void MoveCategoryDown(Category category)
        {
            if (category == null)
            {
                return;
            }
            Group group = GetCategoryGroup(category);

            if (group == null)
            {
                throw new ArgumentException("Category " + category.Name + " does not belong to a group");
            }
            int index = group.Categories.IndexOf(category);

            if (index < 0)
            {
                throw new ArgumentException("Category " + category.Name + " does not exist");
            }
            if (index < group.Categories.Count - 1)
            {
                //Move all the Values rows down
                group.Categories.Move(index, index + 1);
                MoneyGridRow budgetRow = this.sessionService.BudgetValues.Single(x => x.Category == category);
                int          rowIndex  = this.sessionService.BudgetValues.IndexOf(budgetRow);
                this.sessionService.MoveValueRows(rowIndex, rowIndex + 1);
            }
        }
예제 #3
0
        /// <summary>
        /// Called when the category collection is changed. Used to add/remove Values rows.
        /// </summary>
        /// <param name="sender">The modified collection</param>
        /// <param name="e">The arguments</param>
        private void CategoryCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
        {
            //Adds Values rows
            if (e.NewItems != null && e.Action != NotifyCollectionChangedAction.Move)
            {
                foreach (Category newCategory in e.NewItems)
                {
                    Group group = GetCategoryGroup(newCategory);
                    if (group == null)
                    {
                        throw new ArgumentException("Could not match group to category " + newCategory.Name);
                    }
                    this.BudgetValues.Add(new MoneyGridRow(group, newCategory));
                    this.SpendingValues.Add(new MoneyGridRow(group, newCategory));
                    this.ComparisonValues.Add(new MoneyGridRow(group, newCategory));
                }
            }
            //Removes Values rows. Order is important to avoid triggering data that doesn't exist. (1/4/2017: May be fixed now)
            if (e.OldItems != null && e.Action != NotifyCollectionChangedAction.Move)
            {
                foreach (Category oldCategory in e.OldItems)
                {
                    MoneyGridRow oldRow = this.ComparisonValues.Where(row => row.Category == oldCategory).ElementAt(0);
                    if (oldRow == null)
                    {
                        throw new ArgumentException("Cannot locate deleted row");
                    }
                    this.ComparisonValues.Remove(oldRow);

                    oldRow = this.SpendingValues.Where(row => row.Category == oldCategory).ElementAt(0);
                    if (oldRow == null)
                    {
                        throw new ArgumentException("Cannot locate deleted row");
                    }
                    this.SpendingValues.Remove(oldRow);

                    oldRow = this.BudgetValues.Where(row => row.Category == oldCategory).ElementAt(0);
                    if (oldRow == null)
                    {
                        throw new ArgumentException("Cannot locate deleted row");
                    }
                    this.BudgetValues.Remove(oldRow);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Fires when a cell is edited in the values grid.
        /// Allows the user to apply the same value to an entire row with Ctrl+Enter when editing
        /// </summary>
        /// <param name="sender">The sending object</param>
        /// <param name="e">The arguments</param>
        private void ValuesGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
        {
            //Check if either Control key is pressed
            if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
            {
                //Get the current MoneyGridRow object
                DataGridCellInfo cellInfo = ValuesGrid.SelectedCells[0];
                MoneyGridRow     row      = cellInfo.Item as MoneyGridRow;

                //Parse the new value into a decimal
                decimal currentVal = decimal.Parse((e.EditingElement as TextBox).Text, System.Globalization.NumberStyles.Currency);

                //Change the other values in the MoneyGridRow
                //Note: A new array is used to avoid multiple PropertyChanged notifications
                decimal[] values = new decimal[12];
                for (int i = 0; i < row.Values.Count; i++)
                {
                    values[i] = currentVal;
                }
                row.Values.Values = values;
            }
        }
예제 #5
0
        private void CalculateColumnTotals(ObservableCollection <MoneyGridRow> columnValues, ObservableCollection <MoneyGridRow> columnTotals, String propertyName)
        {
            //Don't do anything if not all the rows have been loaded yet
            if (columnValues.Count < this.Categories.Count || columnTotals.Count < this.Groups.Count)
            {
                return;
            }
            double totalGridIncomeTotal      = 0.0;
            double totalGridExpenditureTotal = 0.0;

            foreach (Group group in this.Groups) //For each group, find its total row and then sum all the category rows that are part of the group
            {
                double       groupTotal = 0.0;
                decimal[]    groupSum   = new decimal[12];
                MoneyGridRow total;
                try
                {
                    total = columnTotals.Single(x => x.Category.Name.Equals(group.Name));
                }
                catch (Exception ex)
                {
                    this._errorhandler.DisplayError($"Could not find corresponding total row: {group.Name}").Wait();
                    throw new ArgumentException("Could not find corresponding total row: " + group.Name, ex);
                }
                foreach (Category category in group.Categories)
                {
                    try
                    {
                        MoneyGridRow row = columnValues.Single(x => x.Group == group && x.Category == category);
                        for (int i = 0; i < row.Values.Count; i++)
                        {
                            groupSum[i] += row.Values[i];
                        }
                        groupTotal += (double)row.Sum;
                    }
                    catch (Exception ex)
                    {
                        this._errorhandler.DisplayError($"{propertyName} does not contain row for group {group} and category {category}").Wait();
                        continue;
                        throw new ArgumentException("Could not find corresponding row", ex);
                    }
                }
                total.Values.Values = groupSum;
                groupTotal          = (double)total.Sum;
                if (group.IsIncome)
                {
                    totalGridIncomeTotal += (double)total.Sum;
                }
                else
                {
                    totalGridExpenditureTotal += (double)total.Sum;
                }
                foreach (Category category in group.Categories)
                {
                    try
                    {
                        MoneyGridRow row = columnValues.Single(x => x.Group == group && x.Category == category);
                        row.Percentage = (double)row.Sum / groupTotal;
                    }
                    catch (Exception ex)
                    {
                        this._errorhandler.DisplayError($"{propertyName} does not contain row for group {group} and category {category}").Wait();
                        continue;
                        throw new ArgumentException("Could not find corresponding row", ex);
                    }
                }
                //RaisePropertyChanged(propertyName);
            }
            foreach (MoneyGridRow row in columnTotals)
            {
                if (row.Group.IsIncome)
                {
                    row.Percentage = (double)row.Sum / totalGridIncomeTotal;
                }
                else
                {
                    row.Percentage = (double)row.Sum / totalGridExpenditureTotal;
                }
            }
        }
예제 #6
0
        public async Task LoadDataFromFile(string filePath)
        {
            //Clears all existing data
            this.Groups.Clear();
            this.Categories.Clear();
            this.Transactions.Clear();
            this.PaymentMethods.Clear();
            this.BudgetValues.Clear();
            this.BudgetTotals.Clear();
            this.SpendingValues.Clear();
            this.SpendingTotals.Clear();
            this.ComparisonValues.Clear();
            this.ComparisonTotals.Clear();

            Group        testGroup    = new Model.Group();
            Category     testCategory = new Category();
            MoneyGridRow testRow      = new MoneyGridRow(testGroup, testCategory);
            //this.Groups.Add(testGroup);
            //this.Categories.Add(testCategory);
            //this.BudgetValues.Add(testRow);
            //return;

            //Retrieves the data using the serialize attributes
            DataWrapper data = new DataWrapper();

            try
            {
                using (FileStream file = new FileStream(filePath, FileMode.Open))
                {
                    XmlSerializer dataSerializer = new XmlSerializer(typeof(DataWrapper));
                    data = (DataWrapper)dataSerializer.Deserialize(file);
                }
            }
            catch (IOException ex) //File does not exist; set everything to defaults
            {
                await CreateNewFile(Properties.Settings.Default.DefaultDirectory + "\\data_new.xml");
            }
            catch (InvalidOperationException ex)
            {
                await this._errorhandler.DisplayError($"Error reading XML from file {filePath}\n{ex.Message}");
            }
            catch (System.Xml.XmlException ex)
            {
                await this._errorhandler.DisplayError($"Error in XML file\n{ex.Message}");
            }
            //Process the data
            this.CurrentYear = data.Year;
            int index = 0;
            //Add groups, categories, and budget values
            List <Group>    tempGroups     = new List <Group>();
            List <Category> tempCategories = new List <Category>();

            this.BudgetValues.MemberChanged -= UpdateBudgetTotals;
            foreach (Group group in data.Groups)
            {
                Group newGroup = new Group(group.IsIncome, group.Name);
                this.Groups.Add(newGroup);
                foreach (Category category in group.Categories)
                {
                    newGroup.Categories.Add(category);
                    this.Categories.Add(category);
                    MoneyGridRow row = this.BudgetValues.Single(x => x.Category == category);
                    row.Values.Values = data.BudgetValues.ElementAt(index);
                    index++;
                }
            }
            this.BudgetValues.MemberChanged += UpdateBudgetTotals;
            RefreshBudgetTotals();
            //Add payment methods
            foreach (PaymentMethod payment in data.PaymentMethods)
            {
                this.PaymentMethods.Add(payment);
            }
            //Adds the transactions
            //Transactions are stored with different instances of the category and payment method objects. These need to
            //be matched to the data loaded above. Matching is done using the name of each.
            List <Transaction> tempTransactions = new List <Transaction>();

            foreach (Transaction transaction in data.Transactions)
            {
                string categoryName = transaction.Category.Name;
                string paymentName  = transaction.PaymentMethod.Name;
                try
                {
                    transaction.Category = this.Categories.Single(x => x.Name.Equals(categoryName));
                }
                catch (ArgumentException ex)
                {
                    throw new ArgumentException("Cannot find matching category " + transaction.Category.Name + " in categories list");
                }
                try
                {
                    transaction.PaymentMethod = this.PaymentMethods.Single(x => x.Name.Equals(paymentName));
                }
                catch (ArgumentException ex)
                {
                    throw new ArgumentException("Cannot find matching payment method " + transaction.PaymentMethod.Name + " in payment methods list");
                }
                tempTransactions.Add(transaction);
            }
            this.Transactions.InsertRange(tempTransactions);
        }
예제 #7
0
        private void RefreshBudgetPieChart()
        {
            List <MoneyGridRow> filteredRows = new List <MoneyGridRow>();

            foreach (MoneyGridRow row in this.Session.BudgetValues)
            {
                MoneyGridRow tempRow = row.Copy();
                if (this.BudgetGraphConfiguration.Filter(tempRow))
                {
                    filteredRows.Add(tempRow);
                }
            }
            this.Series.Clear();
            this.PointLabel = this.FormatPieChartLabel;
            decimal sum = 0.0M;

            switch (this.BudgetGraphConfiguration.Grouping)
            {
            case BudgetGraphGrouping.Category:
                foreach (Category category in this.Session.Categories)
                {
                    sum = 0.0M;
                    sum = filteredRows.Where(x => x.Category.Equals(category)).Sum(x => x.Sum);
                    if (sum < 0.0M)
                    {
                        sum = 0.0M;
                    }
                    this.Series.Add(new PieSeries
                    {
                        Title  = category.Name,
                        Values = new ChartValues <decimal> {
                            sum
                        },
                        DataLabels    = true,
                        LabelPoint    = this.PointLabel,
                        LabelPosition = PieLabelPosition.OutsideSlice,
                    });
                }
                break;

            case BudgetGraphGrouping.Month:
                for (int i = 0; i < 12; i++)
                {
                    sum = 0.0M;
                    sum = filteredRows.Select(x => x.Values[i]).Sum();
                    if (sum < 0.0M)
                    {
                        sum = 0.0M;
                    }
                    this.Series.Add(new PieSeries
                    {
                        Title  = (new DateTime(1, i + 1, 1)).ToString("MMMM"),
                        Values = new ChartValues <decimal> {
                            sum
                        },
                        DataLabels    = true,
                        LabelPoint    = this.PointLabel,
                        LabelPosition = PieLabelPosition.OutsideSlice
                    });
                }
                break;

            case BudgetGraphGrouping.Group:
                foreach (Group group in this.Session.Groups)
                {
                    sum = 0.0M;
                    sum = filteredRows.Where(x => x.Group.Equals(group)).Sum(x => x.Sum);
                    if (sum < 0.0M)
                    {
                        sum = 0.0M;
                    }
                    this.Series.Add(new PieSeries
                    {
                        Title  = group.Name,
                        Values = new ChartValues <decimal> {
                            sum
                        },
                        DataLabels    = true,
                        LabelPoint    = this.PointLabel,
                        LabelPosition = PieLabelPosition.OutsideSlice
                    });
                }
                break;

            case BudgetGraphGrouping.IsIncome:
                sum  = 0.0M;
                sum += filteredRows.Where(x => x.Group.IsIncome).Sum(x => x.Sum);
                if (sum < 0.0M)
                {
                    sum = 0.0M;
                }
                this.Series.Add(new PieSeries
                {
                    Title  = "Income",
                    Values = new ChartValues <decimal> {
                        sum
                    },
                    DataLabels    = true,
                    LabelPoint    = this.PointLabel,
                    LabelPosition = PieLabelPosition.OutsideSlice
                });
                sum  = 0.0M;
                sum += filteredRows.Where(x => !x.Group.IsIncome).Sum(x => x.Sum);
                if (sum < 0.0M)
                {
                    sum = 0.0M;
                }
                this.Series.Add(new PieSeries
                {
                    Title  = "Expenditures",
                    Values = new ChartValues <decimal> {
                        sum
                    },
                    DataLabels    = true,
                    LabelPoint    = this.PointLabel,
                    LabelPosition = PieLabelPosition.OutsideSlice
                });
                break;

            default:
                break;
            }
        }