PROJECT: ExpenseTracker


Overview

Expense Tracker is the secure, efficient financial application for the keyboard enthusiast. Boasting such features as daily tips, statistics, expense management and budget setting, Expense Tracker equips users with the necessary tools to become a better saver.

Morphed from the Address Book application, Expense Tracker was developed for an NUS Software Engineering module (CS2103T) under several constraints. Due to said constraints, Command Line Interface (CLI) became the main mode of interaction with the application. However, to ensure user friendliness, a Graphical User Interface (GUI) has been implemented.

This portfolio is a documentation of my contributions to Expense Tracker.

Summary of contributions

Major Enhancement: Implementation of GUI elements for newly added features

What It Does

  • Displays the user’s expenditure information on the GUI. This includes their notifications, monthly budget, monthly expenses and budgets for categories. The Notification System in particular was entirely implemented by me. The feature generates and displays daily saving tips and warnings if the user is about to spend or have spent over their budget.

Justification

  • A well-designed and responsive user interface is able to maximize user experience and allows Expense Tracker to stand out amongst the sea of financial applications.

  • I predict that there will be a subset of users who use Expense Tracker because they have trouble maintaining a budget. The Notification System was implemented to help said users by monitoring their budget management and providing general knowledge about saving money.

Highlights

  • Creativity and many design considerations were required to get the Expense Tracker GUI to look and function as I had envisioned.

  • Additional features such as animation and dynamic changing of text color were also implemented for the GUI for improved visual feedback.

  • The implementation of the Notification System, in particular, was challenging as it involved making additions and modifications to all components of Expense Tracker.

Minor enhancements:

  • Implemented the notification command which allows users to toggle the option for automated notification sending.

  • Completely overhauled the CSS styling of the application.

  • Implemented other minor animations to existing features such a fade-in effect of GUI elements upon login.

  • Added color to Tags.

Code contributed: Reposense Compilation

Other contributions:

  • Documentation:

    • Updated the Notification component section of the User Guide: #187

    • Updated the Use Case, User Stories and User Interface component section of the Developer Guide: #187, #75

    • Made changes to the Developer Guide. Improved language, updated images and edited diagrams: #187, #75, #194

    • Report bugs for other teams: #217, #234, #201, #227, #212

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

Toggling Notifications: notification

Toggles the ability of Expense Tracker to generate and display automated notifications.

There are 2 types of notification to toggle:

  1. Warning - Referenced by warning as the NOTIFICATION_TYPE parameter. These notifications will be sent when you are over or about to go over your budget.

  2. Tip - Referenced by typing tip as the NOTIFICATION_TYPE parameter. These notifications are saving tips that will be sent once every 24 hours when you log onto an account.

As shown below, Warning-type Notifications can be indicated by exclamation mark image displayed along with the notification:

warningExample
Figure 1. Example of a Warning-type Notification

Meanwhile, Tip-type Notifications can be indicated by light bulb image displayed along with the notification:

tipExample
Figure 2. Example of a Tip-type Notification

There are two toggle options, on and off, which can be indicated by 'on' or 'off' respectively in the TOGGLE_OPTION parameter.

TOGGLE_OPTION is a required parameter. NOTIFICATION_TYPE can be omitted.

Format: notification n/NOTIFICATION_TYPE t/TOGGLE_OPTION

Examples:

  • notification n/warning t/off
    Disables the sending Warning type notifications.

  • notification n/tip t/off
    Enables the sending of Tip type notifications.

  • notification t/off
    Disables the sending of both types of notifications.

  • NOTIFICATION_TYPE can only be 'warning' or 'tip'

  • TOGGLE_OPTION can only be 'on' or 'off'

  • NOTIFICATION_TYPE is optional

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.

User Interface Redesign

The UI has been redesigned to implement the following UI elements required for Expense Tracker:

  • Budget Panel

  • Statistics Panel

  • Notifications Panel

  • Categories Panel

UiChange
Figure 3. Before and After shots of the UI

As an example of how the new UI elements were implemented, we will examine the implementation of BudgetPanel.

The Budget Panel

BudgetPanel consists of 4 UI elements:

  • BudgetPanel#expenseDisplay – A Text element that displays the user’s current expenses.

  • BudgetPanel#budgetDisplay – A Text element that displays the user’s monthly budget cap.

  • BudgetPanel#percentageDisplay - A TextFlow objects that manages BudgetPanel#budgetDisplay and BudgetPanel#expenseDisplay.

  • BudgetPanel#budgetBar – A ProgressBar element that visually presents the percentage of the current totalBudget cap that has been used.

Given below are the steps of an example scenario of how BudgetPanel is updated:

  1. The user launches the application and signs up for a new account. The MainWindow creates a new BudgetPanel, which elements are initialized as follows:

    • BudgetPanel#expenseDisplay is green and set to "$0.00".

    • BudgetPanel#budgetDisplay is set to "/ $28.00", with $28.00 being the default totalBudget.

    • BudgetPanel#budgetBar is green and at 0% progress.

  2. The user executes an add command. As the add command modifies budget and expenses, AddCommand#execute() will post a UpdateBudgetPanelEvent event to the EventsCenter.

    If a command fails its execution or does not affect budget or expenses, UpdateBudgetPanelEvent will not be posted.
  3. The UpdateBudgetPanelEvent event is handled by MainWindow#handleBudgetPanelEvent(), which calls BudgetPanel#update().

  4. BudgetPanel#update() calls BudgetPanel#animateBudgetPanel(), which creates a new Timeline object.

  5. Two KeyFrame objects are added to Timeline, creating the animation BudgetPanel#budgetBar that transits the BudgetPanel#budgetBar#progress to the updated number.

    If the updated percentage is more than 1.0, BudgetPanel#budgetBar#progress will be set to 1.0. Barring oversights, it should never fall below 0.0.
  6. A call to 'BudgetPanel#addTextAnimationKeyFrames()` is made to add the KeyFrame objects required to create the incrementing animation for BudgetPanel#expenseDisplay and BudgetPanel#budgetCapDisplay. In each KeyFrame, BudgetPanel#updateExpenseDisplay() and BudgetPanel#updateBudgetCapDisplay() is called to increment the BudgetPanel#expenseDisplay and BudgetPanel#budgetCapDisplay respectively.

    The number of KeyFrame objects and the time interval between each KeyFrame has been predetermined.
  7. A call is also made to BudgetPanel#alterTextSize() in each KeyFrame. This method checks the height of BudgetPanel#percentageDisplay. If said height is different from BudgetPanel#percentageDisplay#maxHeight, BudgetPanel#percentageDisplay will be rescaled accordingly such that its new width is equal to BudgetPanel#percentageDisplay#maxHeight.

  8. A call to Timeline#playFromStart() is made to execute the animations.

  9. A call is also made concurrently to BudgetPanel#setBudgetUiColors(). If BudgetPanel#expenseDisplay is larger than BudgetPanel#budgetCapDisplay, the color of BudgetPanel#expenseDisplay and BudgetPanel#budgetBar changes to red, indicating that the user is over budget.

    Similarly, if the user has gone from over budget to under budget, the color of 'BudgetPanel#expenseDisplay` and BudgetPanel#budgetBar changes to green.

The following sequence diagram shows the process of updating the BudgetPanel UI elements:

BudgetPanelSequenceDiagram
Figure 4. Sequence diagram of the BudgetPanel update

Design Considerations

Aspect: Choosing which library to use for animation implementation
  • Alternative 1 (current choice): Use Timeline and KeyFrame classes.

    • Pros: More flexible; Able to create the animation frame by frame.

    • Cons: More tedious to implement. Animations effects will require manual addition of KeyFrame objects for the intended effect.

  • Alternative 2: Use the Transition class

    • Pros: The class is specialized, and thus has built-in methods to create better animations For example, EASE-BOTH can be used to cause the transition to accelerate at different points for a better effect)

    • Cons: Does not work for certain desired effects, such as the 'incrementing' effect required for Text elements of BudgetPanel.

Aspect: Implementation of Text elements
  • Alternative 1 (Initial Choice): Use two Label objects; one to display currentExpenses and another to display budgetCap.

    • Pros: Allows the implementation of separate text color changing and animation.

    • Cons: Difficult to keep both text objects centralized in relation to the budgetBar, especially if currentExpenses or budgetCap are large numbers.

  • Alternative 2: Use one Text object to display both currentExpenses and budgetCap.

    • Pros: Easy to centralize the Text object with budgetbar.

    • Cons: Implementation of animation was messy and tedious. JavaFX also does not support multiple colors for a single Text object.

  • Alternative 3 (Current Choice): Wrap two Text objects in a TextFlow object

    • Pros: Easy to centralize the Text objects by taking advantage of the properties of TextFlow. Allows the implementation of separate text color changing and animation.

    • Cons: Does not solve the issue of decentralized text when currentExpenses or budgetCap are large numbers.

Aspect: Solving the issue of TextFlow positioning when currentExpenses or budgetCap are large numbers.
  • Alternative 1: During the budget update, manipulate the font size of both Text objects when the TextFlow object reaches a certain height.

    • Pros: -

    • Cons: Difficult to adjust the fonts of both Text objects such that the final font size is neither too large nor too short.

  • Alternative 2: Manipulate the scale of the TextFlow object such that it always maintains a predetermined width.

    • Pros: A solution that is simple and easy to implement.

    • Cons: In the case of very large numbers, the TextFlow object is shrunk down to a point where the text in non-legible. However, we assume that the average user who is seriously using ExpenseTracker will not set currentExpenses or budgetCap to such large numbers.

Notification System

The Notification System is comprised of the following classes:

  • Notification - An abstract class that consists of a header, type and body. There are two types of Notification, TipNotification and WarningNotification.

  • NotificationPanel and NotificationCard - UI elements that displays the list the notifications that have been sent to the user.

  • NotificationHandler - Manages the list of notifications.

  • NotificationCommand - Allows the user to toggle what type of notifications they wish to receive.

  • NotificationHandler - Handles the storage and creation of Notification objects.

  • Tips - Reads and stores Tip objects in a list.

  • XmlAdaptedNotificationHandler, JsonTipsStorage and XmlAdaptedNotificationHandler - Manages the saving and reading on Notification and Tip objects.

Adding a Notification

Given below are the steps of an example scenario of how the Notification System functions:

  1. The user launches the application for the first time. A new NotificationHandler is instantiated. A new Tips object is instantiated, and a call to JsonTipsStorage#readTips is made to read a list of Tip objects from a JSON file.

  2. A call to NotificationHandler#isTimeToSendTip() is made upon login. In turn, a check is made to see if it has been 24 hours since the last TipNotification has been sent. It also checks if NotificationHandler#isTipEnabled is true. If both conditions are met, a new `TipNotification is added to the NotificationHandler#internalList via a call to NotificationPanel#addTipNotification().

    If this is the user’s first time logging into their account, a new TipNotification will be sent.
  3. The user executes the command add n/Lunch $/30.00 c/Food. The add command calls NotificationHandler#isTimeToSendWarning() to check if the user is nearing or over their budget. It also checks if NotificationPanel#isWarningEnabled is true. If both conditions are met, a WarningNotification is added to NotificationHandler#internalList via a call to NotificationPanel#addWarningNotification().

    The same procedure is carried out if the user executes an edit command.
  4. If the size of NotificationHandler#internalList reaches 11 or more, the oldest Notification in the list is then replaced with the new Notification.

Executing Notification Command

Given below is an example scenario of how NotificationCommand functions: . The user executes notification n/warning t/off. THe command is received by ExpenseTrackerParser.

  1. A call to NotificationCommand#parse is made, which creates a NotificationCommandDescriptor object with the two extracted parameters warning and off. A NotificationCommand is returned to LogicManager.

    The n/ suffix and parameter can be omitted. In this case, all types of notifications will be affected by the toggle.
  2. LogicManager then calls NotificationCommand#execute(), which calls NotificationHandler#toggleWarningNotifications() to set NotificationPanel#isWarningEnabled to false.

    If notification n/tip t/on was executed, NotificationHandler#toggleTipNotifications() would be called to set NotificationHandler#isTipEnabled to true.
    If notification t/on was executed, NotificationHandler#toggleBothNotifications() will be called instead to set both NotificationHandler#isTipEnabled and NotificationPanel#isWarningEnabled.

The following sequence diagram shows the process of executing a NotificationCommand:

NotificationCommandSequenceDiagram
Figure 5. Sequence Diagram for Exectuing a Notification Command

Design Considerations

Aspect: Storing of Tips
  • Alternative 1: Code the tips as a list of String object in a class.

    • Pros: Easy to implement.

    • Cons: Changes to the list might impact the base code and testing results.

  • Alternative 2 (Current Choice): Read a set of predetermined tips from a JSON file.

    • Pros: Allows for easy configuration of tips that will not impact the base code.

    • Cons: More tedious to implement, as the given JsonUtil does not have a method to read an array from a JSON file.