diff --git a/.gitignore b/.gitignore
index 2873e189e1..bf5b078f8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,5 +13,7 @@ src/main/resources/docs/
*.iml
bin/
-/text-ui-test/ACTUAL.TXT
+data
+data/save.txt
+text-ui-test/ACTUAL.TXT
text-ui-test/EXPECTED-UNIX.TXT
diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..d5edb48ae4
--- /dev/null
+++ b/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: seedu.bankwithus.BankWithUs
+
diff --git a/README.md b/README.md
index f82e2494b7..99b50adb0a 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Duke project template
+# Duke project template Team 3
This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it.
diff --git a/build.gradle b/build.gradle
index d5e548e85f..521b899823 100644
--- a/build.gradle
+++ b/build.gradle
@@ -29,11 +29,11 @@ test {
}
application {
- mainClass = "seedu.duke.Duke"
+ mainClass = "seedu.bankwithus.BankWithUs"
}
shadowJar {
- archiveBaseName = "duke"
+ archiveBaseName = "bankwithus"
archiveClassifier = null
}
@@ -43,4 +43,5 @@ checkstyle {
run{
standardInput = System.in
+ enableAssertions = true
}
diff --git a/docs/AboutUs.md b/docs/AboutUs.md
index 0f072953ea..2470b6293a 100644
--- a/docs/AboutUs.md
+++ b/docs/AboutUs.md
@@ -1,9 +1,10 @@
# About us
-Display | Name | Github Profile | Portfolio
---------|:----:|:--------------:|:---------:
- | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
- | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
- | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
- | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
- | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
+| Display | Name | Github Profile | Portfolio |
+|------------------------------------------------------|:-----------:|:----------------------------------------:|:-----------------------------------------------------------------------------:|
+|  | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/manushridiv.html) |
+|  | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/tyuyang.html) |
+|  | Liu Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/xiaoge26.html) |
+|  | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/vishnuvk47.html) |
+|  | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/Sherlock-YH.html) |
+
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 64e1f0ed2b..22128e6bc4 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -1,38 +1,498 @@
# Developer Guide
+* [Acknowledgements](#acknowledgements)
+* [Setting Up, Getting Started](#setting-up-getting-started)
+* [Design](#design-and-implementation)
+ * [Architecture](#architecture)
+ * [UI Component](#ui-component)
+ * [Parser Component](#parser-component)
+ * [BankWithUs Component](#bankwithus-component)
+ * [Account Component](#account-component)
+ * [AccountList Component](#accountlist-component)
+ * [SaveGoal Component](#savegoal-component)
+ * [Storage Component](#storage-component)
+ * [Withdrawal Limit Component](#withdraw-limit-checker-component)
+ * [Transaction Component](#transaction-component)
+ * [TransactionList Component](#transactionlist-component)
+* [Implementation](#design-and-implementation)
+ * [Add Account](#command--add-account-)
+ * [Delete](#command--delete)
+ * [Deposit](#command--deposit-)
+ * [Check Withdrawal Limit](#command--check-wl)
+ * [Setting Save Goal](#command--set-save-goal-)
+ * [Set Withdrawal Limit](#command--set-wl)
+ * [Show Save Goal](#command--show-save-goal-)
+ * [Withdraw](#command--withdraw-)
+ * [Switch Account](#command--switch-to)
+ * [View accounts](#command--view-account-)
+ * [Help](#command--help)
+ * [Summary of overall architecture](#summary-of-overall-architecture)
+* [Appendix](#appendix)
+ * [Product Scope](#product-scope)
+ * [Target User Profile](#target-user-profile)
+ * [Value Proposition](#value-proposition)
+ * [User Stories](#user-stories)
+ * [Non-Functional Requirements](#non-functional-requirements)
+ * [Glossary](#glossary)
+ * [Instructions for Manual Testing](#instructions-for-manual-testing)
+
+---
+
+
+
## Acknowledgements
+We adapted the structure of this document from the
+[AddressBook-Level3](https://se-education.org/addressbook-level3/DeveloperGuide.html)
+project created by the [SE-EDU initiative](https://se-education.org/).
+We used the content from the above project for
+the "Setting Up, Getting Started" and "Non-Functional Requirements" sections in
+this document as well.
+
+
+## Setting up, getting started
+First, **fork** this repo, and **clone** the fork into your computer.
+
+If you plan to use Intellij IDEA (highly recommended):
+
+1. **Configure the JDK**: Follow the guide
+[_[se-edu/guides] IDEA: Configuring the JDK_](https://se-education.org/guides/tutorials/intellijJdk.html) to ensure Intellij is configured to use JDK 11
+2. **Import the project as a Gradle project**:
+Follow the guide [_[se-edu/guides] IDEA: Importing a Gradle project_](https://se-education.org/guides/tutorials/intellijImportGradleProject.html)
+to import the project into IDEA.
+❗ Note: Importing a Gradle project is slightly different from importing
+a normal Java project
+3. **Verify the setup**:
+* Run the `seedu/bankwithus/BankWithUs.java` and try a few commands.
+You may want to refer to our User Guide for the list of commands
+* Run the tests to ensure they all pass
+
+
+
+## Design and Implementation
+
+### Architecture
+
+The Architecture Diagram given above explains the high-level design of the App.
+
+Given below is a quick overview of main components and how they interact with each other.
+
+For a quick link to a summary refer to: [Summary of overall architecture](#summary-of-overall-architecture)
+
+
+
+**Interactions**
+
+The sequence diagram below shows how components interact with each other when the user issues the command `deposit 100`.
+
+
+
+Note: The lifeline of the Transaction class does not end after the cross due to a limitation with PlantUML.
+
+
+### UI-Component
+
+Class: `Ui.java`
+
+* Contains all code that interfaces directly with the CLI
+
+
+
+### Parser-Component
+Class: `Parser.java`
+
+
+
+* Determines what the program would do with the input retrieved from the CLI
+
+### Account-Component
+Class: `Account.java`
+
+
+
+The `Account` component:
+
+* Contains `name`, `balance`, `saveGoal`, `withdrawChecker` attribute
+* Stores and manages all the account details that pertains to one account
+
+### AccountList-Component
+
+Class: `AccountList.java`
+
+The `AccountList` component:
+
+* Contains an `ArrayList` named `accountList` that contains the various
+different accounts that the user has
+* The `accountList` is used to navigate between accounts for the switch-to feature
+* When a new account is created it is appended to `accountList`
+
+### BankWithUs-Component
+Class: `BankWithUs.java`
+
+
+
+The `BankWithUs` component:
+
+* The Main Class
+* The whole program executes through the `BankWithUs` class
+
+### SaveGoal-Component
+Class: `SaveGoal.java`
+
+The `SaveGoal` component:
+
+* Allows users to add a savings goal
+* Allows users to add a deadline to the savings goal
+
+### Storage-Component
+Class: `Storage.java`
+
+The `Storage` component:
+
+* Handles storing data in the save files and also loading data, if any, when program opens
+
+### Withdraw-Limit-Checker-Component
+Class: `WithdrawalChecker.java`
+* Checks if the user has exceeded the withdrawal limit
+* Shows the current withdrawal limit and the total amount of money withdrawn in the current month
+
+
+### Transaction-Component
+Class: `Transaction.java`
+
+The `Transaction` component:
+
+* Stores the details of a transaction
+
+### TransactionList-Component
+Class: `TransactionList.java`
+
+The `TransactionList` component:
+* Contains an ArrayList
+that contains the various different transactions that the user has
+* Contains methods to add, delete and view transactions
+
+---
+
+# Implementation
+
+## Command: `help`
+
+* If a user command begins with help, it will call a method in the UI class to print the help screen.
+* Feature with the most basic implementation
+
+## Command: `view-account` :
+
+**Step 1**:
+
+* Calls `getAllAccountDetails()` method from the AccountList class.
+
+* The `getAllAccountDetails()` method parses the `ArrayList` from the AccountLits class
+
+* This builds a String where each Account is separated by a newline character and the attributes of an Account is separated by `;`
+
+**Step 2**:
+
+* This string is then passed to the `viewAccount()` class in UI, where the string is decoded and print to screen
+
+* Identify attributes that belong to a particular user by splitting the string based on a new line
+
+* The relevant attributes(Name, balance) of the account can ge identified by separating the string again by `;` and accessing index 0 and 1 respectively
+
+## Command: `withdraw` :
+
+**Step 1**:
+
+* Checks the args(AMOUNT to withdraw) for a negative sign in the `checkNegative()` method
+
+**Step 2**:
+
+* Calls the `withdrawMoney` method in the AccountList class
+
+* Checks if the AMOUNT entered is empty, number of decimal places(accepts only 2 d.p) and checks if the AMOUNT to be withdrawn is less than or equal to the available balance
+
+**Step 3**:
+
+* Checks if the AMOUNT to withdraw exceeds the set withdrawal limit, if any, in the `willExceedWithdrawalLimit` method of the withdrawalChecker class
+
+**Step 4**:
+
+* Checks if the AMOUNT to withdraw will cause the user to default on their set savings goal; though, users can proceed at their own discretion
+
+**Step 5**:
+
+* If it passes all the above checks or if the users decide to continue despite defaulting on save goal then it will call the `subtractBalance` method in the Account class
+
+* The `subtractBalance` will deduct the AMOUNT withdrawn from the users balance
+
+Note: Withdrawal will be cancelled if it fails to meet withdrawal limit or if users choose to meet savings goal
+
+**Step 6**:
+
+* New balance is displayed to the user via the `showBal()` method from AccountList class that makes use of the UI class' method to print to screen
-{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well}
+**Sequence Diagram**
-## Design & implementation
+General sequence diagram
-{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.}
+
+
+*Note: Many details especially from the SaveGoal and WithdrawalChecker classes have been omitted for brevity.*
+
+
+
+Exceed withdrawal limit case
+
+
+
+
+
+Fail save goal case
+
+
+
+
+
+
+## Command: `add-account`:
+
+**Step 1**:
+
+* Calls the `createNewAccount` method in AccountList class
+
+**Step 2**:
+
+* The `createNewAccount` request from the user via the interface for their username(name) and password
+
+* The method will continuously prompt users to enter a unique name, if a unique one wasnt already provided
+
+**Step 3**:
+
+* Based on the name and balance provided, a new account is created via the `addAccount` method
+
+**Step 4**:
+
+* Add account creates a new instance of an Account class with the specified attributes and appends to the current ArrayList
+
+## Command: `deposit`:
+
+**Step 1**:
+
+* Checks the args(AMOUNT to deposit) for a negative sign in the `checkNegative()` method
+
+**Step 2**:
+
+* Calls the `depositMoney` method in the AccountList class
+
+* Checks if the AMOUNT entered is empty, number of decimal places(accepts only 2 d.p)
+
+**Step 3**:
+
+* inside the `depositMoney` method, once it passes all the checks will call the `addBalance` method from the Account class to increment the balance as appropriate
+
+## Command: `set-save-goal`:
+
+**Step 1**:
+
+* Checks the args(minimum AMOUNT to save in balance) for a negative sign in the `checkNegative()` method
+
+**Step 2**:
+
+* If the AMOUNT to save is not empty then it request the user to enter a deadline for their savings goal
+
+* The parser then calls the `handleSaveGoal` method from the AccountList class
+
+**Step 3**:
+
+* Checks if the date format entered complies with the dd-MM-yyyy format in the `isDateFormatValid` method in AccountList class
+
+* If data entered matches the specified formats, then it will call the `setSaveGoal` method from the Account class which will set the relevant Save goal for the main account
+
+## Command: `show-save-goal`:
+
+**Step 1**:
+
+* Calls the `showGoal` method in the AccountList class which then prints the Save Goal attributes to the UI, if save goal amount is greater than 0
+
+## Command: `switch-to`
+
+**Step 1**:
+
+* Calls the `switchMainAccount` method from teh AccountList class with the NAME of the account to switch into.
+
+* If that account is found the method uses the `swap` method from `Collections` to swap the account that matches the NAME into index 0
+
+## Command: `delete`
+
+**Step 1**:
+
+* Calls the `deleteAccount` method from AccountList
+
+* This find the index of the account that matches the NAME of the account to be deleted and removes it from the ArrayList
+
+## Command: `set-wl`
+
+**Step 1**:
+
+* Calls the `setWithdrawalLimit` method in the AccountList class
+
+* The method will check for a number format exception and negative number exception before setting the specified AMOUNT as the withdrawal limit
+
+## Command: `check-wl`
+
+**Step 1**:
+
+* Calls the `checkWithdrawalLimit` method in AccountList class
+
+* Calls the getter method which then returns the Withdrawal limit
+
+**Step 2**:
+
+* Adds the attributes to a String array of size 2 which is then returned to the parser, where it then accesses the UI method to print to screen
+
+## Summary of overall architecture
+
+The application follows a simplified MVC architecture, where the Model is the `Storage` class, View is the `Ui` class
+and the controller is the `Parser` class and makes use of the command-line interface (CLI) where the user interacts with the
+program through the command-line prompt. The main class responsible for the CLI interaction is in the `BankWithUs` class
+that uses the `Ui` class to interact with the user and the `Parser` class to "route" and deal with commands as appropriate.
+The `BankWithUS` class contains a loop that continuously prompts the user for commands and then executes the corresponding action using the `Parser` class.
+
+The AccountList class is responsible for managing a list of Account objects. The Account class represents
+individual user accounts, and it contains attributes such as account number, balance, and savings goal. It
+also provides methods to manipulate the account data, such as depositing or withdrawing funds, checking the
+account balance, and setting the savings goal.
+
+When the user enters a command to interact with an account, such as deposit or withdraw, the `Parser` class calls
+the corresponding method in the AccountList class, which in turn calls the corresponding method in the Account
+class to modify the account data. If the command entered by the user is to create a new account, the AccountList
+class creates a new Account object and adds it to the ArrayList.
+
+The UI class, called `Ui`, is responsible for displaying messages to the user and decoding and displaying
+account information. It contains methods to display messages such as account creation success or failure and prompts
+for user input. It also has methods to display account information, such as the account balance, savings goal, and
+transaction history.
+
+Overall, the architecture is designed to separate concerns between the UI, the account management logic, and the
+individual account data. The `Parser` class acts as the intermediary between the user and the account management
+logic, while the `Ui` class handles the display of information to the user. The AccountList class manages the
+list of accounts, and the Account class represents the individual accounts and their data.
+
+---
+
+
+
+## Appendix
+
+### Product scope
+
+BankWithUs is a powerful and user-friendly CLI-based banking system
+that provides users with an easy and quick way to manage their financial
+transactions and budget accordingly. With its wide range of features and
+easy-to-use command syntax, BankWithUs makes it simple for users to manage their finances on the go.
-## Product scope
### Target user profile
-{Describe the target user profile}
+The target audience for the command line-based Banking System is individuals who value
+efficiency and simplicity in their financial management. This group includes students,
+freelancers, and small business owners who are looking for a fast and straightforward way to manage their finances.
+
### Value proposition
-{Describe the value proposition: what problem does it solve?}
+People who can type fast may benefit more from the CLI
+version of the banking system as it allows for
+quick navigation and interaction with the system using keyboard shortcuts.
+This can lead to a faster and more efficient workflow compared to using a graphical user interface (GUI),
+which may require more clicks and navigation. Additionally, fast typers may prefer the simplicity and
+minimalism of a CLI interface, as it provides only the essential information and features needed to manage their finances.
+
-## User Stories
+### User Stories
+
+| Version | As a ... | I want to ... | So that I can ... |
+|---------|----------|---------------------------------------|-----------------------------------------------------------------------------------------|
+| v1.0 | user | Add deposits | so that I can check my financial status |
+| v1.0 | user | Withdraw money | so that i can see the effect of my spending on balance |
+| v1.0 | user | view account | so that i can keep track of my minimum balance |
+| v2.0 | user | add a withdrawal limit | so that i can be forced to maintain a frugal habit |
+| v2.0 | user | add a savings goal | so that i can keep track of my spending in tandem with my savings goal |
+| v2.0 | user | add a new account | so that i can categorise my accounts and manage financial better |
+| v2.0 | user | switch account | so that i can navigate between the various accounts i have and keep track of financials |
+| v2.0 | user | list all the command that can be used | so that i can have a basic overview of the apps functionalities |
+| v2.1 | user | delete transaction records | so that i can get rid of trivial transaction records |
-|Version| As a ... | I want to ... | So that I can ...|
-|--------|----------|---------------|------------------|
-|v1.0|new user|see usage instructions|refer to them when I forget how to use the application|
-|v2.0|user|find a to-do item by name|locate a to-do without having to go through the entire list|
## Non-Functional Requirements
-{Give non-functional requirements}
+1. The application should work on any mainstream OS as long as it has Java 11 installed.
+2. A user with above average typing speed for regular English text
+ should be able to accomplish most of the tasks faster using commands than using the mouse.
## Glossary
-* *glossary item* - Definition
+* *Mainstream OS*: Windows, Linux, Unix, OS-X
+* *CLI*: Command Line Interface
+Some Operating Systems and their respective CLIs are listed below:
+Windows: Command Prompt
+ Linux: Linux Bash Shell
+ MacOs: Mac Terminal
## Instructions for manual testing
+### Launch
+1. Ensure you have Java 11 installed in your Computer
+2. Download the latest release from [here](https://github.com/AY2223S2-CS2113-T13-3/tp/releases)
+3. Copy the file to the folder you want to use as the home folder for BankWithUs, and rename the file to `BankWithUs.jar`
+4. Open a command terminal, cd into the folder you put the `BankWithUs.jar` file in, and use `java -jar BankWithUs.jar`
+command to run the application. A CLI should appear in a few seconds
+
+### Sample Test Cases
+
+#### Withdraw
+For these test cases, you need to have an account with a balance of at least 100 but not greater than 1000,
+and a withdrawal limit of 500.
+
+* Test case: `withdraw 100`
+Expected: A successful message and the new balance will be shown, and the balance of the account should be reduced by 100
+ ```
+ Withdrawal successful!
+ You have $600.00 remaining!
+ ```
+* Test case: `withdraw 1001`
+Expected: An alert message `You do not have sufficient Balance` will be shown, and the balance of the account should not be changed
+* Test case: `withdraw 501`
+Expected: An alert message will be shown, including the current withdrawal limit
+ and the amount you have withdrawn in this month. The balance of the account should not be changed
+The alert message should be similar to this:
+ ```
+ Apologies! Your transaction did not go through as it will result
+ in you exceeding your withdrawal limit!
+ Withdrawal limit is currently $500.
+ You have withdrawn $100 this month.
+ ```
+
+* Test case: `withdraw abcd`
+Expected: An error message `The input is not a valid number! Please try again.` will be shown, and the balance of the account should not be changed
+* Test case: `withdraw -100`
+Expected: An error message `Negative amount entered!` will be shown, and the balance of the account should not be changed
+
+
+#### Deposit
+Similar to withdraw, you can try out the following test cases:
+
+* Test case: `deposit 100`
+Expected: A successful message and the new balance will be shown,
+ and the balance of the account should be increased by 100
+The successful message should be similar to this:
+ ```
+ New deposit added!
+ You have $800.00 remaining!
+ ```
+* Test case: `deposit abc`
+Expected: An error message `The input is not a valid number! Please try again.` will be shown, and the balance of the account should not be changed
+* Test case: `deposit -100`
+Expected: An error message`Negative amount entered!`will be shown, and the balance of the account should not be changed
+
-{Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing}
+Please refer to the Features section in our [UserGuide](UserGuide.md) for more details on other test cases
+that you can try out.
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
index bbcc99c1e7..04b6c7fbd0 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,6 +1,18 @@
-# Duke
+# BankWithUs
-{Give product intro here}
+### Product description
+
+BankWithUs is a powerful and user-friendly CLI-based banking system
+that provides users with an easy and quick way to manage their financial
+transactions and budget accordingly. With its wide range of features and
+easy-to-use command syntax, BankWithUs makes it simple for users to manage their finances on the go.
+
+
+### Target user profile
+
+The target audience for the command line-based Banking System is individuals who value
+efficiency and simplicity in their financial management. This group includes students,
+freelancers, and small business owners who are looking for a fast and straightforward way to manage their finances.
Useful links:
* [User Guide](UserGuide.md)
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index abd9fbe891..911b5c3dab 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -1,42 +1,441 @@
-# User Guide
+# BankWithUs User Guide
-## Introduction
+--------------------------------------------------------------------------------------------------------------------
+## Table of contents:
+* [Quick-start guide](#quick-start)
+* [Features](#features)
+ * [Help Message](#help-message)
+ * [Add New Account](#add-account)
+ * [Switch Account](#switch-account)
+ * [Delete Account](#delete-account)
+ * [View Account](#view-account)
+ * [Deposit](#deposit)
+ * [Withdraw](#withdraw)
+ * [Transaction History](#view-transaction)
+ * [Set Save Goal](#set-save-goal)
+ * [Show Save Goal](#show-save-goal)
+ * [Withdraw Limit](#set-wl)
+ * [Check Withdraw Limit](#check-wl)
+ * [Delete Transaction History](#delete-transaction)
+ * [Exiting Program](#exit)
+* [Frequently Asked Questions (FAQ)](#FAQ)
+* [Command Summary](#command-summary)
-{Give a product intro}
+--------------------------------------------------------------------------------------------------------------------
-## Quick Start
+
+## Quick-start guide
-{Give steps to get started quickly}
+1. Ensure you have Java `11` or above installed in your Computer.
-1. Ensure that you have Java 11 or above installed.
-1. Down the latest version of `Duke` from [here](http://link.to/duke).
-## Features
+2. Download the latest `BankWithUs.jar` from [here](https://github.com/AY2223S2-CS2113-T13-3/tp/releases).
-{Give detailed description of each feature}
-### Adding a todo: `todo`
-Adds a new item to the list of todo items.
+3. Copy the file to the folder you want to use as the _home folder_ for your BankWithUs app.
-Format: `todo n/TODO_NAME d/DEADLINE`
-* The `DEADLINE` can be in a natural language format.
-* The `TODO_NAME` cannot contain punctuation.
+4. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar BankWithUs.jar` command to run the application.
-Example of usage:
-`todo n/Write the rest of the User Guide d/next week`
+5. Follow the instruction as per the CLI and create your new account. e.g. typing **`help`** and pressing Enter will open the help option.
+ Some example commands you can try:
-`todo n/Refactor the User Guide to remove passive voice d/13/04/2020`
+ * `view-transactions-all` : Lists all recorded transactions.
-## FAQ
+ * `withdraw 300` : Withdraws $300 from the current balance. (Subsitute 300 for other numbers)
-**Q**: How do I transfer my data to another computer?
+ * `delete ACCOUNT_NAME` : Deletes the account with the given account name.
-**A**: {your answer here}
+ * `deposit 100` : Deposits $100 into the users account. (Subsitute 100 for other numbers)
-## Command Summary
+ * `exit` : Exits the application.
-{Give a 'cheat sheet' of commands here}
+6. For first-time user the program will ask you to create one account when launched.
-* Add todo `todo n/TODO_NAME d/DEADLINE`
+
+7. Refer to the [Features](#features) below for details of each command.
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+## Features
+
+
+
+**Notes about the command format:**
+
+* Words in `UPPER_CASE` are the parameters to be supplied by the user.
+ e.g. in `deposit AMOUNT`, `AMOUNT` is a parameter. `deposit 300` is an example of a valid command syntax.
+
+
+* All `AMOUNT` parameter has to be less than three decimal places or it would not be taken in.
+ e.g. `deposit 100.111` will be treated as an input error
+
+
+* Parameters MUST be in the specified order for the command to take appropriate effect.
+
+
+* Extraneous parameters for commands that do not take in parameters (such as `help`, `view-transactions-all`, `exit`, `add-account`) will be ignored.
+ e.g. If the command specifies `help 123`, it will be interpreted as `help`.
+
+
+* We use `>>` to indicate the user input.
+ e.g. `>>help` means the user input "help" and press enter.
+
+
+
+### Viewing help : `help`
+
+
+Shows a list of all the commands available and what they do.
+
+Format: `help`
+
+Example:
+```
+>>help
+----------------------------
+help: displays the current menu
+view-account: shows all the accounts' name and balance
+withdraw : withdraws from available balance
+deposit : deposits and adds deposit to balance
+set-save-goal : sets a saveGoal of until
+show-save-goal: shows the current save goal and the deadline
+add-account: adds a new account
+switch-to : switches to account
+delete : deletes the account with username
+set-wl : sets to be the withdrawal limit
+check-wl: shows the withdrawal limit and the amount of money withdrawn this month
+view-transactions-all: views all transactions across all accounts
+delete-transaction : deletes the transaction with the given transaction index
+view-current: shows the relevant details of the current account
+exit: quits program and saves
+```
+
+
+### Adding an account: `add-account`
+
+
+Initiates the process of adding a new account. The user is not required to input any parameters when calling the command.
+However, once the command starts, it will prompt the user for their name and initial balance.
+
+Format: `add-account`
+CLI prompts: "Whats your name?"
+your input: `NAME`
+CLI prompts: "How much would you like to add as Balance?"
+your input: `BALANCE` Note: Balance has to be a valid number.
+
+
+
+Example:
+
+```
+>>add-account
+What is your name?
+>>Steve
+How much would you like to add as Balance?
+>>1000
+Account added!
+Name: Steve
+Balance: $1000
+----------------------------
+```
+
+
+### Switch to another account: `switch-to`
+
+
+Switches from the *current account* to the new requested account, if it exists.
+
+Format: `switch-to NAME`
+
+* The search is case-sensitive. e.g `jane` will NOT match `Jane`
+* Only the name is searched.
+* Only full words will be matched e.g. `Ben` will not match `Benjamin`
+
+
+
+Example:
+```
+>>switch-to jenson
+Current Account switched
+----------------------------
+Current Account is:
+----------------------------
+Name: jenson
+Balance: $90.00
+----------------------------
+```
+
+
+
+### Delete an account: `delete`
+
+
+Format: `delete ACCOUNT_NAME`
+
+* Deletes the account with the given account name
+* The match is case-sensitive. e.g `jane` will NOT match `Jane`
+* Only the name is searched
+* Only full words will be matched e.g. `Ben` will not match `Benjamin`
+
+Examples:
+```
+>>delete jameson
+Account: jameson deleted
+----------------------------
+```
+Deletes the jameson account.
+
+
+### View the details of all the accounts: `view-account`
+
+
+Shows a list of all the available accounts with their account name and balance.
+
+Format: `view-account`
+
+Example:
+```
+>>view-account
+Current Account:
+Name: james
+Balance: $1000.00
+----------------------------
+Name: john
+Balance: $300.00
+----------------------------
+```
+
+
+### View the details of the current account: `view-current`
+
+
+Shows the details of the current account.
+Format: `view-current`
+Example:
+```
+>>view-current
+Name: john
+Balance: $300.00
+----------------------------
+```
+
+
+### Deposit: `deposit`
+
+
+Deposits AMOUNT into the *current account*.
+
+Format: `deposit AMOUNT`
+
+Example:
+```
+>>deposit 100
+New deposit added!
+You have $190.00 remaining!
+```
+
+* Cannot deposit negative numbers
+* Cannot deposit arguments that are not numbers
+
+Attempting to do the above cause the program to show error messages.
+
+
+
+### Withdraw: `withdraw`
+
+
+Withdraws AMOUNT from the users balance.
+
+Format: `withdraw AMOUNT`
+
+Example:
+```
+>>withdraw 50
+Withdrawal successful!
+You have $140.00 remaining!
+----------------------------
+```
+
+* Cannot withdraw more than balance.
+* Cannot withdraw negative numbers.
+* Cannot withdraw arguments that are not numbers.
+
+Attempting to do so will show error messages.
+
+
+### List all transactions: `view-transactions-all`
+
+Shows a list of all the transactions processed by all the accounts of the user.
+
+Format: `view-transactions-all`
+
+Example:
+```
+>>view-transactions-all
+1. Account Name: jenson Transaction Type: deposit Amount: 100 Date: 26/03/2023
+2. Account Name: jenson Transaction Type: withdraw Amount: 10 Date: 26/03/2023
+```
+
+### Add a savings goal to the current account: `set-save-goal`
+
+Adds a savings goal to the *current account*.
+Will raise an alert when user attempting to `withdraw` more than the savings goal, if attempt is before deadline
+
+Format: `set-save-goal AMOUNT` The app will then prompt the user for the deadline.
+
+* The amount to save has to be a number, -ve numbers allowed -- can be used to overwrite as no savings goal
+* Deadline entered has to be in dd-mm-YYYY format. No other format will be entertained by the program
+* Any error will only be displayed after the deadline is received and processed
+
+Examples:
+```
+>>set-save-goal 300
+What would be the end date for the duration of your Saving goal?
+>>11-11-2023
+Try saving a minimum of $300 until 11-11-2023
+Save Goal has been created, Have fun staying frugal!
+```
+
+
+
+### Check the current savings goal: `show-save-goal`
+
+
+Shows the current savings goal and the deadline of the current account.
+```
+>>show-save-goal
+Min amount to save: $300
+Deadline: 11-11-2023
+----------------------------
+```
+
+
+### Set a withdrawal limit: `set-wl`
+
+
+Adds a withdrawal limit to the *current account*.
+Will prevent the user from making the withdrawal if it will result in them exceeding the withdrawal limit in the current month. The amount of withdrawals will reset at the beginning of every month.
+
+Format: `set-wl AMOUNT` will set `AMOUNT` as the withdrawal limit.
+
+* `AMOUNT` must be a valid number. If `AMOUNT` is not valid, an error message will be shown.
+
+```
+>>set-wl 100
+Withdrawal limit set to $100!
+----------------------------
+>>withdraw 1000
+Apologies! Your transaction did not go through as it will result
+in you exceeding your withdrawal limit!
+Withdrawal limit is currently $100.
+You have withdrawn $0 this month.
+----------------------------
+```
+
+### Check the current withdrawal limit: `check-wl`
+
+Shows the current withdrawal limit and the total amount of money withdrawn in the current month.
+
+Format: `check-wl`
+
+Example:
+```
+>>set-wl 100
+Withdrawal limit set to $100!
+----------------------------
+>>check-wl
+Withdrawal limit is currently $100
+You have withdrawn $0 this month.
+----------------------------
+>>withdraw 50
+Withdrawal successful!
+You have $9950 remaining!
+----------------------------
+>>check-wl
+Withdrawal limit is currently $100.
+You have withdrawn $50 this month.
+```
+
+### Delete a transaction record: `delete-transaction`
+
+Delete the transaction record with the given transaction index.
+The index is the number shown in the list of transactions when `view-transactions-all` is called.
+Take note that this will only delete the transaction record, but will not affect the balance of the account.
+
+Format: `delete-transaction INDEX`
+
+Example:
+```
+view-transactions-all
+1. Account Name: xixi Transaction Type: withdraw Amount: 234 Date: 04/04/2023
+2. Account Name: xixi Transaction Type: deposit Amount: 1 Date: 04/04/2023
+----------------------------
+delete-transaction 2
+Transaction deleted successfully
+----------------------------
+view-transactions-all
+1. Account Name: xixi Transaction Type: withdraw Amount: 234 Date: 04/04/2023
+```
+
+
+### Exit the program : `exit`
+
+
+Exits the program.
+
+Format: `exit`
+
+### Saving the data
+
+BankWithUs data is automatically stored when user exits the program. No manual inteference is required.
+
+### Editing the data files
+
+Please do not edit the data files.
+
+
+Warning:
+If you attempt to manipulate the data files (save.txt and transaction.txt)
+and corrupted data is being parsed, you will be thrown exceptions.
+If this inhibits the program from running,
+please delete the existing files and run program again.
+Please keep in mind that this will result in irreversible data loss.
+
+
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+## FAQ
+
+**Q**: How do I transfer my data to another Computer?
+**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder.
+
+
+**Q**: Why was my recurring transactions not updated in the text file?
+**A**: The text file is updated every time when user exit the program.
+--------------------------------------------------------------------------------------------------------------------
+
+## Command summary
+
+| Action | Format, Examples |
+|----------------------------------|----------------------------|
+| **Add an account** | `add-account` |
+| **View all accounts details** | `view-account` |
+| **View current account details** | `view-current` |
+| **Switch to a new account** | `switch-to ACC_NAME` |
+| **Delete an account** | `delete ACC-NAME` |
+| **Withdraw some amount** | `withdraw AMOUNT` |
+| **Deposit some amount** | `deposit AMOUNT` |
+| **Add a savings goal** | `set-save-goal AMOUNT` |
+| **Show the savings goal** | `show-save-goal` |
+| **Add a withdraw limit** | `set-wl AMOUNT` |
+| **Show the withdraw limit** | `check-wl` |
+| **View all the transactions** | `view-transactions-all` |
+| **Delete a transaction** | `delete-transaction INDEX` |
+| **View help menu** | `help` |
+| **Exit** | `exit` |
\ No newline at end of file
diff --git a/docs/diagrams/BWU_class.puml b/docs/diagrams/BWU_class.puml
new file mode 100644
index 0000000000..e22637a1b2
--- /dev/null
+++ b/docs/diagrams/BWU_class.puml
@@ -0,0 +1,21 @@
+@startuml
+skinparam classAttributeIconSize 0
+hide circle
+class BankWithUs {
+ -isExitEntered: boolean
+ -storage: Storage
+ -ui: Ui
+ -accountList: AccountList
+ -transactionList: TransactionList
+ -parser: Parser
+ +ACCOUNTS_FILE_PATH: String
+ +TRANSACTIONS_FILE_PATH: String
+ +BankWithUs(accountsFilePath: String, transactionsFilePath: String)
+ +getAccountList(): AccountList
+ +getTransactionList(): TransactionList
+ +getUi(): Ui
+ +exit(): void
+ +run(): void
+ +main(args: String[]): void
+}
+@enduml
\ No newline at end of file
diff --git a/docs/diagrams/Parser_classdiag.puml b/docs/diagrams/Parser_classdiag.puml
new file mode 100644
index 0000000000..ec99f14c7b
--- /dev/null
+++ b/docs/diagrams/Parser_classdiag.puml
@@ -0,0 +1,14 @@
+@startuml
+skinparam classAttributeIconSize 0
+hide circle
+class Parser {
+ -scanner: Scanner
+ -commandFactory: CommandFactory
+ -accountsFile: File
+ -transactionsFile: File
+ +Parser(accountsFile: File, transactionsFile: File)
+ +parseCommand(commandString: String): Command
+ +parseAccount(accountString: String): Account
+ +parseTransaction(transactionString: String): Transaction
+}
+@enduml
diff --git a/docs/diagrams/account_class.puml b/docs/diagrams/account_class.puml
new file mode 100644
index 0000000000..c3e542a450
--- /dev/null
+++ b/docs/diagrams/account_class.puml
@@ -0,0 +1,20 @@
+@startuml
+skinparam classAttributeIconSize 0
+hide circle
+class Account {
+ - saveGoal: SaveGoal
+ - name: String
+ - balance: BigDecimal
+ - withdrawalChecker: WithdrawalChecker
+ + Account(name: String, balance: String, amtToSave: String, untilWhen: LocalDate)
+ + Account(name: String, balance: String, totalAmtWithdrawn: String, lastWithdrawnDate: LocalDate, amtToSave: String, untilWhen: LocalDate)
+ + getAccountName(): String
+ + getAccountBalance(): BigDecimal
+ + getWithdrawalChecker(): WithdrawalChecker
+ + addBalance(balanceToBeAdded: BigDecimal): void
+ + subtractBalance(currentBalance: BigDecimal, withdrawal: BigDecimal): void
+ + setSaveGoal(saveGoal: SaveGoal, args: String, untilWhenStr: String): void
+ + getName(): String
+ + getSaveGoal(): SaveGoal
+}
+@enduml
diff --git a/docs/diagrams/example_sequence_diagram.puml b/docs/diagrams/example_sequence_diagram.puml
new file mode 100644
index 0000000000..14072b0009
--- /dev/null
+++ b/docs/diagrams/example_sequence_diagram.puml
@@ -0,0 +1,70 @@
+@startuml deposit100SeqDiagram
+actor Shawn
+participant ":Ui"
+participant ":BWU"
+participant ":Parser"
+participant ":AccountList"
+participant ":Account"
+participant ":TransactionList"
+activate ":BWU"
+loop if exit not entered
+":BWU" -> ":Ui":getNextLine()
+activate ":Ui"
+Shawn -> ":Ui":deposit 100
+":Ui" --> ":BWU":"deposit 100"
+deactivate ":Ui"
+":BWU" -> ":Parser":parseUserInput(line)
+activate ":Parser"
+alt deposit
+":Parser" -> ":AccountList":depositMoney(args)
+activate ":AccountList"
+":AccountList" -> ":Account":addBalance()
+activate ":Account"
+":Account" -> ":Account":balance += 100
+":Account" --> ":AccountList"
+deactivate ":Account"
+":AccountList" --> ":Parser"
+deactivate ":AccountList"
+":Parser" -> ":TransactionList":createNewTransaction()
+activate ":TransactionList"
+create ":Transaction"
+":TransactionList" -> ":Transaction":new ":Transaction"()
+activate ":Transaction"
+":Transaction" --> ":TransactionList"
+deactivate ":Transaction"
+":TransactionList" -> ":TransactionList":add(transaction)
+activate ":TransactionList"
+":TransactionList" --> ":TransactionList"
+deactivate ":TransactionList"
+destroy ":Transaction"
+":TransactionList" --> ":Parser"
+deactivate ":TransactionList"
+":Parser" -> ":Ui":showDepositMessage()
+activate ":Ui"
+":Ui" -> Shawn: New deposit added!
+":Ui" --> ":Parser"
+deactivate ":Ui"
+":Parser" -> ":AccountList":showBal()
+activate ":AccountList"
+":AccountList" -> ":Account":getMain":Account"()
+":Account" -> ":Account":get":Account"Balance()
+activate ":Account"
+":Account" --> ":AccountList"
+deactivate ":Account"
+":AccountList" -> ":Ui":showBal()
+activate ":Ui"
+":Ui" -> Shawn:You have $140 remaining!
+":Ui" --> ":AccountList"
+deactivate ":Ui"
+":AccountList" --> ":Parser"
+deactivate ":AccountList"
+":Parser" -> ":Ui":printLine()
+activate ":Ui"
+":Ui" -> Shawn:------------------------
+":Ui" --> ":Parser"
+deactivate ":Ui"
+end
+":Parser" --> ":BWU"
+deactivate ":Parser"
+end
+@enduml
\ No newline at end of file
diff --git a/docs/diagrams/exceed_wl_seq_diagram.puml b/docs/diagrams/exceed_wl_seq_diagram.puml
new file mode 100644
index 0000000000..5c86e1e73b
--- /dev/null
+++ b/docs/diagrams/exceed_wl_seq_diagram.puml
@@ -0,0 +1,21 @@
+@startuml ExceedWLCase
+participant ":AccountList"
+participant ":Account"
+participant ":WithdrawalChecker"
+activate ":AccountList"
+":AccountList" -> ":Account":getMainAccount()
+activate ":Account"
+":Account" --> ":AccountList"
+deactivate ":Account"
+":AccountList" -> ":Account":getWithdrawalChecker()
+activate ":Account"
+":Account" --> ":AccountList"
+deactivate ":Account"
+":AccountList" -> ":WithdrawalChecker":willExceedWithdrawalLimit()
+activate ":WithdrawalChecker"
+opt no withdrawal limit set
+":WithdrawalChecker" --> ":AccountList":return false
+end
+":WithdrawalChecker" --> ":AccountList":return totalAmtWithdrawn + \nwithdrawnAmount > withdrawalLimit
+deactivate ":WithdrawalChecker"
+@enduml
\ No newline at end of file
diff --git a/docs/diagrams/fail_save_goal_case_seq_diagram.puml b/docs/diagrams/fail_save_goal_case_seq_diagram.puml
new file mode 100644
index 0000000000..0372d800ba
--- /dev/null
+++ b/docs/diagrams/fail_save_goal_case_seq_diagram.puml
@@ -0,0 +1,46 @@
+@startuml FailSaveGoalCase
+participant ":Parser"
+participant ":AccountList"
+participant ":Account"
+participant ":SaveGoal"
+participant ":Ui"
+activate ":AccountList"
+":AccountList" -> ":AccountList":willFailsSaveGoal()
+activate ":AccountList"
+":AccountList" -> ":Account":getMainAccount()
+activate ":Account"
+":Account" --> ":AccountList"
+deactivate ":Account"
+":AccountList" -> ":SaveGoal":getSaveGoal()
+activate ":SaveGoal"
+":SaveGoal" --> ":AccountList":return amtToSave
+deactivate ":SaveGoal"
+":AccountList" -> ":SaveGoal":getSaveGoal()
+activate ":SaveGoal"
+":SaveGoal" --> ":AccountList":return untilWhen
+deactivate ":SaveGoal"
+":AccountList" --> ":AccountList":return amtToSave\n&& untilWhen
+deactivate ":AccountList"
+":AccountList" -> ":Ui":failToMeetSaveGoal()
+activate ":Ui"
+":Ui" --> ":AccountList"
+deactivate ":Ui"
+":AccountList" -> ":AccountList":handleProceed()
+activate ":AccountList"
+loop yesOrNo is not 'Y' or 'N'
+":AccountList" -> ":Ui":getNextLine()
+activate ":Ui"
+":Ui" --> ":AccountList"
+deactivate ":Ui"
+end
+alt yesOrNo == 'Y'
+":AccountList" -> ":Account":getMainAccount().\nsubtractBalance()
+activate ":Account"
+":Account" --> ":AccountList"
+deactivate ":Account"
+else yesOrNo == 'N'
+":AccountList" --> ":Parser":throws WithdrawalCancelled\nException
+end
+":AccountList" --> ":AccountList"
+deactivate ":AccountList"
+@enduml
\ No newline at end of file
diff --git a/docs/diagrams/main_architecture.puml b/docs/diagrams/main_architecture.puml
new file mode 100644
index 0000000000..156ea10ced
--- /dev/null
+++ b/docs/diagrams/main_architecture.puml
@@ -0,0 +1,22 @@
+@startuml MainArchitecture
+class BankWithUs
+class Storage
+class AccountList
+class Ui
+class TransactionList
+class Parser
+BankWithUs --> Storage
+AccountList ..> Storage
+TransactionList ..> Storage
+BankWithUs --> Parser
+BankWithUs --> AccountList
+AccountList ..> BankWithUs
+BankWithUs --> TransactionList
+BankWithUs --> Ui
+Parser --> Ui
+Parser <--> AccountList
+Parser <--> TransactionList
+AccountList --> Ui
+TransactionList --> Ui
+
+@enduml
\ No newline at end of file
diff --git a/docs/diagrams/withdraw_seq_diagram.puml b/docs/diagrams/withdraw_seq_diagram.puml
new file mode 100644
index 0000000000..7880c7bcd3
--- /dev/null
+++ b/docs/diagrams/withdraw_seq_diagram.puml
@@ -0,0 +1,49 @@
+@startuml WithdrawFunction
+participant ":Parser"
+participant ":AccountList"
+participant ":Account"
+participant ":TransactionList"
+activate ":Parser"
+":Parser" -> ":Parser":checkNegative()
+activate ":Parser"
+":Parser" --> ":Parser"
+deactivate ":Parser"
+":Parser" -> ":AccountList":withdrawMoney()
+activate ":AccountList"
+opt amt blank ||\namt negative ||\namt insufficient||\nexceed wl||\nfail save goal
+":AccountList" --> ":Parser" : throws exception
+end
+":AccountList" -> ":Account":getMainAccount().\nsubtractBalance()
+activate ":Account"
+":Account" --> ":AccountList"
+deactivate ":Account"
+":AccountList" --> ":Parser"
+deactivate ":AccountList"
+":Parser" -> ":TransactionList":createTransaction()
+activate ":TransactionList"
+create ":Transaction"
+":TransactionList" -> ":Transaction":new ":Transaction"()
+activate ":Transaction"
+":Transaction" --> ":TransactionList"
+deactivate ":Transaction"
+":TransactionList" -> ":TransactionList":add(transaction)
+activate ":TransactionList"
+":TransactionList" --> ":TransactionList"
+deactivate ":TransactionList"
+destroy ":Transaction"
+":TransactionList" --> ":Parser"
+deactivate ":TransactionList"
+":Parser" -> ":AccountList":showBal()
+activate ":AccountList"
+":AccountList" -> ":Account":getMainAccount().\ngetAccountBalance()
+activate ":Account"
+":Account" --> ":AccountList"
+deactivate ":Account"
+":AccountList" -> ":Ui":showBal()
+activate ":Ui"
+":Ui" --> ":AccountList"
+deactivate ":Ui"
+":AccountList" --> ":Parser"
+deactivate ":AccountList"
+
+@enduml
\ No newline at end of file
diff --git a/docs/images/ExceedWLCase.png b/docs/images/ExceedWLCase.png
new file mode 100644
index 0000000000..693bb5e72d
Binary files /dev/null and b/docs/images/ExceedWLCase.png differ
diff --git a/docs/images/FailSaveGoalCase.png b/docs/images/FailSaveGoalCase.png
new file mode 100644
index 0000000000..f2726d8901
Binary files /dev/null and b/docs/images/FailSaveGoalCase.png differ
diff --git a/docs/images/MainArchitecture.png b/docs/images/MainArchitecture.png
new file mode 100644
index 0000000000..0184c70364
Binary files /dev/null and b/docs/images/MainArchitecture.png differ
diff --git a/docs/images/UML_CLASS_DIAGS/ACCOUNT_CLASS.png b/docs/images/UML_CLASS_DIAGS/ACCOUNT_CLASS.png
new file mode 100644
index 0000000000..9a63630d73
Binary files /dev/null and b/docs/images/UML_CLASS_DIAGS/ACCOUNT_CLASS.png differ
diff --git a/docs/images/UML_CLASS_DIAGS/BWU_CLASS.png b/docs/images/UML_CLASS_DIAGS/BWU_CLASS.png
new file mode 100644
index 0000000000..4a2a9f30a4
Binary files /dev/null and b/docs/images/UML_CLASS_DIAGS/BWU_CLASS.png differ
diff --git a/docs/images/UML_CLASS_DIAGS/PARSER_CLASS.png b/docs/images/UML_CLASS_DIAGS/PARSER_CLASS.png
new file mode 100644
index 0000000000..5a81099d8b
Binary files /dev/null and b/docs/images/UML_CLASS_DIAGS/PARSER_CLASS.png differ
diff --git a/docs/images/WithdrawFunction.png b/docs/images/WithdrawFunction.png
new file mode 100644
index 0000000000..e599f966c3
Binary files /dev/null and b/docs/images/WithdrawFunction.png differ
diff --git a/docs/images/deposit100SeqDiagram.png b/docs/images/deposit100SeqDiagram.png
new file mode 100644
index 0000000000..12ef89bc01
Binary files /dev/null and b/docs/images/deposit100SeqDiagram.png differ
diff --git a/docs/team/Sherlock-YH.md b/docs/team/Sherlock-YH.md
new file mode 100644
index 0000000000..76c1db6b3a
--- /dev/null
+++ b/docs/team/Sherlock-YH.md
@@ -0,0 +1,39 @@
+# Project Portfolio Page (Sherlock-YH)
+
+## Overview
+
+Created a CLI-based application which acts as a Banking system with other team members.
+
+
+Users can create accounts, deposit money, withdraw money, set save goal, set withdrawal limit, and view previous transactions with this application.
+
+## Summary of Contributions
+
+[Link to code contributed](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=T13-3&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=true&tabType=authorship&tabAuthor=Sherlock-YH&tabRepo=AY2223S2-CS2113-T13-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
+
+### Enhancements implemented
+
+* Created switch main account feature
+
+* Created saving and loading saved account data features
+
+* Created delete account feature
+
+* Created getAllAccountDetail method which complements many other methods
+
+* Created many Exceptions catches which helps the whole program run properly. Eg. Check whether input of users is valid
+
+
+### Team-based tasks
+
+* Helped in resolving bugs
+
+* Reviewed and approved many PRs not authored by myself.
+
+* Helped in adding contents in User Guide
+
+* Add table of contents in User Guide
+
+#### Contributions beyond the project team
+
+* [reported 10 bugs during the PE-D](https://github.com/Sherlock-YH/ped/issues)
\ No newline at end of file
diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md
deleted file mode 100644
index ab75b391b8..0000000000
--- a/docs/team/johndoe.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# John Doe - Project Portfolio Page
-
-## Overview
-
-
-### Summary of Contributions
diff --git a/docs/team/manushridiv.md b/docs/team/manushridiv.md
new file mode 100644
index 0000000000..f754f21ca4
--- /dev/null
+++ b/docs/team/manushridiv.md
@@ -0,0 +1,40 @@
+# Project Portfolio Page (manushridiv)
+
+## Overview
+
+A CLI-based banking application was created that allows users to edit and maintain any withdrawal balances from their account by taking any amount required from their created account, and showing the remaining levels of savings in their account.
+
+## Summary of Contributions
+
+### Code contributed
+[Link to code contributed](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=manushridiv&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=true&tabType=authorship&tabAuthor=manushridiv&tabRepo=AY2223S2-CS2113-T13-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
+
+### Enhancements implemented
+
+I have developed the Withdrawal feature, which allows users to add a new deposit to the current account.
+My teammates have also modified it to suit the evolved needs of the application.
+
+I have also developed and added onto the features relating to withdrawal bug fixes and transaction details which my teammates has enhanced.
+
+### UG contributions
+
+Documented the general features and cleaned up on the phrasing and setup for the various features.
+
+### DG contributions
+
+Added to sections which include 'Acknowledgements' 'Setting Up, Getting Started', and 'Instructions for Manual Testing' with reference to
+[AddressBoook-Level3](https://se-education.org/addressbook-level3/DeveloperGuide.html).
+Modified the DG template and fixed the typos and standardized the format.
+
+
+### Team-based tasks
+
+* Did extensive bug testing for version 2.0 with [tyuyang](https://github.com/tyuyang)
+* Helped in creating issues for the team to work on
+* Helped to identify existing bugs and squash them as a team
+* Updated User/Developer Guides to a feature e.g. Non-Functional Requirements and Instructions for Manual Testing)
+* Released v2.0 of the application
+* Reviewed and approved PRs authored by members of the organisation
+* Refactored the code to different packages
+* assigned and handled bug testing and added the bug issues to the github org for team to work on
+* completed and conducted reviews for pull requests for the team
\ No newline at end of file
diff --git a/docs/team/tyuyang.md b/docs/team/tyuyang.md
new file mode 100644
index 0000000000..0c104cd7ed
--- /dev/null
+++ b/docs/team/tyuyang.md
@@ -0,0 +1,43 @@
+# Project Portfolio Page (tyuyang)
+
+## Overview
+
+Helped create a CLI-based application that acts like a banking app. Users can create accounts, deposit money, withdraw money, set save goal, set withdrawal limit, and view previous transactions with this application.
+
+## Summary of Contributions
+
+[Link to code contributed](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=T13-3&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=true&tabType=authorship&tabAuthor=tyuyang&tabRepo=AY2223S2-CS2113-T13-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code~other&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
+
+### Enhancements implemented
+
+Created the withdrawal limit feature ([#67](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/67), [#70](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/70), and [#71](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/71)). Since this feature required the tracking of withdrawals in a month, a separate feature that tracks how much money has been withdrawn in the current month had to be created. In addition, the use of LocalDate also had to be integrated into the feature, which adds to the complexity of this feature. This feature also heavily interacts with the withdraw feature, which meant that bugs that arose from integration needed to be prevented. In conclusion, this feature does not really have any bugs and works as expected in all tested situations.
+
+Did some of the infrastructural work, such as the first iteration of the product ([#8](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/8)), the skeleton code for the load() function ([#21](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/21)), and the skeleton code for the run() function ([#29](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/29)). This allowed my teammates to start on their assigned features without having to worry about how classes interact with each other.
+
+### UG contributions
+
+Authored the withdrawal limit section. Worked with [vishnuvk47](https://github.com/vishnuvk47) to add examples of expected program behaviour.
+
+### DG contributions
+
+Created the puml diagrams for [main architecture](../diagrams/main_architecture.puml), [example sequence diagram](../diagrams/example_sequence_diagram.puml), [withdraw command](../diagrams/withdraw_seq_diagram.puml), [exceed withdrawal limit case](../diagrams/exceed_wl_seq_diagram.puml), and [fail save goal case](../diagrams/fail_save_goal_case_seq_diagram.puml).
+
+
+### Team-based tasks
+
+Helped in creating issues for the team to work on, especially at the start of the project.
+
+Did extensive bug testing for version 2.0 with [manushridiv](https://github.com/manushridiv) and published them as issues. Almost all of the functionality bugs found by others in the PED were already found before the PED with the exception of [issue #123](https://github.com/AY2223S2-CS2113-T13-3/tp/issues/123), [issue #114](https://github.com/AY2223S2-CS2113-T13-3/tp/issues/114) and [issue #127](https://github.com/AY2223S2-CS2113-T13-3/tp/issues/127).
+
+Helped restructure and clean up the code in [this PR](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/48).
+
+
+Reviewed and approved a significant number of PRs not authored by myself. Examples below:
+
+[#31](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/31), [#34](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/34), [#39](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/39), [#40](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/40), [#42](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/42), [#57](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/57), [#72](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/72), [#74](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/74), [#101](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/101).
+
+The rest of the pull requests are just LGTM reviews, so those are not included.
+
+### Contributions beyond the project team
+
+[Reported 18 bugs during the PE-D](https://github.com/tyuyang/ped/issues).
diff --git a/docs/team/vishnuvk47.md b/docs/team/vishnuvk47.md
new file mode 100644
index 0000000000..b206fabd37
--- /dev/null
+++ b/docs/team/vishnuvk47.md
@@ -0,0 +1,55 @@
+# Project Portfolio Page (vishnuvk47)
+
+## Overview
+
+Helped create a CLI-based application that acts like a banking app. Users can create accounts, deposit money, withdraw money, set save goal, set withdrawal limit, and view previous transactions with this application.
+
+## Summary of Contributions
+
+[Link to code contributed](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=vishnu&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=true&tabType=authorship&tabAuthor=vishnuvk47&tabRepo=AY2223S2-CS2113-T13-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
+
+### Enhancements implemented
+
+* Created a createAccount method when the save file is empty [#31](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/31)
+
+* Added a view-account feature [#39](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/39)
+
+* Add a very simple help command [#44](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/44)
+
+* I have developed a 'Save Goal' feature that empowers users to adhere to a frugal lifestyle by setting a minimum balance they wish to maintain. The system sends alerts to users when a withdrawal would result in them falling below their set save goal. Although this is not a strict limit, users have the flexibility to override the system's suggestions.
+The development of the 'Save Goal' feature involved integrating the use of LocalDate and closely interacting with the withdrawal feature. This relates to both front end and back end as it needs to parse the user data stored in the save file (back end) and also interact with users via the UI to receive the relevant inputs and process them(front end). [#72](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/72)
+
+Note: Features, UG and DG also had several significant contributions from my team mates as the program grew and evolved. We largely adopted a BFS approach
+
+### UG contributions
+
+Created a User Guide for the BankWithUs software/application, which included a rough template and details on the various features and their use cases. While working on the guide, I received significant assistance from my teammate, Tyuyang and xiaoge26, who helped me improve the guide's consistency and format to align with recommended guidelines. [#76](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/76)
+
+### DG contributions
+
+Templated the layout, wrote documentation for functionalities, implementation of the program for the DG.[#73](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/73) [#175](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/175) [#178](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/178) [#182](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/182)
+Added some Class diagrams as well
+
+### Team-based tasks
+
+* Set up the GitHub team org/repo
+* Updated user/developer docs that are not specific to a feature e.g. documenting the target user profile, user stories, product scope, and value proposition
+* Handled a significant number of issues that were reported in the PE-D.[#109](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/109)
+* refactored the floats into Big Decimal to resolve overflow and precision issues.[#155](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/155)
+
+
+### Review/Mentoring contributions
+
+#### Links to PR reviewed (Most relevant ones are listed below):
+* [#160](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/160())
+* [#159](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/159)
+* [#157](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/157)
+* [#156](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/156)
+* [#154](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/154)
+* [#143](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/143)
+
+#### Contributions beyond the project team
+
+* [Reported 14 bugs during the PE-D](https://github.com/vishnuvk47/ped/issues)
+* Review other colleagues and teams codes, UG and DG during tutorial sessions
+
diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md
new file mode 100644
index 0000000000..30a4979912
--- /dev/null
+++ b/docs/team/xiaoge26.md
@@ -0,0 +1,71 @@
+# Project Portfolio Page (xiaoge26)
+
+## Overview
+
+Helped create a CLI-based application that acts like a banking app. Users can create accounts, deposit money, withdraw money, set save goal, set withdrawal limit, and view previous transactions with this application.
+
+## Summary of Contributions
+
+### Code contributed
+[Link to code contributed](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=xiaoge26&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other)
+
+### Enhancements implemented
+
+I developed the add account and add deposit methods at the very early stage, which allows users to add a new deposit to the current account.
+I would like to thank all my teammates who have modified and improved these feature later to suit the evolved needs of the application.
+* Add Account Feature [#26](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/26)
+ * Allows the user to add a new account
+* Add Deposit Feature [#42](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/42)
+ * Allows the user to add a new deposit to the current account
+
+
+I have also developed the features related to the `Transaction` and `TransactionList` classes, including adding,
+deleting, listing, parsing, saving, and loading the transactions.
+* Add and View Transaction Feature [#74](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/74)
+ * `Transaction` class and `TransactionList` class store the transactions of the user
+ * `TransactionEncoder` and `TransactionDecoder` Classes help save and load the transaction data
+ * Allows the transaction data to be automatically added to the `TransactionList` when the user adds a new transaction
+ * Allows the user to view the transaction history of all the accounts
+ * Allows the user to delete a transaction from the transaction history
+* Delete Transaction Feature [#159](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/159) [#163](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/163)
+ * Allow the user to delete a transaction from the transaction history
+ * Automatically delete all the transactions of a particular account when the user deletes the account
+
+### Contributions to the UG
+
+* Documented `view-current`, `show-save-goal` and the features related to `Transaction` and `TransactionList` components in the User Guide
+* Fixed typos and bugs in the other sections in UG as well
+
+### Contributions to the DG
+
+* Added 'Acknowledgements' 'Setting Up, Getting Started', 'Non-Functional Requirements' and 'Instructions for Manual Testing' with reference to
+[AddressBoook-Level3](https://se-education.org/addressbook-level3/DeveloperGuide.html)
+* Further modified the DG template and fixed the typos and standardized the format (Uppercase/lowercase issues, no full stop at the end of a bullet point etc.)
+
+
+### Contributions to team-based tasks
+
+* Helped in creating issues for the team to work on
+* Updated User/Developer Guides that are not specific to a feature e.g. Non-Functional Requirements and Instructions for Manual Testing)
+* Released v2.0 of the application
+* Reviewed and approved a significant number of PRs not authored by myself
+* Refactored the code to different packages
+* Created milestones and assigned issues to them
+
+### Review/mentoring contributions
+#### Links to PRs reviewed
+[#175](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/175)
+[#156](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/156)
+[#166](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/166)
+[#98](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/98)
+[#100](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/100)
+[#71](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/71)
+[#67](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/67)
+[#58](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/58)
+[#24](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/24)
+[#158](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/158)
+
+
+### Contributions beyond the project team
+* [Reported 12 bugs during the PE-D](https://github.com/xiaoge26/ped/issues)
+* Developer Guide reviewed: [[CS2113-T14-2] BagPacker #61](https://github.com/nus-cs2113-AY2223S2/tp/pull/61/files/bf0684974cef3c42639ecce53b4a5ff60dec3a7a)
diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java
new file mode 100644
index 0000000000..7c100a6e4f
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/BankWithUs.java
@@ -0,0 +1,133 @@
+package seedu.bankwithus;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import seedu.bankwithus.exceptions.NegativeAmountException;
+import seedu.bankwithus.user.AccountList;
+import seedu.bankwithus.user.TransactionList;
+import seedu.bankwithus.exceptions.CommandNotFoundException;
+import seedu.bankwithus.parser.Parser;
+import seedu.bankwithus.storage.Storage;
+import seedu.bankwithus.ui.Ui;
+
+public class BankWithUs {
+
+ public static final String ACCOUNTS_FILE_PATH = "data/save.txt";
+ public static final String TRANSACTIONS_FILE_PATH = "data/transaction.txt";
+ public boolean isExitEntered = false;
+ private Storage storage;
+ private Ui ui;
+ private AccountList accountList;
+
+ private TransactionList transactionList;
+ private Parser parser;
+
+ /**
+ * Creates a new instance of BankWithUs. Initialises storage, ui,
+ * accounts and transactions. Should load data into accounts and transaction list too.
+ *
+ * @param accountsFilePath the accounts filepath. Should be data/save.txt by default
+ * @param transactionsFilePath the transactions filepath. Should be data/transaction.txt by default
+ * @throws IOException thrown when something goes really, really wrong
+ */
+ public BankWithUs(String accountsFilePath, String transactionsFilePath) throws IOException {
+ // Main object instantiations
+ ui = new Ui();
+ storage = new Storage(accountsFilePath, transactionsFilePath);
+
+ // Ui stuff
+ ui.createScanner();
+ ui.greet();
+
+ // Initialising accountList
+ try {
+ accountList = new AccountList(storage.loadAccounts(), this);
+ ui.showNumberOfAccount(accountList.getSize());
+ } catch (FileNotFoundException e) {
+ // If saveFile not created
+ ui.showFileNotFoundError();
+ try {
+ storage.createNewAccountsFile();
+ ui.showFileCreated();
+ } catch (IOException ioE) {
+ ui.showIOError();
+ throw ioE;
+ }
+ accountList = new AccountList(this);
+ }
+
+ try {
+ transactionList = new TransactionList(storage.loadTransactions());
+ } catch (FileNotFoundException e) {
+ // If transactionFile not created
+ ui.showFileNotFoundError();
+ try {
+ storage.createNewTransactionsFile();
+ } catch (IOException ioE) {
+ ui.showIOError();
+ throw ioE;
+ }
+ transactionList = new TransactionList();
+ }
+ parser = new Parser(this);
+ }
+
+ public AccountList getAccountList() {
+ return accountList;
+ }
+
+ public TransactionList getTransactionList() {
+ return transactionList;
+ }
+
+ public Ui getUi() {
+ return ui;
+ }
+
+ //@@author Sherlock-YH
+ /**
+ * Exit the programme, save the data and show farewell message.
+ *
+ * @throws IOException throw error if the data cannot be saved
+ */
+ public void exit() throws IOException {
+ isExitEntered = true;
+ ui.showFarewellMessage();
+ ui.closeScanner();
+ try {
+ storage.saveToFile(accountList);
+ storage.saveTransactionsToFile(transactionList);
+ } catch (IOException e) {
+ ui.showIOError();
+ throw e;
+ }
+ }
+ //@@author tyuyang
+ /**
+ * The main command and output loop. Takes in user input line by line
+ * and gives it to the parser to execute the command.
+ *
+ * @throws IOException if something goes wrong while exiting the program
+ */
+ public void run() throws IOException {
+ while (!isExitEntered) {
+ String line = ui.getNextLine();
+ try {
+ parser.parseUserInput(line);
+ } catch (CommandNotFoundException e) {
+ ui.showCommandNotFoundError();
+ } catch (NegativeAmountException e) {
+ ui.showNegativeAmountError();
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ new BankWithUs(ACCOUNTS_FILE_PATH, TRANSACTIONS_FILE_PATH).run();
+ } catch (IOException e) {
+ return;
+ }
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/common/SaveGoal.java b/src/main/java/seedu/bankwithus/common/SaveGoal.java
new file mode 100644
index 0000000000..8a2d072290
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/common/SaveGoal.java
@@ -0,0 +1,27 @@
+package seedu.bankwithus.common;
+
+import java.math.BigDecimal;
+import java.time.DateTimeException;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+//@@author vishnuvk47
+public class SaveGoal {
+ public BigDecimal amtToSave;
+ public LocalDate untilWhen;
+
+ public SaveGoal(BigDecimal amtToSave, String untilWhenStr) {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
+ try {
+ this.untilWhen = LocalDate.parse(untilWhenStr, formatter);
+ this.amtToSave = amtToSave;
+ } catch (DateTimeException e) {
+ System.out.println("Incorrect Date format, Try again following dd-MM-YYYY format!");
+ }
+ }
+
+ public SaveGoal(BigDecimal amtToSave, LocalDate untilWhen) {
+ this.amtToSave = amtToSave;
+ this.untilWhen = untilWhen;
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java
new file mode 100644
index 0000000000..a5c3918494
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java
@@ -0,0 +1,117 @@
+package seedu.bankwithus.common;
+
+import java.math.BigDecimal;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.text.DecimalFormat;
+import java.time.LocalDate;
+
+public class WithdrawalChecker {
+ private String totalAmtWithdrawn;
+ private LocalDate lastWithdrawnDate;
+ private String withdrawalLimit;
+ private Logger logger = Logger.getLogger("Foo");
+
+ /**
+ * Instantiates withdrawalChecker without any amount withdrawn.
+ */
+ public WithdrawalChecker() {
+ logger.log(Level.FINE, "Default WithdrawalChecker contructor called");
+ this.totalAmtWithdrawn = "0";
+ logger.log(Level.FINE, "totalAmtWithdrawn set to " + totalAmtWithdrawn);
+ }
+
+ /**
+ * Instantiates withdrawalChecker with amount withdrawn and
+ * last known withdrawal date.
+ * @param totalAmtWithdrawn amount withdrawn
+ * @param lastWithdrawnDate last known withdrawal date
+ */
+ public WithdrawalChecker(String totalAmtWithdrawn, LocalDate lastWithdrawnDate) {
+ logger.log(Level.FINE, "WithdrawalChecker contructer with set withdrawals called");
+ this.totalAmtWithdrawn = totalAmtWithdrawn;
+ this.lastWithdrawnDate = lastWithdrawnDate;
+ logger.log(Level.FINE, "totalAntWithdrawn set to " + totalAmtWithdrawn);
+ logger.log(Level.FINE, "lastWithdrawnDate set to " + lastWithdrawnDate.toString());
+ }
+
+ public String getTotalAmtWithdrawn() {
+ return this.totalAmtWithdrawn;
+ }
+
+ //@@author tyuyang
+ /**
+ * Updates the totalAmtWithdrawn attribute. In general, if the current month is
+ * the same as the last withdrawn month, then add to the total amount withdrawn,
+ * if not, then reset the total amount withdrawn.
+ *
+ * @param withdrawal the amount that was just withdrawn
+ */
+ public void updateTotalAmtWithdrawn(BigDecimal withdrawal) {
+ logger.log(Level.FINE, "updateTotalAmtWithdrawn in WithdrawalChecker called");
+ LocalDate currentDate = LocalDate.now();
+ DecimalFormat df = new DecimalFormat("#.##");
+ logger.log(Level.FINE, "Checking if account has withdrawal history");
+ if (lastWithdrawnDate == null) {
+ logger.log(Level.FINE, "No withdrawal history found, setting values now");
+ lastWithdrawnDate = currentDate;
+ String formatted = df.format(withdrawal);
+ totalAmtWithdrawn = String.valueOf(formatted);
+ return;
+ }
+ assert totalAmtWithdrawn != null;
+ if (lastWithdrawnDate.getMonth() == currentDate.getMonth() &&
+ lastWithdrawnDate.getYear() == currentDate.getYear()) {
+ logger.log(Level.FINE, "Previous withdrawal in the same month, adding to total");
+ String formatted = df.format(new BigDecimal(totalAmtWithdrawn).add(withdrawal));
+ totalAmtWithdrawn = String.valueOf(formatted);
+ } else {
+ logger.log(Level.FINE, "Previous withdrawal in previous months, setting to new value");
+ String formatted = df.format(withdrawal);
+ totalAmtWithdrawn = String.valueOf(formatted);
+ }
+ lastWithdrawnDate = currentDate;
+ }
+
+ public String getWithdrawalLimit() {
+ return this.withdrawalLimit;
+ }
+
+ public void setWithdrawalLimit(BigDecimal withdrawalLimit) {
+ DecimalFormat df = new DecimalFormat("#.##");
+ String formatted = df.format(withdrawalLimit);
+ this.withdrawalLimit = String.valueOf(formatted);
+ }
+
+ /**
+ * Checks if the amount withdrawn will exceed the withdrawal limit.
+ *
+ * @param withdrawAmount the amount withdrawn
+ * @return true if will exceed, false otherwise
+ */
+ public boolean willExceedWithdrawalLimit(BigDecimal withdrawAmount) {
+ if (totalAmtWithdrawn.isBlank() || withdrawalLimit == null) {
+ return false;
+ }
+ BigDecimal totalAmtWithdrawnBigDecimal = new BigDecimal(totalAmtWithdrawn);
+ BigDecimal withdrawalLimitBigDecimal = new BigDecimal(withdrawalLimit);
+ return ((totalAmtWithdrawnBigDecimal.add(withdrawAmount)).compareTo(withdrawalLimitBigDecimal) == 1 );
+ }
+
+ @Override
+ public String toString() {
+ String lastWithdrawnDateString;
+ if (lastWithdrawnDate == null) {
+ lastWithdrawnDateString = " ";
+ } else {
+ lastWithdrawnDateString = lastWithdrawnDate.toString();
+ }
+ String withdrawalLimitString;
+ if (withdrawalLimit == null) {
+ withdrawalLimitString = " ";
+ } else {
+ withdrawalLimitString = withdrawalLimit;
+ }
+ return totalAmtWithdrawn + ";" + lastWithdrawnDateString + ";" + withdrawalLimitString;
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java b/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java
new file mode 100644
index 0000000000..b71278dfc5
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java
@@ -0,0 +1,6 @@
+package seedu.bankwithus.exceptions;
+
+//@@author Sherlock-YH
+public class AccountNotFoundException extends Exception {
+
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/CommandNotFoundException.java b/src/main/java/seedu/bankwithus/exceptions/CommandNotFoundException.java
new file mode 100644
index 0000000000..d75d9119f4
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/CommandNotFoundException.java
@@ -0,0 +1,8 @@
+package seedu.bankwithus.exceptions;
+
+/**
+ * Thrown when command is not recognised
+ */
+public class CommandNotFoundException extends Exception {
+
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/CorruptedSaveFileException.java b/src/main/java/seedu/bankwithus/exceptions/CorruptedSaveFileException.java
new file mode 100644
index 0000000000..8076887183
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/CorruptedSaveFileException.java
@@ -0,0 +1,5 @@
+package seedu.bankwithus.exceptions;
+
+public class CorruptedSaveFileException extends Exception {
+
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/CorruptedTransactionFileException.java b/src/main/java/seedu/bankwithus/exceptions/CorruptedTransactionFileException.java
new file mode 100644
index 0000000000..b56d5e6dae
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/CorruptedTransactionFileException.java
@@ -0,0 +1,4 @@
+package seedu.bankwithus.exceptions;
+
+public class CorruptedTransactionFileException extends Exception {
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/ExceedsWithdrawalLimitException.java b/src/main/java/seedu/bankwithus/exceptions/ExceedsWithdrawalLimitException.java
new file mode 100644
index 0000000000..7f3637b7d6
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/ExceedsWithdrawalLimitException.java
@@ -0,0 +1,5 @@
+package seedu.bankwithus.exceptions;
+
+public class ExceedsWithdrawalLimitException extends Exception {
+
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/InsufficientBalanceException.java b/src/main/java/seedu/bankwithus/exceptions/InsufficientBalanceException.java
new file mode 100644
index 0000000000..22ba8317d4
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/InsufficientBalanceException.java
@@ -0,0 +1,5 @@
+package seedu.bankwithus.exceptions;
+
+public class InsufficientBalanceException extends Exception {
+
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/MoreThanTwoDecimalPlace.java b/src/main/java/seedu/bankwithus/exceptions/MoreThanTwoDecimalPlace.java
new file mode 100644
index 0000000000..848fd84ecf
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/MoreThanTwoDecimalPlace.java
@@ -0,0 +1,6 @@
+package seedu.bankwithus.exceptions;
+
+//@@author Sherlock-YH
+public class MoreThanTwoDecimalPlace extends Exception{
+
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/NegativeAmountException.java b/src/main/java/seedu/bankwithus/exceptions/NegativeAmountException.java
new file mode 100644
index 0000000000..277cd19097
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/NegativeAmountException.java
@@ -0,0 +1,8 @@
+package seedu.bankwithus.exceptions;
+
+/**
+ * Thrown when negative number is entered when not supposed to
+ */
+public class NegativeAmountException extends Exception {
+
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/NoAccountException.java b/src/main/java/seedu/bankwithus/exceptions/NoAccountException.java
new file mode 100644
index 0000000000..6e70aeeaf5
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/NoAccountException.java
@@ -0,0 +1,8 @@
+package seedu.bankwithus.exceptions;
+
+//@@author Sherlock-YH
+/**
+ * thrown when there is no account at all
+ */
+public class NoAccountException extends Exception {
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/NoTransactionsFoundException.java b/src/main/java/seedu/bankwithus/exceptions/NoTransactionsFoundException.java
new file mode 100644
index 0000000000..e8fe31dfb7
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/NoTransactionsFoundException.java
@@ -0,0 +1,5 @@
+package seedu.bankwithus.exceptions;
+
+public class NoTransactionsFoundException extends Exception {
+
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/NoValueInputException.java b/src/main/java/seedu/bankwithus/exceptions/NoValueInputException.java
new file mode 100644
index 0000000000..099377fe76
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/NoValueInputException.java
@@ -0,0 +1,5 @@
+package seedu.bankwithus.exceptions;
+
+//@@author Sherlock-YH
+public class NoValueInputException extends Exception {
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java b/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java
new file mode 100644
index 0000000000..d015cb7717
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java
@@ -0,0 +1,9 @@
+package seedu.bankwithus.exceptions;
+
+//@@author Sherlock-YH
+/**
+ * Thrown when the saved file has no data
+ */
+public class SaveFileIsEmptyException extends Exception {
+
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/TransactionFileIsEmptyException.java b/src/main/java/seedu/bankwithus/exceptions/TransactionFileIsEmptyException.java
new file mode 100644
index 0000000000..cf0389d11e
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/TransactionFileIsEmptyException.java
@@ -0,0 +1,4 @@
+package seedu.bankwithus.exceptions;
+
+public class TransactionFileIsEmptyException extends Exception{
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/TransactionNotFoundException.java b/src/main/java/seedu/bankwithus/exceptions/TransactionNotFoundException.java
new file mode 100644
index 0000000000..f0cc8d9f97
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/TransactionNotFoundException.java
@@ -0,0 +1,7 @@
+package seedu.bankwithus.exceptions;
+
+/**
+ * Thrown when the saved file has no transaction history.
+ */
+public class TransactionNotFoundException extends Exception {
+}
diff --git a/src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledException.java b/src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledException.java
new file mode 100644
index 0000000000..b81e706338
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledException.java
@@ -0,0 +1,5 @@
+package seedu.bankwithus.exceptions;
+
+public class WithdrawalCancelledException extends Exception{
+
+}
diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java
new file mode 100644
index 0000000000..bdb4e7b607
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/parser/Parser.java
@@ -0,0 +1,312 @@
+package seedu.bankwithus.parser;
+
+import seedu.bankwithus.exceptions.CorruptedTransactionFileException;
+import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace;
+import seedu.bankwithus.exceptions.NoValueInputException;
+import seedu.bankwithus.exceptions.TransactionFileIsEmptyException;
+import seedu.bankwithus.user.Account;
+import seedu.bankwithus.user.AccountList;
+import seedu.bankwithus.BankWithUs;
+import seedu.bankwithus.user.Transaction;
+import seedu.bankwithus.user.TransactionList;
+import seedu.bankwithus.storage.TransactionDecoder;
+import seedu.bankwithus.ui.Ui;
+import seedu.bankwithus.exceptions.AccountNotFoundException;
+import seedu.bankwithus.exceptions.CommandNotFoundException;
+import seedu.bankwithus.exceptions.CorruptedSaveFileException;
+import seedu.bankwithus.exceptions.ExceedsWithdrawalLimitException;
+import seedu.bankwithus.exceptions.InsufficientBalanceException;
+import seedu.bankwithus.exceptions.NegativeAmountException;
+import seedu.bankwithus.exceptions.NoAccountException;
+import seedu.bankwithus.exceptions.NoTransactionsFoundException;
+import seedu.bankwithus.exceptions.SaveFileIsEmptyException;
+import seedu.bankwithus.exceptions.WithdrawalCancelledException;
+
+import java.io.IOException;
+import java.time.LocalDate;
+import java.util.Scanner;
+
+public class Parser {
+ private BankWithUs bwu;
+ private AccountList accountList;
+ private TransactionList transactionList;
+ private Ui ui;
+ /**
+ * Instantiates a bwu Parser object.
+ *
+ * @param bwu the main bankWithUs program
+ */
+ public Parser(BankWithUs bwu) {
+ this.bwu = bwu;
+ this.ui = bwu.getUi();
+ this.accountList = bwu.getAccountList();
+ this.transactionList = bwu.getTransactionList();
+ }
+
+ /**
+ * Instantiates a accountList Parser object.
+ *
+ * @param accountList the accountList
+ */
+ public Parser(AccountList accountList) {
+ this.accountList = accountList;
+ }
+
+ public Parser(TransactionList transactionList) {
+ this.transactionList = transactionList;
+ }
+
+ /**
+ * Parses the user input into command and arguments.
+ *
+ * @throws IOException
+ */
+ public void parseUserInput(String input) throws CommandNotFoundException, IOException, NegativeAmountException {
+ // Split input by space
+ String[] split = input.trim().split("\\s+", 2);
+ String command = split[0];
+ String args = split.length == 2 ? split[1] : "";
+ switch (command) {
+ case "exit":
+ try {
+ bwu.exit();
+ } catch (IOException e) {
+ throw e;
+ }
+ break;
+ case "deposit":
+ try {
+ checkNegative(args);
+ accountList.depositMoney(args);
+ transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(),
+ "deposit", args, LocalDate.now());
+ ui.showDepositMessage();
+ accountList.showBal();
+ ui.printLine();
+ } catch (NumberFormatException e) {
+ ui.showNumberFormatError();
+ } catch (NullPointerException e) {
+ ui.showNullInputError();
+ } catch (NegativeAmountException e) {
+ ui.showNegativeAmountError();
+ } catch (MoreThanTwoDecimalPlace e) {
+ ui.showDecimalPlacesError();
+ }
+ break;
+ case "view-account":
+ try {
+ String accDetails = accountList.getAllAccountDetails();
+ ui.viewAccount(accDetails);
+ } catch (AccountNotFoundException e) {
+ ui.showAccountNotFound();
+ }
+ break;
+ case "withdraw":
+ try {
+ checkNegative(args);
+ accountList.withdrawMoney(args);
+ transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(),
+ "withdraw", args, LocalDate.now());
+ accountList.showBal();
+ ui.printLine();
+ } catch (NumberFormatException e) {
+ ui.showNumberFormatError();
+ } catch (NegativeAmountException e) {
+ ui.showNegativeAmountError();
+ } catch (InsufficientBalanceException e) {
+ ui.showInsufficientBalanceMessage();
+ } catch (ExceedsWithdrawalLimitException e) {
+ ui.showExceedsWithdrawalLimitError();
+ String[] wlInfo = accountList.checkWithdrawalLimit();
+ ui.showWithdrawalLimit(wlInfo[0]); //print wl
+ ui.showTotalAmountWithdrawn(wlInfo[1]); //print total amt withdrawn
+ ui.printLine();
+ } catch (WithdrawalCancelledException e) {
+ ui.showWithdrawCancelled();
+ ui.printLine();
+ } catch (MoreThanTwoDecimalPlace e) {
+ ui.showDecimalPlacesError();
+ } catch (NoValueInputException e) {
+ ui.showNoValueInput();
+ }
+ break;
+ case "add-account":
+ accountList.createNewAccount();
+ break;
+ case "switch-to":
+ try {
+ accountList.switchMainAccount(args);
+ } catch (NoAccountException e) {
+ ui.showAccountNotFound();
+ }
+ break;
+ case "set-wl":
+ checkNegative(args);
+ try {
+ accountList.setWithdrawalLimit(args);
+ String withdrawalLimit = accountList.getMainAccount()
+ .getWithdrawalChecker().getWithdrawalLimit();
+ ui.showWithdrawalLimitSet(withdrawalLimit);
+ ui.printLine();
+ } catch (NumberFormatException e) {
+ ui.showNumberFormatError();
+ } catch (NegativeAmountException e) {
+ ui.showNegativeAmountError();
+ }
+ break;
+ case "check-wl":
+ String[] wlInfo = accountList.checkWithdrawalLimit();
+ ui.showWithdrawalLimit(wlInfo[0]); //print wl
+ ui.showTotalAmountWithdrawn(wlInfo[1]); //print total amt withdrawn
+ ui.printLine();
+ break;
+ case "help":
+ ui.showHelp();
+ break;
+ case "set-save-goal":
+ checkNegative(args);
+ if(args.length() > 0) {
+ String untilWhenStr = ui.getDeadline();
+ accountList.handleSaveGoal(args, untilWhenStr);
+ } else {
+ ui.showInsufficientArgsEntered();
+ }
+ break;
+ case "show-save-goal":
+ accountList.showGoal();
+ break;
+ case "delete":
+ checkNegative(args);
+ accountList.deleteAccount(args);
+ transactionList.deleteTransactionsForAccount(args);
+ break;
+ case "view-transactions-all":
+ try {
+ transactionList.printAllTransactions();
+ ui.printLine();
+ } catch (NoTransactionsFoundException e) {
+ ui.noTransactionsFoundError();
+ }
+ break;
+ case "delete-transaction":
+ checkNegative(args);
+ try {
+ transactionList.deleteTransaction(args);
+ ui.printLine();
+ } catch (NoTransactionsFoundException e) {
+ ui.noTransactionsFoundError();
+ } catch (NumberFormatException e) {
+ ui.showNumberFormatError();
+ } catch (IndexOutOfBoundsException e) {
+ ui.showIndexOutOfBoundsError();
+ }
+ break;
+ case "view-current":
+ Account mainAcc = accountList.getMainAccount();
+ ui.showCurrentAccount(mainAcc);
+ break;
+ default:
+ throw new CommandNotFoundException();
+ }
+ }
+
+ //@@author Sherlock-YH
+ /**
+ * Parses the save file. Takes in the scanner to the save file.
+ * Splits the name and balance by ; character.
+ * Part of AccountList parser, not bwu parser.
+ *
+ * @param scanner
+ * @throws CorruptedSaveFileException if any of the parameters are corrupted
+ */
+ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, SaveFileIsEmptyException {
+ boolean hasAccounts = false;
+ while (scanner.hasNextLine()) {
+ String accountDetails = scanner.nextLine();
+ if (accountDetails.isBlank()) {
+ continue;
+ }
+ String[] splitDetails = accountDetails.split(";");
+ try {
+ String name = splitDetails[0].trim();
+ String balanceString = splitDetails[1].trim();
+ String totalAmtWithdrawn = splitDetails[2].trim();
+ String lastWithdrawnDate = splitDetails[3].trim();
+ String withdrawalLimit = splitDetails[4].trim();
+ String amtToSave;
+ String untilWhenStr;
+ if (splitDetails.length > 5) {
+ amtToSave = splitDetails[5].trim();
+ untilWhenStr = splitDetails[6].trim();
+ } else {
+ amtToSave = "0";
+ untilWhenStr = "2001-01-01";
+ }
+ LocalDate untilWhen = LocalDate.parse(untilWhenStr);
+ if (name.isEmpty() || balanceString.isEmpty() || totalAmtWithdrawn.isEmpty()) {
+ throw new CorruptedSaveFileException();
+ }
+ if (lastWithdrawnDate.isEmpty()) {
+ //if no history of withdrawing
+ accountList.addAccount(name, balanceString, withdrawalLimit, amtToSave, untilWhen);
+ } else {
+ accountList.addAccount(name, balanceString, totalAmtWithdrawn,
+ LocalDate.parse(lastWithdrawnDate), withdrawalLimit, amtToSave, untilWhen);
+ }
+ hasAccounts = true;
+ } catch (Exception e) {
+ throw new CorruptedSaveFileException();
+ }
+ if (!hasAccounts) {
+ throw new SaveFileIsEmptyException();
+ }
+ }
+ scanner.close();
+ if (accountList.getSize() == 0){
+ throw new SaveFileIsEmptyException();
+ }
+ }
+
+ /**
+ * Reads the transaction data from the transaction save file.
+ * @param scanner Scanner to the transaction save file.
+ * @throws CorruptedTransactionFileException if the transaction file is corrupted.
+ * @throws TransactionFileIsEmptyException if the transaction file is empty.
+ */
+ public void parseTransactionFile(Scanner scanner) throws CorruptedTransactionFileException,
+ TransactionFileIsEmptyException {
+ boolean isCorrupted = false;
+ while (scanner.hasNextLine()) {
+ String transactionDetails = scanner.nextLine();
+ try {
+ if (transactionDetails.isBlank()) {
+ throw new TransactionFileIsEmptyException();
+ }
+ TransactionDecoder decoder = new TransactionDecoder();
+ Transaction temp = decoder.decodeTransaction(transactionDetails);
+ transactionList.addTransaction(temp);
+ } catch (Exception e) {
+ isCorrupted = true;
+ }
+ }
+ if (isCorrupted) {
+ throw new CorruptedTransactionFileException();
+ }
+ scanner.close();
+ if (transactionList.getSize() == 0) {
+ throw new TransactionFileIsEmptyException();
+ }
+ }
+
+ /**
+ * Throws an exception if argument(Amount/index) has -ve sign.
+ * Extra layer of check to avoid any -0 ambiguity.
+ * @param args
+ * @throws NegativeAmountException
+ */
+ public void checkNegative(String args) throws NegativeAmountException {
+ if (args.length() > 0 && args.charAt(0) == '-') {
+ throw new NegativeAmountException();
+ }
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/storage/Storage.java b/src/main/java/seedu/bankwithus/storage/Storage.java
new file mode 100644
index 0000000000..9c18bd6bf7
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/storage/Storage.java
@@ -0,0 +1,95 @@
+package seedu.bankwithus.storage;
+
+import seedu.bankwithus.user.AccountList;
+import seedu.bankwithus.user.TransactionList;
+import seedu.bankwithus.exceptions.AccountNotFoundException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Scanner;
+
+public class Storage {
+
+ protected File accountFile;
+ protected File transactionFile;
+ private final File saveDir = new File("data");
+
+
+ /**
+ * Creates a new instance of Storage. Initialises the saveFile.
+ *
+ * @param accountsFilepath the accounts filepath. Should be data/save.txt by default
+ * @param transactionsFilepath the transactions filepath. Should be data/transaction.txt by default
+ */
+ public Storage(String accountsFilepath, String transactionsFilepath) {
+ this.accountFile = new File(accountsFilepath);
+ this.transactionFile = new File(transactionsFilepath);
+ }
+
+ /**
+ * Loads the saveFile contexts into AccountList.
+ *
+ * @return the scanner containing the contents of the saveFile
+ * @throws FileNotFoundException if file is not found
+ */
+ public Scanner loadAccounts() throws FileNotFoundException {
+ return new Scanner(accountFile);
+ }
+
+ //@@author xiaoge26
+ public Scanner loadTransactions() throws FileNotFoundException {
+ return new Scanner(transactionFile);
+ }
+
+ //@@author
+ /**
+ * Creates a new saveFile if file is not found. Also creates the data directory.
+ *
+ * @throws IOException if something goes really wrong. Should almost never happen
+ */
+ public void createNewAccountsFile() throws IOException {
+ saveDir.mkdir();
+ accountFile.createNewFile();
+ }
+
+
+ //@@author xiaoge26
+ //Take note that it does not create a new directory if it does not exist as
+ //the data directory is created in the createNewAccountsFile() method
+ //It does not show creation message as well, as it is not necessary
+ public void createNewTransactionsFile() throws IOException {
+ transactionFile.createNewFile();
+ }
+
+
+ //@@author Sherlock-YH
+ /**
+ * This method saves all account details to data/save.txt.
+ *
+ * @param list The AccountList that stores all accounts
+ */
+ public void saveToFile(AccountList list) throws IOException {
+ FileWriter fw = new FileWriter(accountFile);
+ try {
+ fw.write(list.getAllAccountDetails());
+ fw.close();
+ } catch (AccountNotFoundException e) {
+ fw.close();
+ }
+ }
+
+ //@@author xiaoge26
+ /**
+ * This method saves all transaction details to data/save.txt.
+ *
+ * @param transactionList The TransactionList that stores all transactions
+ */
+ public void saveTransactionsToFile(TransactionList transactionList) throws IOException {
+ FileWriter fw = new FileWriter(transactionFile);
+ TransactionEncoder transactionEncoder = new TransactionEncoder();
+ fw.write(transactionEncoder.encodeTransactionList(transactionList));
+ fw.close();
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java b/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java
new file mode 100644
index 0000000000..1c2f5fd17f
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java
@@ -0,0 +1,24 @@
+package seedu.bankwithus.storage;
+
+import seedu.bankwithus.user.Transaction;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+
+public class TransactionDecoder {
+
+ public Transaction decodeTransaction(String encodedTransaction) {
+ //code quality recs
+ String[] split;
+ split = encodedTransaction.split(";");
+ if (split.length == 4) {
+ String accountName = split[0];
+ String type = split[1];
+ String amount = split[2];
+ LocalDate date = LocalDate.parse(split[3], DateTimeFormatter.ofPattern("dd/MM/yyyy"));
+ return new Transaction(accountName, type, amount, date);
+ } else {
+ throw new IllegalArgumentException("Invalid transaction format: " + encodedTransaction);
+ }
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java
new file mode 100644
index 0000000000..032e268c89
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java
@@ -0,0 +1,39 @@
+package seedu.bankwithus.storage;
+
+import seedu.bankwithus.user.Transaction;
+import seedu.bankwithus.user.TransactionList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+class TransactionEncoder {
+ private static final Logger logger =
+ Logger.getLogger(TransactionEncoder.class.getName());
+ public String encodeTransaction(Transaction transaction) {
+
+ //minor fix in the code, buggy
+ final StringBuilder encodedTransactionBuilder;
+ encodedTransactionBuilder = new StringBuilder();
+
+ encodedTransactionBuilder.append(transaction.getAccountName());
+ encodedTransactionBuilder.append(";").append(transaction.getType());
+ encodedTransactionBuilder.append(";").append(transaction.getAmount());
+ encodedTransactionBuilder.append(";").append(transaction.getDateStr());
+
+ return encodedTransactionBuilder.toString();
+ }
+
+ public String encodeTransactionList(TransactionList transactionList) {
+ logger.log(Level.FINE, "Encoding TransactionList");
+ if (transactionList.getSize() == 0) {
+ return "";
+ } else {
+ final StringBuilder encodedTransactionListBuilder = new StringBuilder();
+ for (Transaction transaction : transactionList.getTransactions()) {
+ encodedTransactionListBuilder.append(encodeTransaction(transaction));
+ encodedTransactionListBuilder.append(System.lineSeparator());
+ }
+ return encodedTransactionListBuilder.toString();
+ }
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java
new file mode 100644
index 0000000000..2744a3860a
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/ui/Ui.java
@@ -0,0 +1,320 @@
+package seedu.bankwithus.ui;
+
+import seedu.bankwithus.user.Account;
+import seedu.bankwithus.common.SaveGoal;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.Scanner;
+
+public class Ui {
+
+ private Scanner scanner;
+
+ public void showSaveGoalCreated(String args, String untilWhenStr) {
+ System.out.println("Try saving a minimum of $" + args + " until " + untilWhenStr);
+ System.out.println("Save Goal has been created, Have fun staying frugal!");
+ }
+ public void showFileNotFoundError() {
+ System.out.println("File not found, trying to create file.");
+ }
+
+ public void showFileCreated() {
+ System.out.println("Savefile created successfully!");
+ }
+
+ public void showIOError() {
+ System.out.println("Something's really wrong! Exiting program now.");
+ }
+
+ public void showNumberFormatError() {
+ System.out.println("The input is not a valid number! Please try again.");
+ }
+
+ public void showNullInputError() {
+ System.out.println("The input cannot be empty! Please try again.");
+ }
+
+ public void showCommandNotFoundError() {
+ System.out.println("Not a valid command!");
+ }
+
+ public void showFarewellMessage() {
+ System.out.println("Goodbye! Hope to see you again! :)");
+ }
+
+ public void showAddAccountMessage() {
+ System.out.println("Account created!");
+ }
+ public void showNoTransactionsFoundMessage () {
+ System.out.println("No transactions found!");
+ }
+
+ public void showDepositMessage() {
+ System.out.println("New deposit added!");
+ }
+
+ public void showWithdrawMessage() {
+ System.out.println("Withdrawal successful!");
+ }
+
+ /**
+ * Creates a scanner in the Ui class.
+ */
+ public void createScanner() {
+ this.scanner = new Scanner(System.in);
+ }
+
+ /**
+ * Gets the next line of user input.
+ *
+ * @return the next of user input
+ */
+ public String getNextLine() {
+ return scanner.nextLine();
+ }
+
+ /**
+ * Closes the scanner.
+ */
+ public void closeScanner() {
+ this.scanner.close();
+ }
+
+ public void printLine() {
+ System.out.println("----------------------------");
+ }
+
+ public void viewAccount(String accDetails) {
+ String[] accounts = accDetails.split("\\n");
+ System.out.println("Current Account:");
+ for (String account : accounts) {
+ String name = account.split(";")[0];
+ String bal = account.split(";")[1];
+ System.out.println("Name: " + name);
+ System.out.println("Balance: $" + bal);
+ printLine();
+ }
+ }
+
+ public void showBal(BigDecimal finalBal) {
+ System.out.println("You have $" + finalBal.setScale(2, RoundingMode.CEILING) + " remaining!");
+ }
+
+ public void showNegativeAmountError() {
+ System.out.println("Negative amount entered!");
+ }
+
+ public void showInsufficientBalanceMessage() {
+ System.out.println("You do not have sufficient Balance");
+ printLine();
+ }
+
+ public void showHelp() {
+ printLine();
+ System.out.println("help: displays the current menu");
+ System.out.println("view-account: shows all the accounts' name and balance");
+ System.out.println("withdraw : withdraws from available balance");
+ System.out.println("deposit : deposits and adds deposit to balance");
+ System.out.println("set-save-goal : sets a saveGoal of "
+ + " until ");
+ System.out.println("show-save-goal: shows the current save goal and the deadline");
+ System.out.println("add-account: adds a new account");
+ System.out.println("switch-to : switches to account");
+ System.out.println("delete : deletes the account with username ");
+ System.out.println("set-wl : sets to be the withdrawal limit");
+ System.out.println("check-wl: shows the withdrawal limit and the amount of money withdrawn "
+ + "this month");
+ System.out.println("view-transactions-all: views all transactions across all accounts");
+ System.out.println("delete-transaction : " +
+ "deletes the transaction with the given transaction index");
+ System.out.println("view-current: Shows the current account");
+ System.out.println("exit: quits program and saves");
+ printLine();
+ }
+
+ public void greet() {
+ System.out.println("Welcome to: ");
+ System.out.println("\n" +
+ " /$$$$$$$ /$$ /$$ /$$" +
+ " /$$ /$$ /$$ /$$ /$$ \n" +
+ "| $$__ $$ | $$ | $$ /$ | $$" +
+ "|__/ | $$ | $$ | $$ | $$ \n" +
+ "| $$ \\ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$|" +
+ " $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$\n" +
+ "| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$" +
+ " $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/\n" +
+ "| $$__ $$ /$$$$$$$| $$ \\ $$| $$$$$$/ | $$$$_ " +
+ "$$$$| $$ | $$ | $$ \\ $$| $$ | $$| $$$$$$\n" +
+ "| $$ \\ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \\ " +
+ "$$$| $$ | $$ /$$| $$ | $$| $$ | $$ \\____ $$\n" +
+ "| $$$$$$$/| $$$$$$$| $$ | $$| $$ \\ $$| $$/ \\ " +
+ " $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/\n" +
+ "|_______/ \\_______/|__/ |__/|__/ \\__/|__/ " +
+ "\\__/|__/ \\___/ |__/ |__/ \\______/ |_______/\n"
+ );
+ }
+
+ public void askForName() {
+ System.out.println("What's your name?");
+ }
+
+ public void showBlankUserNameError() {
+ System.out.println("User Name cannot be blank.");
+ }
+
+ public void askForBalance() {
+ System.out.println("How much would you like to add as Balance?");
+ }
+
+ public void showCorruptedSaveFileError() {
+ System.out.println("Save file is corrupted!!! Creating new account...");
+ }
+ public void showCorruptedTransactionFileError() {
+ System.out.println("Transaction file is corrupted!!! Deleting the corrupted entries...");
+ }
+
+ public void showForbiddenCharacterError() {
+ System.out.println("Please do not put the character ';' in the name.");
+ }
+ //@@author Sherlock-YH
+ public void showAccountDeleted(String name) {
+ System.out.println("Account: " + name + " deleted");
+ printLine();
+ }
+ //@@author Sherlock-YH
+ public void showNoAccountFound() {
+ System.out.println("Account is not found, please rectify the name");
+ printLine();
+ }
+ //@@author Sherlock-YH
+ public void showAccountNotFound() {
+ System.out.println("There is no account");
+ printLine();
+ }
+
+ public void showEmptyFile() {
+ System.out.println("There is no saved account, please create a new account");
+ printLine();
+ }
+ //@@author Sherlock-YH
+ public void showNumberOfAccount(int accSize) {
+ System.out.println("Found " + accSize + " Account");
+ printLine();
+ }
+ //@@author Sherlock-YH
+ public void showNewAccountAdded(Account acc) {
+ System.out.println("Account added!");
+ System.out.println("Name: " + acc.getAccountName());
+ System.out.println("Balance: $" + acc.getAccountBalance());
+ printLine();
+ }
+ //@@author Sherlock-YH
+ public void showThereIsOnlyOneAccount() {
+ System.out.println("There is only one account");
+ printLine();
+ }
+ //@@author Sherlock-YH
+ public void showMainAccountSwitched() {
+ System.out.println("Current Account switched");
+ printLine();
+ System.out.println("Current Account is:");
+ printLine();
+ }
+
+ public void showCurrentAccount(Account acc){
+ System.out.println("Name: " + acc.getAccountName());
+ System.out.println("Balance: $" + acc.getAccountBalance());
+ printLine();
+ }
+
+ public void showWithdrawCancelled() {
+ System.out.println("Withdrawal has been cancelled!");
+ }
+
+ public void showInsufficientArgsEntered() {
+ System.out.println("missing one of the arguments relevant to the entered command, TRY AGAIN!");
+ }
+
+ public void failToMeetSaveGoal() {
+ System.out.println("Withdrawing the requested amount would lead to failing to meet your personal Save goal");
+ System.out.println("Are you sure you want to follow through? (Y/N)");
+ }
+
+ public void showGoal(SaveGoal goal) {
+ System.out.println("Min amount to save: $" + goal.amtToSave);
+ LocalDate date = goal.untilWhen;
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
+ String untilwhen = date.format(formatter);
+ System.out.println("Deadline: "+untilwhen);
+ printLine();
+ }
+
+ public void showArgsWrongFormat() {
+ System.out.println("please try again with a valid float and/or dd-mm-yy format");
+ }
+
+ public String getDeadline() {
+ System.out.println("What would be the end date for the duration of your Saving goal?");
+ return getNextLine();
+ }
+
+ //@@author tyuyang
+ public void showWithdrawalLimitSet(String withdrawalLimit) {
+ System.out.println("Withdrawal limit set to $" + withdrawalLimit + "!");
+ }
+
+ public void showWithdrawalLimit(String withdrawalLimit) {
+ if (withdrawalLimit != null) {
+ System.out.println("Withdrawal limit is currently $" + withdrawalLimit + ".");
+ } else {
+ System.out.println("No withdrawal limit set!");
+ }
+ }
+
+ public void showTotalAmountWithdrawn(String totalAmtWithdrawn) {
+ System.out.println("You have withdrawn $" + totalAmtWithdrawn + " this month.");
+ }
+
+ public void showExceedsWithdrawalLimitError() {
+ System.out.println("Apologies! Your transaction did not go through as it will result");
+ System.out.println("in you exceeding your withdrawal limit!");
+ }
+ public void accountAlreadyExists() {
+ System.out.println("Account already exists, try again!");
+ }
+ public void noTransactionsFoundError() {
+ System.out.println("No transactions found!");
+ printLine();
+ }
+
+ //@@author Sherlock-YH
+ public void showDecimalPlacesError(){
+ System.out.println("There are more than two decimal places!\n" + "Please re-enter the command");
+ printLine();
+ }
+
+ //@@author Sherlock-YH
+ public void showNoValueInput() {
+ System.out.println("You did not enter any value. Please re-enter");
+ printLine();
+ }
+
+ //@@author xiaoge26
+
+ //This is shown when the user deleted all the accounts.
+ public void showAddAccountPrompt() {
+ System.out.println("You don't have any account now, please create a new account");
+ printLine();
+ }
+ public void showIndexOutOfBoundsError() {
+ System.out.println("Index out of bounds, please try again");
+ printLine();
+ }
+ public void showTransactionDeletedMessage() {
+ System.out.println("Transaction deleted successfully");
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/user/Account.java b/src/main/java/seedu/bankwithus/user/Account.java
new file mode 100644
index 0000000000..87c6b43101
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/user/Account.java
@@ -0,0 +1,73 @@
+package seedu.bankwithus.user;
+
+import seedu.bankwithus.common.SaveGoal;
+import seedu.bankwithus.common.WithdrawalChecker;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+
+public class Account {
+ public SaveGoal saveGoal;
+ private String name;
+ private BigDecimal balance;
+ private WithdrawalChecker withdrawalChecker;
+ //@@author Sherlock-YH
+ /**
+ * Instantiates an account object.
+ *
+ * @param name initialise in the name of the account
+ * @param balance initialise the balance of the account
+ */
+ public Account(String name, String balance, String amtToSave, LocalDate untilWhen) {
+ this.name = name;
+ this.balance = new BigDecimal(balance).setScale(2, RoundingMode.CEILING);
+ this.withdrawalChecker = new WithdrawalChecker();
+ this.saveGoal = new SaveGoal(new BigDecimal(amtToSave), untilWhen);
+ }
+
+ //@@author tyuyang
+ public Account(String name, String balance, String totalAmtWithdrawn,
+ LocalDate lastWithdrawnDate, String amtToSave, LocalDate untilWhen) {
+ this.name = name;
+ this.balance = new BigDecimal(balance).setScale(2, RoundingMode.CEILING);;
+ this.withdrawalChecker = new WithdrawalChecker(totalAmtWithdrawn, lastWithdrawnDate);
+ this.saveGoal = new SaveGoal(new BigDecimal(amtToSave), untilWhen);
+ }
+ //@@author Sherlock-YH
+ public String getAccountName() {
+ return name;
+ }
+ //@@author Sherlock-YH
+ public BigDecimal getAccountBalance() {
+ return balance;
+ }
+
+ //@@author tyuyang
+ public WithdrawalChecker getWithdrawalChecker() {
+ return withdrawalChecker;
+ }
+
+ //@@author xiaoge26
+ public void addBalance(BigDecimal balanceToBeAdded) {
+ this.balance = this.balance.add(balanceToBeAdded).setScale(2, RoundingMode.CEILING);
+ }
+
+ //@@author manushridiv
+ public void subtractBalance(BigDecimal currentBalance, BigDecimal withdrawal) {
+ this.balance = currentBalance.subtract(withdrawal);
+ withdrawalChecker.updateTotalAmtWithdrawn(withdrawal);
+ }
+
+ //@@author vishnuvk47
+ public void setSaveGoal(SaveGoal saveGoal, String args, String untilWhenStr) {
+ this.saveGoal = saveGoal;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+ public SaveGoal getSaveGoal() {
+ return this.saveGoal;
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java
new file mode 100644
index 0000000000..099fbccc03
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/user/AccountList.java
@@ -0,0 +1,575 @@
+package seedu.bankwithus.user;
+
+import seedu.bankwithus.BankWithUs;
+import seedu.bankwithus.common.SaveGoal;
+import seedu.bankwithus.common.WithdrawalChecker;
+import seedu.bankwithus.exceptions.AccountNotFoundException;
+import seedu.bankwithus.exceptions.CorruptedSaveFileException;
+import seedu.bankwithus.exceptions.ExceedsWithdrawalLimitException;
+import seedu.bankwithus.exceptions.InsufficientBalanceException;
+import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace;
+import seedu.bankwithus.exceptions.NegativeAmountException;
+import seedu.bankwithus.exceptions.NoAccountException;
+import seedu.bankwithus.exceptions.NoValueInputException;
+import seedu.bankwithus.exceptions.SaveFileIsEmptyException;
+import seedu.bankwithus.exceptions.WithdrawalCancelledException;
+import seedu.bankwithus.parser.Parser;
+import seedu.bankwithus.ui.Ui;
+
+import java.math.BigDecimal;
+import java.time.DateTimeException;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Scanner;
+
+
+
+public class AccountList {
+ private ArrayList accounts;
+ private Ui ui;
+ private HashMap doesNameExist = new HashMap();
+
+ /**
+ * Instantiates AccountList and creates a new account.
+ * Called only when save file is not found.
+ *
+ * @param bwu the main bankWithUs program
+ */
+ public AccountList(BankWithUs bwu) {
+ accounts = new ArrayList();
+ this.ui = bwu.getUi();
+ createNewAccount();
+ }
+
+ /**
+ * Instantiates AccountList for unit testing.
+ */
+ public AccountList() {
+ accounts = new ArrayList();
+ this.ui = new Ui();
+ }
+
+ /**
+ * Instantiates AccountList and either:
+ * 1. Load the saved information in the save file into
+ * the account list.
+ * 2. Create a new account if the save file was
+ * empty.
+ *
+ * @param scanner the scanner that reads the save file
+ * @param bwu the main bankWithUs program
+ */
+ public AccountList(Scanner scanner, BankWithUs bwu) {
+ accounts = new ArrayList<>();
+ this.ui = bwu.getUi();
+ Parser parser = new Parser(this);
+ try {
+ parser.parseSavedFile(scanner);
+ for (Account acc : accounts) {
+ doesNameExist.put(acc.getName(), true);
+ }
+ } catch (CorruptedSaveFileException e) {
+ ui.showCorruptedSaveFileError();
+ createNewAccount();
+ } catch (SaveFileIsEmptyException e) {
+ ui.showEmptyFile();
+ createNewAccount();
+ }
+ }
+
+ //@@author xiaoge26
+
+ /**
+ * @return - Returns the current account.
+ */
+ public Account getMainAccount() {
+ return accounts.get(0);
+ }
+
+ //@@author
+
+ /**
+ * Asks the user for the name and returns it in the form of
+ * a string. Will keep looping so long as the user does not
+ * give a valid name.
+ *
+ * @return the userName String
+ */
+ public String askUserForName() {
+ ui.askForName();
+ String userName = ui.getNextLine();
+ userName.trim();
+ if (userName.isBlank()) {
+ ui.showBlankUserNameError();
+ return askUserForName();
+ }
+ if (userName.contains(";")) {
+ ui.showForbiddenCharacterError();
+ return askUserForName();
+ }
+ return userName;
+ }
+
+ /**
+ * Asks the user for their initial balance and returns it as a String.
+ * Will keep looping so long as the user does not give
+ * a valid balance.
+ *
+ * @return balance in the form of a String
+ */
+ public String askUserForBalance() {
+ ui.askForBalance();
+ String balanceString = ui.getNextLine();
+ balanceString = balanceString.trim();
+ balanceString = balanceString.replaceFirst("^0+(?!$)", "");
+ try {
+ BigDecimal balance = new BigDecimal(balanceString);
+ if (balance.signum() == -1) {
+ throw new NegativeAmountException();
+ }
+ if (balance.compareTo(new BigDecimal("0")) == -1 ) {
+ balanceString = "0" + balanceString;
+ return balanceString;
+ }
+ balance = balance.abs();
+ return balance.toString();
+ } catch (NumberFormatException e) {
+ ui.showNumberFormatError();
+ return askUserForBalance();
+ } catch (NegativeAmountException e) {
+ ui.showNegativeAmountError();
+ return askUserForBalance();
+ }
+ }
+
+ //@@author xiaoge26
+
+ /**
+ * Creates a new account and adds it to the AccountList.
+ *
+ * @param name Name of the new account to be added
+ * @param balance Balance of the new account to be added
+ * @param withdrawalLimit Withdrawal limit set by the user, blank if not set
+ */
+ public void addAccount(String name, String balance, String withdrawalLimit) {
+ Account newAccount = new Account(name, balance, "0", LocalDate.parse("2001-01-01"));
+ if (!withdrawalLimit.isBlank()) {
+ BigDecimal withdrawalLimitFloat = new BigDecimal(withdrawalLimit);
+ newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat);
+ }
+ accounts.add(newAccount);
+ ui.showNewAccountAdded(newAccount);
+ }
+
+ /**
+ * Simple method that adds an account.
+ *
+ * @param name - Name of the account
+ * @param balance -The available balance
+ * @param withdrawalLimit - withdrawal limit to be set
+ * @param amtToSave - save Goal amount
+ * @param untilWhen - deadline for save goal amount
+ */
+ public void addAccount(String name, String balance, String withdrawalLimit, String amtToSave, LocalDate untilWhen) {
+ Account newAccount = new Account(name, balance, amtToSave, untilWhen);
+ if (!withdrawalLimit.isBlank()) {
+ BigDecimal withdrawalLimitFloat = new BigDecimal(withdrawalLimit);
+ newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat);
+ }
+ accounts.add(newAccount);
+ ui.showNewAccountAdded(newAccount);
+ }
+
+ //@@author tyuyang
+
+ /**
+ * Creates a new account with withdrawal info and adds it to the AccountList.
+ *
+ * @param name Name of the new account to be added
+ * @param balance Balance of the new account to be added
+ * @param totalAmtWithdrawn Total amount withdrawn from the account this month
+ * @param lastWithdrawnDate Date of the last withdrawal from the account
+ * @param withdrawalLimit Withdrawal limit set by the user, blank if not set
+ */
+ public void addAccount(String name, String balance, String totalAmtWithdrawn,
+ LocalDate lastWithdrawnDate, String withdrawalLimit, String amtToSave, LocalDate untilWhen) {
+ Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate, amtToSave, untilWhen);
+ if (!withdrawalLimit.isBlank()) {
+ BigDecimal withdrawalLimitFloat = new BigDecimal(withdrawalLimit);
+ newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat);
+ }
+ accounts.add(newAccount);
+ ui.showNewAccountAdded(newAccount);
+ }
+
+ //@@author vishnuvk47
+
+ /**
+ * Creates a new Account for a first time user.
+ */
+ public void createNewAccount() {
+ String userName = askUserForName();
+ while (doesNameExist.containsKey(userName) && doesNameExist.get(userName)) {
+ ui.accountAlreadyExists();
+ userName = askUserForName();
+ }
+ doesNameExist.put(userName, true);
+ String balance = askUserForBalance();
+ addAccount(userName, balance, "");
+ }
+
+ //@@author Sherlock-YH
+
+ /**
+ * Name and balance are separated by ; prepared to be saved.
+ *
+ * @return returns all accounts details in String format
+ */
+ public String getAllAccountDetails() throws AccountNotFoundException {
+ if (accounts.isEmpty()) {
+ throw new AccountNotFoundException();
+ } else {
+ StringBuilder temp = new StringBuilder();
+ for (Account acc : accounts) {
+ temp.append(acc.getAccountName()).append(";").append(acc.getAccountBalance());
+ //saving withdrawal information
+ temp.append(";").append(acc.getWithdrawalChecker().toString());
+ //save Save Goal info
+ SaveGoal savings = acc.getSaveGoal();
+ temp.append(";").append(savings.amtToSave);
+ temp.append(";").append(savings.untilWhen);
+ temp.append("\n");
+ }
+ return temp.toString();
+ }
+ }
+
+ /**
+ * Prints to the UI the available balance of the current user.
+ */
+ //@@author
+ public void showBal() {
+ BigDecimal balance = getMainAccount().getAccountBalance();
+ ui.showBal(balance);
+ }
+
+ //@@author xiaoge26
+
+ /**
+ * Deposits money into the current account.
+ * @param depositAmountString the amount to be deposited
+ * @throws NumberFormatException if the amount is not a number
+ * @throws NullPointerException if the amount is null
+ * @throws NegativeAmountException if the amount is negative
+ * @throws MoreThanTwoDecimalPlace if the amount has more than 2 decimal places
+ */
+ public void depositMoney(String depositAmountString) throws NumberFormatException,
+ NullPointerException, NegativeAmountException, MoreThanTwoDecimalPlace {
+ BigDecimal amtToDeposit = new BigDecimal(depositAmountString);
+ if (amtToDeposit.compareTo(BigDecimal.ZERO) == -1) {
+ throw new NegativeAmountException();
+ }
+ if (isMoreThanTwoDecimalPlaces(depositAmountString)) {
+ throw new MoreThanTwoDecimalPlace();
+ }
+ getMainAccount().addBalance(amtToDeposit);
+ }
+
+ //@@author vishnuvk47
+
+ /**
+ * Formats the date into the dd-MM-yyyy format.
+ *
+ * @param date
+ * @return the date in the dd-MM-yyyy format
+ */
+ public LocalDate handleDate(LocalDate date) {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
+ String formattedDate = date.format(formatter);
+ DateTimeFormatter format = DateTimeFormatter.ofPattern("dd-MM-yyyy");
+ return LocalDate.parse(formattedDate, format);
+ }
+
+ /**
+ * Withdraws a user specified amount from the current account.
+ * Also checks if user meets their withdrawal limit and save goal requirement.
+ * Throws exceptions if withdrawal does not go through.
+ *
+ * @param withdrawAmountString - amount to be withdrawn
+ * @throws NumberFormatException
+ * @throws NegativeAmountException
+ * @throws InsufficientBalanceException
+ * @throws ExceedsWithdrawalLimitException
+ * @throws WithdrawalCancelledException
+ */
+ //@@author manushridiv
+ public void withdrawMoney(String withdrawAmountString) throws NumberFormatException,
+ NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException,
+ WithdrawalCancelledException, MoreThanTwoDecimalPlace, NoValueInputException {
+ if (withdrawAmountString.trim().isBlank()){
+ throw new NoValueInputException();
+ }
+ BigDecimal amtToDraw = new BigDecimal(withdrawAmountString);
+ if (amtToDraw.compareTo(BigDecimal.ZERO) == -1) {
+ throw new NegativeAmountException();
+ }
+ BigDecimal currentBalance = getMainAccount().getAccountBalance();
+ if (currentBalance.compareTo(amtToDraw) < 0) {
+ throw new InsufficientBalanceException();
+ }
+ if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(amtToDraw)) {
+ throw new ExceedsWithdrawalLimitException();
+ }
+ if (isMoreThanTwoDecimalPlaces(withdrawAmountString)) {
+ throw new MoreThanTwoDecimalPlace();
+ }
+ if (willFailsSaveGoal(currentBalance, amtToDraw)) {
+ ui.failToMeetSaveGoal();
+ handleProceed(amtToDraw, currentBalance);
+ } else {
+ getMainAccount().subtractBalance(currentBalance, amtToDraw);
+ if (amtToDraw.compareTo(new BigDecimal("0")) == 0) {
+ System.out.println("Withdrawing $0 has no effect!");
+ } else {
+ ui.showWithdrawMessage();
+ }
+ }
+ }
+
+ //@vishnuvk47
+ /**
+ * Finds the respective account to be deleted at users request.
+ * Forces users to create a new account if no account remains after deletion executes.
+ *
+ * @param name - name of the account to delete
+ * @param acc - the account to be checked if it matches the account name to be deleted
+ */
+ public Boolean foundAccountToDelete(String name, Account acc) {
+ if (acc.getAccountName().equals(name)) {
+ accounts.remove(acc);
+ doesNameExist.remove(name);
+ ui.showAccountDeleted(name);
+ doesNameExist.remove(name);
+ if (accounts.size() < 1) {
+ ui.showAddAccountPrompt();
+ createNewAccount();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Baseline method for the delete account command.
+ *
+ * @param name - name of the account to be deleted
+ */
+ //@@author Sherlock-YH
+ public void deleteAccount(String name) {
+ boolean accountDeleted = false;
+ for (int i = 0; i < accounts.size(); i++) {
+ if (foundAccountToDelete(name, accounts.get(i))) {
+ accountDeleted = true;
+ i--;
+ }
+ }
+ if (!accountDeleted) {
+ ui.showNoAccountFound();
+ }
+ if (accounts.size() < 1) {
+ createNewAccount();
+ }
+ }
+
+
+ //@@author Sherlock-YH
+ public int getSize() {
+ return accounts.size();
+ }
+
+ /**
+ * Method that handles switching between users.
+ *
+ * @param accName - account to be switched into
+ * @throws NoAccountException
+ */
+ //@@author Sherlock-YH
+ public void switchMainAccount(String accName) throws NoAccountException {
+ //swap acc to the head of AccountList
+ if (accounts.size() == 0) {
+ throw new NoAccountException();
+ } else if (accounts.size() == 1) {
+ ui.showThereIsOnlyOneAccount();
+ } else {
+ for (int i = 0; i < accounts.size(); i++) {
+ if (accounts.get(i).getAccountName().equals(accName)) {
+ Collections.swap(accounts, i, 0);
+ ui.showMainAccountSwitched();
+ ui.showCurrentAccount(accounts.get(0));
+ return;
+ }
+ }
+ ui.showNoAccountFound();
+ }
+ }
+
+ //@@author tyuyang
+
+ /**
+ * Sets the withdrawal limit of the main account. Modifies the attribute
+ * withdrawalLimit in the WithdrawalChecker class directly.
+ *
+ * @param args the user input
+ * @throws NegativeAmountException if input is negative
+ */
+ public void setWithdrawalLimit(String args) throws NegativeAmountException {
+ BigDecimal withdrawalLimit;
+ try {
+ withdrawalLimit = new BigDecimal(args);
+ } catch (Exception e) {
+ throw new NumberFormatException();
+ }
+ if (withdrawalLimit.compareTo(BigDecimal.ZERO) == -1) {
+ throw new NegativeAmountException();
+ }
+ getMainAccount().getWithdrawalChecker().setWithdrawalLimit(withdrawalLimit);
+ }
+
+ //@@author Sherlock-YH
+ public ArrayList getAccounts() {
+ return accounts;
+ }
+
+ public void setAccounts(ArrayList accounts) {
+ this.accounts = accounts;
+ }
+
+ //@@author vishnuvk47
+
+ /**
+ * Handles overwriting of saveGoal at users own discretion.
+ *
+ * @param withdrawAmount
+ * @param currentBalance
+ */
+ public void handleProceed(BigDecimal withdrawAmount, BigDecimal currentBalance) throws
+ WithdrawalCancelledException {
+ String yesOrNo = ui.getNextLine();
+ while (!(yesOrNo.equalsIgnoreCase("y") || yesOrNo.equalsIgnoreCase("n"))) {
+ System.out.println("Please enter ONLY either Y for Yes and N for No.");
+ yesOrNo = ui.getNextLine();
+ }
+
+ if (yesOrNo.equalsIgnoreCase("y")) {
+ getMainAccount().subtractBalance(currentBalance, withdrawAmount);
+ getMainAccount().saveGoal.amtToSave = new BigDecimal(0);
+ ui.showWithdrawMessage();
+ } else {
+ throw new WithdrawalCancelledException();
+ }
+ }
+
+ //@@author Vishnu
+
+ /**
+ * Primary function that handles the setting and exception handling when saveGoal is called.
+ *
+ * @param args
+ * @param untilWhenStr
+ */
+ public void handleSaveGoal(String args, String untilWhenStr) {
+ try {
+ BigDecimal toSave = new BigDecimal(args);
+ if (toSave.compareTo(BigDecimal.ZERO) == -1) {
+ ui.showNegativeAmountError();
+ } else if (isDateFormatValid(untilWhenStr)) {
+ assert toSave.compareTo(BigDecimal.ZERO) != -1 : "Invalid amount entered.";
+ SaveGoal saveGoal = new SaveGoal(new BigDecimal(args), untilWhenStr);
+ assert getMainAccount() != null : "Users should always have one account intact";
+ getMainAccount().setSaveGoal(saveGoal, args, untilWhenStr);
+ ui.showSaveGoalCreated(args, untilWhenStr);
+ }
+ } catch (NumberFormatException e) {
+ ui.showNumberFormatError();
+ }
+ }
+
+ //@@author Vishnu
+
+ /**
+ * Checks if the date is entered in teh valid DD-MM-YYYY format.
+ *
+ * @param date
+ * @return True if valid format and False if invalid format
+ */
+ public boolean isDateFormatValid(String date) {
+ assert date != null : "Input date should not be null.";
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
+ try {
+ LocalDate.parse(date, formatter);
+ return true;
+ } catch (DateTimeException e) {
+ System.out.println("Incorrect Date format, Try again following dd-MM-YYYY format!");
+ return false;
+ }
+
+ }
+
+ /**
+ * Prints to UI the save goal that the user has set for himself.
+ */
+ public void showGoal() {
+ SaveGoal goal = getMainAccount().getSaveGoal();
+ BigDecimal zero = new BigDecimal("0");
+ if (zero.compareTo(goal.amtToSave) == 0) {
+ System.out.println("you do not have any Save Goal");
+ } else {
+ ui.showGoal(goal);
+ }
+ }
+
+ /**
+ * Checks to see if the amount being withdrawn exceeds save Goal requirements.
+ *
+ * @param currentBalance
+ * @param withdrawAmount
+ * @return True if fails to meet save Goal and False if meets save Goal requirements
+ */
+ public Boolean willFailsSaveGoal(BigDecimal currentBalance, BigDecimal withdrawAmount) {
+
+ assert currentBalance != null : "Current balance cannot be null";
+ assert withdrawAmount != null : "Withdraw amount cannot be null";
+ assert withdrawAmount.compareTo(BigDecimal.ZERO) == 1 : "Withdraw amount must be positive";
+
+ BigDecimal expectedBal = currentBalance.subtract(withdrawAmount);
+ LocalDate tdy = LocalDate.now();
+ LocalDate tdyDate = handleDate(tdy);
+ boolean exceedsSaveGoal = (getMainAccount().getSaveGoal().amtToSave.compareTo(expectedBal) == 1);
+ boolean deadlineNotPassed = getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate);
+ return (exceedsSaveGoal && deadlineNotPassed);
+ }
+
+ //@@author tyuyang
+ public String[] checkWithdrawalLimit() {
+ String[] wlInfo = new String[2];
+ WithdrawalChecker withdrawalChecker = this.getMainAccount().getWithdrawalChecker();
+ withdrawalChecker.updateTotalAmtWithdrawn(new BigDecimal("0"));
+ wlInfo[0] = withdrawalChecker.getWithdrawalLimit();
+ wlInfo[1] = withdrawalChecker.getTotalAmtWithdrawn();
+ return wlInfo;
+ }
+
+ //@@author Sherlock-YH
+ public static boolean isMoreThanTwoDecimalPlaces(String num) {
+ int decPosition = num.indexOf(".");
+ if (decPosition == -1) {
+ // No decimal point found, so the number has zero decimal places
+ return false;
+ }
+ return (num.length() - (decPosition + 1) > 2);
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/user/Transaction.java b/src/main/java/seedu/bankwithus/user/Transaction.java
new file mode 100644
index 0000000000..067cedd593
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/user/Transaction.java
@@ -0,0 +1,48 @@
+package seedu.bankwithus.user;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+public class Transaction {
+ private String accountName;
+ private String amount;
+
+ //Take Note of this date is in LocalDate format, but not a String!
+ private LocalDate date;
+ private String type;
+
+ public Transaction(String accountName, String type, String amount, LocalDate date) {
+ this.accountName = accountName;
+ this.type = type;
+ this.amount = amount;
+ this.date = date;
+ }
+
+ @Override
+ public String toString() {
+ assert date != null;
+ return "Account Name: " + accountName
+ + " Transaction Type: " + type
+ + " Amount: " + amount
+ + " Date: " + date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
+ }
+ public String getAccountName() {
+ return accountName;
+ }
+
+ public String getAmount() {
+ return amount;
+ }
+
+ public String getDateStr() {
+ return date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public LocalDate getDate() {
+ return date;
+ }
+}
diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java
new file mode 100644
index 0000000000..b8fd48a576
--- /dev/null
+++ b/src/main/java/seedu/bankwithus/user/TransactionList.java
@@ -0,0 +1,132 @@
+package seedu.bankwithus.user;
+
+import seedu.bankwithus.exceptions.CorruptedTransactionFileException;
+import seedu.bankwithus.exceptions.NoTransactionsFoundException;
+import seedu.bankwithus.exceptions.TransactionFileIsEmptyException;
+import seedu.bankwithus.parser.Parser;
+import seedu.bankwithus.ui.Ui;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+public class TransactionList {
+
+ private ArrayList transactions;
+ private int size;
+
+ public TransactionList() {
+ this.transactions = new ArrayList<>();
+ this.size = 0;
+ }
+
+ /**
+ * Creates a new instance of TransactionList. Initialises transactions.
+ * Should load data into transactions list too.
+ * @param scanner the scanner to be used to read the transaction file
+ */
+ public TransactionList(Scanner scanner) {
+ this.size = 0;
+ transactions = new ArrayList<>();
+ Ui ui = new Ui();
+ Parser parser = new Parser(this);
+ try {
+ parser.parseTransactionFile(scanner);
+ } catch (CorruptedTransactionFileException e) {
+ ui.showCorruptedTransactionFileError();
+ } catch (TransactionFileIsEmptyException e) {
+ //shows "No transactions found!" as this catch block
+ ui.showNoTransactionsFoundMessage();
+ }
+ }
+
+
+ /**
+ * Creates a new transaction and adds it to the transaction list.
+ *
+ * @param accountName the name of the account
+ * @param type the type of transaction
+ * @param amount the amount of money involved in the transaction
+ * @param date the date of the transaction
+ */
+ public void createNewTransaction(String accountName, String type, String amount, LocalDate date) {
+ Transaction transaction = new Transaction(accountName, type, amount, date);
+ assert transaction != null;
+ transactions.add(transaction);
+ size++;
+ }
+
+ /**
+ * Adds a transaction to the transaction list.
+ *
+ * @param transaction the transaction to be added
+ */
+ public void addTransaction(Transaction transaction) {
+ transactions.add(transaction);
+ size++;
+ }
+
+ public ArrayList getTransactions() {
+ return transactions;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ /**
+ * Prints all transactions in the transaction list.
+ *
+ * @throws NoTransactionsFoundException thrown when there are no transactions in the transaction list
+ */
+ public void printAllTransactions() throws NoTransactionsFoundException {
+ if (size == 0) {
+ throw new NoTransactionsFoundException();
+ }
+ for (int i = 0; i < size; i++) {
+ System.out.println(i + 1 + ". " + transactions.get(i).toString());
+ }
+ }
+
+ //@xiaoge26
+ /**
+ * Deletes a transaction from the transaction list.
+ * @param args the index of the transaction to be deleted
+ */
+ public void deleteTransaction(String args) throws NoTransactionsFoundException,
+ NumberFormatException, IndexOutOfBoundsException {
+ Ui ui = new Ui();
+ if (size == 0) {
+ throw new NoTransactionsFoundException();
+ }
+ try {
+ int index = Integer.parseInt(args) - 1;
+ if (index > size || index < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ transactions.remove(index);
+ size--;
+ ui.showTransactionDeletedMessage();
+ } catch (NumberFormatException e) {
+ throw new NumberFormatException();
+ } catch (IndexOutOfBoundsException e) {
+ throw new IndexOutOfBoundsException();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Deletes all transactions for a particular account.
+ * @param accountName the name of the account
+ */
+ public void deleteTransactionsForAccount(String accountName) {
+ for (int i = 0; i < size; i++) {
+ if (transactions.get(i).getAccountName().equals(accountName)) {
+ transactions.remove(i);
+ size--;
+ i--;
+ }
+ }
+ }
+}
diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java
deleted file mode 100644
index 5c74e68d59..0000000000
--- a/src/main/java/seedu/duke/Duke.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package seedu.duke;
-
-import java.util.Scanner;
-
-public class Duke {
- /**
- * Main entry-point for the java.duke.Duke application.
- */
- public static void main(String[] args) {
- String logo = " ____ _ \n"
- + "| _ \\ _ _| | _____ \n"
- + "| | | | | | | |/ / _ \\\n"
- + "| |_| | |_| | < __/\n"
- + "|____/ \\__,_|_|\\_\\___|\n";
- System.out.println("Hello from\n" + logo);
- System.out.println("What is your name?");
-
- Scanner in = new Scanner(System.in);
- System.out.println("Hello " + in.nextLine());
- }
-}
diff --git a/src/test/java/seedu/bankwithus/BankWithUsTest.java b/src/test/java/seedu/bankwithus/BankWithUsTest.java
new file mode 100644
index 0000000000..fb2b0a0be1
--- /dev/null
+++ b/src/test/java/seedu/bankwithus/BankWithUsTest.java
@@ -0,0 +1,15 @@
+package seedu.bankwithus;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class BankWithUsTest {
+ //This may need to be changed later
+ @Test
+ public void bankWithUs_emptyInput_exceptionThrown() {
+ assertThrows(IOException.class, () -> new BankWithUs("", ""));
+ }
+}
diff --git a/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java b/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java
new file mode 100644
index 0000000000..742b1a71df
--- /dev/null
+++ b/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java
@@ -0,0 +1,50 @@
+//@@author tyuyang
+package seedu.bankwithus.common;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+import org.junit.jupiter.api.Test;
+
+public class WithdrawalCheckerTest {
+ @Test
+ public void updateTotalAmtWithdrawn_validInput_noException() {
+ WithdrawalChecker wcNoWithdrawals = new WithdrawalChecker();
+ //test without withdrawals
+ assertDoesNotThrow(() -> wcNoWithdrawals.updateTotalAmtWithdrawn(new BigDecimal("10.1")));
+ assertEquals("10.1", wcNoWithdrawals.getTotalAmtWithdrawn());
+
+ //test with prior withdrawals
+ assertDoesNotThrow(() -> wcNoWithdrawals.updateTotalAmtWithdrawn(new BigDecimal("1.1")));
+ assertEquals("11.2", wcNoWithdrawals.getTotalAmtWithdrawn());
+
+ WithdrawalChecker wcWithWithdrawals = new WithdrawalChecker("10.01",
+ LocalDate.parse("2023-01-10"));
+
+ //test with prior withdrawals in a different month
+ assertDoesNotThrow(() -> wcWithWithdrawals.updateTotalAmtWithdrawn(new BigDecimal("1.11")));
+ assertEquals("1.11", wcWithWithdrawals.getTotalAmtWithdrawn());
+ }
+
+ @Test
+ public void toStringTest() {
+ WithdrawalChecker wc = new WithdrawalChecker();
+ //test without withdrawal and withdrawal limit
+ assertEquals("0; ; ", wc.toString());
+
+ //test without withdrawal and with withdrawal limit
+ assertDoesNotThrow(() -> wc.setWithdrawalLimit(new BigDecimal("10.1")));
+ assertEquals("0; ;10.1", wc.toString());
+
+ //test with withdrawal and without withdrawal limit
+ WithdrawalChecker wc2 = new WithdrawalChecker("1000", LocalDate.parse("2023-01-10"));
+ assertEquals("1000;2023-01-10; ", wc2.toString());
+
+ //test with withdrawal and with withdrawal limit
+ assertDoesNotThrow(() -> wc2.setWithdrawalLimit((new BigDecimal( 100.10))));
+ assertEquals("1000;2023-01-10;100.1", wc2.toString());
+ }
+}
diff --git a/src/test/java/seedu/bankwithus/storage/StorageTest.java b/src/test/java/seedu/bankwithus/storage/StorageTest.java
new file mode 100644
index 0000000000..9aab00d6ce
--- /dev/null
+++ b/src/test/java/seedu/bankwithus/storage/StorageTest.java
@@ -0,0 +1,13 @@
+//@@author tyuyang
+package seedu.bankwithus.storage;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+public class StorageTest {
+ @Test
+ public void load_normalSaveFile_noMessage() {
+ assertDoesNotThrow(() -> new Storage("data/save.txt", "data/transaction.txt"));
+ }
+}
diff --git a/src/test/java/seedu/bankwithus/storage/TransactionDecoderTest.java b/src/test/java/seedu/bankwithus/storage/TransactionDecoderTest.java
new file mode 100644
index 0000000000..4bd37ceabb
--- /dev/null
+++ b/src/test/java/seedu/bankwithus/storage/TransactionDecoderTest.java
@@ -0,0 +1,53 @@
+package seedu.bankwithus.storage;
+
+import org.junit.jupiter.api.Test;
+import seedu.bankwithus.user.Transaction;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class TransactionDecoderTest {
+ @Test
+ void testDecodeTransaction_validInput() {
+ TransactionDecoder transactionDecoder = new TransactionDecoder();
+ String encodedTransaction = "MyAccount;withdraw;1000.00;23/08/2021";
+ Transaction expectedTransaction = new Transaction("MyAccount", "withdraw", "1000.00",
+ LocalDate.parse("23/08/2021", DateTimeFormatter.ofPattern("dd/MM/yyyy")));
+
+ Transaction result = transactionDecoder.decodeTransaction(encodedTransaction);
+
+ assertEquals(expectedTransaction.getAccountName(), result.getAccountName());
+ assertEquals(expectedTransaction.getType(), result.getType());
+ assertEquals(expectedTransaction.getAmount(), result.getAmount());
+ assertEquals(expectedTransaction.getDate(), result.getDate());
+ }
+
+ @Test
+ void testDecodeTransaction_invalidInput_missingField() {
+ TransactionDecoder transactionDecoder = new TransactionDecoder();
+ String encodedTransaction = "MyAccount;withdraw;1000.00";
+
+ assertThrows(IllegalArgumentException.class, () -> transactionDecoder.decodeTransaction(encodedTransaction));
+ }
+
+ @Test
+ void testDecodeTransaction_invalidInput_wrongDateFormat() {
+ TransactionDecoder transactionDecoder = new TransactionDecoder();
+ String encodedTransaction = "MyAccount;credit;1000.00;23-08-2021";
+
+ assertThrows(DateTimeParseException.class, () -> transactionDecoder.decodeTransaction(encodedTransaction));
+ }
+
+ @Test
+ void testDecodeTransaction_invalidInput_extraField() {
+ TransactionDecoder transactionDecoder = new TransactionDecoder();
+ String encodedTransaction = "MyAccount;deposit;1000.00;23/08/2021;extraField";
+
+ assertThrows(IllegalArgumentException.class, () -> transactionDecoder.decodeTransaction(encodedTransaction));
+ }
+
+}
diff --git a/src/test/java/seedu/bankwithus/user/AccountListTest.java b/src/test/java/seedu/bankwithus/user/AccountListTest.java
new file mode 100644
index 0000000000..834d7d3d4b
--- /dev/null
+++ b/src/test/java/seedu/bankwithus/user/AccountListTest.java
@@ -0,0 +1,307 @@
+package seedu.bankwithus.user;
+
+import org.junit.jupiter.api.Test;
+import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace;
+import seedu.bankwithus.exceptions.NegativeAmountException;
+import seedu.bankwithus.exceptions.NoAccountException;
+import seedu.bankwithus.exceptions.ExceedsWithdrawalLimitException;
+import seedu.bankwithus.exceptions.NoValueInputException;
+import seedu.bankwithus.exceptions.InsufficientBalanceException;
+import seedu.bankwithus.exceptions.WithdrawalCancelledException;
+
+import java.math.BigDecimal;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class AccountListTest {
+ //@@author xiaoge26
+ @Test
+ void depositMoney_notANumber_expectException() {
+ String amountString = "abc";
+ String name = "Bob";
+ String balance = "0";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertThrows(NumberFormatException.class,
+ () -> accountList.depositMoney(amountString));
+ }
+
+ @Test
+ void depositMoney_negativeNumber_expectException() {
+ String amountString = "-1000";
+ String name = "Bob";
+ String balance = "100";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertThrows(NegativeAmountException.class,
+ () -> accountList.depositMoney(amountString));
+ }
+
+ //@@author Sherlock-YH
+ @Test
+ void depositMoney_moreThanTwoDecimalPlaces_expectException() {
+ String amountString = "1000.111";
+ String name = "SHhhh";
+ String balance = "1234";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertThrows(MoreThanTwoDecimalPlace.class,
+ () -> accountList.depositMoney(amountString));
+
+ }
+
+ //@@author Sherlock-YH
+ @Test
+ void withdrawMoney_moreThanTwoDecimalPlaces_expectException() {
+ String amountString = "0.111";
+ String name = "SHhhh";
+ String balance = "12333";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertThrows(MoreThanTwoDecimalPlace.class,
+ () -> accountList.withdrawMoney(amountString));
+
+ }
+
+ //@@author vishnuvk47
+ @Test
+ void withdrawNegativeAmount() {
+ AccountList accountList = new AccountList();
+ accountList.addAccount("James", "1000", "");
+ assertThrows(NegativeAmountException.class, () -> {
+ accountList.withdrawMoney("-100");
+ });
+ }
+
+ @Test
+ void withdrawNegativeAmountWithDecimal() {
+ AccountList accountList = new AccountList();
+ accountList.addAccount("James", "1000", "");
+ assertThrows(NegativeAmountException.class, () -> {
+ accountList.withdrawMoney("-21.67");
+ });
+ }
+
+ //@@author xiaoge26
+ @Test
+ void testingAddAccount_validInput_expectNewAccount() {
+ AccountList testAccountList = new AccountList();
+ testAccountList.addAccount("Jane", "1000", "");
+ assertEquals("Jane", testAccountList.getMainAccount().getName());
+ assertEquals(new BigDecimal("1000.00"), testAccountList.getMainAccount().getAccountBalance());
+ }
+
+ //@@author tyuyang
+ @Test
+ void setWithdrawalLimit_validInput_noException() {
+ AccountList testAccountList = new AccountList();
+ //No initial withdrawal limit
+ testAccountList.addAccount("Hihi", "1000", "");
+ assertDoesNotThrow(() -> testAccountList.setWithdrawalLimit("1.11"));
+ assertEquals("1.11", testAccountList.getMainAccount()
+ .getWithdrawalChecker().getWithdrawalLimit());
+
+ //With initial withdrawal limit
+ assertDoesNotThrow(() -> testAccountList.setWithdrawalLimit("2.23"));
+ assertEquals("2.23", testAccountList.getMainAccount()
+ .getWithdrawalChecker().getWithdrawalLimit());
+ }
+
+ //@@author tyuyang
+ @Test
+ void setWithdrawalLimit_negativeInput_negativeAmountExceptionThrown() {
+ AccountList testAccountList = new AccountList();
+ //No initial withdrawal limit
+ testAccountList.addAccount("Hihi", "1000", "");
+ assertThrows(NegativeAmountException.class,
+ () -> testAccountList.setWithdrawalLimit("-100"));
+ assertEquals(null, testAccountList.getMainAccount()
+ .getWithdrawalChecker().getWithdrawalLimit());
+
+ //With initial withdrawal limit
+ assertDoesNotThrow(() -> testAccountList.setWithdrawalLimit("1000"));
+ assertThrows(NegativeAmountException.class,
+ () -> testAccountList.setWithdrawalLimit("-1.10"));
+ assertEquals("1000", testAccountList.getMainAccount()
+ .getWithdrawalChecker().getWithdrawalLimit());
+ }
+
+ //@@author tyuyang
+ @Test
+ void setWithdrawalLimit_nonNumberInput_numberFormatExceptionThrown() {
+ AccountList testAccountList = new AccountList();
+ //No initial withdrawal limit
+ testAccountList.addAccount("Byebye", "10010", "");
+ assertThrows(NumberFormatException.class,
+ () -> testAccountList.setWithdrawalLimit("ab"));
+ assertEquals(null, testAccountList.getMainAccount()
+ .getWithdrawalChecker().getWithdrawalLimit());
+
+ //With initial withdrawal limit
+ assertDoesNotThrow(() -> testAccountList.setWithdrawalLimit("11000"));
+ assertThrows(NumberFormatException.class,
+ () -> testAccountList.setWithdrawalLimit(""));
+ assertEquals("11000", testAccountList.getMainAccount()
+ .getWithdrawalChecker().getWithdrawalLimit());
+ }
+
+ //@@author vishnuvk47
+ @Test
+ public void testIsDateFormatValid() {
+ AccountList acc = new AccountList();
+ String validDate = "07-04-2023";
+ String invalidDate = "2023-04-07";
+
+ assertEquals(true, acc.isDateFormatValid(validDate));
+ assertEquals(false, acc.isDateFormatValid(invalidDate));
+ }
+
+ @Test
+ void depositMoney_nullAmount_expectException() {
+ String amountString = null;
+ String name = "SHhhh";
+ String balance = "1234";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertThrows(NullPointerException.class,
+ () -> accountList.depositMoney(amountString));
+ }
+
+ @Test
+ void depositMoney_negativeAmount_expectException() {
+ String amountString = "-1000.11";
+ String name = "SHhhh";
+ String balance = "1234";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertThrows(NegativeAmountException.class,
+ () -> accountList.depositMoney(amountString));
+ }
+
+ @Test
+ void depositMoney_validAmount_expectDeposit() throws NegativeAmountException, MoreThanTwoDecimalPlace {
+ String amountString = "1000.11";
+ String name = "SHhhh";
+ String balance = "1234";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ BigDecimal expectedBalance = new BigDecimal(balance).add(new BigDecimal(amountString));
+ accountList.depositMoney(amountString);
+ assertEquals(expectedBalance, accountList.getMainAccount().getAccountBalance());
+ }
+
+ @Test
+ void withdrawMoney_validAmount_expectWithdrawal() throws NegativeAmountException, NoValueInputException,
+ WithdrawalCancelledException, InsufficientBalanceException, ExceedsWithdrawalLimitException,
+ MoreThanTwoDecimalPlace {
+ String amountString = "500.00";
+ String name = "Test Account";
+ String balance = "1000.00";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ BigDecimal expectedBalance = new BigDecimal(balance).subtract(new BigDecimal(amountString));
+ accountList.withdrawMoney(amountString);
+ assertEquals(expectedBalance, accountList.getMainAccount().getAccountBalance());
+ }
+
+ @Test
+ void withdrawMoney_negativeAmount_expectException() {
+ String amountString = "-1000.00";
+ String name = "Test Account";
+ String balance = "1234.56";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertThrows(NegativeAmountException.class,
+ () -> accountList.withdrawMoney(amountString));
+ }
+
+ @Test
+ void withdrawMoney_insufficientBalance_expectException() {
+ String amountString = "5000.00";
+ String name = "Test Account";
+ String balance = "1234.56";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertThrows(InsufficientBalanceException.class,
+ () -> accountList.withdrawMoney(amountString));
+ }
+
+ @Test
+ void withdrawMoney_exceedWithdrawalLimit_expectException() {
+ String amountString = "5000.00";
+ String name = "Test Account";
+ String balance = "12345.67";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "10");
+ assertThrows(ExceedsWithdrawalLimitException.class,
+ () -> accountList.withdrawMoney(amountString));
+ }
+
+ @Test
+ void withdrawMoney_noValueInput_expectException() {
+ String amountString = " ";
+ String name = "Test Account";
+ String balance = "1234.56";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertThrows(NoValueInputException.class,
+ () -> accountList.withdrawMoney(amountString));
+ }
+
+ //As per [PE-D][Tester A] [Bug] #144
+ @Test
+ void depositMoney_largestPossibleNumber_expectNoException() {
+ String amountString = new BigDecimal(Double.MAX_VALUE).toString();
+ String name = "Test Account";
+ String balance = "0";
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertDoesNotThrow(() -> accountList.depositMoney(amountString));
+ }
+
+ ////As per [PE-D][Tester A] [Bug] #144 --> extension from this bug
+ @Test
+ void depositMoney_onAccountLargeBalance_expectNoException() {
+ String amountString = new BigDecimal(Double.MAX_VALUE).toString();
+ String name = "Test Account";
+ String balance = amountString;
+ AccountList accountList = new AccountList();
+ accountList.addAccount(name, balance, "");
+ assertDoesNotThrow(() -> accountList.depositMoney(amountString));
+ }
+
+ //As per [PE-D][Tester A] [Bug] #144 --> also extension from this bug
+ @Test
+ void newAccount_largestPossibleNumber_expectNoException() {
+ String balance = new BigDecimal(Double.MAX_VALUE).toString();
+ String name = "Test Account";
+ AccountList accountList = new AccountList();
+ assertDoesNotThrow(() -> accountList.addAccount(name, balance, ""));
+ }
+
+ //[PE-D][Tester E] Accounts with similar name (or substring) ends up not being able to get switched over
+ @Test
+ void switchMainAccountSubstring_accountExists_expectSuccess() throws NoAccountException {
+ AccountList accountList = new AccountList();
+ accountList.addAccount("Account 1", "1000.00", "");
+ accountList.addAccount("Account 2", "500.00", "");
+
+ accountList.switchMainAccount("Account 2");
+
+ assertEquals("Account 2", accountList.getMainAccount().getAccountName());
+ }
+
+ //Bug occurs where deleting an account will cause that name to be "blacklisted" #148
+ @Test
+ void deleteAccount_createNewAccountWithNameOfDeletedAccount_accountExpectSuccess() throws NoAccountException {
+ AccountList accountList = new AccountList();
+ accountList.addAccount("Account 1", "1000.00", "");
+ accountList.addAccount("Account 2", "500.00", "");
+ accountList.deleteAccount("Account 2");
+ accountList.addAccount("Account 2", "500.00", "");
+ accountList.switchMainAccount("Account 2");
+ assertEquals("Account 2", accountList.getMainAccount().getAccountName());
+ }
+}
diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/seedu/duke/DukeTest.java
deleted file mode 100644
index 2dda5fd651..0000000000
--- a/src/test/java/seedu/duke/DukeTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package seedu.duke;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.junit.jupiter.api.Test;
-
-class DukeTest {
- @Test
- public void sampleTest() {
- assertTrue(true);
- }
-}
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 892cb6cae7..175b069434 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -1,9 +1,133 @@
-Hello from
- ____ _
-| _ \ _ _| | _____
-| | | | | | | |/ / _ \
-| |_| | |_| | < __/
-|____/ \__,_|_|\_\___|
+Welcome to:
-What is your name?
-Hello James Gosling
+ /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$
+| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$
+| $$ \ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$| $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$
+| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$ $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/
+| $$__ $$ /$$$$$$$| $$ \ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \ $$| $$ | $$| $$$$$$
+| $$ \ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \ $$$| $$ | $$ /$$| $$ | $$| $$ | $$ \____ $$
+| $$$$$$$/| $$$$$$$| $$ | $$| $$ \ $$| $$/ \ $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/
+|_______/ \_______/|__/ |__/|__/ \__/|__/ \__/|__/ \___/ |__/ |__/ \______/ |_______/
+
+File not found, trying to create file.
+Savefile created successfully!
+What's your name?
+Please do not put the character ';' in the name.
+What's your name?
+How much would you like to add as Balance?
+The input is not a valid number! Please try again.
+How much would you like to add as Balance?
+The input is not a valid number! Please try again.
+How much would you like to add as Balance?
+Account added!
+Name: hihi
+Balance: $1000.00
+----------------------------
+File not found, trying to create file.
+Not a valid command!
+Current Account:
+Name: hihi
+Balance: $1000.00
+----------------------------
+Negative amount entered!
+The input is not a valid number! Please try again.
+Current Account:
+Name: hihi
+Balance: $1000.00
+----------------------------
+New deposit added!
+You have $1100.21 remaining!
+----------------------------
+You did not enter any value. Please re-enter
+----------------------------
+Current Account:
+Name: hihi
+Balance: $1100.21
+----------------------------
+Account is not found, please rectify the name
+----------------------------
+What's your name?
+How much would you like to add as Balance?
+Account added!
+Name: sherlock
+Balance: $123778.10
+----------------------------
+Current Account:
+Name: hihi
+Balance: $1100.21
+----------------------------
+Name: sherlock
+Balance: $123778.10
+----------------------------
+You do not have sufficient Balance
+----------------------------
+Current Account switched
+----------------------------
+Current Account is:
+----------------------------
+Name: sherlock
+Balance: $123778.10
+----------------------------
+Current Account:
+Name: sherlock
+Balance: $123778.10
+----------------------------
+Name: hihi
+Balance: $1100.21
+----------------------------
+The input is not a valid number! Please try again.
+Withdrawal successful!
+You have $123678.10 remaining!
+----------------------------
+Current Account:
+Name: sherlock
+Balance: $123678.10
+----------------------------
+Name: hihi
+Balance: $1100.21
+----------------------------
+No withdrawal limit set!
+You have withdrawn $100 this month.
+----------------------------
+Negative amount entered!
+The input is not a valid number! Please try again.
+No withdrawal limit set!
+You have withdrawn $100 this month.
+----------------------------
+Withdrawal limit set to $100!
+----------------------------
+Withdrawal limit is currently $100.
+You have withdrawn $100 this month.
+----------------------------
+Apologies! Your transaction did not go through as it will result
+in you exceeding your withdrawal limit!
+Withdrawal limit is currently $100.
+You have withdrawn $100 this month.
+----------------------------
+There are more than two decimal places!
+Please re-enter the command
+----------------------------
+New deposit added!
+You have $123678.20 remaining!
+----------------------------
+Withdrawal limit is currently $100.
+You have withdrawn $100 this month.
+----------------------------
+Apologies! Your transaction did not go through as it will result
+in you exceeding your withdrawal limit!
+Withdrawal limit is currently $100.
+You have withdrawn $100 this month.
+----------------------------
+Current Account:
+Name: sherlock
+Balance: $123678.20
+----------------------------
+Name: hihi
+Balance: $1100.21
+----------------------------
+1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 10/04/2023
+2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 10/04/2023
+3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 10/04/2023
+----------------------------
+Not a valid command!
+Goodbye! Hope to see you again! :)
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index f6ec2e9f95..f8809ecf5a 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -1 +1,39 @@
-James Gosling
\ No newline at end of file
+hi;hi
+hihi
+hihi
+
+1000
+view account
+view-account
+deposit -1
+deposit java
+view-account
+deposit 100.21
+withdraw
+view-account
+delete sherlock
+add-account
+sherlock
+123778.1
+view-account
+withdraw 100000
+switch-to sherlock
+view-account
+withdraw dba
+withdraw 100
+view-account
+check-wl
+set-wl -1
+set-wl bal
+check-wl
+set-wl 100
+check-wl
+withdraw 10.111
+deposit 9.112
+deposit 0.1
+check-wl
+withdraw 100
+view-account
+view-transactions-all
+
+exit
\ No newline at end of file