예제 #1
0
        /// <summary>
        /// Finds and returns all expenses in the database that match the given filter. Sorted by Date in ascending order.
        /// </summary>
        /// <param name="filter">Filter to select expenses by.</param>
        /// <returns>All expenses that match the filter, empty list if none are found.</returns>
        public List <Expense> FindAll(ExpenseFilter filter)
        {
            List <Expense> expenses = new List <Expense>();

            using (SqliteConnection db = new SqliteConnection(this.CreateConnectionString()))
            {
                db.Open();
                using (SqliteCommand cmd = db.CreateCommand())
                {
                    string cmdText = string.Format(
                        "SELECT * FROM {0} WHERE ",
                        DataAccessFactory.EXPENSE_TABLE_NAME);

                    DataAccessFactory.PrepareFilterConstraintCommand(cmdText, cmd, filter);

                    using (SqliteDataReader rdr = cmd.ExecuteReader())
                    {
                        while (rdr.Read())
                        {
                            Expense e = DataAccessFactory.FromRow(rdr);
                            expenses.Add(e);
                        }
                    }
                }
            }

            return(expenses);
        }
예제 #2
0
        /// <summary>
        /// Finds the first expense in the database that matches the filter. Sorted by Date in ascending order.
        /// </summary>
        /// <param name="filter">Filter to select expenses by.</param>
        /// <returns>The first expense that matches the filter, otherwise null.</returns>
        public Expense FindOne(ExpenseFilter filter)
        {
            using (SqliteConnection db = new SqliteConnection(this.CreateConnectionString()))
            {
                db.Open();
                using (SqliteCommand cmd = db.CreateCommand())
                {
                    string cmdText = string.Format(
                        "SELECT * FROM {0} WHERE ",
                        DataAccessFactory.EXPENSE_TABLE_NAME);

                    DataAccessFactory.PrepareFilterConstraintCommand(cmdText, cmd, filter);
                    Console.WriteLine(cmd.CommandText);

                    using (SqliteDataReader rdr = cmd.ExecuteReader())
                    {
                        if (rdr.Read())
                        {
                            return(DataAccessFactory.FromRow(rdr));
                        }
                        else
                        {
                            return(null);
                        }
                    }
                }
            }
        }
예제 #3
0
 /// <summary>
 /// Checks that the two filters functionally are the same. That is they match the same set of expenses.
 /// The name is left out during this comparison.
 /// </summary>
 /// <param name="f">Filter to compare against.</param>
 /// <returns>True if the filters are functionaly equal. False if not.</returns>
 public bool FunctionalEquals(ExpenseFilter f)
 {
     return((this.MinValue == f.MinValue) &&
            (this.MaxValue == f.MaxValue) &&
            (this.MinDate == f.MinDate) &&
            (this.MaxDate == f.MaxDate) &&
            this.Place.SetEquals(f.Place) &&
            this.Tag.SetEquals(f.Tag) &&
            this.Keywords.SetEquals(f.Keywords) &&
            ExpenseFilter.MethodEqual(this.Method, f.Method));
 }
예제 #4
0
        /// <inheritdoc/>
        public override bool Equals(object obj)
        {
            ExpenseFilter f = (ExpenseFilter)obj;

            return((this.Name == f.Name) &&
                   (this.MinValue == f.MinValue) &&
                   (this.MaxValue == f.MaxValue) &&
                   (this.MinDate == f.MinDate) &&
                   (this.MaxDate == f.MaxDate) &&
                   this.Place.SetEquals(f.Place) &&
                   this.Tag.SetEquals(f.Tag) &&
                   this.Keywords.SetEquals(f.Keywords) &&
                   ExpenseFilter.MethodEqual(this.Method, f.Method));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ExpenseController"/> class.
        /// Internal so that it may only be instantiated by backend code. Must be created
        /// by the Authenticator.
        /// </summary>
        /// <param name="user">The user whose expenses the object will be interacting with.</param>
        internal ExpenseController(User user)
        {
            // Setup members
            this.CurrentUser       = user;
            this.ExpenseDataAccess = new DataAccessFactory(this.CurrentUser);

            // only place we dont use property because we dont want to refresh table as we are jsut creating it.
            this.activeFilter = null;

            // If the expense table doesnt yet exist, create it before loading expenses.
            if (!this.ExpenseDataAccess.ExpenseTableExists)
            {
                this.ExpenseDataAccess.CreateNewExpenseTable();
            }

            // Initially load all expenses into controller
            this.currentExpenses = this.ExpenseDataAccess.GetAll();
        }
예제 #6
0
        /// <summary>
        /// computes union of two filters and returns a new filter.
        /// </summary>
        /// <param name="f1">First Filter to intersect with.</param>
        /// <param name="f2">Second Filter to intersect with.</param>
        /// <param name="filterName">Name to be given to the new filter. Defaults to "f1.Name|f2.Name".</param>
        /// <returns>ExpenseFilter containing the union.</returns>
        public static ExpenseFilter Union(ExpenseFilter f1, ExpenseFilter f2, string filterName = "")
        {
            if (filterName == string.Empty)
            {
                filterName = f1.Name + '|' + f2.Name;
            }

            return(new ExpenseFilter(
                       name: filterName,
                       maxValue: new[] { f1.MaxValue, f2.MaxValue }.Max(),
                       minValue: new[] { f1.MinValue, f2.MinValue }.Min(),
                       maxDate: new[] { f1.MaxDate, f2.MaxDate }.Max(),
                       minDate: new[] { f1.MinDate, f2.MinDate }.Min(),
                       place: new HashSet <string>(f1.Place.Union(f2.Place)),
                       tag: new HashSet <string>(f1.Tag.Union(f2.Tag)),
                       keywords: new HashSet <string>(f1.Keywords.Union(f2.Keywords)),
                       method: ExpenseFilter.MethodEqual(f1.Method, f2.Method) ? f1.Method : null));
        }
예제 #7
0
        /// <summary>
        /// Summarizes the ExpenseFilters set of expenses in SQL, that can be easily added to a where clause.
        /// Sorts by date.
        /// </summary>
        private static void PrepareFilterConstraintCommand(string prefix, SqliteCommand cmd, ExpenseFilter filter)
        {
            // TODO: TEST THIS
            string outstring = string.Empty;

            // add date clause
            outstring += "(Date BETWEEN @mindate AND @maxdate) AND ";
            cmd.Parameters.Add(new SqliteParameter("@mindate", filter.MinDate));
            cmd.Parameters.Add(new SqliteParameter("@maxdate", filter.MaxDate));

            // handle value clause
            outstring += "(Value BETWEEN @minvalue AND @maxvalue)";
            cmd.Parameters.Add(new SqliteParameter("@minvalue", filter.MinValue));
            cmd.Parameters.Add(new SqliteParameter("@maxvalue", filter.MaxValue));

            // handle place clause
            if (filter.Place.Count > 0)
            {
                int i = 0;
                outstring += " AND (Place IN (";
                foreach (var place in filter.Place)
                {
                    outstring += "@place" + i;
                    outstring += (filter.Place.Count - 1 == i) ? string.Empty : ", ";
                    cmd.Parameters.Add(new SqliteParameter("@place" + i, place));
                    ++i;
                }

                outstring += "))";
            }

            // handle tag clause
            if (filter.Tag.Count > 0)
            {
                int i = 0;
                outstring += " AND (";
                foreach (var tag in filter.Tag)
                {
                    outstring += "(Tag LIKE @tag" + i + ")";
                    outstring += (filter.Tag.Count - 1 == i) ? string.Empty : " OR ";
                    cmd.Parameters.Add(new SqliteParameter("@tag" + i, "%" + tag + "%"));
                    ++i;
                }

                outstring += ")";
            }

            // handle keyword clause
            if (filter.Keywords.Count > 0)
            {
                int i = 0;
                outstring += " AND (";
                foreach (var word in filter.Keywords)
                {
                    outstring += "(Notes LIKE @word" + i + ")";
                    outstring += (filter.Keywords.Count - 1 == i) ? string.Empty : " OR ";
                    cmd.Parameters.Add(new SqliteParameter("@word" + i, "%" + word + "%"));
                    ++i;
                }

                outstring += ")";
            }

            // prepare purchasemethod args
            if (filter.Method != null)
            {
                if (filter.Method is Cash)
                {
                    // This is an undesireable solution - ideally would like a way for derived classes to provide this information themselves,
                    // but we dont want that functionality available outside of the engine.
                    Cash c = (Cash)filter.Method;
                    outstring += " AND (Type = @type) AND (Currency = @currency)";
                    cmd.Parameters.Add(new SqliteParameter("@type", (int)EpurchaseMethod.CASH));
                    cmd.Parameters.Add(new SqliteParameter("@currency", c.Currency));
                }
                else if (filter.Method is Card)
                {
                    Card c = (Card)filter.Method;
                    outstring += " AND (Type = @type) AND (Debit = @debit) AND (Provider = @provider) AND (Number = @number) AND (Name = @name)";
                    cmd.Parameters.Add(new SqliteParameter("@type", (int)EpurchaseMethod.CARD));
                    cmd.Parameters.Add(new SqliteParameter("@debit", c.Debit));
                    cmd.Parameters.Add(new SqliteParameter("@provider", c.Provider));
                    cmd.Parameters.Add(new SqliteParameter("@number", c.Number));
                    cmd.Parameters.Add(new SqliteParameter("@name", c.Name));
                }
                else if (filter.Method is DirectDeposit)
                {
                    DirectDeposit d = (DirectDeposit)filter.Method;
                    outstring += " AND (Type = @type) AND (Savings = @savings) AND (Bankname = @bankname) AND (Number = @number) AND (Name = @name)";
                    cmd.Parameters.Add(new SqliteParameter("@type", (int)EpurchaseMethod.DIRECT_DEPOSIT));
                    cmd.Parameters.Add(new SqliteParameter("@savings", d.Savings));
                    cmd.Parameters.Add(new SqliteParameter("@bankname", d.BankName));
                    cmd.Parameters.Add(new SqliteParameter("@number", d.Number));
                    cmd.Parameters.Add(new SqliteParameter("@name", d.Name));
                }
            }

            outstring += " ORDER BY Date ASC;";

            cmd.CommandText = prefix + outstring;
            cmd.Prepare();
        }
예제 #8
0
 /// <summary>
 /// Inserts the given filter into the users filter table.
 /// </summary>
 /// <param name="filter">The filter object to be placed in the table.</param>
 public void InsertFilter(ExpenseFilter filter)
 {
     throw new NotImplementedException();
 }
예제 #9
0
 /// <summary>
 /// computes intersection of two filters and returns a new filter.
 /// if the two filters produce a null intersection, null is returned.
 /// </summary>
 /// <param name="f1">First Filter to intersect with.</param>
 /// <param name="f2">Second Filter to intersect with.</param>
 /// <returns>ExpenseFilter containing the intersection.</returns>
 public static ExpenseFilter Intersection(ExpenseFilter f1, ExpenseFilter f2)
 {
     // NOTE: Implementation is stretch goal
     throw new NotImplementedException();
 }