By: Team T14-4      Since: Sep 2019      Licence: MIT

1. Setting up

Refer to the guide here.

2. Design

2.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 .puml files used to create diagrams in this document can be found in the diagrams folder. Refer to the Using PlantUML guide to learn how to create and edit diagrams.

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 its 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.

2.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, ExpenseListPanel, 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.

2.3. Logic component

LogicClassDiagram
Figure 5. Structure of the Logic Component

API : Logic.java

  1. Logic uses the MymParser 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 an expense).

  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
The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

2.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 a BudgetList object that represents the user’s budgets.

  • stores an ExpenseList object that represents the user’s untagged expenses.

  • stores an ExchangeData object that represents the foreign exchange rates for conversion of currencies.

  • exposes an unmodifiable ObservableList<Expense> and an unmodifiable ObservableList<Budget> that can be 'observed' e.g. the UI can be bound to either list so that the UI automatically updates when the data in the list change.

2.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 Budget objects in json format and read it back.

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

  • can read Exchange objects in json format.

2.6. Common classes

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

3. Implementation

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

3.1. Budget Feature

3.1.1. Overview

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

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

3.1.2. Implementation

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

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

AddBudgetActivityDiagram

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

AddExpenseActivityDiagram

Given below is a class diagram of a Budget.

BudgetClassDiagram

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

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

BudgetObjectDiagram

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

3.1.3. Design Consideration

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

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

  • Alternative 1: Have a master expense list to store all expenses created and a budget list that consist of an internal expense list that stores copies of the expenses from master expense list that fall into the budget. In this option, commands that affect expenses, will require an update in the master expense list and the expense lists inside budgets affected.

    • Pros: Easy to implement, easy to keep track of a overall expenses.

    • Cons: Multiple objects of the same expense. An update to an expense in the overall expense list will require a same update to the same expense located in the budget. May result in bugs when commands affect expenses.

  • Alternative 2: Have a default expense list that stores only expenses that do not fall into a budget, and a budget list that consist of an internal expense list that stores the expenses that fall into a budget when the expense is added or edited. In this option, there is only 1 copy of any expense created by the user. Any edit or delete of an expense affects directly to the original expense object.

    • Pros: Achieve a single source of truth. Does not introduce possible bugs that may be present if there were multiple copies of the same expense.

    • Cons: More complex to implement. In order to view all expenses in the app, the program will have to loop through the default expense list and the expense lists of every single budget.

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

3.2. AutoComplete Feature

3.2.1. Implementation

Autocomplete is facilitated by several parts. The logic part is implemented through java.seedu.address.logic.search package which contains AutoComplete and BinarySearch.

The model is constructed through java.seedu.address.model.autocomplete which contains AutoCompleteModel and Word.

The Ui part is implemented through java.seedu.address.ui.QueryCard on top of CommandBox.

Given below is an example usage scenario and how the autocomplete mechanism behaves at each step. (p.s. details are omitted)

Step 1. The user launches MYMorise and the user will be prompted to enter a command as shown in the command box.

Step 2. User enter a and the listener is triggered. Then AutoComplete#initAc() and AutoComplete#getSuggestions() is invoked.

Step 3. initAc() calls AutoComplete#readWordsFromFile() which reads the vocabulary from our local dictionary to get the database and then construct an AutocompleteModel with the vocabulary read.

Step 4. getSuggestions(input) calls AutocompleteModel#allMatches() which utilises the improved version of binary search algorithm BinarySearch. The algorithm will return the first and last index of potential matched results. Since the result is based on a pre-order for sorting, all the words inside this range will be the qualified ones.

Step 5. The listview of QueryCard will be updated based on the words and weights given and attached to the TextField.

The following sequence diagram shows how autocomplete operation works:

AutocompleteSequenceDiagram

The following activity diagram summarizes what happens when a user enter something new.

AutocompleteActivityDiagram

3.2.2. Design Considerations

Aspect: How Autocomplete works

In terms of the retrieving suggestion list, an enhanced binary search algorithm is used. Since a word (which represents a autocomplete term) has a name and weight, the default "vocabulary" will be first sort based on weight and for same weight, sort alphanumerically.

In terms of replacing the target term to the TextField, 2 approaches are proposed

  • Approach 1 (current choice): 2 listeners were added. 1) 1st listener for TextFormatter, this is especially utilised to retrieving the updated cursor position, which is where it outperforms. 2) 2nd listener for TextInputControl to detect the text change of TextField. Then combined with previously returned caret position, we can replace the corresponding position with target term (the one user selected)

  • Approach 2. 1 listener for caretProperty is added to detect the change of position of caret (i.e., cursor). This approach is simpler with regard to logic but more complicated during implementation. Since caret position change does not necessarily mean textField change, therefore extra check would be required, also resulting in potential inaccuracy.

In terms of user interaction, different listeners are added for different valid actions (e.g. press TAB, ENTER and navigate using UP and DOWN) to make user benefit by typing faster.

3.3. History Feature

3.3.1. Implementation

History is mainly facilitated by CommandHistory with HistoryPointer. When the app starts, a CommandHistory instance is created and any command executed (no matter valid or not) will be saved to a list of history commands. And when the user calls the history, the overall history list will display on the resultDisplayPanel. And when user press F3 and F4 to navigate through the history list, the HistoryPointer will point to corresponding history.

Similar to Section 3.1, the history displayed on textField is facilitated by KeyEventListener. When the keyinput event of F3 or F4 is triggered, it will navigate to previous input and next input correspondingly.

The following class diagram illustrates the interaction between historyCommand and other parts:

HistoryClassDiagram

The following sequence diagram illustrates the flow of how history commands works:

HistorySequenceDiagram

3.4. Currency Conversion

3.4.1. Implementation

The Currency conversion is achieved by having a default base currency that all expenses and budgets use if one is not specified. The expenses that are stored with a different currency can be converted from the base currency and back. Every time a currency is specified, the present day exchange rate is stored with the expense. This is to ensure that the expense value is timeless.

This was implemented in the java.seedu.address.model.exchangedata package, which contains ExchangeDataSingleton, ExchangeData, and Rates. These classes facilitate retrieval of exchange rates that will be requested from various parts of the app, namely Expense and Budget.

Step 1 The foreign currency exchange rates are downloaded for the app to use from ExchangeRatesAPI.io using their endpoint https://api.exchangeratesapi.io/latest?base=SGD. The endpoint returns the data in JSON format, which works well with the existing JSON based storage used for Expense and Budget. This was implemented in the java.seedu.address.commons.utils package containing HttpsClientUtil which facilitates the Asynchronous calls to the endpoint to update the local copy of the foreign currency exchange rates upon app startup.

Step 2 The JSON response is persisted on disk. A default data-set of exchange rates will be generated at runtime (but not stored) in the case of unstable or no internet access if one is not yet present. If one was present however a more recent one could not be downloaded, the existing data will be reused.

Step 3 If the exchange data is present as a JSON, it will first be loaded into its JSON reflection class JsonAdaptedExchangeData which depends on JsonAdaptedRates. These classes assist in the conversions of the JSON to the Model Class ExchangeData.

Presently, ExchangeData is also stored in the StorageManager which was intended to be used to store multiple instances of ExchangeData to load historical exchange rates when the user does an edit, however this proved to be infeasible to implement within the course of the project.

Step 4 The ExchangeDataSingleton is updated with the new ExchangeData using the ExchangeDataSingleton#updateInstance. The reason for using the Singleton pattern in this case was to ensure that one and only one instance of ExchangeData is being referenced to retrieve data at any point in time. Since it is also required to be accessed by Expense and Budget.

Step 5 Conversions are done in Expense#getConvertedAmount for conversion back into the base currency (SGD) and Expense#getConvertedAmount(Currency currency) for conversions to any other currency. As most transactions in the app that require the conversion of currency involve an expense (including recomputing amountLeft of Budget), the computation is done in the expense. The following are the instance where the currency is converted:

  • Whenever an expense is displayed on the ExpenseCard or CommandResult, its converted value will be computed and displayed together with its conversion rate and original amount.

The following sequence diagram shows how currency conversion works:

CurrencyConversionSequenceDiagram

3.4.2. Design Consideration

There were 3 main design choices we had to choose from for the implementation of the Currency Conversion Feature.

  • Alternative 1: Do not store currency rates when expenses are added with a selected currency and simply store the currency.

    • Pros: Easy to implement, recompute the amount of the expense based on the present day currency exchange rate.

    • Cons: If there was a crash in any currency, the expense amount will no longer be timeless. For instance, if an expense of of 10 MYR was stored today and was converted to 3 SGD (converted at 3.33), then the exchange rate became 2.0 the following day, the budget would reflect the amount left wrongly when it was recomputed the next day.

  • Alternative 2: Persist all the exchange rates to file every time the app is launched to ensure that the user’s expenses are computed based on the exchange rate that was on that specific day. The specific exchange rate used is not stored in the expense itself.

    • Pros: Achieve timeless expense which will provide the most accurate values when computing the budget amount left.

    • Cons: Slightly harder to implement as there are multiple sources for exchange rate data based on dates. This will also bloat the amount of space requirement of the app as time persists.

  • Alternative 3: Store the specific exchange rate used together with the expense whenever it is added, update the exchange rates daily and only persist the latest rates.

    • Pros: Achieve timeless expense which will provide the most accurate values when computing the budget amount left, without the need to store historical exchange rates. Reduced space used and single source of truth for computing exchange rates.

    • Cons: Expenses added in the past that have their currencies changed will not be able to use the exchange rate of that specific day.

Alternative 3 was chosen as it was a balance between the cons across all 3 considerations, and the timelessness of an expense carries more weight than the unlikely event that the user would need to alter the currency of a past expense.

3.5. 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 3.6, “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

3.6. Configuration

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

4. Documentation

Refer to the guide here.

5. Testing

Refer to the guide here.

6. Dev Ops

Refer to the guide here.

Appendix A: Product Scope

Target user profile:

  • has a need to manage expenses,

  • requires categorization of expenses,

  • prefer desktop apps,

  • prefers CLI type interfaces.

Value proposition:

  • manage expenses faster than a typical mouse/GUI driven app.

  • easily view spending metrics.

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…​

Basic Functionality

* * *

new user

see usage instructions

refer to instructions when I forget how to use the App

* * *

user

create an expense

* * *

user

create an expense with a tag

identify my expenses by tags

* * *

user

retrieve all expenses

review my spending

* * *

user

find an expense name

locate a specific expense without having to go through the entire list

* * *

user

edit an expense

change the expense amount, date or tag

* * *

user

delete an expense

* *

user

terminate a recurring expense

* *

user

retrieve all expenses for today

review my spending for the day

* *

user

create a recurring expense

don’t have to input recurring expenses every time

* *

user

retrieve list of all recurring expenses

view all my recurring expenses

* *

user

retrieve all expenses for the week

review my spending for the week

* *

user

retrieve all expenses for the month

review my spending for the month

* *

user

retrieve all expenses for the year

review my spending for the year

Budgeting

* * *

user

set a budget for a period

track my expenses according to the budget amount

* * *

user

delete a budget

remove a budget that is not needed anymore

* * *

user

edit a budget

change my budget details

* * *

user

view a list of my budgets

see what budgets i have already set

* * *

user

view a budget

know my expenses and how much I have left to spend in the budget

* *

user

be notified every time I add an expense if I have less than 50% of my budget left

notify myself that i may be spending too much according to my budget

UI

* * *

user

view in a pie chart expenditure breakdown by tag

view my expenses easily with visual aid

* * *

user

view in a pie chart how much of my budget is spent/available for the current month

view how much of my budget is left

* *

user

view in a bar chart my expenditure

visualise my spending habits

Inputs

* *

user

recall commands previously used in session

improve my productivity

*

user

command autocomplete suggestions

improve my productivity

Multi-Currency

* * *

user

set my default currency for tracking

* *

user

store expenses in a specific currency

track expenses in a different currency

* *

user

automatically convert the expense to my default currency

track expenses of different currency in terms of my default currency

{More may be added}

Appendix C: Use Cases

Note: For all use cases below, the System is MYMorise(MYM), the Actor is the user and the Precondition is MYMorise is running, unless specified otherwise).

Inputs specified in a square bracket i.e [input] are optional inputs from the user.

C.1. UC01 - Get Help

Guarantees:

  • The list of all commands will be shown.

MSS

  1. User requests for help.

  2. MYM responds with the list of all commands.

    Use case ends.

C.2. UC02 - Create an expense

Guarantees:

  • A new expense will be added into MYM if valid data were specified.

MSS

  1. User requests to add an expense specifying data.

  2. MYM creates and stores the expense with the specified data.

    Use case ends.

Extensions

  • 1a. MYM detects an error in entered data.

    • 1a1. MYM informs the user what data was invalid.

      Use case ends.

C.3. UC03 - Create a recurring expense

Guarantees:

  • A new recurring expense with will be added into MYM if valid data were specified.

  • A single expense with will be added into MYM if valid data were specified.

MSS

  1. User requests to add a recurring expense specifying data.

  2. MYM creates and stores the expense with the specified data .

    Use case ends.

Extensions

  • 1a. MYM detects an error in entered data.

    • 1a1. MYM informs the user what data was invalid.

      Use case ends.

C.4. UC04 - Retrieve all expenses

Preconditions: MYMorise is running, there is at least 1 expense stored. Guarantees:

  • A list of all expenses is shown.

MSS

  1. User requests to see all expenses.

  2. MYM shows all expenses.

    Use case ends.

Extensions

  • 1a. User requests to see all expenses made today.

    • 1a1. MYM shows a list of all expenses made today.

      Use case ends.

  • 1b. User requests to see all expenses made for the current week.

    • 1b1. MYM shows a list of all expenses made for the current week.

      Use case ends.

  • 1c. User requests to see all expenses made for the current month.

    • 1c1. MYM shows a list of all expenses made for the current month.

      Use case ends.

  • 1d. User requests to see all expenses made for the specified date range.

    • 1d1. MYM shows a list of all expenses made for the the specified date range.

      Use case ends.

C.5. UC05 - Retrieve all recurring expenses

Preconditions: MYMorise is running, there is at least 1 recurring expense stored.
Guarantees:

  • A list of all recurring expenses is shown.

MSS

  1. User requests to see for all recurring expenses.

  2. MYM shows a list of all expenses made for the day.

    Use case ends.

C.6. UC06 - Find an expense

Preconditions: MYMorise is running, there is at least 1 recurring expense stored.
Guarantees:

  • A list of all expenses containing the specified keyword if any were found

MSS

  1. User requests for all expenses containing a keyword.

  2. MYM shows a list of all expenses containing the keyword.

    Use case ends.

Extensions

  • 1a. No expenses contain the keyword specified.

    • 1a1. MYM informs user that no matching expenses were found.

      Use case ends.

C.7. UC07 - Update an expense

Preconditions: MYMorise is running, there is at least 1 expense stored.
Guarantees:

  • The expense selected for editing will be updated with the new data.

MSS

  1. User requests to see all expenses (UC04).

  2. User reviews the list of expenses.

  3. User requests to update an expense from the list and provides the new data.

  4. MYM updates the selected expense with the new data.

    Use case ends.

Extensions

  • 2a. User decides not to edit the expense.

    Use case ends.

  • 2b. User could not locate the expense to be edited.

    Use case resumes at step 1.

  • 3a. MYM detects an error in entered data.

    • 3a1. MYM informs the user what data was invalid.

      Use case resumes at step 2.

C.8. UC08 - Delete an expense

Preconditions: MYMorise is running, there is at least 1 expense stored.
Guarantees:

  • The expense specified for deletion will be deleted.

MSS

  1. User requests to see all expenses (UC04).

  2. User reviews the list of expenses.

  3. User requests to delete the expense with a specific index from the list.

  4. MYM deletes the expense with the specified index.

    Use case ends.

Extensions

  • 2a. User decides not to delete the expense.

    Use case ends.

  • 2b. User could not locate the expense to be deleted.

    Use case resumes at step 1.

  • 3a. MYM detects an error in entered data.

    • 3a1. MYM informs the user what data was invalid.

      Use case resumes at step 2.

C.9. UC09 - Delete a recurring expense

Preconditions: MYMorise is running, there is at least 1 recurring expense stored.
Guarantees:

  • The recurring expense specified for deletion will be deleted.

MSS

  1. User requests to see all recurring expenses (UC05)

  2. User reviews the list of recurring expenses.

  3. User requests to delete the recurring expense with a specific index from the list.

  4. MYM deletes the expense with the specified index.

    Use case ends.

Extensions

  • 2a. User decides not to delete the recurring expense.

    Use case ends.

  • 3a. MYM detects an error in entered data.

    • 3a1. MYM informs the user what data was invalid.

      Use case resumes at step 2.

C.10. UC10 - Set a budget for a specific period

Guarantees:

  • The budget will be set to a specified amount for a specific period.

MSS

  1. User requests to set the budget, specifying the amount, the start date and the end date of the period.

  2. MYM sets the budget for the amount and period specified.

    Use case ends.

Extensions

  • 1a. MYM detects an error in the entered data.

    • 1a1. MYM requests for the correct data.

    • 1a2. User enters new data.

    • Steps 1a1-1a2 are repeated until the data are correct.

    • Use case resumes from step 2.

  • 1b. MYM detects a budget period clash.

    • 1b1. MYM requests for different period dates.

    • 1b2. User enters new data.

    • Steps 1b1-1b2 are repeated until the dates do not clash with existing budget periods.

    • Use case resumes from step 2.

C.11. UC11 - Visualize funds left for current month

Preconditions: MYMorise is running, A budget should have been set (UC10)
Guarantees:

  • Visualization of funds left for current month will be updated.

MSS

  1. User creates an expense (UC02) OR User updates an expense (UC07) OR User deletes an expense (UC08)

  2. MYM updates the visualization of funds left for the month.

    Use case ends.

C.12. UC12 - Notify when funds are < 50%

Preconditions: MYMorise is running, A budget should have been set (UC10)

Guarantees:

  • The user is notified that funds are low, if resulting budget balance is < 50%.

MSS

  1. User adds an expense (UC02)

    Use case ends.

Extensions

  • 1a. Resulting budget balance is < 50%

    • 1a1. MYM informs the user the new budget balance and that funds are running low.

      Use case ends.

C.13. UC13 - Visualize expenditure

Guarantees:

  • Visualisation of expenditure will be shown if there is sufficient data.

MSS

  1. User requests for all expenses

  2. MYM updates visualization based on expenses requested in Step 1.

    Use case ends.

Extensions

  • 2a. There are no expenditures.

    • 2a1. MYM informs User that there is not enough data to visualise expenditure breakdown by tag.

      Use case ends.

C.14. UC14 - Visualize expenditure breakdown by tag

Guarantees:

  • Breakdown by tag visualisation will be shown if there is sufficient data.

MSS

  1. User creates an expense (UC02) OR User updates an expense (UC07) OR User deletes an expense (UC08)

  2. MYM updates the breakdown of expenditure by tag visualisation.

    Use case ends.

Extensions

  • 2a. There are no expenditures.

    • 2a1. MYM informs User that there is not enough data to visualise expenditure breakdown by tag.

      Use case ends.

C.15. UC15 - Recall commands previously used in current session

Guarantees:

  • Commands used previously can be cycled through by the user if there are previously used commands in the current session.

MSS

  1. User request for previous command.

  2. Step 1 is repeated till user found the target command.

    Use case ends.

Extensions

  • 1a. No prior commands entered.

    Use case ends.

C.16. UC16 - Set default currency of expenses

Guarantees:

  • MYMorise will convert display amounts in the specified currency, if the specified currency is valid..

MSS

  1. User requests to set the default currency

  2. MYM converts all expenses into the defualt currency and updates the display.

    Use case ends.

Extensions

  • 1a. The specified currency is not valid.

    • 1a1. MYM informs the user that the currency specified is not valid.

      Use case ends.

C.17. UC17 - Create expense with specific currency

Guarantees:

  • A new expense with the specified currency will be added into MYM if the specified data is valid.

MSS

  1. User requests to create an expense specifying required data.

  2. MYM creates and stores the expense with the specified data.

    Use case ends.

Extensions

  • 1a. MYM detects an error in entered data.

    • 1a1. MYM informs the user what data was invalid.

      Use case ends.

C.18. UC18 - Automatically convert expenses in foreign currencies to default currency

Preconditions: Preconditions: MYMorise is running, at least 1 expense stored in foreign currency

Guarantees:

  • Expense will display expense amount in both default and foreign currencies but all computations will default converted amount.

MSS

  1. User creates an expense with specific currency

  2. User requests for all expenses

  3. MYM shows list of expenses. Expenses with foreign currencies are shown together with their default currency converted amounts.

    Use case ends.

{More may be added}

Appendix D: Non Functional Requirements

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

  2. (Capacity, Performance) Should be able to hold up to 10000 expenses without a noticeable sluggishness in performance for typical usage.

  3. (Scalability) Should be able to handle expense amounts up to 1012.

  4. (Process) Project should be production ready by 11th November 2019.

{More to be added}

Appendix E: Glossary

Mainstream OS

Windows, Linux, Unix, OS-X

Appendix F: Product Survey

Product Name

Author: …​

Pros:

  • …​

  • …​

Cons:

  • …​

  • …​

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: Shows the GUI with a set of sample contacts. The window size may not be optimum.

  2. Saving window preferences

    1. Resize the window to an optimum size. Move the window to a different location. Close the window.

    2. Re-launch the app by double-clicking the jar file.
      Expected: The most recent window size and location is retained.

{ more test cases …​ }

G.2. Deleting an expense

  1. Deleting an expense while all expenses are listed

    1. Prerequisites: List all expenses using the list command. Multiple expenses in the list.

    2. Test case: delete 1
      Expected: First expense is deleted from the list. Details of the deleted expense shown in the status message. Timestamp in the status bar is updated.

    3. Test case: delete 0
      Expected: No expense is deleted. Error details shown in the status message. Status bar remains the same.

    4. Other incorrect delete commands to try: delete, delete x (where x is larger than the list size) {give more}
      Expected: Similar to previous.

{ more test cases …​ }

G.3. Saving data

  1. Dealing with missing/corrupted data files

    1. {explain how to simulate a missing/corrupted file and the expected behavior}

{ more test cases …​ }