Developer Guide
Table of Contents
- 1. Introduction
- 2. Setting Up
- 3. Design
- 4. Implementation
1. Introduction
NUSave is a desktop application built for university students who stay on campus to help them organise, track and manage their budgets.
It aims to alleviate the hassle that comes along with managing multiple budgets on different documents by providing a one-stop solution. With NUSave, you can create, edit and delete budgets or expenditures, as well as generate statistics based on your entries to gain useful insights regarding your spending habits.
What’s more, NUSave has:
- a Command Line Interface (CLI) catered to those who can type fast and prefer to use a keyboard. In other words, you navigate the application and execute instructions by keying in text-based commands into the command box provided.
- a Graphical User Interface (GUI) to provide you with a visually appealing, aesthetic and intuitive user experience.
Purpose
This document describes both the design and architecture of NUSave. It aims to serve as a guide for developers, testers, and designers who are interested in working on NUSave.
2. Setting Up
(Contributed by Yu Ming)
Refer to the guide Setting up and getting started.
3. Design
(Contributed by Song Yu)
This section elaborates on the high-level design of NUSave.
3.1. Architecture
(Contributed by Chin Hui)
This section elaborates on the high-level components of NUSave.

Figure 3.1.1. Architecture diagram of NUSave.
Figure 3.1.1 shows the relationship between the high-level components in NUSave.
Given below is a quick overview of each component:
The Main component has two classes called Main and MainApp.
It has two primary responsibilities:
- At launch: Initializes the components in the correct sequence and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
The Commons component represents a collection of classes used by other components.
The rest of the application consists of five components:
UI: Handles the UI of the application.Logic: Executes the commands.Model: Holds the data of the application in memory.State: Remembers the current state of the application.Storage: Reads data from, and writes data to, the hard disk.
For each of the five components:
- Its API is defined in an
interfacewith the same name as the Component. - Its functionality is exposed using a concrete
{Component Name} Managerclass which implements the corresponding APIinterfacementioned in the previous point.- For example, the
Logiccomponent (see the class diagram below) defines its API in theLogic.javainterface and exposes its functionality using theLogicManager.javaclass which implements theLogicinterface.
- For example, the

Figure 3.1.2. Sequence diagram of the delete command.
Figure 3.1.2 shows how the components interact with each other for the scenario where the user issues the command delete 1 in a budget page.
3.2. Components
This section elaborates on the different high-level components of NUSave.
3.2.1. UI component
(Contributed by Song Yu)

Figure 3.2.1.1. Architecture diagram of the UI component.
API: Ui.java
The UI consists of a MainWindow that is made up of various UI parts e.g.CommandBox, ResultDisplay,
StatusBarFooter etc. All of these classes inherit from the abstract UiPart class.
The UI component uses the JavaFX UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml.
In order to dynamically render data to be displayed to the user, when setUpGuiComponents() in MainWindow is called,
the method setStateBinders() sets observer objects to observe changes in State. For a complete explanation,
refer to 4.4.2. Dynamic Updating.
In summary, the UI component:
- Executes user commands using the
Logiccomponent. - Listens for changes to
ModelandStatedata.
3.2.2. Logic component
(Contributed by Yu Ming)

Figure 3.2.2.1. Architecture diagram of the Logic component.
API: Logic.java
Logic uses the MainPageParser and BudgetPageParser classes to parse user commands. This results in a
Command object which is executed by the LogicManager. The command execution can affect the Model
(e.g. adding an expenditure). The result of the command execution is encapsulated as a CommandResult object
which is passed back to the Ui. In addition, the CommandResult object can also instruct the Ui to perform
certain actions, such as displaying help to the user.
MainPageParser:
- Parses all the commands that is entered by the user when the state of the NUSave is on
MAIN. - Includes commands such as
CreateBudgetCommandandOpenBudgetCommandthat are unique to the main page.
BudgetPageParser:
- Parses all the commands that is inputted by the user when the state of the NUSave is on
BUDGET. - Includes commands such as
AddExpendtureCommandandCloseBudgetCommandthat are unique to the budget page.
Commands:
- The
Logiccomponent includes all commands that are executable on both the main and budget page. For a complete elaboration on what each command does, refer to 4.3. Commands.

Figure 3.2.2.1. Sequence Diagram for the command: delete 1.
Figure 3.2.2.1 above represents the interactions within the Logic component for the delete 1 command to delete a budget in NUSave.
3.2.3. Model component
(Contributed by Chin Hui)

Figure 3.4.1: Architecture diagram of the Model component.
API : Model.java
The Model:
- Stores a
UserPrefobject that represents the user’s preferences. - Stores a
Nusaveobject that encapsulatesBudgetandExpendituredata. - Exposes an unmodifiable
FilteredList<Renderable>that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - Does not depend on any of the other three components.
FilteredListwas used in favor ofObservableListto facilitate the find command implementation. The list can be filtered based on aPredicate, allowing for more flexibility for other filtering extensions i.e. filter by number of expenditures.
The Nusave:
- Implements methods that interact with
BudgetandExpenditure. - Stores an
ObservableList<Renderable>that is passed up to populate theFilteredList<Renderable>. - Stores a
BudgetList(wrapper class for aList<Budget>) to accessExpenditurewithin aBudgetsinceExpenditurecannot be accessed throughObservableList<Renderable>.
The Budget:
- Implements the
Renderableinterface and can thus be stored inFilteredList<Renderable>. - Contains a
Name,Date,Optional<Threshold>and aList<Expenditure>.
The Expenditure:
- Implements the
Renderableinterface and can thus be stored in theFilteredList<Renderable>. - Contains a
Name,Date,PriceandSet<Tag>.
3.2.4. State component
(Contributed by Song Yu)
API: State.java

Figure 3.5.1. Architecture diagram of the State component.
The State component:
- Represents the page NUSave is currently on. Specifically, it represents whether the user is looking at
the main page view or budget page view. The cuurent page is represented by an attribute in
StateManager. - Stores data related to the current state of NUSave. This refers to data such as the page NUSave is currently on or the current budget that it is accessing.
State lives inside Model, where Model will use State to store stateful data. This data will be used to
update information displayed on the GUI, such as the current expenditure of the accessed budget, or list of expenditures
belonging to the accessed budget.
3.2.5. Storage component
(Contributed by Wen Hao)
API : Storage.java
The Storage component:
- Saves
UserPrefobjects in JSON format and reads it back. - Saves all NUSave data in JSON format and reads it back.

Figure 3.6.1. Structure of the storage component.
The Storage component uses the Jackson API to convert Plain Old Java Objects (POJOs) into JSON files which are then
stored locally. It uses the same API to read existing JSON files during the launch of the application to load the stored
data into NUSave. As seen in Figure 3.6.1, JsonUserPrefsStorage is responsible for the reading and writing of
UserPref objects and contains the file path of its JSON file while JsonNusaveStorage is responsible for the
reading and writing of all NUSave data and contains the file path of its JSON file.

Figure 3.6.2. Structure of the data stored by NUSave.
In order for them to be recognised by the Jackson API, NUSave data objects (such as Budget and Expenditure) must be
converted into POJOs. Figure 3.6.2 depicts how the respective POJO classes for each of the data objects interact with
one another.
3.3. Commons classes
(Contributed by Chin Hui)
Classes used by multiple components are in the seedu.addressbook.commons package, these include exceptions, error messages and classes with static methods that can be used by all components without instantiation.
4. Implementation
(Contributed by Song Yu)
This section elaborates on the implementations of various commands and components in NUSave.
4.1. State
(Contributed by Song Yu)
This section elaborates on how State affects how commands are parsed by parsers in NUSave.
State stores what page NUSave is currently on. If NUSave is on the main page, State stores an attribute of
Page.MAIN. If NUSave is on the budget page, State stores an attribute of Page.BUDGET.
The Logic component in NUSave relies on this data stored in State to decide which parser in NUSave will take
control of the execution of commands.

Figure 4.1.1. Activity Diagram of the command: delete 1.
To elaborate further, using Figure 4.1.1. as a reference, when the user executes a delete command, delete 1,
while on the main page:
Logicexecutes the command, checking whether the current page is a budget page or main page, depending on the current page (represented bycurrentPageattribute inStateManager) of NUSave.- Since NUSave is currently on
Page.MAIN,MainPageParsertakes control of the execution, parsing the command input by the user. -
If the command syntax is valid, the delete command is parsed.
3a. If the syntax is invalid, a
ParseExceptionis thrown. - NUSave deletes the budget based on the index specified by the user, i.e. the 1st budget displayed.
4.2. Parsers
(Contributed by Wen Hao)
This section elaborates on the details surrounding the parsers which are responsible for converting user inputs into Command objects.
All user inputs are parsed by two types of parsers:
- Page Parsers
- Command Parsers
These parsers are part of the Logic component as seen from the class diagram in Figure 4.2.1 below:

Figure 4.2.1. Class diagram of parsers.
Design Considerations
- Option A: Use a single parser to parse both main and budget page commands
- Pros: Less code to write.
- Cons: Parser class will messy as it needs to differentiate between main and budget page commands that use the same command word.
- Option B (Chosen): Use page parsers to parse commands that are available on a page
- Pros: Code is more organised and readable.
- Cons: More code to write.
4.2.1. Page parsers
(Contributed by Wen Hao)
Page parsers are responsible for determining the type of Command object that will be generated from a user input.
They enable NUSave to only recognise a set of commands specific to a certain Page when the user is on that Page.
They implement the PageParser interface.
All user inputs are first parsed by a page parser.
It identifies the first word to be the command word and uses it to determine the type of Command object that will be generated.
The remaining words are then passed as arguments to the respective command parsers.
A ParseException is thrown if the command word is not recognised by the page parser.
There are two types of page parsers:
MainPageParserBudgetPageParser
User inputs are parsed by the MainPageParser if they are entered while NUSave is on the main page.
User inputs are parsed by the BudgetPageParser if they are entered while NUSave is on a budget page.
More information regarding what page the user is on can be found here.
4.2.2. Command parsers
(Contributed by Wen Hao)
Command parsers are responsible for generating the different types of Command object.
They implement the Parser<T> interface.
Arguments in user inputs are parsed by a command parser to generate the respective Command object.
The type of Command object generated by a command parser follows the generic type of the Parser<T> it implements.
For example, AddExpenditureCommandParser implements the Parser<AddExpenditureCommand> interface. Hence, it will only generate AddExpenditureCommand objects.
A ParseException is thrown if the necessary arguments to generate the respective Command object are invalid or missing.
4.2.3. Interaction between parsers
(Contributed by Wen Hao)
The interaction between the parsers is illustrated by the example usage seen in Figure 4.2.3.1 below:

Figure 4.2.3.1. Sequence diagram of the command: delete .
4.3. Commands
(Contributed by Song Yu)
This section elaborates on the implementations of the commands available in NUSave.
4.3.1. Add commands
This section describes the details surrounding events at which users would wish to add information into NUSave. Specifically, when a user wishes to create a new budget to the Main Page, or when a user wishes to add an expenditure to a budget.
4.3.1.1. Create budget
(Contributed by Yu Ming)
This section elaborates on the CreateBudgetCommand.
The following activity diagram shows the events that occur when the user executes the CreateBudgetCommand.

Figure 4.3.1.1: Activity diagram of the CreateBudgetCommand.
The command occurs in the Main Page of NUSave and results in the specified budget being created in
NUSave. This command therefore requires a compulsory name to specify the name of the budget to be created.
The following sequence diagram shows the interaction between the Logic component and Model component of NUSave
depicting a scenario when the user wants to create a budget for his Temasek Hall Basketball CCA by entering the command
create n/Temasek Hall Basketball p/100.

Figure 4.3.1.2: Sequence diagram of the CreateBudgetCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- The
LogicManageruses theMainPageParserto parse the given user input. - The
MainPageParserwill identify the command given by the user and pass the user input down to theCreateBudgetCommandParser. - The
CreateBudgetCommandParserwill create aBudgetwith the given parameters name and threshold from the user input. - The
CreateBudgetCommandParserwill then create aCreateBudgetCommandobject with the createdBudgetobject as the input parameter. - The
CreateBudgetCommandParserwill then return aCreateBudgetCommandobject. LogicManagerwill now call theexecutemethod in theCreateBudgetCommandobject.- The
CreateBudgetCommandwill now call theaddBudgetmethod of the existingModelobject and add theBudgetobject created into NUSave. - The
CreateBudgetCommandthen returns aCommandResultindicating the successful addition of theBudgetobject.
With the above sequence, a budget will be successfully created by the user in his NUSave application and will be reflected on the user interface.
4.3.1.2. Add expenditure
(Contributed by David)
This section elaborates on the AddExpenditureCommand.
The following activity diagram shows the events that occur when the user executes the AddExpenditureCommand.

Figure 4.3.1.2.1: Activity diagram of the AddExpenditureCommand.
Similar to creating a budget, the add expenditure command also shows the interaction between the Logic
and Model components of NUSave. The sequence diagram depicts a scenario when the user wants to add an expenditure for
his budget by entering the command add n/Basketball p/20 t/Ball.

Figure 4.3.1.2.2: Sequence diagram of the AddExpenditureCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- Beginning with the
LogicManager, theLogicManagerhands the given user input to theBudgetPageParserto be parsed. - The
BudgetPageParserwill identify the command given by the user and passes the user input down to theAddExpenditureCommandParserto be parsed. - The
AddExpenditureCommandParserwill create anExpenditurewith the given parameters name, price and optionally tags from the user input. - The
AddExpenditureCommandParserwill then create anAddExpenditureCommandobject with the createdBudgetobject as the input parameter. - The
AddExpenditureCommandParserwill then return anAddExpenditureCommandobject. LogicManagerwill now call theexecutemethod in theAddExpenditureCommandobject.- The
AddExpenditureCommandwill now call theaddExpendituremethod of the existingModelobject and add theExpenditureobject created into NUSave. - The
AddExpenditureCommandthen returns aCommandResultindicating the successful addition of theExpenditureobject.
With the above sequence, an expenditure will be successfully created by the user in his NUSave application under the specific budget and it will be immediately reflected on the user interface.
4.3.2. Delete commands
(Contributed by David)
This section describes the details surrounding events at which users would wish to delete information from NUSave. Specifically, deletion can happen in two areas; when a user wishes to delete a budget from the Main Page, or when a user wishes to delete an expenditure from a budget.
4.3.2.1. Delete budget
(Contributed by David)
This section elaborates on the DeleteBudgetCommand.
The following activity diagram to shows the events that occur when the user executes the Delete Budget Command.

Figure 4.3.2.1.1: Activity diagram of the DeleteBudgetCommand.
The following command occurs in the Main Page of NUSave, and results in the specified budget of the particular index
to be removed from NUSave. This command therefore requires a compulsory index to specify the particular budget to be
removed.
Only when the index given by the user is valid (within the range of existing budgets), does the command execute successfully.
The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to delete the first budget on his list.

Figure 4.3.2.1.2: Sequence diagram of the DeleteBudgetCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- The
LogicManageruses theMainPageParserto parse the given user input. - The
MainPageParserwill identify the command given by the user and pass the user input down to theDeleteBudgetCommandParser. - The
DeleteBudgetCommandParserwill create aBudgetIndexwith the given parameters index from the user input. - The
DeleteBudgetCommandParserwill then create aDeleteBudgetCommandobject with the createdBudgetIndexobject as the input parameter. - The
DeleteBudgetCommandParserwill then return aDeleteBudgetCommandobject back to theLogicManager. LogicManagerwill now call theexecutemethod in theDeleteBudgetCommandobject, with theModelas a parameter.- The
DeleteBudgetCommand’sexecutemethod will now call thedeleteBudgetmethod of the existingModelobject passed in and delete theBudgetobject within NUSave. - The
DeleteBudgetCommandthen returns aCommandResultindicating the successful deletion of theBudgetobject.
With the above sequence, a budget will be successfully deleted by the user in his NUSave application, and it will be
reflected on the user interface through the successful CommandResult and updated budget list.
4.3.2.2. Delete expenditure
(Contributed by David)
This section elaborates on the DeleteExpenditureCommand.
The following activity diagram to shows the events that occur when the user executes the Delete Expenditure Command.

Figure 4.3.2.2.1: Activity diagram of the DeleteExpenditureCommand.
The following command occurs in the Budget Page of NUSave, and results in the specified expenditure of the particular
index to be removed from NUSave. This command therefore requires a compulsory index to specify the particular
expenditure to be removed.
Only when the index given by the user is valid (within the range of existing budgets), does the command execute successfully.
The following sequence diagram is similar to Figure 4.3.2.1.1 which shows the interactions between the Logic and
Model components of NUSave, depicting a scenario where the user within a budget would like to delete the first
expenditure on his list.

Figure 4.3.2.2.2: Sequence diagram of the DeleteExpenditureCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- The
LogicManageruses theBudgetPageParserto parse the given user input. - The
BudgetPageParserwill identify the command given by the user and create aDeleteBudgetCommandParser. - The
BudgetPageParserwill pass the user input into the newly createdDeleteBudgetCommandParser. - The
DeleteExpenditureCommandParserwill create aExpenditureIndexwith the given parameters index from the user input. - The
DeleteExpenditureCommandParserwill then create aDeleteExpenditureCommandobject with the createdExpenditureIndexobject as the input parameter. - The
DeleteExpenditureCommandParserwill then return theDeleteExpenditureCommandobject back to theLogicManager. LogicManagerwill now call theexecutemethod in theDeleteExpenditureCommandobject, with theModelas a parameter.- The
DeleteExpenditureCommand’sexecutemethod will now call thedeleteExpendituremethod of the existingModelobject passed in and delete theExpenditureobject within NUSave. - The
DeleteExpenditureCommandthen returns aCommandResultindicating the successful deletion of theExpenditureobject.
With the above sequence, a budget will be successfully deleted by the user in his NUSave application, and it will be
reflected on the user interface through the successful CommandResult and updated budget list.
4.3.3. Edit Commands
(Contributed by David)
This section elaborates on the details surrounding events at which users would wish to edit information from NUSave.
Specifically, editing can happen in two areas; when a user wishes to edit a budget from the Main Page, or when a
user wishes to edit an expenditure from a budget within the Budget Page.
4.3.3.1. Edit budget
(Contributed by Yu Ming)
This section elaborates on the EditBudgetCommand.
The following activity diagram to shows the events that occur when the user executes the Edit Budget Command.

Figure 4.3.3.1.1: Activity diagram of the EditBudgetCommand.
The following command occurs in the Main Page of NUSave, and results in the specified budget of the particular index
to be edited within NUSave. As such, this command requires a compulsory index to specify the particular budget,
along with fields at which the user would like to edit.
Only when the index is valid (within the range of existing budgets), and the user provides at least one field to be edited, does the command execute successfully.
The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to edit the first budget on his/her list, and change the NAME and
THRESHOLD of the budget to Temasek Hall Basketball and 1000 accordingly.

Figure 4.3.3.1.2: Sequence diagram of the EditBudgetCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- Beginning with the
LogicManager, theLogicManagerhands the given user input to theMainPageParserto be parsed. - The
MainPageParserwill identify the command given by the user and create anEditBudgetCommandParser. - The
MainPageParserwill pass the user input into the newly createdEditBudgetCommandParser. - The
EditBudgetCommandParserwill create anBudgetIndexwith the given parametersindexfrom the user input. - The
EditBudgetCommandParserwill then create anEditBudgetDescriptorwith the given parameters ofnameandthreshold. - The
EditBudgetCommandParserwill then create anEditBugetCommandwith theBudgetIndexandEditBudgetDescriptor. - The
EditBudgetCommandParserwill then return theEditBudgetCommandobject back to theLogicManager. LogicManagerwill now call theexecutemethod in theEditBudgetCommandobject, with theModelas a parameter.- The
EditBudgetCommand’sexecutemethod will now call theeditBudgetmethod of the existingModelobject passed in and update theBudgetwith a new editedBudgetobject within NUSave. - The
EditBudgetCommandthen returns aCommandResultindicating the successful editing of theBudget.
With the above sequence, a budget will be successfully edited by the user in his NUSave application, and it will
be reflected on the user interface through the successful CommandResult and updated budget list.
4.3.3.2. Edit expenditure
(Contributed by David)
This section elaborates on the EditExpenditureCommand.
The following activity diagram to shows the events that occur when the user executes the Edit Expenditure Command.

Figure 4.3.2.2.1: Activity Diagram of the EditExpenditureCommand.
The following command results in the specified expenditure of the particular index to be edited within the
Budget Page. As such, this command requires a compulsory index to specify the particular expenditure, along with a
field at which the user would like to edit (NAME, PRICE, TAG).
Only when the index is valid (within the range of existing expenditures), and the user provides at least one field to be edited, does the command execute successfully.
The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to edit the first expenditure on his/her list, and change the previous
NAME, PRICE and TAG to Basketball, 50 and Ball accordingly.

Figure 4.3.3.2.1: Sequence diagram of the EditExpenditureCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- Beginning with the
LogicManager, theLogicManagerhands the given user input to theBudgetPageParserto be parsed. - The
BudgetPageParserwill identify the command given by the user and create anEditExpenditureCommandParser. - The
BudgetPageParserwill pass the user input into the newly createdEditExpenditureCommandParser. - The
EditExpenditureCommandParserwill create anExpenditureIndexwith the given parameters index from the user input. - The
EditExpenditureCommandParserwill then create anEditExpenditureDescriptorwith the given parameters of name, price and tags. - The
EditExpenditureCommandParserwill then create anEditExpenditureCommandwith theExpenditure IndexandEditExpenditureDescriptor. - The
EditExpenditureCommandParserwill then return theEditExpenditureCommandobject back to theLogicManager. LogicManagerwill now call theexecutemethod in theEditExpenditureCommandobject, with theModelas a parameter.- The
EditExpenditureCommand’sexecutemethod will now call theeditExpendituremethod of the existingModelobject passed in and update theExpenditurewith a newExpenditureobject within NUSave. - The
EditExpenditureCommandthen returns aCommandResultindicating the successful editing of theExpenditure.
With the above sequence, an expenditure will be successfully edited by the user in his NUSave application, and it will
be reflected on the user interface through the successful CommandResult and updated budget list.
4.3.4. Sort commands
(Contributed by Yu Ming)
This section elaborates on the events surrounding the sorting of budgets and expenditures.
The following activity diagram to shows the events that occur when the user executes the SortBudgetCommand.

Figure 4.3.4.1: Activity diagram of the SortBudgetCommand.
The following command can occur either in the Main Page or Budget Page of NUSave, and results in either the budgets
or the expenditures to be sorted by name or created date. As such, this command requires a compulsory SortType field
to specify the particular type of sorting required.
Only when the SortType is valid (NAME or TIME) does the command execute successfully.
The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to sort the budgets by thier name in alphabetical order.

Figure 4.3.4.2: Sequence diagram of the SortBudgetCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- Beginning with the
LogicManager, theLogicManagerhands the given user input to theMainPageParserto be parsed. - The
MainPageParserwill identify the command given by the user and create anSortBudgetCommandParser. - The
MainPageParserwill pass the user input into the newly createdSortBudgetCommandParser. - The
SortBudgetCommandParserwill then create anSortBugetCommandwith the sort typeNAME - The
SortBudgetCommandParserwill then return theSortBudgetCommandobject back to theLogicManager. LogicManagerwill now call theexecutemethod in theSortBudgetCommandobject, with theModelas a parameter.- The
SortBudgetCommand’sexecutemethod will now call thesortBudgetsByNamemethod of the existingModeland this will sort the list of budgets in NUSave according with the given sort typeNAME. - The
SortBudgetCommandthen returns aCommandResultindicating the successful sorting of theBudgetin NUSave by their name in alphabetical oredr.
With the above sequence, budgets will be successfully sorted by the user in his NUSave application by name in
alphabetical order, and it will be reflected on the user interface through the successful CommandResult
and updated budget list.
Note that the sort command can be executed on Budget Page view as well to sort the list of expenditures of a given
budget. The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to sort the expenditures by their created date with the lastest created
expenditure at the top of list of expenditures.

Figure 4.3.4.3: Sequence diagram of the SortExpenditureCommand
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The details of the flow of SortExpenditureCommand will not be elaborate in details as it is similiar to
SortBudgetCommand.
4.3.5. Find & list commands
This section elaborates on the events surrounding the find and list commands.
4.3.5.1 List budget
(Contributed by Chin Hui)
The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to list all budgets.

Figure 4.3.5.1.1: Sequence diagram of the ListBudgetCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- The
LogicManageruses theMainPageParserto parse the give user input. - The
MainPageParserwill identify the command given by the user and create aListBudgetCommand. - The
MainPageParserwill then return theListBudgetCommandobject back to theLogicManager. LogicManagerwill now call theexecutemethod in theListBudgetCommandobject.- The
ListBudgetCommandexecutemethod will now call thelistBudgetsmethod of the existingModelobject and list all existing budgets within NUSave. - The
ListBudgetCommandthen returns aCommandResultindicating the successful listing of all budgets.
With the above sequence, all budgets will be listed by the user in his NUSave application and it will be reflected on the user interface.
4.3.5.2 Find budget
(Contributed by Chin Hui)
The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to find budgets by a search term/phrase.

Figure 4.3.5.2.1: Sequence diagram of the FindBudgetCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- The
LogicManageruses theMainPageParserto parse the give user input. - The
MainPageParserwill identify the command given by the user and pass the user input down to theFindBudgetCommandParser. - The
FindBudgetCommandParserwill then create aFindBudgetCommandwith the user input as the search term. FindBudgetCommandParserthen returns theFindBudgetCommandobject back to theLogicManager.- The
LogicManagerwill now call theexecutemethod in theFindBudgetCommandobject. - The
FindBudgetCommandexecutemethod will now call thefindBudgetmethod of the existingModelobject and apply a filter for budgets displayed by NUSave. - The
FindBudgetCommandthen returns aCommandResultindicating that all budgets containing the search term has been displayed.
With the above sequence, all budgets containing the search term entered will be filtered and displayed on the user interface.
4.3.5.3 List expenditure
(Contributed by Chin Hui)
The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to list all expenditure within the current budget.

Figure 4.3.5.3.1.: Sequence diagram of the ListExpenditureCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- The
LogicManageruses theBudgetPageParserto parse the give user input. - The
BudgetPageParserwill identify the command given by the user and create aListExpenditureCommand. - The
BudgetPageParserwill then return theListExpenditureCommandobject back to theLogicManager. LogicManagerwill now call theexecutemethod in theListExpenditureCommandobject.- The
ListExpenditureCommandexecutemethod will now call thelistExpendituremethod of the existingModelobject and list all existing expenditures within the current budget. - The
ListExpenditureCommandthen returns aCommandResultindicating the successful listing of all expenditures.
With the above sequence, all expenditures will be listed by the user in his NUSave application, and it will be reflected on the user interface.
4.3.5.4 Find expenditure
(Contributed by Chin Hui)
The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to find expenditures in a budget by a search term/phrase.

Figure 4.3.5.4.1.: Sequence diagram of the FindExpenditureCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- The
LogicManageruses theBudgetPageParserto parse the give user input. - The
BudgetPageParserwill identify the command given by the user and pass the user input down to theFindExpenditureCommandParser. - The
FindExpenditureCommandParserwill then create aFindExpenditureCommandwith the user input as the search term. FindExpenditureCommandParserthen returns theFindExpenditureCommandobject back to theLogicManager.- The
LogicManagerwill now call theexecutemethod in theFindExpenditureCommandobject. - The
FindExpenditureCommandexecutemethod will now call thefindExpendituresmethod of the existingModelobject and apply a filter for expenditures displayed by NUSave. - The
FindExpenditureCommandthen returns aCommandResultindicating that all expenditures in the current budget containing the search term has been displayed.
With the above sequence, all expenditures containing the search term entered will be filtered and displayed on the user interface.
4.3.6. Undo & redo commands
(Contributed by Wen Hao)
This section elaborates on the events of the undo and redo commands.
The undo and redo commands are implemented using the following classes:
| Class | Details | Purpose |
|---|---|---|
VersionedNusave |
Contains a BudgetList and BudgetIndex |
Represents the data and view of NUSave at a certain point in time |
Node<T> |
Contains a value of type T, next Node<T> and previous Node<T> |
Represents a doubly linked list |
HistoryManager<T> |
Contains a pointer to a Node<T> |
Represents an iterator to iterate through a doubly linked list represented by Node<T> |
The following class diagram shows how the classes interact with each other:

Figure 4.3.6.1. Class diagram of the classes related to undo and redo command.
The pointer in HistoryManager<VersionedNusave> is always pointing to the latest VersionedNusave in a doubly linked list represented by Node<T>. If an undo command is executed, it will load the previous VersionedNusave and move the pointer backward. If a redo command is executed, it will load the next VersionedNusave and move the pointer forward. Whenever the user makes changes to NUSave data, a VersionedNusave is instantiated with a deep copy of the BudgetList from Nusave and the BudgetIndex from State. It replaces the next Node<T> (if any) of the Node<T> that HistoryManager<VersionedNusave> is currently pointing to before the pointer is moved forward.
To better illustrate the process, an example usage shown below:
Step 1: The user launches NUSave. HistoryManager<VersionedNusave> is instantiated with an empty doubly linked list.

Step 2: The user makes changes to NUSave data by creating a Budget named “demo”. Before the change is made, a VersionedNusave is instantiated in case the user wants to undo. HistoryManager<VersionedNusave> adds this VersionedNusave to the doubly linked list.

Step 3: The user executes the undo command. Before reverting the changes, a VersionedNusave is instantiated in case the user wants to redo. HistoryManager<VersionedNusave> adds this VersionedNusave to the doubly linked list before moving its pointer backward to retrieve the previous VersionedNusave. The BudgetList from the previous VersionedNusave is loaded into Nusave while the BudgetIndex from the previous VersionedNusave is used to set State. Once this is done, the GUI should reflect that the “demo” budget is removed from NUSave.

Step 4: The user executes the redo command. HistoryManager<VersionedNusave> retrieves the next VersionedNusave from the pointer and moves its pointer forward. The BudgetList from the next VersionedNusave is loaded into Nusave while the BudgetIndex from the next VersionedNusave is used to set State. Once this is done, the GUI should reflect that the “demo” budget is added back to NUSave.

Step 5: The user makes changes to NUSave data by creating a Budget named “demo2”. Before the change is made, a VersionedNusave is instantiated in case the user wants to undo. HistoryManager<VersionedNusave> adds this VersionedNusave to the doubly linked list before moving its pointer forward.

The following sequence diagram shows how the undo command is executed:

Figure 4.3.6.2. Sequence diagram of the UndoCommand.
4.3.7 Help command
(Contributed by Yu Ming)
This section explains the Help Command.
The following activity diagram to shows the events that occur when the user executes the Help Command.

Figure 4.3.7.1: Activity diagram of the HelpCommand.
The following command can occur either in the Main Page or Budget Page of NUSave, and the help notes will be
displayed in the result box of the UI Component.
The following sequence diagram shows the interactions between the Logic and Model components of NUSave,
depicting a scenario where the user would like to ask for help to be displayed.

Figure 4.3.7.1.2: Sequence diagram of the HelpCommand.
Lifelines with a destroy marker (X) should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
- Beginning with the
LogicManager, theLogicManagerhands the given user input to theMainPageParserto be parsed. - The
MainPageParserwill identify the command given by the user and create anHelpBudgetCommand. - The
MainPageParserwill then return theHelpBudgetCommandobject back to theLogicManager. LogicManagerwill now call theexecutemethod in theHelpBudgetCommandobject, with theModelas a parameter.- The
HelpBudgetCommand’sexecutemethod will return aCommandResultindicating the successful calling for the help command, and the help information will be displayed in the result box in NUSave.
With the above sequence, the help information will be successfully shown to the user in NUSave and it will be reflected on the user interface.
Note that the help command can be executed on Budget Page view as well, but it will display a different set of help
message that is unique to the Budget Page view with commands that can be executed on the view.
4.4. UI
This section elaborates on the implementations of various Ui features.
4.4.1. List View Rendering
(Contributed by Wen Hao)
This section elaborates on how budget and expenditure cards are rendered within the List View UI component on the GUI of NUSave.
As there is a need to constantly re-render the contents within the List View to reflect user changes, we have adopted the Observer Pattern
so that data can be sent from the Model component to the UI component efficiently. Using the JavaFX API, the List View is binded to an ObservableList
such that any changes to the ObservableList will trigger an update within the List View accordingly.

Figure 4.4.1.1. Class diagram to illustrate the observer pattern
The List View UI component is able to display both budget and expenditure cards interchangeably through the Renderable interface.
Both Budget and Expenditure classes implement the Renderable interface.
As such, Budget and Expenditure objects can be added to the ObservableList of Renderable which the List View is binded to.
Whenever changes are made to the ObservableList, the List View generates either a BudgetCard or ExpenditureCard depending on the runtime type of the Renderable object.
To facilitate sort and find commands, an additional layer of filtering is accomplished using the FilteredList class. Different types of predicates are
supplied to the filtered list depending on user needs.
Design Considerations
- Option A: Use separate List Views for
BudgetandExpenditure- Pros: Less prone to the error where both
BudgetCardandExpenditureCardare displayed simultaneously - Cons: Higher difficulty and more code to write as there is the need to handle the replacement of the entire List View
- Pros: Less prone to the error where both
- Option B (Chosen): Use a single List View to hold both
BudgetandExpenditurewith the use of aRenderableinterface- Pros: Easier to extent as new classes just need to implement the
Renderableinterface to be displayed - Cons: More prone to the error where both
BudgetCardandExpenditureCardare displayed simultaneously
- Pros: Easier to extent as new classes just need to implement the
4.4.2. Dynamic Updating
(Contributed by Song Yu)
This section talks about how data is dynamically updated on the GUI of NUSave.
As an overview, we use the Observer Pattern to dynamically update these modified data. We force this communication by
using a StateBinder interface, where bind() is called to bind all StateBinders to StateManager.

Figure 4.4.2.1. Class diagram to illustrate the observer pattern.
- On initialisation of NUSave,
MainWindowcallsthis.setStateBinders(), which callsStateBinderList.bindAll(). StateBinderListcallsbind()on everyStateBinder.bind()will connect toisBudgetPageProp,infoBoxSecondRowPropandthresholdStringPropinState.- Whenever the attributes in
Stateas referenced in step 3 are updated, theStateBindersare notified, which in turn updates the GUI.
As seen, there is also a combination of the Facade Pattern
and N-tier Architectural Style
to link StateBinder and StateManager together.
4.4.2.1. Description
When a page switches from the main page to a budget page, information in the InfoBox and Title UI classes are updated.
When the StringProperty and BooleanProperty attributes are updated in State, the observers in InfoBox and Title
are notified, which updates the data displayed.
4.4.2.2. Implementation
The change in information displayed occurs when the user inputs one of the following commands:
- Opening a budget:
open - Closing a budget:
close - Adding an expenditure:
add - Editing an expenditure:
edit - Deleting an expenditure:
delete
Sequence Diagram
The following sequence diagram shows the interactions between the Ui, Logic,Model and State components of NUSave,
depicting a scenario where the user opens a budget.

Figure 4.4.2.2.1.1. Sequence diagram of the OpenBudgetCommand.
MainWindowis called with the Stringopen 1.MainWindowusesLogicManagerto execute the given user input.- The
LogicManageruses theMainPageParserto parse the given user input. - The
MainPageParseridentifies the command given by the user and creates anOpenBudgetCommandParser. - The
MainPageParserpasses the user input into the newly createdOpenBudgetCommandParser. - The
OpenBudgetCommandParsercreates aOpenBudgetCommandobject. - The
OpenBudgetCommandParserreturns theOpenBudgetCommandobject back toLogicManager. LogicManagercalls theexecutemethod in theOpenBudgetCommandobject, with theModelas a parameter.- The
OpenBudgetCommand’sexecutemethod calls theopenBudgetmethod of the existingModelobject passed in. ModelManagercalls its ownsetOpenCommandStatemethod, which retrieves relevant data to updateState.ModelManagercallsState’ssetOpenCommandStatemethod, updating state data relevant to opening a budget.State’sStringPropertyandBooleanPropertyattributes are updated, which notifiesInfoBoxandTitleto update.
With the above sequence, a budget will successfully be opened, and the Title component reflects the name of
the budget, while the InfoBox component reflects the total expenditure and threshold of the budget.
Design Considerations
- Option A: Use Model-View Controller (MVC) Pattern to update GUI
- Pros: Good separation of concern, with controller being in charge of updating both the model and Ui.
- Cons: Hard to implement as controllers will have to be set up from scratch.
- Option B (Chosen): Use Observer Pattern to update GUI
- Pros: Able to use proprietary JavaFx library to implement, enforce loose coupling with Observer interface.
- Cons: External code can easily invoke observer as
bind()method is public.
5. Guides
5.1. Documentation
5.2. Testing
5.3. Logging
5.4. Configuration
5.5. DevOps
Appendix
Product Scope
(Contributed by Yu Ming and David)
Target User Profile:
- university students staying on campus
- has a need to manage a multiple budgets and expenditures
- prefers using desktop over other platforms
- types fast and prefers typing to mouse interactions
Value Proposition:
- manages expenditures faster than a typical mouse/GUI driven application
- allows users to keep track of their budgets on a centralised platform
User Stories
Priorities:
- High (must have) -
* * * - Medium (nice to have) -
* * - Low (unlikely to have) -
*
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * |
new user | see a list of available commands | refer to instructions when I forget how to use the application |
* * * |
new user | view sample data | have a better understanding of how the application works |
* * * |
new user | clear my existing data | remove all the sample data from my application |
* * * |
user | create a budget | add a new budget that I need |
* * * |
user | delete a budget | remove a budget that I no longer need |
* * * |
user | edit a budget | edit the name or the threshold that needs to be changed |
* * |
user | sort my budgets | view my budgets based on name or date |
* * |
user | find a budget by search term | locate a budget easily |
* * |
user | list out my budgets | view by budgets in the default manner after finding or sorting |
* * * |
user | open a budget | view the expenditures of a budget |
* * * |
user | close a budget | return to the main window |
* * |
user | see how many expenditures I have in a budget | have a better understanding of the particular budget |
* * * |
user | add an expenditure | add a new expenditure to a budget |
* * * |
user | delete an expenditure | remove an expenditure that I no longer need |
* * * |
user | edit an expenditure | edit the name, price and tag that needs to be changed |
* * |
user | sort my expenditures | view my expenditures based on name or date |
* * |
user | find an expenditure by search term | locate an expenditure easily |
* * |
user | list out my expenditures | view by expenditures in the default manner after finding or sorting |
* * |
user | see if I have passed my threshold | manage my expenses better |
* * |
user | add tags to my expenditure | categorise my expenditures |
* * |
user | exit NUSave | stop using the application |
Use Cases
Use Case: UC01 - Viewing the help menu
(Contributed by Yu Ming)
System: NUSave
Use Case: UC01 - Viewing the help menu
Actor: User
MSS:
- User enters the command to show the help menu in NUSave.
- NUSave displays the help menu to the user.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command.
- 1a1. NUSave shows an error message.
- 1a2. User enters new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
Use Case: UC02 - Creating a budget
(Contributed by Yu Ming)
System: NUSave
Use Case: UC02 - Creating a budget
Actor: User
Preconditions: User is on the main page
MSS:
- User enters the command to add a new budget in NUSave.
- NUSave adds the new budget and displays the updated list of budgets to the user.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command (for example, an invalid threshold).
- 1a1. NUSave shows an error message.
- 1a2. User enters a new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
Use Case: UC03 - Editing a budget
(Contributed by Yu Ming)
System: NUSave
Use Case: UC03 - Editing a budget
Actor: User
Preconditions: User is on the main page
MSS:
- User enters the command to edit a budget in NUSave.
- NUSave replaces the old budget with the newly edited budget and displays the updated list of budgets to the user.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command.
- 1a1. NUSave shows an error message.
- 1a2. User enters new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
- 1b. NUSave detects that the given budget does not exist in NUSave.
- 1b1. NUSave shows an error message.
- 1b2. User enters new command.
Steps 1b1-1b2 are repeated until the command entered is correct.
Use case resumes at step 2.
Use Case: UC04 - Deleting a budget
(Contributed by David)
System: NUSave
Use Case: UC04 - Deleting a budget
Actor: User
Preconditions: User is on the Main page, there must be an existing budget
MSS:
- User enters the command to delete a budget.
- NUSave deletes the budget and displays the updated list to the user.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command.
- 1a1. NUSave shows an error message.
- 1a2. User enters new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
Use Case: UC05 - Opening a budget
MSS (Contributed by Song Yu)
System: NUSave
Use Case: UC05 - Opening a budget
Actor: User
Preconditions: User is on the main page
MSS:
- User enters the command to open a budget in NUSave.
- NUSave opens the budget displays the list of expenditures belonging to that budget to the user.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command.
- 1a1. NUSave shows an error message.
- 1a2. User enters new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
Use Case: UC06 - Closing a budget
MSS (Contributed by Song Yu)
System: NUSave
Use Case: UC06 - Closing a budget
Actor: User
Preconditions: User is on the budget page
MSS:
- User enters the command to close a budget in NUSave.
- NUSave closes the budget and displays the list of budgets in NUSave.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command.
- 1a1. NUSave shows an error message.
- 1a2. User enters new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
Use Case: UC07 - Sorting budgets
(Contributed by Yu Ming)
System: NUSave
Use Case: UC07 - Sorting budgets
Actor: User
Preconditions: User is on the main page, NUSave contains at least 2 or more budgets
MSS:
- User enters the command to sort budgets in NUSave.
- NUSave sorts all budgets and displays the updated list of budgets to user.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command.
- 1a1. NUSave shows an error message.
- 1a2. User enters new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
Use Case: UC08 - Finding budgets
(Contributed by Chin Hui)
System: NUSave
Use Case: UC08 - Finding budgets
Actor: User
Preconditions: User is on the main page.
MSS:
- User enters the command to find budgets in NUSave.
- NUSave finds all budgets matching the user input and displays the updated list of budgets to user.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command.
- 1a1. NUSave shows an error message.
- 1a2. User enters new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
- 2a. NUSave detects that no budgets were found.
- 2a1. NUS displays an empty list view with a message noting that no budgets matched the user input.
Use Case: UC09 - Listing budgets
(Contributed by Chin Hui)
System: NUSave
Use Case: UC10 - Listing budgets
Actor: User
Preconditions: User is on the main page.
MSS:
- User enters the command to list all budgets in NUSave.
- NUSave lists all existing budgets in memory, displaying them in the list view and shows the success message.
Use case ends.
Use Case: UC10 - Clearing budgets
(Contributed by Wen Hao)
System: NUSave
Use Case: UC10 - Clearing budgets
Actor: User
Preconditions: User is on the main page.
MSS:
- User enters the command to clear all budgets in NUSave.
- NUSave deletes all existing budgets, displays an empty list view and shows the success message.
Use case ends.
Use Case: UC11 - Adding an expenditure
(Contributed by Song Yu)
System: NUSave
Use Case: UC11 - Adding an expenditure
Actor: User
Preconditions: User is on the budget page
MSS:
- User enters the command to add a new expenditure in NUSave.
- NUSave adds the new expenditure and displays the updated list of expenditures to the user.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command (for example, an invalid price).
- 1a1. NUSave shows an error message.
- 1a2. User enters new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
Use Case: UC12 - Editing an expenditure
(Contributed by David)
System: NUSave
Use Case: UC12 - Editing an expenditure
Actor: User
Preconditions: User is on the Budget page, there must be an existing expenditure
MSS:
- User requests to open a budget (UC05) to view the list of expenditures in the budget page view.
- NUSave opens the budget and displays the list of expenditures belonging to that budget.
- User enters the command to edit an expenditure within the budget.
- NUSave edits the expenditure and displays the updated list to the user.
Use case ends.
Extensions
- 3a. NUSave detects an error in the entered command.
- 3a1. NUSave shows an error message.
- 3a2. User enters new command.
Steps 3a1-3a2 are repeated until the command entered is correct.
Use case resumes at step 4.
Use Case: UC13 - Deleting an expenditure
(Contributed by David)
System: NUSave
Use Case: UC13 - Deleting an expenditure
Actor: User
Preconditions: User is on the Budget page, there must be an existing expenditure
MSS:
- User requests to open a budget (UC05) to view the list of expenditures in the budget page view.
- NUSave opens the budget and displays the list of expenditures belonging to that budget.
- User enters the command to delete an expenditure within the budget.
- NUSave deletes the expenditure and displays the updated list to the user.
Use case ends.
Extensions
- 3a. NUSave detects an error in the entered command.
- 3a1. NUSave shows an error message.
- 3a2. User enters new command.
Steps 3a1-3a2 are repeated until the command entered is correct.
Use case resumes at step 4.
Use Case: UC14 - Sorting expenditures
(Contributed by Yu Ming)
System: NUSave
Use Case: UC14 - Sorting expenditures
Actor: User
Preconditions: User is on the budget page, the given budget contains at least 2 or more expenditures
MSS:
- User requests to open a budget (UC05) to view the list of expenditures in the budget page view.
- NUSave opens the budget and displays the list of expenditures belonging to that budget.
- User enters the command to sort expenditures in NUSave.
- NUSave sorts the expenditures and displays the updated list to the user.
Use case ends.
Extensions
- 3a. NUSave detects an error in the entered command.
- 3a1. NUSave shows an error message.
- 3a2. User enters new command.
Steps 3a1-3a2 are repeated until the command entered is correct.
Use case resumes at step 4.
Use Case: UC15 - Finding expenditures
(Contributed by Chin Hui)
System: NUSave
Use Case: UC08 - Finding expenditures
Actor: User
Preconditions: User is on the budget page.
MSS:
- User enters the command to find expenditures in NUSave.
- NUSave finds all expenditures matching the user input and displays the updated list of expenditures to user.
Use case ends.
Extensions
- 1a. NUSave detects an error in the entered command.
- 1a1. NUSave shows an error message.
- 1a2. User enters new command.
Steps 1a1-1a2 are repeated until the command entered is correct.
Use case resumes at step 2.
- 2a. NUSave detects that no expenditures were found.
- 2a1. NUS displays an empty list view with a message noting that no expenditures matched the user input.
Use Case: UC16 - Listing expenditures
(Contributed by Chin Hui)
System: NUSave
Use Case: UC10 - Listing expenditures
Actor: User
Preconditions: User is on the budget page.
MSS:
- User enters the command to list all expenditures in NUSave.
- NUSave lists all existing expenditures in the current budget in memory, displaying them in the list view and
shows the success message.
Use case ends.
Use Case: UC17 - Undoing an action
(Contributed by Wen Hao)
System: NUSave
Use Case: UC17 - Undoing an action
Actor: User
Preconditions: User has just launched NUSave that contains a budget named “demo”.
MSS:
- User deletes the “demo” budget (UC04).
- NUSave deletes the “demo” budget and removes it from the list view.
- User enters the undo command.
- NUSave loads the state before the previous command and adds the “demo” budget into the list view.
Use case ends.
Extensions
- 1a. User enters the undo command without deleting the “demo” budget.
- 1a1. NUSave shows “no action to undo” error message.
- 1a2. Use case resumes at step 1.
Use Case: UC18 - Redoing an action
(Contributed by Wen Hao)
System: NUSave
Use Case: UC18 - Redoing an action
Actor: User
Preconditions: User has just launched NUSave that contains a budget named “demo”.
MSS:
- User undoes the deletion of the “demo” budget (UC17).
- NUSave loads the state before using the delete command and removes the “demo” budget from the list view.
Use case ends. - User enters the redo command.
- NUSave loads the state before using the undo command and adds the “demo” budget into the list view.
Use case ends.
Extensions
- 1a. User enters the redo command without undoing any actions.
- 1a1. NUSave shows “no action to redo” error message.
- 1a2. Use case resumes at step 1.
Non-Functional requirements
(Contributed by Chin Hui)
- NUSave should work on any mainstream OS as long as it has Java
11or above installed. - NUSave should be able to hold up to 1000 budgets and expenditures without a noticeable sluggishness in performance for typical usage.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks at a faster speed compared to clicking with the mouse.
- NUSave should serve only a single user at a time on a single client.
- NUSave should not require an internet connection to run.
- NUSave should have sufficient help messages such that a novice is able to learn to use the commands quickly.
- NUSave should save its data locally.
- NUSave should have proper error handling such that the application does not crash and the corresponding error message is displayed to the user.
- Features should be implemented such that they can undergo automated testing.
- NUSave should have an intuitive User Interface such that a novice user should be able to understand what the elements of the application represents.
Glossary
(Contributed by Song Yu)
| Term | Explanation |
|---|---|
| Expenditure | Refers to a single item to be recorded in NUSave. |
| Budget | Refers to how NUSave stores related expenditures under one group. A budget can also hold additional information about this list of expenditures, such as the target limit of what is to be spent (i.e. threshold). |
| Main Page | Refers to the page that displays the list of budgets that is stored in NUSave. |
| Budget Page | Refers to the page that displays the list of expenditures belonging in a specific budget that is stored in NUSave. |
| Threshold | Refers to the target limit that can be spent in that budget. |
| PlantUML | A software tool used by NUSave’s team to render UML diagrams in this developer guide. |
| NUS | Stands for National University of Singapore. |
| API | Stands for ‘Application Programming Interface’, which abstracts away underlying implementation and only exposes objects or methods a developer needs. |
| JSON | Stands for ‘Javascript Standard Object Notation’, which is a form of syntax used for storing data. |
| CLI | Stands for Command Line Interface. CLI-based Applications (i.e. NUSave) focuses on processing commands in the form of text entered from the keyboard. |
| GUI | Stands for Graphical User Interface. GUIs work as the communication channel between the program and the user. Users interact with NUSave through the GUI, on their devices. |
| UML | Stands for ‘Unified Modeling Diagram’. A general-purpose, standardized modeling language used in the field of software engineering. |
| NFR | Stands for ‘Non-functional Requirements’, which specifies the constraints under which the system is developed and operated. |
| Mainstream OS | Stands for ‘Mainstream Operating Systems’, such as Windows, MacOS, Linux, Unix, OS-X. |
| MSS | Stands for ‘Main Success Scenario’, which describes the interaction for a given use case, assuming nothing goes wrong. |
Instructions for Manual Testing
(Contributed by Chin Hui)
Given below are instructions to test the application manually. These instructions should be complemented with the user guide for comprehensive testing. The state of the application is assumed to contain some data either sample data from when the application is first launched or a customised data set.
Launch and shutdown
-
Launching the application
-
Download the jar file and copy into an empty folder.
-
Double-click the jar file.
Expected: Shows the GUI with a set of sample budgets. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the application by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
Add commands
-
Adding a budget
-
Prerequisites: User is in the main page with multiple budgets in the list.
-
Test case:
create n/Temasek Hall Basketball
Expected: A budget by the name of Temasek Hall Basketball is created with its budget threshold set to $0. Details of the added budget is shown in the status message. The newly added budget is displayed as the first item in the GUI list. -
Test case:
create n/Temasek Hall Basketball p/1000
Expected: A budget by the name of Temasek Hall Basketball is created with its budget threshold set to $1000. Details of the added budget is shown in the status message. The newly added budget is displayed as the first item in the GUI list. -
Test case:
create
Expected: No budget will be created. You will get an error message stating that the command format is invalid, with details of the proper format accompanied by examples. -
Test case:
create n/
Expected: No budget will be created. You will get an error message stating that the name should only contain alphanumeric characters and spaces, it should not be blank.
-
-
Adding an expenditure
-
Prerequisites: User is in the budget page with multiple expenditures in the list.
-
Test case:
add n/shirt p/15 t/clothing
Expected: An expenditure with the name shirt, price of $15 and tag of clothing will be added into the current budget. Details of the added expenditure is shown in the status message. The newly added expenditure is displayed as the first item in the GUI list. -
Test case:
add n/shirt t/clothing
Expected: No expenditure will be created. You will get an error message stating that the command format is invalid, with details of the proper format accompanied by examples. -
Test case:
add n/shirt p/15 t/some of my favourite shirts
Expected: No expenditure will be created. You will get an error message stating that each tag is limited to 15 characters long. -
Test cae:
add n/blue shirt p/15 t/clothing t/tops t/shopping t/blue
Expected: No expenditure will be created. You will get an error message stating that each expenditure can only have a maximum of 3 tags.
-
Delete Commands
-
Deleting a budget
-
Prerequisites: User is in the main page with multiple budgets in the list.
-
Test case:
delete 1
Expected: First budget is deleted from the list. Details of the deleted budget is shown in the status message. -
Test case:
delete 0
Expected: No budget is deleted. You will get an error message stating that the index is out of range and the valid range is from 1-100. -
Test case:
delete
Expected: No budget is deleted. You will get an error message stating that the index should be an integer. -
Test case:
delete x
Expected: No budget is deleted. You will get an error message stating that the index should be an integer.
-
-
Deleting an expenditure
-
Prerequisites: User is in the budget page with multiple expenditures in the list.
-
Test case:
delete 1
Expected: First expenditure is deleted from the list. Details of the deleted expenditure is shown in the status message. -
Test case:
delete 0
Expected: No budget is deleted. You will get an error message stating that the index is out of range and the valid range is from 1-100. -
Test case:
delete
Expected: No budget is deleted. You will get an error message stating that the index should be an integer. -
Test case:
delete x
Expected: No budget is deleted. You will get an error message stating that the index should be an integer.
-
Edit Commands
- Editing a budget
-
Prerequisites: User is in the main page with multiple budgets in the list.
-
Test case:
edit 1 n/Daily Expenses p/500
Expected: The first budget in the list will be edited to have the name ‘Daily Expenses’ and a budget threshold of $500. This is assuming the first budget in the list had a different name with a different budget threshold. -
Test case:
edit 1 n/Daily Expenses
Expected: The first budget in the list will be edited to have the name ‘Daily Expenses’ while its budget threshold will remain the same. This is assuming the first budget in the list had a different name. -
Test case:
edit 1 p/500
Expected: The first budget in the list will be edited to have a budget threshold of $500. This is assuming the first budget in the list had a different budget threshold. -
Test case:
edit 0 p/300
Expected: No budget will be edited. You will get an error message stating that the index is out of range and the valid range is from 1-100. -
Test case:
edit 1 p/-10
Expected: No budget will be edited. You will get an error message stating that thresholds cannot be $0 or less. The valid range of thresholds which is between $0.01 and $1,000,000 will be stated.
-
- Editing an expenditure
-
Prerequisites: User is in the budget page with multiple expenditures in the list.
-
Test case:
edit 1 n/blue shirt p/15 t/clothing
Expected: The first expenditure in the current budget will be edited to have the name ‘blue shirt’, a price of $15 and a clothing tag. This is assuming that the first expenditure in the current budget had a different name, price and the tags clothing, shirt and shopping (tagswill be overwritten). -
Test case:
edit 1 n/blue shirt
Expected: The first expenditure in the current budget will be edited to have the nameblue shirt. This is assuming that the first expenditure in the current budget had a different name. -
Test case:
edit 1 p/15
Expected: The first expenditure in the current budget will be edited to have the price of $15. This is assuming that the first expenditure in the current budget had a different price. -
Test case:
edit 0 n/blue shirt
Expected: No expenditure will be edited. You will get an error message stating that the index is out of range and the valid range is from 1-100. -
Test case:
edit 1 p/-10
Expected: No expenditure will be edited. You will get an error message stating that prices cannot be $0 or less. The valid range of prices which is between $0.01 and $10,000 will be stated.
-
Sort Commands
-
Sorting budgets
-
Prerequisite: User is in the main page with multiple budgets in the list.
-
Test case:
sort name
Expected: Current budgets in the GUI list will be sorted by name in alphabetical order. -
Test case:
sort time
Expected: Current budgets in the GUI list will be sorted by creation date, with the most recently created at the top. If two budgets are created on the same day they will be further sorted by name in alphabetical order. -
Test case:
sort test
Expected: Current budgets will not be sorted. You will get an error message stating that the sort type is not supported.
-
-
Sorting expenditures
-
Prerequisite: User is in the budget page with multiple expenditures in the list.
-
Test case:
sort name
Expected: Current expenditures in the GUI list will be sorted by name in alphabetical order. -
Test case:
sort time
Expected: Current expenditures in the GUI list will be sorted by creation date, with the most recently created at the top. If two expenditures are created on the same day they will be further sorted by name in alphabetical order. -
Test case:
sort test
Expected: Current expenditures will not be sorted. You will get an error message stating that the sort type is not supported.
-
Find Commands
-
Finding Budgets
-
Prerequisite: User is in the main page with multiple budgets in the list.
-
Test case:
find NUS
Expected: Budgets with names that contain the search term ‘NUS’ will be displayed in the GUI list. -
Test case:
find
Expected: You will get an error message stating that the search term should not be blank.
-
-
Finding Expenditures
-
Prerequisite: User is in the budget page with multiple expenditures in the list.
-
Test case:
find shirt
Expected: Expenditures in the current budget with names that contain the search term ‘shirt’ will be displayed in the GUI list. -
Test case:
find
Expected: You will get an error message stating that the search term should not be blank.
-
List Commands
-
Listing Budgets
-
Prerequisite: User is in the main page with multiple budgets in the list. The
findcommand was successfully used, the GUI list currently only displays budgets containing ‘NUS’. -
Test case:
list
Expected: All budgets are now displayed in the GUI list.
-
-
Listing Expenditures
-
Prerequisite: User is in the budget page with multiple expenditures in the list. The
findcommand was successfully used, the GUI list currently only displays expenditures containingshirt. -
Test caes:
list
Expected: All expenditures are now displayed in the GUI list.
-
Universal Commands
-
Help Command
- Test case:
help
Expected: Description, format and examples of all commands are displayed in the result box.
- Test case:
Opening a budget
-
Prerequisite: User is in the main page with multiple budgets in the list.
-
Test case:
open 1
Expected: Opens the first budget in the current GUI list of budgets. The GUI list now displays the expenditures within the first budget. -
Test case:
open -1
Expected: You will get an error message stating that the current index is out of bounds and the correct range which is from 0-100.
Closing a budget
-
Prerequisite: User is in the budget page with multiple expenditures in the list.
-
Test case:
close
Expected: Closes the current budget and return back to the main page.
Redo Command
- Test case:
redo(assuming that theundocommand was used previously to undo acreatecommand)
Expected: Thecreatecommand that was undone will be called again. The budget that was created using thecreatecommand will be reflected in the GUI list.
Undo Command
- Test case:
undo(assuming thatcreatecommand was the most recently called command)
Expected: Thecreatecommand will be undone. The budget that was created will be removed from the GUI list as if thecreatecommand was not called.
Effort
(Contributed by all <3)
Throughout the development, our team shared the common goal of making NUSave an application that is intuitive, object-oriented and presentable. After devoting countless late nights both as a team and individually, we managed to pull through and create a product that we are proud of. Amassing over 10,000 lines of code combined, we had to adhere to strict deadlines, cultivate a culture of open communication and proactively support one another. Aside from the weekly official meetings, we frequently met up to conduct code reviews and pair programming to ensure that everyone was on the same page.
To enable navigation between pages, we had to restructure a large portion of AB3 so that NUSave incorporates the concept of
having states. As such, we implemented a new architectural State component to keep track of what page the user is on and reflect the respective page view.
To fulfil the functional requirements of NUSave, an additional layer of data was integrated. On top of the one to many relationship between Nusave
and Budget, Budget also has a one to many relationship with Expenditure.
To implement the undo and redo commands, we had to come up with our own version of a doubly-linked list, Node<T>, as well as
its own iterator, HistoryManager<T>. Furthermore, not only the data had to be cached, but also the state of NUSave in VersionedNusave.
Coding aside, we placed an equal emphasise on UI/UX.
Firstly, we revamped the GUI entirely. Taking into consideration colour consistency, design trends and ease of navigation, we used Figma to generate a mock-up for our reference throughout the development. Despite the limitations of JavaFX and our knowledge in CSS, we were successful in replicating our ideal design.
To make our application more dynamic, we researched on numerous APIs and narrowed down to using JavaFX’s Property and Bindings interfaces.
Through countless trial and errors, we managed to render NUSave’s UI components dynamically while adhering to OO principles.
Finally, much effort was put into ensuring that our documentation was organised and pleasant to read. We had meetings to standardise every section in terms of language, structure and diagrams. After multiple iterations, consistency was achieved in both our user and developer guides.