Skip to content

Commit

Permalink
Merge pull request #76 from itsmejr257/junRong-FindFeature-DG
Browse files Browse the repository at this point in the history
Add Find Feature implementation into DG
  • Loading branch information
itsmejr257 authored Mar 27, 2024
2 parents 582b3da + 8bdd30f commit 63728c7
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 5 deletions.
87 changes: 84 additions & 3 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

## Design

{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.}

## Implementation

### Edit Expense Feature
Expand Down Expand Up @@ -187,7 +185,90 @@ also constructs a new `Ui` object
7. `BudgetBuddy` then calls `MenuCommand#execute()`
8. `execute()` then calls `Ui#showMenuItem(1)`
9. `showMenuItem()` in `Ui` then prints all commands for `case 1` which is for `Manage Expenses`
=======


### Find Feature

The Find Feature allows users to search for expenses based on a specific criteria such as description, minimum amount
and maximum amount. This feature is orchestrated by the `FindExpensesCommand` class, which is created by the `FindExpensesCommandCreator`
, which is in turn created by the `Parser`. Within the `FindExpensesCommand` object, the `FindExpensesCommandCreator`
would have initialized it with 4 variables, an `ExpenseList` object, along with a `description`, `minAmount` ,
`maxAmount`. The relevance of these Class Attributes in `FindExpensesCommand` is as follows :

| Class Attribute | Variable Type | Relevance |
|-----------------|---------------|---------------------------------------------------------------------------|
| expenses | ExpenseList | ExpenseList Object containing the list of expenses which will be filtered |
| description | String | The description to match against expenses in `expenses` |
| minAmount | Double | The minimum amount matched expenses should be |
| maxAmount | Double | The **maximum** amount matched expenses should be |


Upon the call of the `execute()` method in `BudgetBuddy` using `command.execute()`,
the `FindExpensesCommand` Object, utilizes the following methods from the `ExpenseList` class in order to both
obtain a new `ExpenseList` object containing the filtered expenses, along with printing them.

| Method | Return Type | Relevance |
|------------------|--------------------|-----------------------------------------------------------------|
| filterExpenses() | ArrayList<Expense> | Returns an ArrayList<Expense> containing all filtered expenses |
| listExpenses() | void | Prints the filtered expenses obtained from `filterExpenses()` |

The following UML Sequence diagram below shows how FindExpensesCommandCreator works to
obtain the relevant inputs for the Find Feature, NOTING that the Parser has already determined the input to be a find :
expenses command, and has also created the FindExpensesCommandCreator.
![Sequence Diagram for Parser for Find Feature](diagrams/sequenceDiagram-Parser%20For%20Find%20Command.jpg)

The following is a step-by-step explanation for the processes that occur before the FindExpensesCommand is created :
1. `BudgetBuddy` calls `Parser#parseCommand(input)` with `input` being the entire user input.
E.g `find expenses d/bruno`
2. Within the `Parser`, it will have determined that the `input` is a Find Command from the `isFindCommand(input)`.
3. The `Parser` then creates a `FindExpensesCommandCreator` object, initializing it with the overall Expense List and
the provided user input
4. The `Parser` then calls `FindExpensesCommandCreator#createCommand()`.
5. `FindExpensesCommandCreator#createCommand()` then calls `FindExpensesCommandCreator#handleFindExpensesCommand()`
4. Within `handleFindExpensesCommand(input)`, the first check would be the check for the existence of any combination of
`d/ , morethan/ and lessthan/`. If none of these combinations were found, it immediately returns `null`
5. This is then followed by a second check `checkForDuplicateParameters()`, which checks for duplicates of parameters
in the user input. It duplicates are found, similarly, it immediately returns `null`.
5. If the checks in `4.` and `5` is passed, Three variables would be initialized.

* | Variable Name | Variable Type |
|---------------|---------------|
| description | String |
| minAmount | Double |
| maxAmount | Double |
6. Depending on which parameters were present, the corresponding input would be extracted and placed into each variable
using the `FindExpensesCommandCreator#parse*()`, where `*` represents the variable name we wish to obtain.
7. Should the values of `minAmount` and `maxAmount` not be empty, a check is done to ensure `minAmount` is less than
or equals to `maxAmount`. If this check does not pass, the function immediately returns `null`
8. Finally, `FindExpensesCommandCreator#handleFindExpensesCommand()` creates and returns a
`FindExpensesCommand` containg the extracted description, minAmount and maxAmount,to
9. `FindExpensesCommandCreator#createCommand()`, which is returned to, `Parser#parseCommand()`
, which is then returned to `BudgetBuddy`

The following UML Sequence diagram below shows how the Find Feature command works when a user provides a **valid**
find expenses command:

![Sequence diagram for Find Feature](diagrams/sequenceDiagram_FindExpenses.jpg)

The following is an example of the processes that occur when the user uses the find expenses feature:


**Important Note** : Although d/ , morethan/ and lessthan/ are optional parameters, the optional component would mean
user has left that option empty if not in use, e.t.c `find expenses d/ morethan/ lessthan/200`. Hence,
unused parameters are treated a null variables instead.

1. The user types `find expenses d/bruno morethan/30 lessthan/200`. This input is passed through the `Parser`
class from `BudgetBuddy`, which constructs a `FindExpenseCommand` Object with `expenses : current overall ExpenseList`,
`description : bruno`, `minAmount : 30`, `maxAmount : 200`.
2. `Parser` returns this created `FindExpenseCommand` Object to `BudgetBuddy` and `BudgetBuddy` calls
`FindExpenseCommand#execute()`
3. `execute()` is called, which initializes a variable `filteredExpenses` of type `ArrayList<Expense>`.
4. `execute()`then calls `ExpenseList#filterexpenses`, which returns the filtered expenses based on the `description`,
`minAmount` and `maxAmount` into the `filteredExpenses` variable.
5. If `filteredExpenses` is empty, "No Matching Expenses Found" is printed and `execute` ends here.
5. If `filteredExpenses` is not empty, `execute()` then initializes a new variable `filteredExpenseList`
of type `ExpenseList` with `filteredExpenses` initialized as the `expenses` Class attribute.
6. Finally `execute()` calls `filteredExpenseList#listexpenses()` to print filtered expenses into the CLI.

## Product scope
### Target user profile
Expand Down
Binary file added docs/diagrams/SequenceDiagram_FindExpenses.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public void execute() {

LOGGER.log(Level.INFO, "Creating filteredExpenses");
ArrayList<Expense> filteredExpenses = expenses.filterExpenses(description, minAmount, maxAmount);
ExpenseList filteredExpensesList = new ExpenseList(filteredExpenses);
ExpenseList filteredExpenseList = new ExpenseList(filteredExpenses);

if (filteredExpenses.isEmpty()) {
LOGGER.log(Level.INFO, "filtered expenses is empty, returning no expenses found");
Expand All @@ -57,7 +57,7 @@ public void execute() {

ui.printDivider();
System.out.println("Here are the matching expenses : ");
filteredExpensesList.listExpenses(null);
filteredExpenseList.listExpenses(null);
ui.printDivider();
}
}
Expand Down

0 comments on commit 63728c7

Please sign in to comment.