Skip to content

Commit

Permalink
Merge pull request #164 from AY1920S1-CS2103-T14-4/New_Add_Budget
Browse files Browse the repository at this point in the history
Update Dg
  • Loading branch information
Cary-Xx committed Nov 11, 2019
2 parents 253a3b9 + 6e88912 commit df9d8ca
Show file tree
Hide file tree
Showing 14 changed files with 185 additions and 9 deletions.
69 changes: 63 additions & 6 deletions docs/DeveloperGuide.adoc
Expand Up @@ -126,12 +126,6 @@ The `Model`,
* stores an `ExchangeData` object that represents the foreign exchange rates for conversion of currencies.
* stores the MYMorise data.
* exposes an unmodifiable `ObservableList<Expense>` and an unmodifiable `ObservableList<Budget>` that can be 'observed' e.g. the UI can be bound to either list so that the UI automatically updates when the data in the list change.
* does not depend on any of the other three components.

[NOTE]
As a more OOP model, we can store a `Tag` list in `Address Book`, which `Person` can reference. This would allow `Address Book` to only require one `Tag` object per unique `Tag`, instead of each `Person` needing their own `Tag` object. An example of how such a model may look like is given below. +
+
image:BetterModelClassDiagram.png[]

[[Design-Storage]]
=== Storage component
Expand All @@ -155,6 +149,69 @@ Classes used by multiple components are in the `seedu.addressbook.commons` packa

This section describes some noteworthy details on how certain features are implemented.

=== Budget Feature
==== Overview
The Budget feature allows users to track their expenses in relation to the budget set. Expenses created by the user after a budget is set and falls into a budget period will
automatically be added into that budget.

The feature allows the user to view a list of all the budgets created in the app. From the list of budgets, users may view any specific budget
showing all the expenses allocated into the budget, along with the amount left in the budget.
Users may add, delete, edit a budget as well as the expenses inside the budget.

==== Implementation
The `BudgetList` stores all the budgets created in the App. To facilitate the adding, deleting and editing of budgets, the BudgetList provides a
few operations such as: +
`BudgetList#addBudget(budget)` - Add a new budget into the list of budgets in the budget list. +
`BudgetList#setBudget(budget, editedBudget)` - Edit a current existing budget to a different budget +
`BudgetList#removeBudget(budget)` - Remove a specified budget

Given below is an activity diagram to show how a budget is added.

image::AddBudgetActivityDiagram.png[]

Given below is an activity diagram to show how an expense is added after the implementation of budget.

image::AddExpenseActivityDiagram.png[]

Given below is a class diagram of a Budget.

image::BudgetClassDiagram.png[]

Notice that the budget consists of 2 Amounts and 2 Dates. +
The 2 Amounts refer to the Budget Amount set by the user and the Budget Amount
currently left after deducting all expenses in the budget. +
The 2 Dates refer to the Start Date of the Budget and the End Date of the budget. All expenses added after the budget is created,
and fall within this 2 dates, will be automatically added into the budget.

Given below is an example of a object diagram of a newly created Budget.

image::BudgetObjectDiagram.png[]

The Budget consists of an ExpenseList which holds all expenses added into the Budget.

==== Design Consideration
There were 2 main design choices we had to choose from for the implementation of the Budget Feature. +

*Aspect: A single source of truth* +
The model consists of an expense list and a budget list.

- *Alternative 1:* Have a master expense list to store all expenses created and a budget list that consist of an internal
expense list that stores copies of the expenses from master expense list that fall into the budget. In this option, commands that affect expenses, will require
an update in the master expense list and the expense lists inside budgets affected. +
* Pros: Easy to implement, easy to keep track of a overall expenses.
* Cons: Multiple objects of the same expense. An update to an expense in the overall expense list will require a same update
to the same expense located in the budget. May result in bugs when commands affect expenses.

- *Alternative 2:* Have a default expense list that stores only expenses that do not fall into a budget, and a budget list that consist
of an internal expense list that stores the expenses that fall into a budget when the expense is added or edited. In this option, there is only
1 copy of any expense created by the user. Any edit or delete of an expense affects directly to the original expense object.
* Pros: Achieve a single source of truth. Does not introduce possible bugs that may be present if there were multiple copies of the same expense.
* Cons: More complex to implement. In order to view all expenses in the app, the program will have to loop through the default expense list
and the expense lists of every single budget.

*Alternative 2* was chosen. Reason is because a single source of truth would eliminate duplicate entries of the same data. This would
also reduce the possibility of bugs that may come with duplicate entries.

=== AutoComplete Feature
==== Implementation
Autocomplete is facilitated by several parts.
Expand Down
18 changes: 18 additions & 0 deletions docs/diagrams/AddBudgetActivityDiagram.puml
@@ -0,0 +1,18 @@
@startuml
start
:User executes AddExpense command;
'diamond
if () then ([budget does not exist])
'diamond
if () then ([budget period doesn't clash with existing budgets])
: add budget into the budget list;
: Update UI;
: Save default expense list and budget list;
else ([else])
: user receives budget clash message;
endif
else ([else])
: user receives budget duplicate message;
endif
stop
@enduml
21 changes: 21 additions & 0 deletions docs/diagrams/AddExpenseActivityDiagram.puml
@@ -0,0 +1,21 @@
@startuml
start
:User executes AddExpense command;

'diamond
if () then ([expense does not exist])
'diamond
if () then ([expense falls into a budget period])
: get budget which expense falls into;
: add expense into the budget;

else ([else])
: add expense into default expense list;
endif
:Update UI;
:Save default expense list and budget list;
else ([else])
: user receives expense duplicate message;
endif
stop
@enduml
15 changes: 14 additions & 1 deletion docs/diagrams/ArchitectureSequenceDiagram.puml
Expand Up @@ -13,11 +13,24 @@ activate ui UI_COLOR
ui -[UI_COLOR]> logic : execute("delete 1")
activate logic LOGIC_COLOR

logic -[LOGIC_COLOR]> model : deleteExpense(e)
logic -[LOGIC_COLOR]> model : getViewState()
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
deactivate model

alt BudgetList
logic -[LOGIC_COLOR]> model : deleteBudget(b)
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
deactivate model

else ExpenseList
logic -[LOGIC_COLOR]> model : deleteExpense(e)
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
deactivate model
end


logic -[LOGIC_COLOR]> storage : saveMymorise()
activate storage STORAGE_COLOR
Expand Down
23 changes: 23 additions & 0 deletions docs/diagrams/BudgetClassDiagram.puml
@@ -0,0 +1,23 @@
@startuml
!include style.puml
skinparam arrowThickness 1.1
skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR

Class Budget
Class Amount
Class Currency
Class Date
Class Name
Class ExpenseList

Budget *--> "1" Name
Budget *--> "2" Amount
Budget *--> "2" Date
Budget *--> "1" Currency
Budget *--> "1" ExpenseList

Name -[hidden]right-> Amount
Amount -[hidden]right-> Date

@enduml
30 changes: 30 additions & 0 deletions docs/diagrams/BudgetObjectDiagram.puml
@@ -0,0 +1,30 @@
@startuml
object ":Budget" as o
object "name:Name" as o2
object "currency:Currency" as o3
object "startDate:Date" as o4
object "endDate:Date" as o5
object "amount:Amount" as o6
object "amountLeft:Amount" as o7
object "expenseList:ExpenseList" as o8
object "expenses:UniqueExpenseList" as o9


o2 : fullName = "Japan Travel"
o3 : name = "JPY"
o4 : value = "12 Dec 2019"
o5 : value = "18 Dec 2019"
o6 : value = "9500"
o7 : value = "9500"

o --> o2
o --> o3
o --> o4
o --> o5
o --> o6
o --> o7
o --> o8
o8 --> o9


@enduml
17 changes: 16 additions & 1 deletion docs/diagrams/DeleteSequenceDiagram.puml
Expand Up @@ -48,8 +48,23 @@ deactivate MymParser
LogicManager -> DeleteCommand : execute()
activate DeleteCommand

DeleteCommand -> Model : deleteExpense(1)
DeleteCommand -> Model : getViewState()
activate Model
Model --> DeleteCommand
deactivate Model

alt BudgetList
DeleteCommand -> Model : deleteBudget(b)
activate Model
Model --> DeleteCommand
deactivate Model

else ExpenseList
DeleteCommand -> Model : deleteExpense(e)
activate Model
Model --> DeleteCommand
deactivate Model
end

Model --> DeleteCommand
deactivate Model
Expand Down
Binary file added docs/images/AddBudgetActivityDiagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/AddExpenseActivityDiagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/ArchitectureSequenceDiagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/BudgetClassDiagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/BudgetObjectDiagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/DeleteSequenceDiagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion src/main/java/seedu/address/ui/MainWindow.java
Expand Up @@ -225,7 +225,6 @@ private CommandResult executeCommand(String commandText) throws CommandException
expenseListPanel = new ExpenseListPanel(logic.updateExpenses());
//Update Left panel with all expenses.
leftListPanelPlaceHolder.getChildren().add(expenseListPanel.getRoot());
// statsDisplayPlaceHolder.getChildren().add(statsDisplay.getRoot());

if (commandResult.isShowHelp()) {
handleHelp();
Expand Down

0 comments on commit df9d8ca

Please sign in to comment.