Acknowledgements


Setting up, getting started

Refer to the guide Setting up and getting started.


Design

:bulb: Tip: The .puml files used to create diagrams in this document docs/diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.

Architecture

The Architecture Diagram given above explains the high-level design of the App.

Disclaimer: Our team has decided to add the spleetwaise.commons package as a common package for classes that are used by multiple components, in our case, address and transaction. This is an enhancement for modularity on top of the original design of the AddressBook-Level3 project, which only have a seedu.address package. The refactoring is almost 90% complete, and we are working on the remaining 10%.

Given below is a quick overview of main components and how they interact with each other.

Main components of the architecture

The app consists of three packages: address, transactions, and common.

  • common is where the main application logic lives. It contains general classes that are used by multiple components in the app.
  • address contains classes related to address book.
  • transactions contains classes related to transactions.
:information_source: Package structure: Packages follow this general package structure:
- logic: Contains classes related to commands/command parsing.
- model: Contains classes for representing data in the app.
- storage: Contains classes related to reading and writing data from, and to storage.
- ui: Contains classes related to the GUI of the app.

Main application

The entry-point to the app, Main (consisting of classes Main and MainApp), lives in the common package, and is in charge of managing the app’s lifecycle.

  • At app launch, it initializes the other components in the correct sequence, and connects them up with each other.
  • At shut down, it shuts down the other components and invokes cleanup methods where necessary.

The bulk of the app’s work is done by the following 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.

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.

Each of the four main components (also shown in the diagram above),

  • defines its API in an interface with the same name as the Component.
  • implements its functionality using a concrete {Component Name}Manager class (which follows the corresponding API interface mentioned in the previous point.

For example, the Logic component defines its API in the Logic.java interface and implements its functionality using the LogicManager.java class which follows the Logic interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component’s being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.

The sections below give more details of each component.

UI component

The API of this component is specified in Ui.java

Structure of the UI Component

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PersonListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class which captures the commonalities between classes that represent parts of the visible GUI.

The UI component uses the JavaFx UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml

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.
  • keeps a reference to the Logic component, because the UI relies on the Logic to execute commands.

Logic component

API : Logic.java

Here’s a (partial) class diagram of the Logic component:

The sequence diagram below illustrates the interactions within the Logic component, taking execute("delete 1") API call as an example.

Interactions Inside the Logic Component for the `delete 1` Command

:information_source: Note: The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.

Dual-parser setup

How the Logic component works:

  1. When Logic is called upon to execute a command, it will first check whether the command is known by the AddressBookParser:

    1.1. It is first passed to an AddressBookParser object which will attempt to parse it. If there is a matching command, it creates a parser that matches the command (e.g., DeleteCommandParser) and uses it to parse the command.

    1.2. If there is no matching command, Logic will try to parse it with a TransactionParser. If there is a matching command, a similar thing happens as with AddressBookParser. The partial sequence diagram below illustrates this case clearly:

    Partial sequence diagram for transaction command

  2. This ultimately results in a non-null Command object (more precisely, an object of one of its subclasses e.g., DeleteCommand) which is executed by the LogicManager.

  3. The command can communicate with the Model when it is executed (e.g. to delete a person).

    Note that although this is shown as a single step in the diagram above (for simplicity), in the code it can take several interactions (between the command object and the Model) to achieve.

  4. The result of the command execution is encapsulated as a CommandResult object which is returned back from Logic.

Here are the other classes in Logic (omitted from the class diagram above) that are used for parsing a user command:

How the parsing works:

  • When called upon to parse a user command, the AddressBookParser or TransactionParser class creates a respective AbCommandParser (Ab is a placeholder for some specific address book command name e.g., AddCommandParser), which uses the other classes shown above to parse the user command and create a AbCommand object (e.g., AddCommand) which the AddressBookParser returns back as a Command object. Likewise for TransactionParser and TbCommands.

  • All AbCommandParser and TbCommandParser classes (e.g., AddCommandParser, DeleteCommandParser, …) inherit from a common Parser interface so that they can be treated similarly where possible e.g, during testing.

Model component

AddressBookModel

API : AddressBookModel.java

The AddressBookModel component:

  • stores the address book data i.e., all Person objects (which are contained in a UniquePersonList object).
  • stores the currently ‘selected’ Person objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<Person> 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 (as the Model represents data entities of the domain, they should make sense on their own without depending on other components)
:information_source: Note: An alternative (arguably, a more OOP) model is given below. It has a Tag list in the AddressBook, which Person references. This allows AddressBook to only require one Tag object per unique tag, instead of each Person needing their own Tag objects.

TransactionBookModel

API : TransactionBookModel.java

  • stores the transaction book data i.e., all Transaction objects (which are contained in a ObservableList<Transaction> object).
  • stores the currently ‘selected’ Transaction objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable 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 (as the Model represents data entities of the domain, they should make sense on their own without depending on other components)

CommonModel

API : CommonModel.java

The CommonModel component:

  • stores a UserPref object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref objects.

CommonModelManager

Singleton CommonModel class. The singleton instance of this class contains an instance of both AddressBookModel and TransactionBookModel. The singleton instance acts as a facade, exposing the APIs of both AddressBookModel and TransactionBookModel.

Certain transaction-related features need access to data from both the address and transaction book from different areas of the codebase. For this reason, we decided to go with the CommonModelManager class design described above.

Storage component

API : Storage.java

Storage Class Diagram

The Storage component,

  • can save address book data, transaction book data and user preference data in JSON format, and read them back into corresponding objects.
  • inherits from AddressBookStorage, TransactionBookStorage and UserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed).
  • depends on some classes in the Model component (because the Storage component’s job is to save/retrieve objects that belong to the Model)

Documentation, logging, testing, configuration, dev-ops


Appendix: Requirements

Product scope

Target user profile: University Students in Singapore

  • has a need to manage a significant number of contacts and transactions
  • prefer desktop apps over other types
  • can type fast
  • prefers typing to mouse interactions
  • is reasonably comfortable using CLI apps
  • has a need to track transactions with friends and saved contacts

Value proposition: Make it easy for university students to track transactions with friends and contacts saved in the address book.

Glossary

This Spleetwaise app is a single-user application. Transactions are relative to the user.

  • Mainstream OS: Windows, Linux, Unix, macOS
  • Private contact detail: A contact detail that is not meant to be shared with others
  • Transaction: A Transaction represents a record of a financial interaction between the user and another party (another contact).
    • Not Done Transaction: By default, a newly created transaction is set as not done - e.g. if the transaction is added as addTxn 1 amt/12.3 desc/John owes me for dinner, this transaction is not done, John still owes the user. (The terms “undone” and “not done” may be used interchangeably in Spleetwaise)
    • Done Transaction: A completed transaction, referring to the previous e.g. once John has paid the user, he will mark the transaction as done.

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 add a new person store the contact information of an individual that can be used in transactions
* * * user delete a person remove entries that I no longer need
* * * user find a person by name locate details of persons without having to go through the entire list
* * user hide private contact details minimize chance of someone else seeing them by accident
* user with many persons in the address book sort persons by name locate a person easily
* * * user mark and unmark expenses that are paid off/not paid track which expenses have been settled
* * * user see how much a specific contact owes pay them back easily
* user living abroad handle currency conversion track expenses accurately when paying in different currencies
* user who frequently travels tag expenses by event manage and track costs associated with specific activities or trips
* * * user view a summary of all expenses and balances quickly see who owes what and who has overpaid
* student tight on budget set limits on certain categories better manage my spendings
* * user access frequently contacted people quickly record a transaction in a short amount of time
* * user create templates add transactions quicker
* user set up recurring transactions automate my transactions
* * * student display summary of all transaction tabulate total amount owed or owe for personal tracking
* * user detect duplicate expenses avoid accidentally double-tracking a payment
* * student managing multiple categories tag transactions by category organize and search for them easily later

Use cases

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

UC01 - View Usage Instructions

Actor: New User

MSS

  1. The new user clicks on “Help” in the top bar of the application.
  2. The system displays usage instructions in a browser.
  3. The user reviews the instructions.
    Use case ends.

Extensions

  • 2a. The user can switch between different sections of the instructions (e.g., FAQs, How-to sections).

UC02 - Add a New Person

MSS

  1. The user requests to add a new person with the required details.
  2. The system validates the input.
  3. The system saves the new person to the address book and displays a success message.
  4. The new person is added to the displayed address book list.
    Use case ends.

Extensions

  • 2a. The system detects invalid input(s).
    • 2a1. The system shows an error message.
      Use case restarts from step 1.

UC03 - List All People

MSS

  1. The user requests to list all people.
  2. The system displays the list of all people in the address book.
    Use case ends.

UC04 - Edit Details of a Person

MSS

  1. The user requests to list all people (UC03) or find a person (UC06).
  2. The user selects a person to edit and provides new details.
  3. The system validates the input.
  4. The system updates the person with the new details and displays a success message.
  5. The edited person is updated and displayed in the address book.
    Use case ends.

Extensions

  • 1a. The address book is empty.
    Use case ends.

UC05 - Delete a Person

MSS

  1. The user requests to list all people (UC03) or find a person (UC06).
  2. The user requests to delete a specific person.
  3. The system deletes the person.
    Use case ends.

Extensions

  • 1a. The address book is empty.
    Use case ends.

UC06 - Find Person(s)

MSS

  1. The user requests to search for a person by specific detail(s).
  2. The system performs a search and displays all matching people.
    Use case ends.

Extensions

  • 2a. The system finds no matches.
    • 2a1. The system displays an empty address book list.
      Use case ends.
  • 2b. The system finds multiple people and displays them in the address book list.
    Use case ends.

UC07 - Add a New Transaction

MSS

  1. The user requests to list all people (UC03) or find a person (UC06).
  2. The user selects a person to add the new transaction with and inputs the required details (e.g., amount, date, description).
  3. The system validates the input.
  4. The system saves the new transaction in the transaction book and displays a success message.
  5. The new transaction is added to the displayed transaction book.
    Use case ends.

Extensions

  • 2a. The system detects invalid input(s).
    • 2a1. The system shows an error message.
      Use case restarts from step 1.
  • 4a. The system detects a duplicate transaction.
    • 4a1. The system discards the duplicate and displays an error message.
      Use case ends.

UC08 - List All Transactions

MSS

  1. The user requests to list all transactions.
  2. The system resets the displayed transaction book.
  3. The system displays all transactions.
    Use case ends.

UC09 - Edit a Transaction

MSS

  1. The user requests to list all transactions (UC08) or filter transactions (UC12).
  2. The user selects a transaction to edit and provides new details.
  3. The system validates the input.
  4. The system updates the transaction with the new details and displays a success message.
  5. The edited transaction is updated and displayed in the transaction book.
    Use case ends.

Extensions

  • 1a. The transaction book is empty.
    Use case ends.
  • 3a. The system detects invalid input(s).
    • 3a1. The system shows an error message.
      Use case resumes from step 2.

UC10 - Delete a Transaction

MSS

  1. The user requests to list all transactions (UC08) or filter transaction(s) (UC12).
  2. The user selects a specific transaction to delete.
  3. The system deletes the transaction.
    Use case ends.

Extensions

  • 2a. The transaction book is empty.
    Use case ends.

UC11 - Mark Transaction(s) as Done or Not Done

MSS

  1. The user requests to list all transactions (UC08) or filter transaction(s) (UC12).
  2. The user selects a specific transaction to mark as done or not done.
  3. The system updates the transaction’s status.
  4. The system displays a success message indicating the status change.
    Use case ends.

UC12 - Filter Transaction(s)

MSS

  1. The user requests to filter transaction(s) by specific detail(s).
  2. The system performs a search and displays all transactions with matching details.
    Use case ends.

Extensions

  • 2a. The system finds no matches.
    • 2a1. The system displays an empty transaction list.
      Use case ends.

Non-Functional Requirements

  1. Should work on any mainstream OS as long as it has Java 17 or above installed.
  2. Should be able to hold up to 1000 persons 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.
  4. There should be only one type of currency used in all transactions for MVP, defaulted to SGD.
  5. The product supports expense tracking and consolidation, no real world exchange of money will be carried out.
  6. The user should be able to restore and use a backup save file as part of disaster recovery.
  7. The user should be able to save the save file on a portable device and continue to work on the save file on another computer.

Appendix: Instructions for manual testing

Given below are instructions to test the app manually.

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

Launch and shutdown

  1. Initial launch

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

    2. Launch the app
      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
      Expected: The most recent window size and location is retained.

Adding a person

  1. Adding a person while all persons are being shown

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

    2. Test case: add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01
      Expected: Assuming no duplicates, a new contact named John Doe is added to the list. Details of the added contact shown in the status message.

    3. Test cases: add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01 when John Doe with phone 98765432 already exists in the address book
      Expected: No person is added. Error details shown in the status message with This person already exists in the address book. Status bar remains the same.

    4. Test case: add n/ p/ e/ a/
      Expected: No person is added. Error details shown in the status message. Status bar remains the same.

    5. Other incorrect add commands to try: add n/John Doe, add p/98765432, add e/johnd@example.com, add a/John street, block 123, #01-01
      Expected: Similar to previous.

Editing a person

  1. Editing a person while all persons are being shown

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

    2. Test case: edit 1 n/Jane Doe
      Expected: Assuming no duplicates, first contact’s name is changed to Jane Doe. Details of the edited contact shown in the status message.

    3. Test case: edit 0 n/Jane Doe
      Expected: No person is edited. Error details shown in the status message.

    4. Other incorrect edit commands to try: edit, edit x n/Jane Doe (where x is larger than the list size), edit 1
      Expected: Similar to previous.

Person Synchronization in transaction list

  1. Ensuring person details changed are accurately reflected in all views and models.

    1. Prerequisites: List all persons and transactions using the list and listTxn command. At least one person and one transaction with that person in the list.

    2. Test case: edit 1 n/New Name (where New Name is the updated name for the person)
      Expected: The person’s name updates in both the address and transaction lists and the UI (assuming no duplicates).

Deleting a person

  1. Deleting a person while all persons are being shown

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

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

    3. Test case: delete 0
      Expected: No person is deleted. Error details shown in the status message.

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

Adding a transaction

  1. Adding a transaction while all transactions are being shown with minimally 1 person in address book

    1. Prerequisites: List all persons and transactions using the list and listTxn command. At least one person in the address book list and multiple transactions in the list

    2. Test cases: addTxn 1 amt/12.3 desc/John owes me for dinner
      Expected: Assuming no duplicates, a new transaction related to the person in the first index of the address book is added to the list along with description of it. The amount reflected in the transaction is displayed green in the transaction panel to signify that the user is owed. The date of the transaction displays the current day. No categories to be displayed. Details of the added transaction is shown in the status message.

    3. Test cases: addTxn 1 amt/-12.3 desc/I owe John for dinner date/10102024
      Expected: Assuming no duplicates, a new transaction related to the person in the first index of the address book is added to the list along with description of it. The amount reflected in the transaction is displayed red in the transaction panel to signify that the user owes. The date of the transaction displays 10 Oct 2024. No categories to be displayed. Details of the added transaction is shown in the status message.

    4. Test cases: addTxn 1 amt/12.3 desc/John owes me for dinner cat/FOOD
      Expected: Assuming no duplicates, a new transaction related to the person in the first index of the address book is added to the list along with description of it. The amount reflected in the transaction is displayed green in the transaction panel to signify that you are owed. The date of the transaction displays the current day. Category of FOOD is displayed. Details of the added transaction is shown in the status message.

    5. Test cases: addTxn 1 amt/-12.3 desc/I owe John for dinner date/10102024 when identical transaction exists
      Expected: No transaction is added. Error details shown in the status message with Transaction already exists in the transaction book. Status bar remains the same.

    6. Test cases: addTxn 0 amt/ desc/ date/ cat/
      Expected: No transaction is added. Error details shown in the status message. Status bar remains the same.

    7. Other incorrect addTxn commands to try: addTxn 1, addTxn amt/1.234, addTxn desc/dinner, addTxn date/10102024, addTxn cat/FOOD
      Expected: Similar to previous.

Marking a transaction as done

  1. Marking a transaction as done while all transactions are being shown.

    1. Prerequisites: List all transactions using the listTxn command. One transaction is in the list.

    2. Test cases: markDone 1
      Expected: The first transaction is marked as done. A “done” icon appears next to the person’s name for that transaction. Details of the updated transaction shown in the status message.

    3. Test cases: markDone 1 (Assumes transaction 1 is already marked)
      Expected: No change in transaction status. The “done” icon remains. A status message confirms that the transaction is already marked.

    4. Test cases: markDone 0
      Expected: No transaction is marked. Error details shown in the status message.

    5. Other incorrect markDone commands to try: markDone, markDone x (where x is larger than the list size)
      Expected: Similar to previous.

Reverting a done transaction back to not done

  1. Reverting a done transaction back to not done while all transactions are being shown.

    1. Prerequisites: List all transactions using the listTxn command. One transaction is in the list.

    2. Test cases: markUndone 1
      Expected: The first transaction is reverted to not done. The existing “done” icon disappears for that transaction. Details of the updated transaction shown in the status message.

    3. Test cases: markUndone 1 (Assumes transaction 1 is already undone)
      Expected: No change in transaction status. The transaction remains to have no “done” icon. A status message confirms that the transaction is already undone.

    4. Test cases: markUndone 0
      Expected: No transaction is marked. Error details shown in the status message.

    5. Other incorrect markUndone commands to try: markUndone, markUndone x (where x is larger than the list size)
      Expected: Similar to previous.

Editing a transaction

  1. Editing a transaction while all persons are being shown

    1. Prerequisites: List all persons and transactions using the list and listTxn command respectively. Multiple persons in the list on the left pane. Multiple transactions in the list on the right pane.

    2. Test case: editTxn 1 amt/1.23
      Expected: Assuming no duplicates, first contact’s amount is changed to $1.23. Details of the edited transaction shown in the status message.

    3. Test case: editTxn 0 desc/Updated description
      Expected: No transaction is edited. Error details shown in the status message.

    4. Other incorrect edit commands to try: editTxn, edit x amt/1.23 (where x is larger than the list size), editTxn 1
      Expected: Similar to previous.

Filter Reuse in Transaction List

  1. Maintaining the current filter state when transactions are modified.

    1. Prerequisites: List all transactions using the listTxn command. Apply a filter via filterTxn command to the list (e.g., filtering by description containing “mac”).

    2. Test cases: addTxn 1 amt/12.3 desc/John owes me for dinner
      Expected: The new transaction appears in the filtered list while preserving the existing filter. Details of the new transaction shown in the status message.

    3. Test cases: editTxn 1 d/happy meal at mac (Assumes transaction 1 description is “KFC”)
      Expected: The updated transaction appears in the filtered list while preserving the existing filter. Details of the updated transaction shown in the status message.

    4. Test cases: editTxn 1 d/KFC (Assumes transaction 1 description is “fries at mac”)
      Expected: The updated transaction disappears in the filtered list while preserving the existing filter. Details of the updated transaction shown in the status message.

    5. Test cases: markDone 1, markUndone 1 (Assumes transaction 1 description is “fries at mac”)
      Expected: The transaction done icon updated in the filtered list while preserving the existing filter. Details of the updated transaction shown in the status message.

Filtering the transaction list.

  1. Filtering the transaction list while all persons are being shown

    1. Prerequisites: List all persons and transactions using the list and listTxn command respectively. Multiple persons in the list on the left pane. Multiple transactions in the list on the right pane.

    2. Test case: filterTxn 1
      Expected: Transaction list will be filtered by the person corresponding to the displayed index 1 in the person list.

    3. Test case: filterTxn 1 amt/1.23
      Expected: Transaction list will show transactions related to the person corresponding to the displayed index 1 in the person list with amount $1.23.

    4. Test case: filterTxn 0
      Expected: Current displayed transaction list will remain the same. Error details shown in the status message.

    5. Other incorrect edit commands to try: filterTxn desc/, filterTxn x (where x is larger than the list size), filterTxn amt/1.222
      Expected: Similar to previous.

Default Behavior on App Startup

  1. Verifying filter state of transaction panel upon app initialization.

    1. Prerequisites: At least one done transaction and one undone transaction in the list.

    2. Test cases: Initial Filter on App Startup
      Expected: The list displays all transactions (both done and not done) by default when the app starts. Initial txn filter state

Saving data

  1. Dealing with missing/corrupted data files

    1. Prerequisites: Multiple persons in addressbook.json and multiple transactions in transactionbook.json data files.

    2. Test cases: Missing name field in addressbook.json data file
      Simulation: Remove the name field from a person entry in the JSON file, then start the app.
      Expected: The person is discarded and not loaded to the app, with log message WARNING: Address book is possibly corrupted: Person's Name field is missing! Ignoring corrupted person.. If the corrupted person has any related transactions in the transaction book, they will be discarded accordingly with log message WARNING: Transaction book is possibly corrupted: Person with id [Person-ID] not found! Ignoring corrupted transactions. - [Person-ID] will be the respective person ID of the corrupted person.

    3. Test cases: Missing isDone field in transactionbook.json data file
      Simulation: Remove the isDone field from a transaction entry in the JSON file, then start the app.
      Expected: The transaction loads as not done by default. Upon closing the app, the transaction is saved as not done in the JSON file.

Appendix: Planned Enhancements

Team Size: 5

  1. Enhancements for Tracking “Not Done” Balances
    Currently, users can calculate all balances that are “Not Done” via filterTxn status/Not Done. However, this doesn’t provide the option to display a filtered transactions list that includes completed transactions while only showing the balance for “Not Done” transactions. Additionally, introducing a command like showBalance status/Not Done would give users a streamlined way to view balances for only “Not Done” transactions, regardless of the state of the filtered list. This command would allow users to easily toggle between viewing total balances and those specifically marked as “Not Done.”

  2. Case-Insensitive Duplicate Detection for Person
    SpleetWaise currently treats names as case-sensitive, so persons with names like “bob” and “Bob” are stored as distinct entries, even with the same phone number. This can lead to duplicate entries if capitalisation is inconsistent (e.g., “Alex Yeoh” vs. “alex yeoh”). Future updates aim to handle fields like names, emails, tags and remarks in a case-insensitive manner, treating persons with identical names with matching phone numbers as potential duplicates and alerting the user to confirm or discard the entries.

  3. Case-Insensitive Duplicate Detection for Transaction
    Currently, transaction with addTxn 1 amt/12 desc/ntuc fairprice and addTxn 1 amt/12 desc/NTUC FAIRPRICE is allowed without a warning/confirmation/alert to users even though it could be a potential duplicate (notice that the description in both the commands are treated as different). We aim to implement case-insensitive matching for the description field to detect potential duplicates of transaction and prompt users to confirm or discard duplicate entries.

  4. Improve find Command for Partial Matching Across Parameters
    Allow find command to search for persons through more fields and implement partial matches for names, phone numbers, emails, addresses, remarks, and tags. This makes it easier for users to locate contacts even if they don’t have exact matches.

  5. Enhance filterTxn Command for Partial Matching Across Parameters
    Implement partial matching in filterTxn for parameters like amount, person, date (day, month, year), status, and category, enabling users to search transactions with related keywords without exact matches.

  6. International Phone Number Format Support
    Update phone number validation to accept international formats, including country codes and special characters (e.g., “+”, “-“). This allows users to store numbers in formats like “+65 91234567” or “+1-123-456-7890”.

  7. Flexible Input Validation for Tags
    Allow special characters in tags, enabling users to create tags such as “#Business_Partner” or “Friends & Family” for better organization.

  8. Flexible Input Validation for Categories
    Allow special characters in categories, enabling users to create categories such as “#Business_Trip” or “Food & Beverage” for better organization.

  9. Enhanced Email Validation for Full Domain Structure
    Enforce email validation to require a fully qualified domain (e.g., “username@example.com”) to prevent invalid formats, ensuring more reliable email entries.

  10. Improve Duplicate Transaction Error Message
    Provide detailed information in duplicate transaction error messages, specifying duplicate fields (e.g., description, date, and amount) to help users resolve conflicts faster.

These enhancements address search functionality, error handling, input validation, duplicate detection, and user interface improvements, collectively enhancing SpleetWaise’s usability and functionality.

Appendix: Effort

Difficulty Level

Compared to iP (rated 10/20), this project rates at 17/20 due to:

  • 2 points for comprehensive UG and DG documentation, providing detailed explanations of each feature, use case, and design decision.
  • 2 points for extensive refactoring in a large codebase. Approximately 17,000 lines of code were added/modified to improve modularity and maintainability through reusable components, simplifying development in later stages.
  • 2 points for implementing complex validation and equality checks. Significant effort was spent on robust validation across various input fields, handling edge cases thoroughly.
  • 1 point for collaborative development and effective Git workflows, including pull requests, reviews, and conflict resolution.

Additional Complexity in Transaction Features

Much more effort was spent on implementing transaction features in SpleetWaise compared to the AB3 features.

One example is the find command in AB3 vs. filterTxn in SpleetWaise. In AB3, find only filters by name using a single NameContainsKeywordsPredicate class. In SpleetWaise, filterTxn filters transactions by multiple parameters (e.g., description, amount, status, person) in any combination. This required a modular FilterPredicate system, resulting in seven *FilterPredicate classes and a FilterCommandPredicate wrapper, each with its own test cases. This approach reduced code complexity and duplication by reusing FilterPredicate classes in the UI.

Achievements of the Project

  1. Feature Implementation: Delivered core transaction management features, including filtering and searching.
  2. Comprehensive Documentation: UG and DG support long-term use and maintenance.
  3. Modular Codebase with High Test Coverage: Achieved a modular structure with over 90% code coverage for core functionalities, reducing technical debt.