logo

By: Team AY1920S1-CS2103T-W12-4      Since: Sep 2019      Licence: MIT

1. Introduction

IchiFund is a financial tracking application that manages transactions, loans, as well as budgets.

Shown below is the GUI of IchiFund:

Ui

This document serves to give an introduction to the architecture of IchiFund for developers who wish to modify the software, or simply to understand how it works. We describe the high-level architecture, and also delve into important details of the implementation of each feature.

2. Setting Up

Refer to the guide here.

3. Design

3.1. Architecture

ArchitectureDiagram
Figure 1. Architecture Diagram

The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.

The .drawio files used to create diagrams in this document can be found in the diagrams folder. To edit, go to and import the .drawio files in the repository.

Main has two classes called Main and MainApp. It is responsible for,

  • At app 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 method where necessary.

Commons represents a collection of classes used by multiple other components. The following class plays an important role at the architecture level:

  • LogsCenter : Used by many classes to write log messages to the App’s log file.

The rest of the App consists of four components.

  • UI: The UI of the App.

  • Logic: The command executor.

  • Model: Holds the data of the App in-memory.

  • Storage: Reads data from, and writes data to, the hard disk.

Each of the four components

  • Defines its API in an interface with the same name as the Component.

  • Exposes its functionality using a {Component Name}Manager class.

For example, the Logic component (see the class diagram given below) defines it’s API in the Logic.java interface and exposes its functionality using the LogicManager.java class.

LogicClassDiagram
Figure 2. Class Diagram of the Logic Component

How the architecture components interact with each other

The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1.

ArchitectureSequenceDiagram
Figure 3. Component interactions for delete 1 command

The sections below give more details of each component.

3.2. UI Component

UiClassDiagram
Figure 4. Structure of the UI Component

API : Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, TransactionListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class.

The UI component uses 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

The UI component,

  • Executes user commands using the Logic component.

  • Listens for changes to Model data so that the UI can be updated with the modified data.

  • Listens for changes to the index of the FeatureParser used by the Logic component to change tabs.

  • Sets the FeatureParser used by the Logic component when the user manually changes tabs.

3.3. Logic Component

LogicClassDiagram
Figure 5. Structure of the Logic Component

API : Logic.java

  1. Logic uses the IchiFundParser class to parse the user command.

  2. This results in a Command object which is executed by the LogicManager.

  3. The command execution can affect the Model (e.g. adding a person).

  4. The result of the command execution is encapsulated as a CommandResult object which is passed back to the Ui.

  5. In addition, the CommandResult object can also instruct the Ui to perform certain actions, such as displaying help to the user.

Given below is the Sequence Diagram for interactions within the Logic component for the execute("delete 1") API call.

DeleteSequenceDiagram
Figure 6. Interactions Inside the Logic Component for the delete 1 Command

3.4. Model Component

ModelClassDiagram
Figure 7. Structure of the Model Component

API : Model.java

The Model,

  • stores a UserPref object that represents the user’s preferences.

  • stores the IchiFund data (in e.g. UniqueBudgetList)

  • keeps track of a TransactionContext object that represents the current filter applied to TransactionList.

  • exposes an unmodifiable version of the TransactionContext object (as ObservableValue<TransactionContext>) that can be observed by the UI.

  • exposes unmodifiable lists (e.g. ObservableList<Transaction>) 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.

3.5. Storage Component

StorageClassDiagram
Figure 8. Structure of the Storage Component

API : Storage.java

The Storage component,

  • can save UserPref objects in json format and read it back.

  • can save the IchiFund data in json format and read it back.

3.6. Common Classes

Classes used by multiple components are in the seedu.ichifund.commons package.

4. Implementation

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

4.1. Global Features

4.1.1. Separate Parsing and Tab Switching

In IchiFund, we separate the features by tabs. This is illustrated in the image below, which displays the five tabs of IchiFund, with the "Transaction" tab selected:

FeatureTabs
Figure 9. Feature Tabs in IchiFund

The parsing of commands for each feature is done separately, tied to their respective tabs. In other words, the commands specific to each feature can only be recognised when the feature is selected as the current tab. This allows for the overloading of commands across different features, reducing the complexity of commands for users.

Implementation

There are two aspects to consider in implementing separate parsing:

  • Detecting when the user switches tabs and communicating this to the Logic component

  • Determining how to parse commands on the end of Logic given which tab is selected.

In our implementation, we first separate the parsing of commands for different features by delegating them to their respective FeatureParser parsers. The main parser, IchiFundParser, keeps track of all FeatureParser objects, as well as the FeatureParser that is currently in use.

This is illustrated in the object diagram below:

ParserObjectDiagram
Figure 10. Object Diagram for Parser Classes in IchiFund

When IchiFundParser parses a command, it first checks whether it is a global command (e.g. help, exit). Otherwise, it passes the command to currentParserManager, which checks if it is a valid command, and passes the arguments to the appropriate Parser.

What remains is determining when to change currentParserManager. Here, we support 3 modes of tab switching:

  1. Specific commands (CLI)

Users can switch between tabs using specific commands (tx, rep, budget, loan, analytics).

These commands are global commands that are directly recognised by IchiFundParser, which changes currentFeatureParser and the index stored.

Much like the Model data, MainWindow listens to changes to the index through FeatureParserIndexListener. Whenever the value of the index changes, the listener triggers an event to change the tab throw the invalidated() method shown in the code snippet below:

ListenerCodeSnippet

The InvalidationListener constructed from the above code is added to an ObservableValue in MainWindow that tracks the index of the current FeatureParser used, and changes to the appropriate tab using the value of the index stored.

  1. Shortcut keys (GUI)

Users can also switch tabs using the shortcut keys Ctrl + 1 to Ctrl + 5. Upon using the shortcut keys, the following handler is triggered:

MainWindowShortcutKeyCodeSnippet

When handleShowTransaction() is called, currentFeatureParser in IchiFundParser, is set to TransactionFeatureParser, which has a tabIndex of zero. Other handler methods are similar to handleShowTransaction, with the only difference being the index passed to Logic.

The control flow of handleShowTransaction() is illustrated with more details in the sequence diagram below:

SetFeatureParserSequenceDiagram
Figure 11. Sequence Diagram for changing FeatureParser

As the different FeatureParser objects have different values for tabIndex, a different index is passed, and a different FeatureParser is set as currentFeatureParser.

After the handler method is run, the change in IchiFundParser is also detected by InvalidationListener, which results in a tab switch similar to how the specific commands would.
For developers who wish to add more features to IchiFund, care has to be taken in ensuring that the indices of the FeatureParser objects matches that of the tabs, as well as its index in featureParsers. In our current implementation, we do not use enum for the indices due to the small scale of usage.
  1. Clicking of tabs (GUI)

Users can switch tabs by clicking on the tabs shown in Figure 9, “Feature Tabs in IchiFund”. This triggers a handler, shown in the following code snippet:

MainWindowMouseCodeSnippet

The control flow for this handler is similar to that of the shortcut keys.

Design Considerations

In designing the specific commands for tab switching, we considered an alternative implementation for passing information about tab switching to Ui.

Description of Implementation Pros and Cons

Ui detects change through an InvalidationListener (current choice)

Pros: Logic does not need to be aware of Ui

Cons: Requires greater understanding of JavaFX API to implement

Logic directly calls Ui whenever the specific command is made.

Pros: Easy to implement

Cons: Creates a dependency from Logic to Ui

While Alternative 2 is much simpler to implement, we chose Alternative 1 as we prioritised preserving the independence of Logic from Ui.

4.1.2. Tasks

Some models in IchiFund must be refreshed after a command is executed. For instance, when a new Transaction is added, all Budget must be recomputed. Task can be used to facilitate such updates.

Implementation

This feature is managed by TaskManager. The role of TaskManager is to maintain a list of all active Task.

The LogicManager holds an instance of the TaskManager. When the LogicManager#execute() is called, the following chain of operations occurs:

  1. After Command#execute() is completed, TaskManager#executeAll() is called.

TaskCode
  1. TaskManager#executeAll() will iterate through all active Task and call the respective Task#execute() method.

4.2. Transactions

4.2.1. Overview of the Transactions Model

Implementation

The transactions in IchiFund are represented using the Transaction class. While users are able to edit transactions, objects of the Transaction class are immutable in the internal structure. The following class diagram summarizes the details of the Transaction class:

TransactionClassDiagram
Figure 12. Class Diagram from Transactions Model
We differentiate income items from expenditure items using the TransactionType field, which accepts two unique string values, "in" for income and "exp" for expenditure in the constructor.

In addition, the list of transactions is subject to a filter created by an immutable TransactionContext. TransactionContext keeps track of the Month, Year, Category (optional) and TransactionType (optional) in the current filter. Naturally, this implies that a filter for Month and Year is always applied to the list of transactions. The TransactionContext is also used to fill in optional fields that are not specified by the user when adding transactions.

We summarise the role of the TransactionContext class in the following conceptual class diagram:

TransactionContextOodm
Figure 13. Conceptual Class Diagram of TransactionContext
Design Considerations

We encountered two major decisions when implementing our model for transactions. Here, we discuss the alternatives we considered, as well as the rationale for the current implementation.

Multiplicity of Category

Currently, each Transaction object can have only one Category object associated to it. In the problem domain, it is also natural to think of transactions being associated with multiple categories. The table below summarizes the pros and cons of each choice.

Description of Implementation Pros and Cons

Each Transaction only has one Category (current choice)

Pros: Simple to implement. No overlaps in apportionment of expenditure to categories

Cons: Less flexibility for the user to classify transactions

Each Transaction can have more than one Category

Pros: More flexibility for the user to classify transactions

Cons: Overlaps in apportionment of expenditure to categories

While both implementations are visible, we chose to only have one Category associated to each Transaction as the absence of overlaps in expenditure allows us to eventually implement a clean visual breakdown of expenditure by category in the future. Developers, however, are welcome to implement an additional Tags field for Transaction objects, to allow for multiple associations.

Differentiating between Income and Expenditure

Currently, we differentiate income items from expenditure items using the TransactionType field in Transaction. We considered the natural alternative of using inheritance as well.

Description of Implementation Pros and Cons

Using the field TransactionType (current choice)

Pros: Fits the parsing methods used in the current architecture well

Cons: More tedious to code for different behaviours for income and expenditure items in the future

Using inheritance

Pros: Allows for polymorphism of methods from a Transaction interface in the long run

Cons: Requires either the use of separate commands, or asymmetry in the parsing of command arguments

While it was a tough decision, we eventually decided to use TransactionType for differentiation as we valued maintaining the symmetry in the implementation of parsing in our current architecture, and we did not want to use separate commands for adding transactions. Furthermore, we did not envision further use of polymorphism in future developments. Hence the benefit of using inheritance becomes very limited.

4.2.2. Filtering Transactions

The filter transactions feature allows the user to change the filter for the list of transactions. As described in Section 3.3, “Logic Component”, this feature is facilitated by TransactionFeatureParser, FilterTransactionCommandParser, and FilterTransactionCommand. The arguments supported by this feature are: Month, Year, Category and TransactionType. All of these arguments are optional, but the user has to input at least one argument for the command to be valid.

Implementation

We omit the details of parsing facilitated by IchiFundParser, TransactionFeatureParser and FilterTransactionCommandParser. Instead, we immediately delve into the details of FilterTransactionCommand#execute.

As prefaced in Section 4.2.1, “Overview of the Transactions Model”, the filter command interacts with TransactionContext to filter the list of transactions exposed to the UI component. Following the creation of FilterTransactionCommand, the execution of the command results in the following chain of events:

Step 1: FilterTransactionCommand retrieves the current TransactionContext from the model.

Step 2: FilterTransactionCommand creates a new TransactionContext, facilitated by TransactionContextBuilder

Step 3: FilterTransactionCommand sets the new context in model as the newly created TransactionContext.

Step 4: ModelManager retrieves a Predicate<Transaction> from the new TransactionContext.

Step 5: ModelManager filters the list of transactions using the Predicate<Transaction>.

The above sequence of events is shown in greater detail in the following sequence diagram:

FilterTransactionSequenceDiagram
Figure 14. Sequence Diagram for FilterTransactionCommand

4.2.3. Adding Transactions

The add transaction feature allows the user to add a transaction into IchiFund. It further ensures that the current filter of the list of transactions is changed to allow the user to view the transaction. As described in Section 3.3, “Logic Component”, this feature is facilitated by TransactionFeatureParser, AddTransactionCommandParser, and AddTransactionCommand. The arguments supported by this feature are: Description, Amount, Category, Day, Month, Year and TransactionType. Of these arguments, only Description and Amount are mandatory.

Implementation

We omit the details of parsing facilitated by IchiFundParser, TransactionFeatureParser and AddTransactionCommandParser. Instead, we immediately delve into the details of the AddTransactionCommand#execute.

As prefaced in Section 4.2.1, “Overview of the Transactions Model”, AddTransactionCommand interacts with TransactionContext to generate a Transaction to be added to the model. The execution of an AddTransactionCommand results in the following sequence of events:

Step 1: AddTransactionCommand retrieves the current TransactionContext from the model.

Step 2: AddTransactionCommand generates a new Transaction based on the arguments and TransactionContext

Step 3: AddTransactionCommand adds the new Transaction to the model.

Step 4: ModelManager automatically sorts the list of transactions.

Step 5: AddTransactionCommand calls model to execute updateTransactionContext

Step 6: ModelManager updates TransactionContext such that the new Transaction is shown.

To create a new Transaction, AddTransactionCommand fills in the missing arguments using values obtained from TransactionContext, or default values. This is illustrated in the activity diagram below:

AddTransactionActivityDiagram
Figure 15. Activity Diagram for Optional Arguments in AddTransactionCommand

The above activity diagram shows the decision flow for a general optional argument. However, some optional arguments are never stored in TransactionContext, and some are always stored. The following table describes the particular details for each optional argument.

Argument Stored in TransactionContext? Default value

Day

Never

Current day of month from system time

Month

Always

Not applicable

Year

Always

Not applicable

Category

Sometimes

Uncategorised

TransactionType

Sometimes

Expenditure

After adding the Transaction, a new TransactionContext is created such that the new Transaction is displayed on the list of transactions. Specifically, the Month and Year filters are set to the Month and Year of the new Transaction respectively, and the Category and TransactionType filters are removed if necessary.

Design Considerations

In implementing the add and filter commands, we had to decide on the underlying data structure for the list of transactions. Currently, we store all transactions in a single iterable list. Given the use of a mandatory month and year filter, a natural alternative would be to store each month’s worth of transactions in a list, and stores these lists in another list, forming a multi-level list.

Description of Implementation Pros and Cons

Storing all transactions in a single list (current choice)

Pros: Suits existing architecture of software very well, easy to implement

Cons: Slow performance anticipated with large number of transactions

Storing transactions in multi-level list

Pros: Faster performance, more scalable

Cons: May disrupt abstractions in current architecture, more time needed to implement

Ultimately, we decided to avoid disrupting the existing architecture, and instead focus our efforts on developing more features to better address the needs of the target user profile.

However, moving forward, we recognise that the current architecture severely lacks scalability, especially given the constantly growing number of transactions we expect users to create. Hence, we eventually intend to switch to a multi-level list.

Developers who choose to change the underlying data structures should bear in mind that many other components (Repeaters, Budgets, Analytics) depend on the model of Transactions, and care must be taken to ensure that these components still work well.

4.2.4. Editing Transactions

The edit transaction feature allows the user to edit a transaction into IchiFund. It further ensures that the current filter of the list of transactions is changed to allow the user to view the transaction. As described in Section 3.3, “Logic Component”, this feature is facilitated by TransactionFeatureParser, EditTransactionCommandParser, and EditTransactionCommand. The arguments supported by this feature are Index, Description, Amount, Category, Day, Month, Year and TransactionType. Of these arguments, only Index is mandatory, but at least one of the optional arguments (which are fields to be edited) need to be present.

Implementation

The execution of the edit command is similar to the delete commands in other components. The following sequence of steps describes the behaviour of EditTransactionCommand at each step:

Step 1: The user executes edit 2 de/Lunch to change the description of the Transaction in the 2nd index to "Lunch".

Step 2: LogicManager uses IchiFundParser#parserCommand() to parse the input from the user.

Step 3: IchiFundParser redirects the input to TransactionFeatureParser.

Step 4: TransactionFeatureParser determines which command is being used and creates the respective EditTransactionCommandParser parser with the user’s input as an argument.

Step 5: EditTransactionCommandParser does a validation check on the user’s input.

Step 6: EditTransactionCommandParser creates an EditTransactionDescriptor which contains the updated description information provided by the user.

Step 7: EditTransactionCommandParser creates and returns an EditTransactionCommand with the Index and EditTransactionDescriptor as arguments.

Step 8: LogicManager calls EditTransactionCommand#execute().

Step 9: EditTransactionCommand checks if the Index is too large, and retrieves the appropriate Transaction to be deleted from the Model.

Step 10: EditTransactionCommand checks that the Transaction is not created from a Repeater.

Step 11: EditTransactionCommand creates a new Transaction using the original Transaction and the EditTransactionDescriptor.

Step 12: EditTransactionCommand replaces the original Transaction in the Model with the newly created Transaction.

Step 13: EditTransactionCommand calls Model#updateTransactionContext with the newly created Transaction as an argument.

Step 14: EditTransactionCommand returns a CommandResult to the LogicManager which is returned back to the user.

4.2.5. Deleting Transactions

The delete transaction feature allows the user to delete a transaction into IchiFund using its index in the displayed list. As described in Section 3.3, “Logic Component”, this feature is facilitated by TransactionFeatureParser, DeleteTransactionCommandParser, and DeleteTransactionCommand. The delete command takes one argument, Index.

Implementation

The execution of the delete command is similar to the delete commands in other components. The following sequence of steps describes the behaviour of DeleteTransactionCommand at each step:

Step 1: The user executes delete 2 to delete the Transaction in the 2nd index.

Step 2: LogicManager uses IchiFundParser#parserCommand() to parse the input from the user.

Step 3: IchiFundParser redirects the input to TransactionFeatureParser.

Step 3: TransactionFeatureParser determines which command is being used and creates the respective DeleteTransactionCommandParser parser with the user’s input as an argument.

Step 4: DeleteTransactionCommandParser does a validation check on the user’s input before creating and returning a DeleteRepeaterCommand with desired Index as an argument.

Step 5: LogicManager calls DeleteTransactionCommand#execute()

Step 6: DeleteTransactionCommand checks if the Index is too large, and retrieves the appropriate Transaction to be deleted from the Model.

Step 7: DeleteTransactionCommand checks that the Transaction is not created from a Repeater.

Step 8: DeleteTransactionCommand deletes the Transaction from the Model.

Step 9: DeleteTransactionCommand returns a CommandResult to the LogicManager which is returned back to the user.

4.3. Repeaters

Repeaters allow for the convenient management of repeated transactions through a single Repeater entity. The list of associated transactions are automatically synchronized to updates in Repeaters. The following class diagram summarizes the details of the Repeater class:

RepeaterClassDiagram
Figure 16. Class Diagram from Repeaters Model

4.3.1. Adding Repeater

This feature allows the user to add a repeater in IchiFund. Adding a repeater also creates the transactions associated with the added repeater.

Implementation

The add command is facilitated by the Logic and Model components of the application. The process of executing an add command is illustrated in the sequence diagram below:

AddRepeaterSequenceDiagram
Figure 17. Sequence Diagram for AddRepeaterCommand

Below is an example usage scenario of how add behaves at each step.

Step 1: In the repeaters tab, the user executes add de/Phone bills a/42.15 c/Utilities ty/exp so/3 eo/2 sd/1 sm/1 sy/2019 ed/31 em/12 ey/2019 to add a repeater for phone bills with an amount of $42.15 on the third and second last day of every month between 1st January 2019 and 31st December 2019.

Step 2: LogicManager uses IchiFundParser#parserCommand() to parse the input from the user.

Step 3: IchiFundParser determines which command is being used and creates the respective AddRepeaterCommandParser parser with the user’s input as an argument.

Step 4: AddRepeaterCommandParser does a validation check on the user’s input.

Step 5: AddRepeaterCommandParser creates and returns an AddRepeaterCommand with the desired Repeater as an arugment.

Step 6: LogicManager calls AddRepeaterCommand#execute().

Step 7: AddRepeaterCommand checks for the following constraints:

  • The Repeater to be added does not already exist in the Model.

  • The end date of the Repeater to be added is no earlier than its start date.

  • The start date and and end date of the Repeater to be added span no more than 60 months.

Step 8: AddRepeaterCommand fetches the running RepeaterUniqueId counter tracked by the Model.

Step 9: AddRepeaterCommand creates the Repeater and sets its unique id as the fetched RepeaterUniqueId.

Step 10: AddRepeaterCommand increments the current RepeaterUniqueId counter in the Model.

Step 11: AddRepeaterCommand adds the newly created Repeater to the Model.

Step 12: AddRepeaterCommand creates the associated Transactions in the Model.

Step 13: AddRepeaterCommand returns a CommandResult to the LogicManager which is returned back to the user.

When creating a Repeater, AddRepeaterCommandParser fills in arguments unspecified by the user with default values, as shown in the activity diagram below:

RepeaterOptionalActivityDiagram
Figure 18. Activity Diagram for Optional Arguments in AddRepeaterCommandParser

4.3.2. Editing Repeater

This feature allows the user to edit a repeater in IchiFund. Editing a repeater also updates the transactions associated with the added repeater.

Implementation

The edit command is facilitated by the Logic and Model components of the application. Given below is an example usage scenario of how edit behaves at each step.

Step 1: In the repeaters tab, the user executes edit 1 a/37.24 so/-1 eo/4 to edit the repeater at the 2nd index for an amount of $37.25, occuring only at the fourth last day of every month.

Step 2: LogicManager uses IchiFundParser#parserCommand() to parse the input from the user.

Step 3: IchiFundParser determines which command is being used and creates the respective EditRepeaterCommandParser parser with the user’s input as an argument.

Step 4: EditRepeaterCommandParser does a validation check on the user’s input.

Step 5: EditRepeaterCommandParser creates an EditRepeaterDescriptor which contains the updated repeater information provided by the user.

Step 6: EditRepeaterCommandParser creates and returns an EditRepeaterCommand with the Index and EditRepeaterDescriptor as arguments.

Step 7: LogicManager executes EditRepeaterCommand#execute().

Step 8: EditRepeaterCommand checks for the following constraints:

  • The updated Repeater does not already exist in the Model.

  • The end date of the updated Repeater is no earlier than its start date.

  • The start date and and end date of the updated Repeater span no more than 60 months.

Step 9: EditRepeaterCommand creates a new Repeater using the original Repeater and the EditRepeaterDescriptor.

Step 10: EditRepeaterCommand replaces the original Repeater in the Model with the newly created Repeater.

Step 11: EditRepeaterCommand deletes all existing associated Transactions from the Model.

Step 12: EditRepeaterCommand creates the Transactions associated with the updated Repeater in the Model.

Step 13: EditRepeaterCommand returns a CommandResult to the LogicManager which is returned back to the user.

4.3.3. Deleting Repeater

This feature allows the user to delete repeater in IchiFund. Deleting a repeater also deletes the transactions associated with the deleted repeater.

Implementation

The delete command is facilitated by the Logic and Model components of the application. Given below is an example usage scenario of how delete behaves at each step.

Step 1: In the repeaters tab, the user executes delete 2 to delete the repeater at the 2nd index.

Step 2: LogicManager uses IchiFundParser#parserCommand() to parse the input from the user.

Step 3: IchiFundParser determines which command is being used and creates the respective DeleteRepeaterCommandParser parser with the user’s input as an argument.

Step 4: DeleteRepeaterCommandParser does a validation check on the user’s input.

Step 5: DeleteRepeaterCommandParser creates and returns a DeleteRepeaterCommand with the desired Index as an argument.

Step 6: LogicManager calls DeleteRepeaterCommand#execute().

Step 7: DeleteRepeaterCommand checks that a Repeater exists at the Index.

Step 8: DeleteRepeaterCommand retrieves the Repeater at the Index from the Model.

Step 9: DeleteRepeaterCommand deletes the Repeater from the Model.

Step 10: DeleteRepeaterCommand deletes all associated Transactions in the Model.

Step 11: DeleteRepeaterCommand returns a CommandResult to the LogicManager which is returned back to the user.

4.3.4. Finding Repeater

This feature allows the user to find repeaters in IchiFund. The search by matching provided keywords against repeater descriptions.

Implementation

The find command is facilitated by the Logic and Model components of the application. Given below is an example usage scenario of how find behaves at each step.

Step 1: In the repeaters tab, the user executes find phone husband to find all repeaters whose descriptions contain any of the keywords "phone" and "husband".

Step 2: LogicManager uses IchiFundParser#parserCommand() to parse the input from the user.

Step 3: IchiFundParser determines which command is being used and creates the respective FindRepeaterCommandParser parser with the user’s input as an argument.

Step 4: FindRepeaterCommandParser does a validation check on the user’s input.

Step 5: FindRepeaterCommandParser creates a RepeaterDescriptionPredicate which filters Repeaters based on whether a Repeater contains all the keywords provided by the user.

Step 6: FindRepeaterCommandParser creates and returns a FindRepeaterCommand with the RepeaterDescriptionPredicate as an arugment.

Step 7: LogicManager calls FindRepeaterCommand#execute().

Step 8: FindRepeaterCommand sets the RepeaterDescriptionPredicate as the filter for the repeater list in the Model.

Step 9: FindRepeaterCommand returns a CommandResult to the LogicManager which is returned back to the user.

4.4. Budget

4.4.1. Adding Budget

The add budget feature allows the user to add a budget into IchiFund. This feature is facilitated by BudgetFeatureParser, AddBudgetCommandParser, and AddBudgetCommand. The arguments supported by this feature includes:

  • Description

  • Amount

  • Category (optional)

  • Month (optional)

  • Year (optional)

Implementation

When the user input the add command in the Budget tab, the following chain of operations occurs:

  1. The IchiFundParser will delegate the parsing of the command to BudgetFeatureParser if the current active tab is Budget.

  2. The BudgetFeatureParser will delegate the parsing of the arguments to AddBudgetCommandParser.

  3. AddBudgetCommandParser#parse() will take in a String input consisting of the arguments.

  4. This arguments will be tokenized and the respective models for each argument are created.

  5. If the parsing of all arguments are successful, a new Budget object is created using the arguments, and a new AddBudgetCommand is returned back to LogicManager.

  6. The LogicManager executes AddBudgetCommand#execute().

  7. The newly created Budget is added to the model.

This process is further illustrated in the following sequence diagram:

AddBudgetSequenceDiagram
Figure 19. Sequence Diagram for add Command under Budget Tab

4.5. Analytics

4.5.1. Overview of the Analytics Model

Implementation

Analytical data in IchiFund is represented using the Data class. Objects of the Data class are immutable in the internal structure. The following class diagram summarizes the details of the Data class:

AnalyticsClassDiagram
Figure 20. Class Diagram from Analytics Model

In addition, analytical data associated with a command is initially stored in a Report. Using polymorphism, this report is initialised as either a TrendReport or a BreakdownReport depending on the command that was executed. The following class diagram summarizes the details of the Report class:

AnalyticsClassDiagram2
Figure 21. Class Diagram from Analytics Model

4.5.2. View Expenditure Trend

The view expenditure trend feature allows the user to view monthly expenditure trend for a year. This feature is facilitated by AnalyticsFeatureParser, ExpenditureTrendCommandParser, and ExpenditureTrendCommand. The argument supported by this feature is:

  • Year (optional)

Implementation

After the user inputs the expenditure command in the Analytics tab, the following chain of operations occurs:

Step 1: The IchiFundParser will delegate the parsing of the command to AnalyticsFeatureParser if the current active tab is Analytics.

Step 2: The AnalyticsFeatureParser will delegate the parsing of the arguments to ExpenditureTrendCommandParser.

Step 3: ExpenditureTrendCommandParser#parse() will take in a String input consisting of the arguments.

Step 4: This arguments will be tokenized and the respective models for each argument are created.

Step 5: If the parsing of all arguments are successful, a new ExpenditureTrendCommand is returned back to LogicManager.

Step 6: The LogicManager executes ExpenditureTrendCommand#execute().

Step 7: The model is updated with the List of Data from the newly created TrendReport.

The above sequence of events is shown in greater detail in the following sequence diagram:

ExpenditureTrendSequenceDiagram
Figure 22. Sequence Diagram for ExpenditureTrendCommand

The details of the fill trend report interactions have been omitted from the diagram above, and are shown in the following separate sequence diagram:

FillTrendReportSequenceDiagram
Figure 23. Sequence Diagram for fill trend report

In addition, this activity diagram shows the action sequence for one iteration of the internal for-loop for the execution of the fillExpenditureTrendReport method of an ExpenditureTrendCommand.

FillExpenditureTrendReportActivityDiagram
Figure 24. Activity Diagram for fillExpenditureTrendReport method

4.5.3. View Income Trend

The view income trend feature allows the user to view monthly income trend for a year. This feature is facilitated by AnalyticsFeatureParser, IncomeTrendCommandParser, and IncomeTrendCommand. The argument supported by this feature is:

  • Year (optional)

Implementation

When the user input the income command in the Analytics tab, the following chain of operations occurs:

Step 1. The IchiFundParser will delegate the parsing of the command to AnalyticsFeatureParser if the current active tab is Analytics.

Step 2. The AnalyticsFeatureParser will delegate the parsing of the arguments to IncomeTrendCommandParser.

Step 3. IncomeTrendCommandParser#parse() will take in a String input consisting of the arguments.

Step 4. This arguments will be tokenized and the respective models for each argument are created.

Step 5. If the parsing of all arguments are successful, a new IncomeTrendCommand is returned back to LogicManager.

Step 6. The LogicManager executes IncomeTrendCommand#execute().

Step 7. The model is updated with the List of Data from the newly created TrendReport.

Observe that the implementation of income is similar to that of expenditure, except that each transaction is tested for whether it is an income item.

4.5.4. View Balance Trend

The view balance trend feature allows the user to view monthly balance trend for a year. This feature is facilitated by AnalyticsFeatureParser, BalanceTrendCommandParser, and BalanceTrendCommand. The argument supported by this feature is:

  • Year (optional)

Implementation

When the user input the balance command in the Analytics tab, the following chain of operations occurs:

  1. The IchiFundParser will delegate the parsing of the command to AnalyticsFeatureParser if the current active tab is Analytics.

  2. The AnalyticsFeatureParser will delegate the parsing of the arguments to BalanceTrendCommandParser.

  3. BalanceTrendCommandParser#parse() will take in a String input consisting of the arguments.

  4. This arguments will be tokenized and the respective models for each argument are created.

  5. If the parsing of all arguments are successful, a new BalanceTrendCommand is returned back to LogicManager.

  6. The LogicManager executes BalanceTrendCommand#execute().

  7. The model is updated with the List of Data from the newly created TrendReport.

Observe that the implementation of balance differs slightly from that of expenditure and income.

The following activity diagram shows the action sequence for one iteration of the internal for-loop for the execution of the fillBalanceTrendReport method of an BalanceTrendCommand.

FillBalanceTrendReportActivityDiagram
Figure 25. Activity Diagram for fillBalanceTrendReport method

4.5.5. View Expenditure Breakdown By Category

The view expenditure breakdown by category feature allows the user to view breakdown of expenditure by category. This feature is facilitated by AnalyticsFeatureParser, BreakdownCommandParser, and BreakdownCommand. The arguments supported by this feature are:

  • Month (optional)

  • Year (optional)

Implementation

When the user input the breakdown command in the Analytics tab, the following chain of operations occurs:

Step 1. The IchiFundParser will delegate the parsing of the command to AnalyticsFeatureParser if the current active tab is Analytics.

Step 2. The AnalyticsFeatureParser will delegate the parsing of the arguments to BreakdownCommandParser.

Step 3. BreakdownCommandParser#parse() will take in a String input consisting of the arguments.

Step 4. This arguments will be tokenized and the respective models for each argument are created.

Step 5. If the parsing of all arguments are successful, a new BreakdownCommand is returned back to LogicManager.

Step 6. The LogicManager executes BreakdownCommand#execute().

Step 7. The model is updated with the List of Data from the newly created BreakdownReport.

Observe that the implementation of breakdown, as well as the following command catrank, involve the creation of a BreakdownReport instead of a TrendReport. This is because the results of these commands are specific to a year and a month, as opposed to the results of the other commands which are only specific to a year.

4.5.6. View Expenditure Category Ranking Chart

The view expenditure category ranking chart allows the user to view the ranked breakdown of expenditure by category. This feature is facilitated by AnalyticsFeatureParser, CategoryRankingCommandParser, and CategoryRankingCommand. The arguments supported by this feature are:

  • Month (optional)

  • Year (optional)

Implementation

When the user input the catrank command in the Analytics tab, the following chain of operations occurs:

Step 1. The IchiFundParser will delegate the parsing of the command to AnalyticsFeatureParser if the current active tab is Analytics.

Step 2. The AnalyticsFeatureParser will delegate the parsing of the arguments to CategoryRankingCommandParser.

Step 3. CategoryRankingCommandParser#parse() will take in a String input consisting of the arguments.

Step 4. This arguments will be tokenized and the respective models for each argument are created.

Step 5. If the parsing of all arguments are successful, a new CategoryRankingCommand is returned back to LogicManager.

Step 6. The LogicManager executes CategoryRankingCommand#execute().

Step 7. The model is updated with the List of Data from the newly created BreakdownReport.

4.5.7. View Expenditure Ranking Chart By Month

The view expenditure ranking chart by month allows the user to view the ranked monthly expenditure trends. This feature is facilitated by AnalyticsFeatureParser, MonthlyExpenditureRankingCommandParser, and MonthlyExpenditureRankingCommand. The argument supported by this feature is:

  • Year (optional)

Implementation

When the user input the mthrank command in the Analytics tab, the following chain of operations occurs:

Step 1. The IchiFundParser will delegate the parsing of the command to AnalyticsFeatureParser if the current active tab is Analytics.

Step 2. The AnalyticsFeatureParser will delegate the parsing of the arguments to MonthlyExpenditureRankingCommandParser.

Step 3. MonthlyExpenditureRankingCommandParser#parse() will take in a String input consisting of the arguments.

Step 4. This arguments will be tokenized and the respective models for each argument are created.

Step 5. If the parsing of all arguments are successful, a new MonthlyExpenditureRankingCommand is returned back to LogicManager.

Step 6. The LogicManager executes MonthlyExpenditureRankingCommand#execute().

Step 7. The model is updated with the List of Data from the newly created TrendReport.

Observe that the implementation of mthrank involves the creation of a TrendReport. Not only are the results of this command only specific to a year, the mthrank command is strikingly similar to the expenditure command, except that the sorted results are used to update the DataList in the Model.

4.5.8. View Expenditure Ranking Chart

The view expenditure ranking chart allows the user to view the ranked expenditure trends. This feature is facilitated by AnalyticsFeatureParser, ExpenditureRankingCommandParser, and ExpenditureRankingCommand. The arguments supported by this feature are:

  • Month (optional)

  • Year (optional)

This command is unique in the sense that if month is not specified, the report is only specific to a year. However, if month is specified, the report is specific to both a month and a year. This is different from the other commands that are only specific to a year, or a month and a year. Hence, there is an extra if-condition in the execution loop of the ExpenditureRankingCommand to account for this discrepancy.
Implementation

When the user input the exprank command in the Analytics tab, the following chain of operations occurs:

Step 1. The IchiFundParser will delegate the parsing of the command to AnalyticsFeatureParser if the current active tab is Analytics.

Step 2. The AnalyticsFeatureParser will delegate the parsing of the arguments to ExpenditureRankingCommandParser.

Step 3. ExpenditureRankingCommandParser#parse() will take in a String input consisting of the arguments.

Step 4. This arguments will be tokenized and the respective models for each argument are created.

Step 5. If the parsing of all arguments are successful, a new ExpenditureRankingCommand is returned back to LogicManager.

Step 6. The LogicManager executes ExpenditureRankingCommand#execute().

Step 7. The model is updated with the List of Data from the newly created TrendReport.

4.6. Loans

4.6.1. Adding Loan : add

Overview

This feature allows the user to add a loan in IchiFund. Adding a loan also creates the default values associated with the added loan.

Implementation

The add command is facilitated by the Logic and Model components of the application. Given below is an example usage scenario of how add behaves at each step.

Step 1: The user executes add a/42.15 d/Utilities sd/1 sm/1 sy/2019 ed/31 em/12 ey/2019 to add a loan for utilities with an amount of $42.15 taken on 1st January 2019 and to be returned on 31st December 2019.

Step 2: LogicManager uses IchiFundParser#parserCommand() to parse the input from the user.

Step 3: IchiFundParser determines which command is being used and creates the respective AddLoanCommandParser parser with the user’s input as an argument.

Step 4: AddLoanCommandParser does a validation check on the user’s input before creating and returning an AddLoanCommand with desired Loan as an argument.

Step 5: LogicManager uses AddLoanCommand#execute() to add the Loan and the associated Loans into the Model which is handled by ModelManager. In doing so, it also fetches the LoanId counter tracked by the Model, sets it as the created Repeater's unique id, and increments the counter in the Model by 1.

Step 6: AddRepeaterCommand returns a CommandResult to the LogicManager which is returned back to the user.

4.6.2. Paying Loan : pay

Overview

This feature allows the user to pay off a marked loan in IchiFund by index.

Implementation

The pay command is facilitated by the Logic and Model components of the application. Given below is an example usage scenario of how pay behaves at each step.

Step 1: The user executes pay 2 to pay off the loan in the 2nd index.

Step 2: LogicManager uses IchiFundParser#parserCommand() to parse the input from the user.

Step 3: IchiFundParser determines which command is being used and creates the respective PayLoanCommandParser parser with the user’s input as an argument.

Step 4: PayLoanCommandParser does a validation check on the user’s input before creating and returning an PayLoanCommand with desired Index as an argument.

Step 5: LogicManager uses PayLoanCommand#execute() to delete the Loan from the Model which is handled by ModelManager.

Step 6: PayLoanCommand returns a CommandResult to the LogicManager which is returned back to the user.

4.7. Logging

We are using java.util.logging package for logging. The LogsCenter class is used to manage the logging levels and logging destinations.

  • The logging level can be controlled using the logLevel setting in the configuration file (See Section 4.8, “Configuration”)

  • The Logger for a class can be obtained using LogsCenter.getLogger(Class) which will log messages according to the specified logging level

  • Currently log messages are output through: Console and to a .log file.

Logging Levels

  • SEVERE : Critical problem detected which may possibly cause the termination of the application

  • WARNING : Can continue, but with caution

  • INFO : Information showing the noteworthy actions by the App

  • FINE : Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size

4.8. Configuration

Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: config.json).

5. Documentation

Refer to the guide here.

6. Testing

Refer to the guide here.

7. Dev Ops

Refer to the guide here.

Appendix A: Product Scope

Target user profile:

  • a financially conscious CS undergraduate

    • has a need to track expenditure and income items

    • has a need to limit expenditure to a budget

    • has a need to quickly analyse how to reduce expenditure

    • has a need to track net worth

    • has a need to track loans and money owed

    • prefers desktop apps over other types

    • can type fast

    • prefers typing over mouse input

    • is reasonably comfortable using CLI apps

Value proposition:

  • manage financial transactions faster than a typical mouse/GUI driven app

  • analyse past expenditure, income and balance trends

Appendix B: 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 usage instructions

refer to instructions when I forget how to use the App

* * *

user who is keeping track of transactions

record transactions

* * *

user who is keeping track of transactions

edit transactions

update any errors made when adding transactions

* * *

user who is keeping track of transactions

view transactions

* * *

user who is keeping track of transactions

organize transactions by category

* * *

user who is keeping track of transactions

delete transactions

delete wrongly added or refunded transactions

* * *

user who is keeping track of transaction recurrence

create transaction repeaters

insert new transaction repeater.

* * *

user who is keeping track of transaction recurrence

edit transaction repeaters

update any changes or errors in existing transaction repeaters.

* * *

user who is keeping track of transaction recurrence

delete transaction repeaters

delete no longer relevant transaction repeaters.

* * *

user who is keeping track of transaction recurrence

filter transaction repeaters

quickly find transaction repeaters relevant to a search query.

* * *

user who is keeping track of net worth

set my current wealth

keep track of how much money I have

* * *

user who is keeping track of budget

set my monthly expenditure budget

keep track of how much I can spend for the month

* * *

user who is keeping track of budget

exclude transaction from budget

* * *

user who is keeping track of budget

include transaction to budget

* * *

user who is keeping track of budget

see an overview of my budget

* * *

user who is trying to reduce expenditure

view my monthly expenditure trends

keep track of how much I spend per month

* * *

user who is trying to reduce expenditure

view my expenditure breakdown by category

keep track of how much I spend by category

* *

user who is trying to reduce expenditure

view my expenditure category ranking chart

keep track of my top expenditure categories

* *

user who is trying to reduce expenditure

view my expenditure ranking chart by month

keep track of my top expenditure months

* *

user who is trying to reduce expenditure

view my expenditure ranking chart

keep track of my top expenditures

* *

user who is keeping track of net worth

view my monthly income trends

keep track of how much I earn per month

* *

user who is keeping track of net worth

view my monthly balance trends

keep track of how much I save per month

* *

long-term user who is keeping track of transactions

find transactions by keyword

conveniently search for transactions to edit or review

* * *

user who wants to keep track of money owed

view all loans

see all money i am owed or currently owe others

* * *

user who wants to keep track of money owed

view all positive loans

see all money people owe me

* * *

user who wants to keep track of money owed

view all negative loans

see all money i owe people

* *

user who wants to keep track of money owed

select loans by names/keywords

see all loans by a particular person

* * *

user who wants to keep track of money owed

new loan in the list

add a new loan to keep track of

* * *

user who wants to keep track of money owed

mark loan as loan paid

remove one of the loans

* *

user who wants to keep track of money owed

paid/add by part

some amont of loan is paid off

*

user who wants to keep track of money owed

reminders to pay loans with dates

I can see updates and reminders for urgent loans

{More to be added}

Appendix C: Use Cases

(For all use cases below, the System is the IchiFund and the Actor is the user, unless specified otherwise)

Use case: Set current wealth

MSS

  1. User requests to set current wealth.

  2. System sets current wealth.

  3. System reflects newly set current wealth.

    Use case ends.

Use case: Add transaction item

MSS

  1. User enters information about transaction.

  2. System creates transaction item.

  3. System shows newly updated list of transaction items.

    Use case ends.

Use case: Edit transaction item

MSS

  1. User finds transaction item.

  2. User specifies transaction to be edited and information to edit.

  3. System updates the transaction item.

  4. System shows newly updated list of transaction items.

    Use case ends.

Use case: Delete transaction item

MSS

  1. User finds transaction item.

  2. User specifies transaction to be deleted.

  3. System removes the transaction item.

  4. System shows newly updated list of transaction items.

    Use case ends.

Use case: Change filter of transaction list

MSS

  1. User specifies month, year, category and/or type of the transaction

  2. System updates filter of list of transaction items.

    Use case ends.

Use case: Find transaction item

MSS

  1. User specifies keywords of the transactions to be found.

  2. System updates list of transaction items to show applicable transactions.

    Use case ends.

Use case: Archive transaction item

MSS

  1. User specifies index of transaction to be archived

  2. System moves transaction to archive.

  3. System shows newly updated list of transaction items.

    Use case ends.

Use case: Create transaction repeater

MSS

  1. User requests to create a transaction repeater with specified arguments.

  2. System creates the transaction repeater.

    Use case ends

Use case: Edit transaction repeater

MSS

  1. User requests to edit a transaction repeated with specified arguments.

  2. System updates the transaction repeater.

    Use case ends

Use case: Delete transaction repeaters including all produced transactions

MSS

  1. User requests to delete a transaction repeater together with all its produced transactions.

  2. System removes existing transactions produced from transaction repeater.

  3. System removes transaction repeater.

    Use case ends

Use case: Filter transaction repeaters

MSS

  1. User requests to find transaction repeaters by specified fields.

  2. System filters existing transaction repeaters against specified fields.

  3. System shows filtered transaction repeaters.

    Use case ends

Use case: Set monthly expenditure budget

MSS

  1. User requests to set the monthly expenditure budget.

  2. System set the monthly expenditure budget.

    Use case ends.

Use case: Add loan

MSS

  1. User requests to add a new loan with name, amount and date by.

  2. System parses request to retrive details.

  3. System adds new loan to list.

  4. System updates list and displays what was added.

    Use case ends

MSS

  1. User requests to search for all loans, with search keywords.

  2. System parses and decides the request search constrains.

  3. System displays seelected search results.

    Use case ends

Use case: Mark loans as part done

MSS

  1. User requests to mark a lone as paid off.

  2. System removes existing loan from the list.

  3. System updates the total loan value.

  4. System shows the new total loan value, with the new paid off loan.

    Use case ends

Extensions

  • 1a. System detect an invalid budget amount.

    • 1a1. System shows an error message.

      Use case ends.

Use case: View expenditure trend

MSS

  1. User requests to view expenditure trend over a period.

  2. System retrieves expenditure entries for each month in the indicated period.

  3. System totals up expenditure for each month in the indicated period.

  4. System shows the expenditure totals for each month in the indicated period.

    Use case ends.

Use case: View expenditure breakdown by category

MSS

  1. User requests to view expenditure breakdown by category over a period.

  2. System retrieves expenditure entries for each category in the indicated period.

  3. System totals up expenditure for each category in the indicated period.

  4. System shows the expenditure totals for each category in the indicated period.

    Use case ends.

Use case: View expenditure ranking chart

MSS

  1. User requests to view expenditure ranking chart over a period.

  2. System retrieves all expenditure entries in the indicated period.

  3. System sorts expenditure entries in the indicated period.

  4. System shows the sorted expenditure entries in the indicated period.

    Use case ends.

Appendix D: Non Functional Requirements

  1. Should work on any mainstream OS as long as it has Java 11 or above installed.

  2. Should be able to hold up to 1000 transactions without a noticeable sluggishness in performance for typical usage.

  3. 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 faster using commands than using the mouse. {More to be added}

Appendix E: Glossary

Mainstream OS

Windows, Linux, Unix, OS-X

Appendix F: Product Survey

DBS digibank SG

Author: DBS Bank Ltd

Pros:

  • Links to bank account and PayLah!

  • Shows visual summary of cashflow

  • Automatically categorizes items

Cons:

  • Does not use CLI

  • Does not allow for customisation of transactions beyond categories

  • Does not have a budgeting feature

Appendix G: Instructions for Manual Testing

Given below are instructions to test the app manually.

These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.

G.1. Launch and Shutdown

  1. Initial launch

    1. Download the jar file and copy into an empty folder

    2. Double-click the jar file
      Expected: GUI shows set of sample transactions. Filter title set to current month and year of system time. Window size is fixed at 960x720px.

    3. Click on repeater tab Expected: Shows the GUI

  2. Launch with corrupted config.json and/or preferences.json

    1. Manually edit config.json and/or preferences.json by adding "aaa" to start of file.

    2. Perform same steps as above test case.

G.2. Tab switching

  1. Tab switching by shortcut key

    1. Press Ctrl+2.
      Expected: GUI shows repeaters tab.

    2. Press Ctrl+3.
      Expected: GUI shows budgets tab.

    3. Press Ctrl+4.
      Expected: GUI shows loan tab.

    4. Press Ctrl+5.
      Expected: GUI shows analytics tab.

    5. Press Ctrl+1.
      Expected: GUI shows transaction tab.

  2. Tab switching by command

    1. Enter command rep.
      Expected: GUI shows repeaters tab.

    2. Enter command budget.
      Expected: GUI shows budgets tab.

    3. Enter command loan.
      Expected: GUI shows loan tab.

    4. Enter command analytics.
      Expected: GUI shows analytics tab.

    5. Enter command tx.
      Expected: GUI shows transaction tab.

  3. Tab switching by mouse click

    1. Click on repeater tab.
      Expected: GUI shows repeaters tab.

    2. Click on budget tab.
      Expected: GUI shows budgets tab.

    3. Click on loan tab.
      Expected: GUI shows loan tab.

    4. Click on analytics tab.
      Expected: GUI shows analytics tab.

    5. Click on transaction tab.
      Expected: GUI shows transaction tab.

  4. Separate parsing for different tabs

    1. Enter add in transaction tab.
      Expected: Console shows error message for AddTransactionCommand.

    2. Go to repeaters tab and enter add.
      Expected: Console shows error message for AddRepeaterCommand.

    3. Go to budgets tab and enter add.
      Expected: Console shows error message for AddBudgetCommand.

    4. Go to loan tab and enter add.
      Expected: Console shows error message for AddLoanCommand.

    5. Go to analytics tab and enter add.
      Expected: Console shows error message for unrecognised command.

G.3. Filtering transactions

  1. Filter title changes correctly

    1. Enter a filter command with all arguments (e.g. filter m/1 y/2008 c/food ty/exp)
      Expected: Filter title contains information of all arguments (e.g. January 2008 Expenditure - Food)

    2. Enter a filter command with only month and year arguments (e.g. filter m/2 y/2009)
      Expected: Filter title retains information on category and transaction type, and updates to show correct month and year.

    3. Enter filter c/!all ty/!all
      Expected: Filter title now only contains information about month and year.

  2. Filters transactions correctly

    1. Prerequisites: No transactions from January 2001 and 2002

    2. Enter add de/a a/1 c/a d/1 m/1 y/2001 ty/exp

    3. Enter add de/b a/1 c/b d/1 m/1 y/2001 ty/exp

    4. Enter add de/c a/1 c/a d/1 m/1 y/2001 ty/in

    5. Enter filter m/1 y/2002
      Expected: No transactions shown

    6. Enter filter y/2001
      Expected: All 3 transactions added shown

    7. Enter filter ty/exp
      Expected: Transactions with descriptions "a", "b" shown

    8. Enter filter c/a
      Expected: Transaction with description "a" shown

    9. Enter filter ty/!all
      Expected: Transactions with descriptions "a", "c" shown

  3. Invalid Month

    1. Enter filter m/13
      Expected: Console shows error message.

    2. Enter filter m/aaa
      Expected: Console shows error message.

  4. Invalid Year

    1. Enter filter y/1999
      Expected: Console shows error message.

    2. Enter filter y/10000
      Expected: Console shows error message.

  5. Invalid TransactionType

    1. Enter filter ty/xxx
      Expected: Console shows error message.

  6. Invalid Category

    1. Enter filter c/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
      Expected: Console shows error message.

    2. Enter filter c/!!!
      Expected: Console shows error message.

G.4. Adding a transaction

  1. Transaction correctly created

    1. Add any valid transaction using add with all fields specified
      Expected: GUI changes context if necessary, and transaction added is shown with correct fields

  2. Optional arguments correctly filled

    1. Enter filter m/3 y/2005 c/food ty/in

    2. Enter add a/1 de/z
      Expected: New transaction("z") appears in the same list, marked as income item with category as "FOOD". Date of transaction is X March 2005, where X is the current day of the month.

    3. Enter filter ty/!all

    4. Enter add a/1 de/y
      Expected: New transaction("y") appears in the same list. Similar to "z", but marked as expenditure.

    5. Enter filter c/!all

    6. Enter add a/1 de/x
      Expected: New transaction("x") appears in the same list. Similar to "y", but under category "UNCATEGORISED".

  3. Automatic sorting of transaction

    1. Prerequisite: Current list of transactions show no transactions.

    2. Enter add de/a a/1 d/3

    3. Enter add de/b a/1 d/2
      Expected: New transaction("b") appears at the bottom of the transaction list.

    4. Enter add de/c a/1 d/4
      Expected: New transaction("c") appears at the top of the transaction list.

    5. Enter add de/d a/1 d/4 c/z
      Expected: New transaction("d") appears at the second index.

    6. Enter add de/e a/1 d/4 c/a
      Expected: New transaction("e") appears at the top of the transaction list. Resulting list: "e", "c", "d", "a", "b".

  4. Filter switch when adding transaction

    1. Prerequisites: Current filter is "November 2019 Expenditure - Food"

    2. Enter add de/a a/1 y/2018
      Expected: Filter changes to "November 2018 Expenditure - Food"

    3. Enter add de/a a/1 m/10
      Expected: Filter changes to "October 2018 Expenditure - Food"

    4. Enter add de/a a/1 c/a
      Expected: Filter changes to "October 2018 Expenditure"

    5. Enter add de/a a/1 ty/in
      Expected: Filter changes to "October 2018"

  5. Invalid Description

    1. Enter add a/1 de/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
      Expected: Console shows error message.

    2. Enter add a/1 de/!!!
      Expected: Console shows error message.

  6. Invalid Amount

    1. Enter de/a a/a
      Expected: Console shows error message.

    2. Enter de/a a/999999
      Expected: Console shows error message.

    3. Enter de/a a/-1
      Expected: Console shows error message.

  7. Invalid Day or Date

    1. Enter add a/1 de/a d/32
      Expected: Console shows error message.

    2. Enter add a/1 de/a d/31 m/11
      Expected: Console shows error message.

    3. Enter add a/1 de/a d/30 m/2
      Expected: Console shows error message.

    4. Enter add a/1 de/a d/29 m/2 y/2003
      Expected: Console shows error message.

G.5. Editing a transaction

  1. Transaction correctly edited

    1. Add any valid transaction using edit with any fields specified
      Expected: GUI changes context if necessary, and transaction edited is shown with correct fields

  2. Filter switch when editing transaction

    1. Prerequisites: Current filter is "November 2019 Expenditure - Food". There is at least 1 transaction shown.

    2. Enter edit 1 y/2018
      Expected: Filter changes to "November 2018 Expenditure - Food"

    3. Enter edit 1 m/10
      Expected: Filter changes to "October 2018 Expenditure - Food"

    4. Enter edit 1 c/a
      Expected: Filter changes to "October 2018 Expenditure"

    5. Enter edit 1 ty/in
      Expected: Filter changes to "October 2018"

  3. Invalid Index

    1. Enter edit 0 de/a
      Expected: Console shows error message.

    2. Prerequisite: less than 20 items shown in list of transactions.

    3. Enter edit 20 de/a
      Expected: Console shows error message.

G.6. Deleting a transaction

  1. Valid deletion of transaction

    1. Prerequisite: at least 2 people shown in list of transactions

    2. Enter delete 2
      Expected: Second transaction in list of items deleted.

  2. Invalid Index

    1. Enter delete 0
      Expected: Console shows error message.

    2. Enter delete x
      Expected: Console shows error message.

    3. Prerequisite: less than 20 items shown in list of transactions.

    4. Enter delete 20
      Expected: Console shows error message.

G.7. Adding a repeater

  1. Adding repeaters creates associated transactions

    1. Go to the repeaters tab.

    2. Add a repeater using any valid add command.
      Expected: Shows newly created repeater with correct fields.

    3. Go to the transaction tab and use filter command to find newly added transactions.
      Expected: Shows newly created transactions with correct fields for appropriate filters.

  2. Boundary value arguments

    1. Add a repeater with end date later than start date by exactly 60 months.
      Expected: Repeater successfully added.

  3. Invalid command arguments

    1. Go to the repeaters tab.

    2. Add a repeater with end date earlier than start date.
      Expected: Error message displayed on console.

    3. Add a repeater with end date later than start date by >60 months.
      Expected: Error message displayed on console.

    4. Add a repeater with both month offsets ignored.
      Expected: Error message displayed on console.

  4. Duplicate repeaters

    1. Add any valid repeater.

    2. Add a repeater with the exact same field.
      Expected: Error message displayed on console.

G.8. Editing a repeater

  1. Editing repeaters edits associated transactions

    1. Go to the repeaters tab.

    2. If required, add a repeater.

    3. Edit a repeater using a valid edit command (e.g. edit 1 a/0.41).
      Expected: Shows newly created repeater with correct fields.

    4. Go to the transaction tab and use filter command to find newly edited transactions.
      Expected: Shows newly edited transactions with correct fields for appropriate filters.

G.9. Deleting a repeater

  1. Deleting repeaters delete associated transactions

    1. Go to the repeaters tab.

    2. If required, add a repeater.

    3. Delete a repeater using a valid delete command (e.g. delete 1).
      Expected: GUI no longer shows deleted repeater.

    4. Go to the transaction tab and use filter command to find associated transactions.
      Expected: Associated transactions cannot be found.

G.10. Adding and modifying a Loan

  1. Adding a Loan while other loans are present

    1. Prerequisites: List all loans. Multiple loans in the list.

    2. Enter `add a/420.42 n/Felix Kjellberg sd/12 sm/12 sy/2019 ed/23 em/2 ey/2020 de/Borrowed for apple earpods `
      Expected: Loan is added to the list. Details of the added loan shown in the status message.

    3. Enter add a/220
      Expected: Loan is added with default values. Loan Details shown in the status message. Status bar remains the same.

    4. Enter add n/Felix Expected: No amount given error is shown. No Loan is added to the list. The status shows correct format to enter.

    5. Other incorrect delete commands to try: add, add a/24 n/123
      Expected: Similar to previous.

  2. Editing Existing loans

    1. Prerequisites: List all loans. Multiple loans in the list.

    2. Enter 'edit 2 a/220 n/NewName sd/12 ey/2012'
      Expected: First loan on the list is changed to new assigned values. No other loans or entries are changed.

    3. Enter 'edit 1 n/NewName sd/12 ey/2012 d/New Description for the Loan'
      Expected: First loan on the list is changed to new assigned values including description. No other loans or entries are changed. Other values are derived from existing entry.

    4. Enter 'edit a/220 n/NewName sd/12 ey/2012'
      Expected: Wrong format for edit command is shown in status. No Loan is edited.

    5. Other incorrect delete commands to try: edit, edit 5
      Expected: Similar to previous.

  3. Paying off Existing loans

    1. Prerequisites: List all loans. Multiple loans in the list.

    2. Enter 'pay 1'
      Expected: First loan on the list is removed from list. No other loans or entries are changed. Status bar indicates deletion.

    3. Enter 'pay a/220'
      Expected: Wrong format for pay command is shown in status. No Loan is removed. Status shows correct format of command.

    4. Other incorrect delete commands to try: pay, pay a
      Expected: Similar to previous.

G.11. Saving data

  1. Launch with corrupted fundbook.json

    1. Manually edit and save data/fundbook.json, corrupting data by entering "aaaaa" at start of file.

    2. Double-click the jar file.
      Expected: Shows the GUI with no data items. Window size is fixed at 960x720px.

  2. Relaunch after changing list of transactions

    1. Go to the transaction tab.

    2. Add a transaction using the add command and exit IchiFund.

    3. Double-click the jar file.

    4. If necessary, use filter command to find newly added transaction.
      Expected: Shows the GUI with newly added transaction.

    5. Edit the transaction using the edit command and exit IchiFund.

    6. Double-click the jar file.

    7. If necessary, use filter command to find newly added transaction.
      Expected: Shows the GUI with newly edited transaction.

    8. Delete the transaction using the delete command and exit IchiFund.

    9. Double-click the jar file.

    10. If necessary, use filter command to find deleted transaction.
      Expected: Shows the GUI without the deleted transaction.

  3. Relaunch after changing list of repeaters

    1. Go to the repeaters tab.

    2. Add a repeater using the add command.

    3. Exit IchiFund.

    4. Double-click the jar file.

    5. Go to repeaters tab.
      Expected: GUI shows newly added repeater.

    6. Go to the repeaters tab.

    7. Edit a repeater using the edit command.

    8. Go to the transaction tab and use filter command to find newly edited transactions.
      Expected: Shows newly edited transactions for appropriate filters.

    9. Exit IchiFund.

    10. Double-click the jar file.

    11. Go to repeaters tab, or search for newly edited transactions in transaction tab.
      Expected: In repeaters tab, shows newly edited repeater; in transaction tab, shows newly edited transactions for appropriate filters.

    12. Go to the repeaters tab.

    13. Add a repeater using the delete command.

    14. Exit IchiFund.

    15. Double-click the jar file.

    16. Go to repeaters tab.
      Expected: In repeaters tab, deleted repeater is not shown.

  4. Relaunch after changing list of budgets

    1. Go to the budget tab.

    2. Add a budget using the add command and exit IchiFund.

    3. Double-click the jar file.

    4. Go to the budget tab.
      Expected: Shows the GUI with newly added budget. Budget progress is the same.

    5. Delete a budget using the delete command and exit IchiFund.

    6. Double-click the jar file.

    7. Go to the budget tab.
      Expected: GUI does not show deleted budget.

  5. Relaunch after changing list of loans

    1. Go to the loan tab.

    2. Add a loan using the add command and exit IchiFund.

    3. Double-click the jar file.

    4. Go to the loan tab.
      Expected: Shows the GUI with newly added loan.