diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 09e2ec45315..a8f3ba8db36 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -52,38 +52,48 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. === Expenses and Income -==== Adding a expense: `addExpense` -Adds a new expenditure to your total/daily/weekly/monthly spending with current timestamp. Inputs can be arranged in a different order. Description and tag may be omitted from the expenditure record. +==== Adding Expense: `add` +Adds a new expenditure to your total/daily/weekly/monthly spending with current timestamp. Inputs can be arranged in a different order.Tag may be omitted from the expenditure record. Category must already exist in the list of category. -Format: `addExpense [--desc ] [--tag ] --amt ` +Format: `add typ/Expense cat/ n/ amt/ d/ [--tag ]` Examples: -* `addExpense --desc deck mala --tag food --amt 5.60` -* `addExpense --tag food --amt 5.60` -* `addExpense --amt 5.60 --cat food` -* `addExpense --amt 5.60` +* `add cat/Food typ/Expense n/Mala amt/5.50 d/2019 09 09 tg/food tg/indulgence` +* `add cat/Travel typ/Expense n/Travel To Alaska amt/550000 d/2019 09 09` -==== Editing a expense: `editExpense` +==== Adding Income : `add` +Adds a new Income to your total/daily/weekly/monthly spending with current timestamp. Inputs can be arranged in a different order. Tag may be omitted from the expenditure record. . Category must already exist in the list of category. -Edits a current expenditure with the given index number +Format: `add typ/Income cat/ n/ amt/ d/ [--tag ]` -Format: `editExpense [--desc ] [--tag ] [--amt ]` +Examples: + +* `add cat/Gifts typ/Income n/Durian amt/200.00 d/2019 09 09 tg/food` +* `add cat/Business typ/Income n/business Trip To Mars amt/20000.00 d/2019 09 09` + +==== Editing a expense/income: `edit` + +Edits a current entry with the given index number. Category must already exist in the list of category. + +Format: `edit [cat/] [n/] [d/] [amt/ ] [--tag ]` Examples: -* `editExpense 1 --desc deck mala with friends` -* `editExpense 1 --tag mala --amt 5.33` +* `edit 1 cat/Food n/deck mala with friends` +* `edit 3 cat/Business n/Selling Coding Services amt/0.01` +* `edit 5 tg/helpmykidneys` -==== Deleting a expense: `deleteExpense` +==== Deleting a expense/income: `delete` Deletes the recorded expenditure with the given index number. -Format: `deleteExpense ` +Format: `delete ` Examples: -* `deleteExpense 2` +* `delete 2` +* `delete 4` ==== Adding AutoExpenditure : `addAutoExpenditure` @@ -112,38 +122,6 @@ Deletes a current automatically recurring expenditure at the given index. Format: `deleteAutoExpenditure ` -==== Adding Income : `addIncome` - -Adds the amount to your total income. Inputs can be arranged in a different order. Description may be omitted from the income record. - -Format: `addIncome [n/] amt/` - -Examples: - -* `addIncome amt/6000` -* `addIncome amt/1000 n/year-end bonus!! :DD` - -==== Editing Income : `editIncome` - -Edits a current income record at the given index number. - -Format: `editIncome [n/] [amt/] [t/]` - -Examples: - -* `editIncome 1 n/salary for feb` -* `editIncome 1 n/february amt/650 t/salary` - -==== Deleting Income : `deleteIncome` - -Deletes the recorded income at the given index number. - -Format: `deleteIncome ` - -Examples: - -* `deleteIncome 3` - ==== Adding Budget : 'addBudget` Adds a new budget for expenditure with a certain tag, if applicable. Period: day/week/month @@ -187,19 +165,122 @@ Examples: * `deleteBudget 2` +==== Adding Category : 'addCategory` + +Adds a new Category for either Income or Expense. The category added must not exist in the application. + +Format: `addCategory cat/ n/` + +Examples: + +* `addCategory cat/Expense n/Transport` +* `addCategory cat/Income n/Lottery` + +==== Editing Category : 'editCategory` +Edits a current category's description. + +Format: `editCategory typ/ cat/ n/` + +Examples: + +* `editCategory typ/Income cat/Business n/HotelManagement` +* `editCategory typ/Expense cat/Family n/Baby Planning` + +==== Listing Categories : 'listCategories` + +Lists all the current categories the user has. + +Format: `listCategories` + +Examples: + +* `listCategories` + +==== Deleting Category : `deleteCategory` +Deletes a category from guiltTrip. The category that is deleted should not have any entries. + +Format: `deleteCategory cat/ n/` + +Examples: + +* `deleteCategory cat/Income n/Business` +* `deleteCategory cat/Expense n/Food` + +==== Adding a Loan : `addLoan` [coming in v2.0] +Adds a new loan with the given description, amount and interest (in percentage) and calculates the total outstanding amount based on the interest. + +Format: `addLoan n/ amt/ i/` + +Example: + +* `addLoan n/student loan amt/30000 i/4.5` + +==== Listing a loan : `listLoan` [coming in v2.0] +Lists all the loans that the user has. + +Format: `listLoan` + +Example: `listLoan` + +==== Editing a loan : `editLoan` [coming in v2.0] +Edits a current loan's description, loan amount, or both. + +Format: `editLoan [n/] [amt/] [i/]` + +Example: + +* `editLoan 1 n/nus tuition loan T.T` +* `editLoan 1 amt/25000 i/4.45%` + +==== Deleting a loan : `deleteLoan` [coming in v2.0] + +Deletes a current loan at the given index. + +Format: `deleteLoan ` + +Example: + +* `deleteLoan 1` + +==== Paying a loan : `payLoan` [coming in v2.0] + +Reduces the loan amount for the loan at the given index after user pays for part of the loan. + +Format: `payLoan amt/` + +Example: + +* `payLoan 1 amt/4000` + === Statistics -==== Viewing History : `viewHistory` -View past expenditure/ income from startDate to endDate (if present). If startDate not present, lists from 1 month before endDate. If endDate not present, list to current time. +==== Switching to Statistics View : `switch` +Switches between the entry view and the statistics summary. + +Format: `switch` + +Example: + +`switch` + +==== Switching to Statistics View : `switchStats` +Switches between the statistics table view and the statistics graph view. -Format: `viewHistory -- cat [--period , ]` +Format: `switchStats` Example: -* `viewHistory -- cat expenditure` -* `viewHistory -- cat expenditure --period 11/9/2019, 21/9/2019` -* `viewHistory -- cat income --period 11/9/2019` -* `viewHistory -- cat expenditure --period ,2 21/9/2019` +`switchStats` + +==== Viewing Statistics : `viewStatistics` +View past expenditure/ income by Month. If not present, will only show current Month. + +Format: `viewStatistics [p/]` + +Example: + +* `viewStatistics` +* `viewStatistics p/2019-09` ==== Sorting : `sort` @@ -213,20 +294,41 @@ Example: * `sort typ/amount s/ascending` * `sort typ/category s/descending` -==== Search : `search` +==== Search : `find` + +Search income/expenditure by Category,Description,Amount,Date or Tags. There must be at least one find parameter. + +Format: `find [cat/] [n/] [amt/] [d/] [--tag ]` + +Example: + +* `find cat/food n/mala: lists each entry in expenditure and income with title containing keyword “mala” and category of Food.` +* `find cat/business d/2019-09-09: lists each entry in expenditure and income with date of "2019-09-09" and category of business.` +* `find d/2019-09-09 tg/a tg/b: lists each entry in expenditure and income with date of "2019-09-09" and tags of a and b.` + +==== Search Wish: `findWish` + +Search Wish by Category,Description,Amount,Date or Tags. There must be at least one find parameter. + +Format: `findWish [cat/] [n/] [amt/] [d/] [--tag ]` + +Example: + +* `findWish cat/food n/mala: lists each entry in Wish with title containing keyword “mala” and category of Food.` +* `findWish cat/business d/2019-09-09: lists each entry in Wish with date of "2019-09-09" and category of business.` +* `findWish d/2019-09-09 tg/a tg/b: lists each entry in Wish with date of "2019-09-09" and tags of a and b.` + +==== Search Budget: `findBudget` -Search income/expenditure list/ wishlist for keyword/ tag. +Search Budget by Category,Description,Amount,Date or Tags. There must be at least one find parameter. -Format: `Search [--cat ] --key || --amt <(== || < || > || <= || >=) amount> || --tag ` +Format: `findBudget [cat/] [n/] [amt/] [d/] [--tag ]` Example: -* `search --cat expenditure --key book: lists each entry in expenditure with title containing keyword “book”.` -* `search --cat wishlist --key monitor: lists each entry in expenditure with title containing keyword “monitor”` -* `search --key book: search everything in database with keyword “book”.` -* `search --cat expenditure --tag _CLOTHING: lists each entry in expenditure with tag _CLOTHING.` -* `search --cat wishlist --tag _BOOK: lists each entry in wishlist with tag _BOOK.` -* `search --cat expenditure --amt >100: list each entry in expenditure over $100.` +* `findBudget cat/food n/mala: lists each entry in Budget with title containing keyword “mala” and category of Food.` +* `findBudget cat/business d/2019-09-09: lists each entry in Budget with date of "2019-09-09" and category of business.` +* `findBudget d/2019-09-09 tg/a tg/b: lists each entry in Budget with date of "2019-09-09" and tags of a and b.` === Organization diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 6405a0e9e59..5776badd000 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -7,9 +7,11 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_DESC; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.function.Predicate; import seedu.address.logic.commands.FindCommand; @@ -17,6 +19,10 @@ import seedu.address.model.person.Entry; import seedu.address.model.person.predicates.AmountContainsValuePredicate; import seedu.address.model.person.predicates.DescriptionContainsKeywordsPredicate; +import seedu.address.model.person.predicates.EntryContainsDatePredicate; +import seedu.address.model.person.predicates.EntryContainsTagsPredicate; +import seedu.address.model.person.predicates.entries.CategoryContainsKeywordsPredicate; +import seedu.address.model.tag.Tag; /** * Parses input arguments and creates a new FindCommand object @@ -31,6 +37,7 @@ public class FindCommandParser implements Parser { public FindCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_CATEGORY, PREFIX_DESC, PREFIX_DATE, PREFIX_AMOUNT, PREFIX_TAG); + List> predicateList = new ArrayList>(); if (argMultimap.getValue(PREFIX_DESC).isPresent()) { String trimmedArgs = ParserUtil.parseDescription(argMultimap.getValue(PREFIX_DESC).get()).fullDesc.trim(); @@ -44,10 +51,25 @@ public FindCommand parse(String args) throws ParseException { } if (argMultimap.getValue(PREFIX_AMOUNT).isPresent()) { - double trimmedDouble = ParserUtil.parseAmount(argMultimap.getValue(PREFIX_AMOUNT).get()).value; + double trimmedDouble = ParserUtil.parseAmount(argMultimap.getValue(PREFIX_AMOUNT).get().trim()).value; predicateList.add(new AmountContainsValuePredicate(trimmedDouble)); } + if (argMultimap.getValue(PREFIX_CATEGORY).isPresent()) { + String name = argMultimap.getValue(PREFIX_CATEGORY).get().trim(); + predicateList.add(new CategoryContainsKeywordsPredicate(name)); + } + + if (argMultimap.getValue(PREFIX_DATE).isPresent()) { + LocalDate dateToCompare = ParserUtil.parseDate(argMultimap.getValue(PREFIX_DATE).get().trim()).getDate(); + predicateList.add(new EntryContainsDatePredicate(dateToCompare)); + } + + if (argMultimap.getValue(PREFIX_TAG).isPresent()) { + Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + predicateList.add(new EntryContainsTagsPredicate(tagList)); + } + if (predicateList.size() == 0) { throw new ParseException(FindCommand.INSUFFICENT_ARGUMENTS); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 963d8eaa605..6d2a656a327 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -336,6 +336,7 @@ public void setEntry(Entry target, Entry editedEntry) { Income incomeToEdit = versionedAddressBook.getIncomeList().filtered(t -> t == target).get(0); Income toEditEntry = new Income(editedEntry.getCategory(), editedEntry.getDesc(), editedEntry.getDate(), editedEntry.getAmount(), editedEntry.getTags()); + versionedAddressBook.setEntry(incomeToEdit, toEditEntry); versionedAddressBook.setIncome(incomeToEdit, toEditEntry); } filteredReminders.filtered(PREDICATE_SHOW_ACTIVE_REMINDERS); diff --git a/src/main/java/seedu/address/model/person/predicates/DescriptionContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/predicates/DescriptionContainsKeywordsPredicate.java index 64db88851b1..ab1cf7592bc 100644 --- a/src/main/java/seedu/address/model/person/predicates/DescriptionContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/predicates/DescriptionContainsKeywordsPredicate.java @@ -7,7 +7,7 @@ import seedu.address.model.person.Entry; /** - * Tests that a {@code Person}'s {@code Name} matches any of the keywords given. + * Tests that a {@code Entry's}'s {@code Description} matches any of the keywords given. */ public class DescriptionContainsKeywordsPredicate implements Predicate { private final List keywords; diff --git a/src/main/java/seedu/address/model/person/predicates/EntryContainsDatePredicate.java b/src/main/java/seedu/address/model/person/predicates/EntryContainsDatePredicate.java new file mode 100644 index 00000000000..5bb054755a2 --- /dev/null +++ b/src/main/java/seedu/address/model/person/predicates/EntryContainsDatePredicate.java @@ -0,0 +1,29 @@ +package seedu.address.model.person.predicates; + +import java.time.LocalDate; +import java.util.function.Predicate; + +import seedu.address.model.person.Entry; + +/** + * Tests that a {@code Entry's}'s {@code LocalDate} matches any of the keywords given. + */ +public class EntryContainsDatePredicate implements Predicate { + private final LocalDate dateToFilter; + + public EntryContainsDatePredicate(LocalDate dateToFilter) { + this.dateToFilter = dateToFilter; + } + + @Override + public boolean test(Entry entry) { + return dateToFilter.equals(entry.getDate().getDate()); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof EntryContainsDatePredicate // instanceof handles nulls + && dateToFilter == (((EntryContainsDatePredicate) other).dateToFilter)); // state check + } +} diff --git a/src/main/java/seedu/address/model/person/predicates/EntryContainsTagsPredicate.java b/src/main/java/seedu/address/model/person/predicates/EntryContainsTagsPredicate.java new file mode 100644 index 00000000000..b3827b33540 --- /dev/null +++ b/src/main/java/seedu/address/model/person/predicates/EntryContainsTagsPredicate.java @@ -0,0 +1,32 @@ +package seedu.address.model.person.predicates; + +import java.util.Set; +import java.util.function.Predicate; + +import seedu.address.model.person.Entry; +import seedu.address.model.tag.Tag; + + +/** + * Tests that a {@code Entry's}'s {@code Tags} matches any of the keywords given. + */ +public class EntryContainsTagsPredicate implements Predicate { + + private Set tagListToCompare; + + public EntryContainsTagsPredicate(Set tagListToCompare) { + this.tagListToCompare = tagListToCompare; + } + + @Override + public boolean test(Entry entry) { + return tagListToCompare.equals(entry.getTags()); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof EntryContainsTagsPredicate // instanceof handles nulls + && tagListToCompare == (((EntryContainsTagsPredicate) other).tagListToCompare)); // state check + } +} diff --git a/src/main/java/seedu/address/model/person/predicates/budget/BudgetContainsDatePredicate.java b/src/main/java/seedu/address/model/person/predicates/budget/BudgetContainsDatePredicate.java new file mode 100644 index 00000000000..b1ae73e76df --- /dev/null +++ b/src/main/java/seedu/address/model/person/predicates/budget/BudgetContainsDatePredicate.java @@ -0,0 +1,30 @@ +package seedu.address.model.person.predicates.budget; + +import java.time.LocalDate; +import java.util.function.Predicate; + +import seedu.address.model.person.Budget; + +/** + * Tests that a {@code Budget's}'s {@code Date} matches any of the keywords given. + */ +public class BudgetContainsDatePredicate implements Predicate { + + private final LocalDate dateToFilter; + + public BudgetContainsDatePredicate(LocalDate dateToFilter) { + this.dateToFilter = dateToFilter; + } + + @Override + public boolean test(Budget entry) { + return dateToFilter.equals(entry.getDate().getDate()); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof BudgetContainsDatePredicate // instanceof handles nulls + && dateToFilter == (((BudgetContainsDatePredicate) other).dateToFilter)); // state check + } +}