Overview
This portfolio aims to document the contributions made by Goh Yin Hao to the Personal Finance Tracker.
Personal Finance Tracker is a desktop finance tracker application used for tracking personal finances such as daily expenses, recurring expenses such as monthly electricity bills, budgets and debts owed to another party. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 30 kLoC. The product was morphed from an Address Book over a period of 8 weeks under the constraints described here.
Summary of contributions
-
Major enhancement: added the ability to manage debts in the finance tracker application
-
What it does: allows the user to add, edit, delete, select debts, as well as easily convert these debts into an expense once the debt is cleared. Integrated to work with current undo/redo, history and list commands.
-
Justification: This feature improves the product significantly because a user can now easily and conveniently keep track of their debts owed to other entities.
-
Highlights: This enhancement is a core feature of any typical finance tracker. It required adjustments and integration with the existing model, logic, UI components and builds the foundation for any future enhancements involving debts.
-
-
Code contributed: [code collated by reposense]
-
Other contributions:
-
Project management:
-
Check all pull requests done by group mates
-
Create issues for tracking in GitHub Issue Tracker
-
In charge of code in model component
-
-
Documentation:
-
Enhancements to existing features:
-
Community:
-
Contributions to the User Guide
Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
Adding a debt: adddebt
Adds a debt to the finance tracker.
Format: adddebt n/PERSON_OWED $/AMOUNT_OWED c/CATEGORY due/DEADLINE [r/REMARK]
Shortcut: ad n/PERSON_OWED $/AMOUNT_OWED c/CATEGORY due/DEADLINE [r/REMARK]
-
The PERSON_OWED should only contain alphanumeric characters and spaces, and it should not be blank.
-
The AMOUNT_OWED should only contain positive numbers and reflect the value in dollars. Values accepted are in the range of $0.01 to $9,999,999.99. A maximum of 2 decimal places are allowed.
-
The CATEGORY is case insensitive and should only be one of the following: FOOD, TRANSPORT, SHOPPING, WORK, UTILITIES, HEALTHCARE, ENTERTAINMENT, TRAVEL, OTHERS.
-
The DEADLINE should be in dd-mm-yyyy format and should not be a date before today’s date.
-
If REMARK is omitted, no remarks will be stored.
You can omit (optional) parameters by leaving them empty. |
Examples:
-
adddebt n/John Doe $/50.00 c/shopping due/25-02-2019 r/Loan from John to finance my new earphones
-
ad n/Jane Doe $/200 c/FOOD due/03-03-2019
Editing a debt: editdebt
Edits an existing debt in the finance tracker.
Format: editdebt INDEX [n/PERSON_OWED] [$/AMOUNT_OWED] [c/CATEGORY] [due/DEADLINE] [r/REMARK]
Shortcut: ed INDEX [n/PERSON_OWED] [$/AMOUNT_OWED] [c/CATEGORY] [due/DEADLINE] [r/REMARK]
-
Edits the debt at the specified
INDEX
. -
The index refers to the index number shown in the displayed debt list. The index must be a positive integer.
-
At least one of the optional fields must be provided.
-
Existing values will be updated to the input values.
You can omit [optional] parameters by leaving them empty. If all parameters are empty, no edits will occur. |
Examples:
-
editdebt 5 n/Tommy $/60
Edits debt owed and amount owed of the 5th debt to beTommy
and$60
respectively.
Deleting a debt: deletedebt
Deletes the specified debt from the finance tracker.
Format: deletedebt INDEX
Shortcut: dd INDEX
-
Deletes the debt at the specified
INDEX
. -
The index refers to the index number shown in the displayed debt list. The index must be a positive integer.
Examples:
-
listdebt v/all
deletedebt 5
Deletes the 5th debt in the finance tracker.
Selecting a debt: selectdebt
Selects the specified debt from the finance tracker.
Format: selectdebt INDEX
Shortcut: sd INDEX
-
Selects the debt at the specified
INDEX
. -
The index refers to the index number shown in the displayed debt list. The index must be a positive integer.
Examples:
-
listdebt v/all
selectdebt 5
Selects the 5th debt in the finance tracker.
Clearing all debts: cleardebt
Clears all debts from the finance tracker.
Format: cleardebt
Shortcut: cd
Paying off a debt: paydebt
Converts the specified debt into an expense.
Format: paydebt INDEX [d/DATE]
Shortcut: pd INDEX [d/DATE]
-
Converts the debt at the specified
INDEX
. -
The index refers to the index number shown in the displayed debt list. The index must be a positive integer.
-
After converting the debt into an expense, the debt is deleted.
-
The DATE should be in dd-mm-yyyy format and can be used to indicate actual day when user paid off the debt.
-
If DATE is omitted, current date will be used.
Examples:
-
listdebt v/all
paydebt 3
Converts the 3rd debt in the finance tracker into an expense.
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
Model component
API : Model.java
The Model
,
-
stores a
UserPref
object that represents the user’s preferences. -
stores the Finance Tracker data.
-
exposes unmodifiable
ObservableList<Expense>
,ObservableList<Recurring>
,ObservableList<Debt>
,ObservableList<Budget>
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.
Debt Feature
The Debt feature consists of adddebt
, editdebt
, listdebt
, deletedebt
, selectdebt
, cleardebt
and paydebt
.
This feature allows users to add debts to the finance tracker and be able to constantly keep track of them. This is done by calling Logic#execute
which creates an AddDebtCommand
. This command then calls Model#addDebt
, adding the specified debt into the debt list.
Editing, deleting, selecting and clearing of debts work in a similar manner.
Pay Debt Feature
The purpose of this feature is to provide the convenience for users to indicate that they have paid off a particular debt and seamlessly convert that into an expense.
Current Implementation
Below is the UML sequence diagram and a step-by-step explanation of an example usage scenario for paydebt
.
-
User enters the command
paydebt 1
, to convert the first listed debt on the user interface into an expense. This command is executed byLogicManager
, which callsFinanceTrackerParser#parseCommand("paydebt 1")
. This creates a newPayDebtCommandParser
object which will help parse the input by the user. -
The newly created object calls
parse("1")
which in turns callsArgumentTokenizer#tokenize("1", "d/")
to split the arguments into its preamble(the index) and the date(if inputted by the user). This returns anargMultiMap
containing the split input. -
The
PayDebtCommandParser
object then callsParserUtil#parseIndex(argMultiMap.getPreamble())
andParserUtil#parseDate(argMultiMap.getValue("d/").get())
to parse the arguments into the index and date into its correct form respectively. If the user does not input a date, the program will use the local date on the system’s clock. APayDebtCommand
object containing the index and date is then created and returned to theLogicManager
. -
The
LogicManager
callsPayDebtCommand#execute()
, which will callModel#getFilteredDebtList()
to retrieve the list of debts stored in the finance tracker. The methodget(index)
is then called to retrieve thedebt
the user was intending to convert. -
An expense is then created by retrieving out the following relevant information from the
debt
entry:-
Person Owed
-
Amount
-
Category
-
Remarks
-
-
The programme then take this information and creates a new Expense
convertedExpense
with the following fields:-
Name
: Paid Debt toPerson Owed
-
Amount
: Same amount will be used -
Category
: Same category will be used -
Date
: Based on user’s input on when the debt is paid, else the program will use the local date in the system’s clock -
Remarks
: Same remarks will be used
-
-
Model#deleteDebt(debt)
andModel#addExpense(convertedExpense)
are then called to delete the targeteddebt
from the debt list and add theconvertedExpense
into the expense list accordingly. -
The command result is then returned to the
LogicManager
which then returns it to theUI
where the changes are then reflected on the user interface.
Design Consideration
This feature can be implemented in different ways in terms of the architecture of the Model component. The alternative ways of implementation are shown below.
-
Alternative 1 (current choice): Debt and Expense classes do not inherit from a common Interface. Container objects such as expense list and debt list, will be initialized to hold objects of their own individual classes.
-
Pros: Lower level of coupling between Expense and Debt classes.
-
Cons: Slower and less flexibility. Conversion between classes, e.g. from Debt to Expense, requires extracting information from debt, creating a new expense, then deleting the old debt.
-
-
Alternative 2: Debt and Expense classes inherit from a common Interface. Container objects such as expense list and debt list, will be initialized to hold objects of this common Interface.
-
Pros: Greater flexibility. Polymorphism allows for easy conversion between different types of entries, such as from debt to expense, simply by moving them across different lists. This will be useful considering that our Finance Tracker will need significant amounts of conversion between different objects.
-
Cons: Higher level of coupling between Expense and Debt classes.
-
Ultimately, the first option was chosen because a lower level of coupling will allow for easier maintenance, integration and testing. Also, it is not significantly slower thus the Finance Tracker will still be able to complete debt-related commands within 2 seconds, which is one of our non-functional requirements.
Debt Notifications (Coming in v2.0)
This is still a work in progress.
The purpose of this feature is to alert users when the deadline for their debts is approaching. These alerts come in the form of either a pop-up notification or an email alert.
It is up to the user on when they would like to receive this notification. Currently, there are plans to implement the following options:
-
1 month
before debt deadline -
1 week
before debt deadline -
3 days
before debt deadline -
1 day
before debt deadline
Future Implementation
Once the duration
option is set, each time the main application loads, the programme will go through every debt in Model#getFilteredDebtList()
, deduct duration
from each Debt#getDeadline()
to get its notificationDate
and add them to a new list notificationDates
.
Each notificationDate
is then checked against LocalDate#now()
. If notificationDate
is before or equals to LocalDate#now
, they are then added to a new list notificationsToBeAlerted
.
Every item in notificationsToBeAlerted
is then printed on an alert box, reminding the user of the upcoming deadlines for their debts.