From 2867de810139027c02d7fdc4ea66e2d657e61aad Mon Sep 17 00:00:00 2001 From: vishnuvk47 <122626659+vishnuvk47@users.noreply.github.com> Date: Thu, 2 Mar 2023 13:30:07 +0800 Subject: [PATCH 001/368] Update README.md Added team ID to readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 832f9b33e33c624a52e5eefb6c6d15288240a9e2 Mon Sep 17 00:00:00 2001 From: vishnu Date: Thu, 2 Mar 2023 21:51:43 +0800 Subject: [PATCH 002/368] added my basic info in the AboutUs.md --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..e6a3f0d434 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +Display | Name | Github Profile | Portfolio +--------|:--------:|:---------------------------------------:|:---------: +![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From c4990b027d9b4c2b171ba12a3d583b8b0bd7bc04 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 2 Mar 2023 23:02:10 +0800 Subject: [PATCH 003/368] Update personal details in AboutUs --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index e6a3f0d434..1eac6b4ab8 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,7 @@ Display | Name | Github Profile | Portfolio --------|:--------:|:---------------------------------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://img1.ak.crunchyroll.com/i/spire3/ce09954d04b9388547d819522f75a01b1663350777_full.png) | Tay Yu Yang | [Github](https://github.com/tyuyang) | No portfolio to speak of. ![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From ee8f0870b13b8e506da77ef02f00b6e6aaa1e997 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 2 Mar 2023 23:17:18 +0800 Subject: [PATCH 004/368] Resized image as it was hilariously large --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 1eac6b4ab8..d377580bd0 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,7 @@ Display | Name | Github Profile | Portfolio --------|:--------:|:---------------------------------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://img1.ak.crunchyroll.com/i/spire3/ce09954d04b9388547d819522f75a01b1663350777_full.png) | Tay Yu Yang | [Github](https://github.com/tyuyang) | No portfolio to speak of. + | Tay Yu Yang | [Github](https://github.com/tyuyang) | No portfolio to speak of. ![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From 2329700b26f792636f0c8cdd002ac8e562d25f16 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Thu, 2 Mar 2023 23:32:21 +0800 Subject: [PATCH 005/368] no message --- docs/AboutUs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..9b48b3c0a0 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:----:|:--------------:|:---------: +Display | Name | Github Profile | Portfolio +--------|:--------:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | No portfolio From 0582772bfc11ba03e1a9e9ecae77e1b1b980125d Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 3 Mar 2023 01:03:42 +0800 Subject: [PATCH 006/368] Add self intro --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 7df31cc643..5c22616ef0 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:--------:|:---------------------------------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) - | Tay Yu Yang | [Github](https://github.com/tyuyang) | No portfolio to speak of. -![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | No portfolio>>>>>>> master +Display | Name | Github Profile | Portfolio +--------|:-----------:|:---------------------------------------:|:---------: +![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) + | Tay Yu Yang | [Github](https://github.com/tyuyang) | No portfolio to speak of. +![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | N.A. +![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | No portfolio>>>>>>> master From f3f1c6a7033d6bb345f65d4fe61c97e25feb38c3 Mon Sep 17 00:00:00 2001 From: manushridiv Date: Thu, 9 Mar 2023 13:12:08 +0800 Subject: [PATCH 007/368] added about me --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 5c22616ef0..6633f92d3c 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,7 +2,7 @@ Display | Name | Github Profile | Portfolio --------|:-----------:|:---------------------------------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](docs/team/johndoe.md) | Tay Yu Yang | [Github](https://github.com/tyuyang) | No portfolio to speak of. ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | N.A. ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) From 7e436382d6b43d6f2633b4bb1a2b0d40f898a8ab Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 15:14:45 +0800 Subject: [PATCH 008/368] Remove the template Duke and Duke test files --- src/main/java/seedu/duke/Duke.java | 21 --------------------- src/test/java/seedu/duke/DukeTest.java | 12 ------------ 2 files changed, 33 deletions(-) delete mode 100644 src/main/java/seedu/duke/Duke.java delete mode 100644 src/test/java/seedu/duke/DukeTest.java 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/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); - } -} From cf0843a6bb0b323e5eb62c53dbb9b19819ebb682 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 15:15:10 +0800 Subject: [PATCH 009/368] Create skeleton code for BankWithUs --- .../java/seedu/bankwithus/BankWithUs.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/seedu/bankwithus/BankWithUs.java diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java new file mode 100644 index 0000000000..c0a5ae727f --- /dev/null +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -0,0 +1,28 @@ +package seedu.bankwithus; + +public class BankWithUs { + + private Storage storage; + private Ui ui; + private AccountList accounts; + + public static final String FILE_PATH = "data/save.txt"; + + public BankWithUs(String filePath) { + ui = new UI(); + storage = new Storage(); + try { + accounts = new AccountList(storage.load()); + } catch (Exception e) { + ui.showLoadingError(); + accounts = new AccountList(); + } + } + + public void run() { + + } + public static void main(String[] args) { + new BankWithUs(FILE_PATH).run(); + } +} From 551fbc6f5b986ee80f1438f7fb99ee3f2499eefd Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 15:19:58 +0800 Subject: [PATCH 010/368] Resolve spelling mistake in the main file --- src/main/java/seedu/bankwithus/BankWithUs.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index c0a5ae727f..70f43a63ea 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -9,7 +9,7 @@ public class BankWithUs { public static final String FILE_PATH = "data/save.txt"; public BankWithUs(String filePath) { - ui = new UI(); + ui = new Ui(); storage = new Storage(); try { accounts = new AccountList(storage.load()); From b50d10276e93cc8997371325a15a225481a4fe85 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 15:20:26 +0800 Subject: [PATCH 011/368] Create java files for AccountList, Storage and Ui --- src/main/java/seedu/bankwithus/AccountList.java | 12 ++++++++++++ src/main/java/seedu/bankwithus/Storage.java | 9 +++++++++ src/main/java/seedu/bankwithus/Ui.java | 8 ++++++++ 3 files changed, 29 insertions(+) create mode 100644 src/main/java/seedu/bankwithus/AccountList.java create mode 100644 src/main/java/seedu/bankwithus/Storage.java create mode 100644 src/main/java/seedu/bankwithus/Ui.java diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java new file mode 100644 index 0000000000..a98a40ad10 --- /dev/null +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -0,0 +1,12 @@ +package seedu.bankwithus; + +public class AccountList { + + public AccountList() { + + } + + public AccountList(String saveString) { + + } +} diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java new file mode 100644 index 0000000000..3f2cf90ee9 --- /dev/null +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -0,0 +1,9 @@ +package seedu.bankwithus; + +public class Storage { + + public String load() { + return null; + } + +} diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java new file mode 100644 index 0000000000..f1e1aea313 --- /dev/null +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -0,0 +1,8 @@ +package seedu.bankwithus; + +public class Ui { + + public void showLoadingError() { + + } +} From 98893970d9365f62f7d124af6fc5c3d443db9b9d Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 16:31:15 +0800 Subject: [PATCH 012/368] Modify file to comply with checkstyle --- src/main/java/seedu/bankwithus/BankWithUs.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 70f43a63ea..9d8ce0fea4 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -2,12 +2,12 @@ public class BankWithUs { + public static final String FILE_PATH = "data/save.txt"; + private Storage storage; private Ui ui; private AccountList accounts; - public static final String FILE_PATH = "data/save.txt"; - public BankWithUs(String filePath) { ui = new Ui(); storage = new Storage(); From e1cc2b3bf81eb42413fd10ee1769778e0fba04f0 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 16:43:46 +0800 Subject: [PATCH 013/368] Added load() function in Storage --- src/main/java/seedu/bankwithus/AccountList.java | 4 +++- src/main/java/seedu/bankwithus/Storage.java | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index a98a40ad10..fd9e3e6e01 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,12 +1,14 @@ package seedu.bankwithus; +import java.util.Scanner; + public class AccountList { public AccountList() { } - public AccountList(String saveString) { + public AccountList(Scanner scanner) { } } diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index 3f2cf90ee9..fc824c2058 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -1,9 +1,14 @@ package seedu.bankwithus; +import java.util.Scanner; + +import static seedu.bankwithus.BankWithUs.FILE_PATH; + public class Storage { - public String load() { - return null; + public Scanner load() { + Scanner s = new Scanner(FILE_PATH); + return s; } } From 30b91b19013f70e2fe7baadfa7292ae72a8146b6 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 16:52:02 +0800 Subject: [PATCH 014/368] Modify code to make it look nicer? --- src/main/java/seedu/bankwithus/BankWithUs.java | 2 +- src/main/java/seedu/bankwithus/Storage.java | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 9d8ce0fea4..8f80b5e5dd 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -10,7 +10,7 @@ public class BankWithUs { public BankWithUs(String filePath) { ui = new Ui(); - storage = new Storage(); + storage = new Storage(filePath); try { accounts = new AccountList(storage.load()); } catch (Exception e) { diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index fc824c2058..e60e9060f5 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -2,12 +2,16 @@ import java.util.Scanner; -import static seedu.bankwithus.BankWithUs.FILE_PATH; - public class Storage { + + private String filepath; + + public Storage(String filepath) { + this.filepath = filepath; + } public Scanner load() { - Scanner s = new Scanner(FILE_PATH); + Scanner s = new Scanner(filepath); return s; } From 2acd29ea7dd22a1d225d13e1c95cf05cb0f7dea8 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 17:22:16 +0800 Subject: [PATCH 015/368] Added load() feature, along with create file feature --- .../java/seedu/bankwithus/BankWithUs.java | 19 +++++++++++++++--- src/main/java/seedu/bankwithus/Storage.java | 20 +++++++++++++++---- src/main/java/seedu/bankwithus/Ui.java | 8 ++++++++ 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 8f80b5e5dd..ca534b07fd 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -1,5 +1,8 @@ package seedu.bankwithus; +import java.io.FileNotFoundException; +import java.io.IOException; + public class BankWithUs { public static final String FILE_PATH = "data/save.txt"; @@ -8,13 +11,19 @@ public class BankWithUs { private Ui ui; private AccountList accounts; - public BankWithUs(String filePath) { + public BankWithUs(String filePath) throws IOException { ui = new Ui(); storage = new Storage(filePath); try { accounts = new AccountList(storage.load()); - } catch (Exception e) { + } catch (FileNotFoundException e) { ui.showLoadingError(); + try { + storage.createNewFile(); + } catch (IOException ioE) { + ui.showIOError(); + throw ioE; + } accounts = new AccountList(); } } @@ -23,6 +32,10 @@ public void run() { } public static void main(String[] args) { - new BankWithUs(FILE_PATH).run(); + try { + new BankWithUs(FILE_PATH).run(); + } catch (IOException e) { + return; + } } } diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index e60e9060f5..39b8032d63 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -1,18 +1,30 @@ package seedu.bankwithus; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.Scanner; public class Storage { - private String filepath; + private File saveFile; + private final File SAVE_DIR = new File("data"); + private Ui ui; public Storage(String filepath) { - this.filepath = filepath; + this.saveFile = new File(filepath); + this.ui = new Ui(); } - public Scanner load() { - Scanner s = new Scanner(filepath); + public Scanner load() throws FileNotFoundException { + Scanner s = new Scanner(saveFile); return s; } + public void createNewFile() throws IOException { + SAVE_DIR.mkdir(); + saveFile.createNewFile(); + ui.showFileCreated(); + } + } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index f1e1aea313..9d471c30b0 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -3,6 +3,14 @@ public class Ui { public void showLoadingError() { + 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."); } } From 4633694ed855d03466414131d9b4feb866985c56 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 17:44:35 +0800 Subject: [PATCH 016/368] Create junit test for BankWithUs.java --- data/save.txt | 0 .../java/seedu/bankwithus/BankWithUsTest.java | 16 ++++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 data/save.txt create mode 100644 src/test/java/seedu/bankwithus/BankWithUsTest.java diff --git a/data/save.txt b/data/save.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/java/seedu/bankwithus/BankWithUsTest.java b/src/test/java/seedu/bankwithus/BankWithUsTest.java new file mode 100644 index 0000000000..371bf4a723 --- /dev/null +++ b/src/test/java/seedu/bankwithus/BankWithUsTest.java @@ -0,0 +1,16 @@ +package seedu.bankwithus; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class BankWithUsTest { + @Test + public void BankWithUs_emptyInput_exceptionThrown() { + Exception exception = assertThrows(IOException.class, () -> { + new BankWithUs(""); + }); + } +} From 252bc8a238d34734a182f1b8e97afc09dc070ba3 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 17:55:14 +0800 Subject: [PATCH 017/368] Add java doc comments --- .../java/seedu/bankwithus/BankWithUs.java | 8 +++++++ src/main/java/seedu/bankwithus/Storage.java | 24 +++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index ca534b07fd..30394ae2f0 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -11,6 +11,14 @@ public class BankWithUs { private Ui ui; private AccountList accounts; + /** + * Creates a new instance of BankWithUs. Initialises storage, ui and + * accounts. Should load data into accounts too. + * + * @param filePath the filepath. Should be data/save.txt by default + * + * @throws IOException thrown when something goes really, really wrong + */ public BankWithUs(String filePath) throws IOException { ui = new Ui(); storage = new Storage(filePath); diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index 39b8032d63..f671de2243 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -7,20 +7,36 @@ public class Storage { - private File saveFile; private final File SAVE_DIR = new File("data"); + private File saveFile; private Ui ui; + /** + * Creates a new instance of Storage. Initialises ui and saveFile. + * + * @param filepath the filepath. Should be data/save.txt by default + */ public Storage(String filepath) { this.saveFile = new File(filepath); this.ui = new Ui(); } - + + /** + * Loads the saveFile contexts into AccountList. + * + * @return the scanner containing the contents of the saveFile + * + * @throws FileNotFoundException if file is not found + */ public Scanner load() throws FileNotFoundException { - Scanner s = new Scanner(saveFile); - return s; + return new Scanner(saveFile); } + /** + * 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 createNewFile() throws IOException { SAVE_DIR.mkdir(); saveFile.createNewFile(); From 43434fc818acb48c3797c5f913da7feb7684641d Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 18:33:47 +0800 Subject: [PATCH 018/368] Added junit test for storage --- .../java/seedu/bankwithus/StorageTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/java/seedu/bankwithus/StorageTest.java diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java new file mode 100644 index 0000000000..49c15d6a5a --- /dev/null +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -0,0 +1,18 @@ +package seedu.bankwithus; + +import org.junit.jupiter.api.Test; + +import java.io.FileNotFoundException; +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class StorageTest { + @Test + public void load_normalSaveFile_noMessage() { + assertDoesNotThrow(() -> new Storage("data/save.txt")); + Storage storage = new Storage("data/save.txt"); + assertDoesNotThrow(() -> storage.load()); + } +} From 2c2b349809b6b3da68e6ae7a7f89875e0319290e Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 18:39:39 +0800 Subject: [PATCH 019/368] Removed unnecessary imports --- src/test/java/seedu/bankwithus/BankWithUsTest.java | 2 +- src/test/java/seedu/bankwithus/StorageTest.java | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/test/java/seedu/bankwithus/BankWithUsTest.java b/src/test/java/seedu/bankwithus/BankWithUsTest.java index 371bf4a723..e2a9934343 100644 --- a/src/test/java/seedu/bankwithus/BankWithUsTest.java +++ b/src/test/java/seedu/bankwithus/BankWithUsTest.java @@ -9,7 +9,7 @@ public class BankWithUsTest { @Test public void BankWithUs_emptyInput_exceptionThrown() { - Exception exception = assertThrows(IOException.class, () -> { + assertThrows(IOException.class, () -> { new BankWithUs(""); }); } diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index 49c15d6a5a..ffd9af35a3 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -2,11 +2,7 @@ import org.junit.jupiter.api.Test; -import java.io.FileNotFoundException; -import java.util.Scanner; - import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; public class StorageTest { @Test From 8061ac7d4bb609e8e02a4ca88843ce5690757a96 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 18:51:48 +0800 Subject: [PATCH 020/368] Modified files to comply with checkstyle --- src/main/java/seedu/bankwithus/Storage.java | 4 ++-- src/test/java/seedu/bankwithus/BankWithUsTest.java | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index f671de2243..0be54bd573 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -7,7 +7,7 @@ public class Storage { - private final File SAVE_DIR = new File("data"); + private final File saveDir = new File("data"); private File saveFile; private Ui ui; @@ -38,7 +38,7 @@ public Scanner load() throws FileNotFoundException { * @throws IOException if something goes really wrong. Should almost never happen */ public void createNewFile() throws IOException { - SAVE_DIR.mkdir(); + saveDir.mkdir(); saveFile.createNewFile(); ui.showFileCreated(); } diff --git a/src/test/java/seedu/bankwithus/BankWithUsTest.java b/src/test/java/seedu/bankwithus/BankWithUsTest.java index e2a9934343..8092890f16 100644 --- a/src/test/java/seedu/bankwithus/BankWithUsTest.java +++ b/src/test/java/seedu/bankwithus/BankWithUsTest.java @@ -8,9 +8,7 @@ public class BankWithUsTest { @Test - public void BankWithUs_emptyInput_exceptionThrown() { - assertThrows(IOException.class, () -> { - new BankWithUs(""); - }); + public void bankWithUs_emptyInput_exceptionThrown() { + assertThrows(IOException.class, () -> new BankWithUs("")); } } From dc9676284de2a1f50030acfe0d9340d24952b99a Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 19:17:49 +0800 Subject: [PATCH 021/368] Modify build.gradle --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index d5e548e85f..fb5d6dd6d5 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 } From dc085fa048386ca91136d1b434919be219996b24 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 19:22:10 +0800 Subject: [PATCH 022/368] Delete text in EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 8 -------- text-ui-test/input.txt | 1 - 2 files changed, 9 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 892cb6cae7..8b13789179 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,9 +1 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| -What is your name? -Hello James Gosling diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index f6ec2e9f95..e69de29bb2 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1 +0,0 @@ -James Gosling \ No newline at end of file From 0b5e54dfc0dc2d4325fc731c3fc0a5584f83cc7c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 19:25:51 +0800 Subject: [PATCH 023/368] Update EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 8b13789179..eaca171ff5 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1 +1,2 @@ - +File not found, trying to create file. +File created successfully! From cceec90f1d5aef5b847f5539142acab575f58495 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 10 Mar 2023 19:27:40 +0800 Subject: [PATCH 024/368] Update EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index eaca171ff5..fde6e33a7c 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,2 +1,2 @@ File not found, trying to create file. -File created successfully! +Savefile created successfully! From 267ed40f73114c62012264cf9e776218858e7c53 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Sat, 11 Mar 2023 23:58:07 +0800 Subject: [PATCH 025/368] add Account class --- src/main/java/seedu/bankwithus/Account.java | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/seedu/bankwithus/Account.java diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java new file mode 100644 index 0000000000..157b4f0222 --- /dev/null +++ b/src/main/java/seedu/bankwithus/Account.java @@ -0,0 +1,28 @@ +package seedu.bankwithus; + +public class Account { + protected String name; + protected float balance; + + + /** + * @param name initialise in the name of the account + * @param balance initialise the balance of the account + */ + public Account(String name, float balance){ + this.name = name; + this.balance = balance; + } + + /** + * @return returns a string contains the name of the Account + */ + public String getAccountName(){ + return name; + } + + public float getAccountBalance(){ + return balance; + } + +} From 2f75e2bfabfc3a8ecf983b1d5355b0c22b6c87ac Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Sun, 12 Mar 2023 00:04:25 +0800 Subject: [PATCH 026/368] Modify EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 9 --------- 1 file changed, 9 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 892cb6cae7..e69de29bb2 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,9 +0,0 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - -What is your name? -Hello James Gosling From 48072520f37d4216c669b4389ffcde84f2972b16 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Sun, 12 Mar 2023 08:59:54 +0800 Subject: [PATCH 027/368] Change function name from showLoadingError() to showFileNotFoundError --- src/main/java/seedu/bankwithus/BankWithUs.java | 2 +- src/main/java/seedu/bankwithus/Ui.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 30394ae2f0..ad3b0df333 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -25,7 +25,7 @@ public BankWithUs(String filePath) throws IOException { try { accounts = new AccountList(storage.load()); } catch (FileNotFoundException e) { - ui.showLoadingError(); + ui.showFileNotFoundError(); try { storage.createNewFile(); } catch (IOException ioE) { diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 9d471c30b0..229648fa68 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -2,7 +2,7 @@ public class Ui { - public void showLoadingError() { + public void showFileNotFoundError() { System.out.println("File not found, trying to create file."); } From 9a71ca5094d28d5b800dfea5c0ce2a88d4723891 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sun, 12 Mar 2023 11:06:07 +0800 Subject: [PATCH 028/368] Add create account feature --- src/main/java/seedu/bankwithus/AccountList.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index a98a40ad10..f84b7a628d 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,9 +1,23 @@ package seedu.bankwithus; +import java.util.ArrayList; + public class AccountList { + protected ArrayList accounts; public AccountList() { - + } + + /** + * Creates a new account and adds it to the AccountList. + * + * @param name the name of the new account to be added + * @param balanceString the balance of the new account to be added in String type + */ + public void addAccount(String name, String balanceString) { + float balance = Float.parseFloat(balanceString); + Account newAccount = new Account(name, balance); + accounts.add(newAccount); } public AccountList(String saveString) { From 4daadf6a6c37ccf90c703686ed3dfe83af421958 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sun, 12 Mar 2023 20:53:12 +0800 Subject: [PATCH 029/368] Add create account feature --- src/test/java/seedu/bankwithus/AccountListTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index e9619db43c..158b7b476e 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,8 +1,6 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; - - import static org.junit.jupiter.api.Assertions.*; class AccountListTest { From 9e8019d682f49f8e7c263604b9b6e3452977d737 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sun, 12 Mar 2023 21:18:48 +0800 Subject: [PATCH 030/368] Fix Checkstyle errors --- src/main/java/seedu/bankwithus/AccountList.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index a7dbfbb313..4bdeeb9387 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,16 +1,18 @@ package seedu.bankwithus; -import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; public class AccountList { protected ArrayList accounts; - public Ui ui; - + private Ui ui; public AccountList() { } + public AccountList(Scanner scanner) { + + } + /** * Creates a new account and adds it to the AccountList. * @@ -27,8 +29,4 @@ public void addAccount(String name, String balanceString) throws NumberFormatExc ui.showNumberFormatError(); } } - - public AccountList(Scanner scanner) { - - } } From e290bf28b9f7e4a5d919ac13b48237c3112d7d86 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sun, 12 Mar 2023 21:24:59 +0800 Subject: [PATCH 031/368] Fix Checkstyle errors --- src/test/java/seedu/bankwithus/AccountListTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 158b7b476e..03fbda095c 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,7 +1,7 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { @@ -13,4 +13,4 @@ void addAccount_invalidBalance_expectException() throws NullPointerException { assertThrows(NullPointerException.class, () -> accountList.addAccount(name, balanceString)); } -} \ No newline at end of file +} From bfca9ce3f437abde3ed4c77d1e5658196a52dddd Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 13 Mar 2023 12:49:58 +0800 Subject: [PATCH 032/368] Add Save Feature and some JavaDoc --- src/main/java/seedu/bankwithus/AccountList.java | 13 +++++++++++++ src/main/java/seedu/bankwithus/Storage.java | 13 ++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 4bdeeb9387..2f85f4476e 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -29,4 +29,17 @@ public void addAccount(String name, String balanceString) throws NumberFormatExc ui.showNumberFormatError(); } } + + /** + * @return returns all accounts details in String + * name and balance are separated by $ prepared to be saved + */ + public String getAllAccountDetails(){ + String temp = ""; + for (Account acc : accounts ) { + temp += acc.name + "$" + acc.balance; + temp += "\n"; + } + return temp; + } } diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index 0be54bd573..f42572d512 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.FileNotFoundException; +import java.io.FileWriter; import java.io.IOException; import java.util.Scanner; @@ -25,7 +26,6 @@ public Storage(String filepath) { * Loads the saveFile contexts into AccountList. * * @return the scanner containing the contents of the saveFile - * * @throws FileNotFoundException if file is not found */ public Scanner load() throws FileNotFoundException { @@ -43,4 +43,15 @@ public void createNewFile() throws IOException { ui.showFileCreated(); } + /** + * 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(saveFile); + fw.write(list.getAllAccountDetails()); + fw.close(); + } + } From 384ed2bd5f8eda491da38ab3337b5f14fab6bbad Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 13 Mar 2023 12:50:32 +0800 Subject: [PATCH 033/368] Add exit method in Main Add farewell message in Ui --- src/main/java/seedu/bankwithus/BankWithUs.java | 17 ++++++++++++++++- src/main/java/seedu/bankwithus/Ui.java | 4 ++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index ad3b0df333..457a5cb305 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -16,7 +16,6 @@ public class BankWithUs { * accounts. Should load data into accounts too. * * @param filePath the filepath. Should be data/save.txt by default - * * @throws IOException thrown when something goes really, really wrong */ public BankWithUs(String filePath) throws IOException { @@ -36,9 +35,25 @@ public BankWithUs(String filePath) throws IOException { } } + /** + * exit the programme, save the data and show farewell message + * + * @throws IOException throw error if the data cannot be saved + */ + private void exit(String filePath) throws IOException { + try { + storage.saveToFile(accounts); + } catch (IOException e) { + ui.showIOError(); + throw e; + } + ui.showFarewellMessage(); + } + public void run() { } + public static void main(String[] args) { try { new BankWithUs(FILE_PATH).run(); diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 4803c07865..5b2d99ef5f 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -17,4 +17,8 @@ public void showIOError() { public void showNumberFormatError() { System.out.println("The input is not a number! Please try again."); } + + public void showFarewellMessage(){ + System.out.println("Goodbye! Hope to see you again! :)"); + } } From 89e5b1d1248c9dfa55031207f34b1e05f44bdced Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 13 Mar 2023 12:55:16 +0800 Subject: [PATCH 034/368] Change incorrect indentation level --- src/main/java/seedu/bankwithus/AccountList.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 2f85f4476e..b02e6e2c23 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -6,6 +6,7 @@ public class AccountList { protected ArrayList accounts; private Ui ui; + public AccountList() { } @@ -16,7 +17,7 @@ public AccountList(Scanner scanner) { /** * Creates a new account and adds it to the AccountList. * - * @param name Name of the new account to be added + * @param name Name of the new account to be added * @param balanceString Balance of the new account to be added in String type * @throws NumberFormatException If balanceString cannot be parsed into a float number */ @@ -34,9 +35,9 @@ public void addAccount(String name, String balanceString) throws NumberFormatExc * @return returns all accounts details in String * name and balance are separated by $ prepared to be saved */ - public String getAllAccountDetails(){ + public String getAllAccountDetails() { String temp = ""; - for (Account acc : accounts ) { + for (Account acc : accounts) { temp += acc.name + "$" + acc.balance; temp += "\n"; } From c3691dbc69f0de6763634fd3ee9f7c45b716e0f2 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 13 Mar 2023 12:58:51 +0800 Subject: [PATCH 035/368] Change indentation level --- src/main/java/seedu/bankwithus/AccountList.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index b02e6e2c23..f049883c71 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -32,8 +32,9 @@ public void addAccount(String name, String balanceString) throws NumberFormatExc } /** - * @return returns all accounts details in String * name and balance are separated by $ prepared to be saved + * + * @return returns all accounts details in String */ public String getAllAccountDetails() { String temp = ""; From 0c4e074072d06a0f7898fcad0996adc9bdf6432d Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 13 Mar 2023 13:01:47 +0800 Subject: [PATCH 036/368] no message --- src/main/java/seedu/bankwithus/Account.java | 8 ++++---- src/main/java/seedu/bankwithus/Ui.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 157b4f0222..9fd5c4a77b 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -6,10 +6,10 @@ public class Account { /** - * @param name initialise in the name of the account + * @param name initialise in the name of the account * @param balance initialise the balance of the account */ - public Account(String name, float balance){ + public Account(String name, float balance) { this.name = name; this.balance = balance; } @@ -17,11 +17,11 @@ public Account(String name, float balance){ /** * @return returns a string contains the name of the Account */ - public String getAccountName(){ + public String getAccountName() { return name; } - public float getAccountBalance(){ + public float getAccountBalance() { return balance; } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 5b2d99ef5f..787b3fb7e3 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -1,7 +1,7 @@ package seedu.bankwithus; public class Ui { - + public void showFileNotFoundError() { System.out.println("File not found, trying to create file."); } @@ -18,7 +18,7 @@ public void showNumberFormatError() { System.out.println("The input is not a number! Please try again."); } - public void showFarewellMessage(){ + public void showFarewellMessage() { System.out.println("Goodbye! Hope to see you again! :)"); } } From bef069940945d4e515a645fa98418e314525ddd1 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 13 Mar 2023 14:16:10 +0800 Subject: [PATCH 037/368] Created Parser class --- .../java/seedu/bankwithus/BankWithUs.java | 22 ++++++++++-- src/main/java/seedu/bankwithus/Parser.java | 28 +++++++++++++++ src/main/java/seedu/bankwithus/Ui.java | 34 +++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/Parser.java diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 457a5cb305..e79e96bab2 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -3,13 +3,18 @@ import java.io.FileNotFoundException; import java.io.IOException; +import seedu.bankwithus.exceptions.CommandNotFoundException; + public class BankWithUs { public static final String FILE_PATH = "data/save.txt"; + public boolean isExitEntered = false; + private Storage storage; private Ui ui; private AccountList accounts; + private Parser parser; /** * Creates a new instance of BankWithUs. Initialises storage, ui and @@ -21,6 +26,7 @@ public class BankWithUs { public BankWithUs(String filePath) throws IOException { ui = new Ui(); storage = new Storage(filePath); + parser = new Parser(this); try { accounts = new AccountList(storage.load()); } catch (FileNotFoundException e) { @@ -40,7 +46,7 @@ public BankWithUs(String filePath) throws IOException { * * @throws IOException throw error if the data cannot be saved */ - private void exit(String filePath) throws IOException { + public void exit(String filePath) throws IOException { try { storage.saveToFile(accounts); } catch (IOException e) { @@ -48,10 +54,20 @@ private void exit(String filePath) throws IOException { throw e; } ui.showFarewellMessage(); + ui.closeScanner(); } - public void run() { - + public void run() throws IOException { + ui.createScanner(); + while (!isExitEntered) { + String line = ui.getNextLine(); + try { + parser.parseUserInput(line); + } catch (CommandNotFoundException e) { + ui.showCommandNotFoundError(); + } + } + exit(FILE_PATH); } public static void main(String[] args) { diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java new file mode 100644 index 0000000000..502df09107 --- /dev/null +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -0,0 +1,28 @@ +package seedu.bankwithus; + +import seedu.bankwithus.exceptions.CommandNotFoundException; + +public class Parser { + + private BankWithUs bwu; + + public Parser(BankWithUs bwu) { + this.bwu = bwu; + } + + public void parseUserInput(String input) throws CommandNotFoundException { + // 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": + bwu.isExitEntered = true; + break; + default: + throw new CommandNotFoundException(); + } + } + +} diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 787b3fb7e3..60f3e714e8 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -1,7 +1,11 @@ package seedu.bankwithus; +import java.util.Scanner; + public class Ui { + private Scanner scanner; + public void showFileNotFoundError() { System.out.println("File not found, trying to create file."); } @@ -18,7 +22,37 @@ public void showNumberFormatError() { System.out.println("The input is not a number! 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! :)"); } + + /** + * 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(); + } } From bebfeb7b6505b6e63bbf58b2e236c4a42beb7bf8 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 13 Mar 2023 14:16:36 +0800 Subject: [PATCH 038/368] Created CommandNotFoundException --- src/main/java/seedu/bankwithus/AccountList.java | 1 + .../bankwithus/exceptions/CommandNotFoundException.java | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 src/main/java/seedu/bankwithus/exceptions/CommandNotFoundException.java diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index f049883c71..9686203934 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -8,6 +8,7 @@ public class AccountList { private Ui ui; public AccountList() { + } public AccountList(Scanner scanner) { 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 { + +} From 7c1aabfe2df19857c84e1106849c7bedaf5dfc0e Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 13 Mar 2023 14:20:06 +0800 Subject: [PATCH 039/368] Fixed bug that will occur when exiting due to accounts being null --- src/main/java/seedu/bankwithus/AccountList.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 9686203934..ac481df27d 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -8,11 +8,11 @@ public class AccountList { private Ui ui; public AccountList() { - + accounts = new ArrayList(); } public AccountList(Scanner scanner) { - + accounts = new ArrayList(); } /** From 5b080ef6997b2f9da019815f9f8fd2524df5afa9 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 13 Mar 2023 14:25:38 +0800 Subject: [PATCH 040/368] Update input and expected text --- text-ui-test/EXPECTED.TXT | 2 ++ text-ui-test/input.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index fde6e33a7c..b5138c75f8 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,2 +1,4 @@ File not found, trying to create file. Savefile created successfully! +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 e69de29bb2..04a8411967 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,2 @@ +hihi +exit From 93adce46b9b40c1f59e67f28d8fec4485b1a8e7c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 13 Mar 2023 14:52:45 +0800 Subject: [PATCH 041/368] Added javadoc comments --- src/main/java/seedu/bankwithus/BankWithUs.java | 6 ++++++ src/main/java/seedu/bankwithus/Parser.java | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index e79e96bab2..308f4aad6e 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -57,6 +57,12 @@ public void exit(String filePath) throws IOException { ui.closeScanner(); } + /** + * 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 { ui.createScanner(); while (!isExitEntered) { diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 502df09107..65e02b86a0 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -10,6 +10,10 @@ public Parser(BankWithUs bwu) { this.bwu = bwu; } + /** + * Parses the user input into command and arguments. + */ + public void parseUserInput(String input) throws CommandNotFoundException { // Split input by space String[] split = input.trim().split("\\s+", 2); From 92a2d9629a0ed2c3d3f3e090e9f65711162a1822 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 13 Mar 2023 17:40:36 +0800 Subject: [PATCH 042/368] Created a createAccount method in BankWithUS class and also changed private AccountList to protected --- src/main/java/seedu/bankwithus/BankWithUs.java | 17 ++++++++++++++++- src/main/java/seedu/bankwithus/Parser.java | 12 ++++++++++-- src/main/java/seedu/bankwithus/Storage.java | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 308f4aad6e..18c8a6d383 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -13,7 +13,7 @@ public class BankWithUs { private Storage storage; private Ui ui; - private AccountList accounts; + protected static AccountList accounts; private Parser parser; /** @@ -65,6 +65,11 @@ public void exit(String filePath) throws IOException { */ public void run() throws IOException { ui.createScanner(); + if (storage.saveFile.length() < 1) { + createAccount(); + } else { + + } while (!isExitEntered) { String line = ui.getNextLine(); try { @@ -83,4 +88,14 @@ public static void main(String[] args) { return; } } + + public void createAccount() { + System.out.println("Whats your name?"); + ui.createScanner(); + String userName = ui.getNextLine(); + System.out.println("How much would you like to add as Balance?"); + float balance = Float.parseFloat(ui.getNextLine()); + Account myAccount = new Account(userName, balance); + accounts.accounts.add(myAccount); + } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 65e02b86a0..d17dd35b4c 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -1,7 +1,7 @@ package seedu.bankwithus; import seedu.bankwithus.exceptions.CommandNotFoundException; - +import seedu.bankwithus.BankWithUs; public class Parser { private BankWithUs bwu; @@ -21,9 +21,17 @@ public void parseUserInput(String input) throws CommandNotFoundException { String args = split.length == 2 ? split[1] : ""; switch (command) { - case "exit": + case "exit": { bwu.isExitEntered = true; break; + } + + case "balance" : { + for(Account acc : BankWithUs.accounts.accounts) { + System.out.println(acc.balance); + } + break; + } default: throw new CommandNotFoundException(); } diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index f42572d512..245e5c8a6a 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -9,7 +9,7 @@ public class Storage { private final File saveDir = new File("data"); - private File saveFile; + protected File saveFile; private Ui ui; /** From fbcd166c57ec3a66bb90963b11bfe4031e3e8191 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 13 Mar 2023 20:03:09 +0800 Subject: [PATCH 043/368] Changed the separator in save.txt from $ to ; and added a createAccount function to make a new account for the current user --- src/main/java/seedu/bankwithus/AccountList.java | 10 ++++++++-- src/main/java/seedu/bankwithus/BankWithUs.java | 6 +++--- src/main/java/seedu/bankwithus/Parser.java | 10 ++++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index ac481df27d..848b656ba0 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,10 +1,14 @@ package seedu.bankwithus; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; public class AccountList { - protected ArrayList accounts; + protected static ArrayList accounts; private Ui ui; public AccountList() { @@ -40,9 +44,11 @@ public void addAccount(String name, String balanceString) throws NumberFormatExc public String getAllAccountDetails() { String temp = ""; for (Account acc : accounts) { - temp += acc.name + "$" + acc.balance; + temp += acc.name + ";" + acc.balance; temp += "\n"; } return temp; } + + } diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 18c8a6d383..7ad6d6a2d7 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -1,6 +1,8 @@ package seedu.bankwithus; +import java.io.BufferedReader; import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; import seedu.bankwithus.exceptions.CommandNotFoundException; @@ -67,8 +69,6 @@ public void run() throws IOException { ui.createScanner(); if (storage.saveFile.length() < 1) { createAccount(); - } else { - } while (!isExitEntered) { String line = ui.getNextLine(); @@ -96,6 +96,6 @@ public void createAccount() { System.out.println("How much would you like to add as Balance?"); float balance = Float.parseFloat(ui.getNextLine()); Account myAccount = new Account(userName, balance); - accounts.accounts.add(myAccount); + AccountList.accounts.add(myAccount); } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index d17dd35b4c..07b8dc6c60 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -2,6 +2,11 @@ import seedu.bankwithus.exceptions.CommandNotFoundException; import seedu.bankwithus.BankWithUs; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; + public class Parser { private BankWithUs bwu; @@ -16,7 +21,7 @@ public Parser(BankWithUs bwu) { public void parseUserInput(String input) throws CommandNotFoundException { // Split input by space - String[] split = input.trim().split("\\s+", 2); + String[] split = input.trim().split(" ", 2); String command = split[0]; String args = split.length == 2 ? split[1] : ""; @@ -27,7 +32,7 @@ public void parseUserInput(String input) throws CommandNotFoundException { } case "balance" : { - for(Account acc : BankWithUs.accounts.accounts) { + for(Account acc : AccountList.accounts) { System.out.println(acc.balance); } break; @@ -37,4 +42,5 @@ public void parseUserInput(String input) throws CommandNotFoundException { } } + } From f86b144ca777804aa77b34311f722456fdfbc425 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 13 Mar 2023 20:35:41 +0800 Subject: [PATCH 044/368] Removed unecessary imports, changed switch to if else in parser; Made changes to comply with checkStyle --- .../java/seedu/bankwithus/AccountList.java | 4 --- .../java/seedu/bankwithus/BankWithUs.java | 6 +---- src/main/java/seedu/bankwithus/Parser.java | 27 +++---------------- src/main/java/seedu/bankwithus/Storage.java | 2 +- 4 files changed, 6 insertions(+), 33 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 848b656ba0..7adc549557 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,9 +1,5 @@ package seedu.bankwithus; -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 7ad6d6a2d7..8bb89093b8 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -1,8 +1,6 @@ package seedu.bankwithus; -import java.io.BufferedReader; import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; import seedu.bankwithus.exceptions.CommandNotFoundException; @@ -10,12 +8,10 @@ public class BankWithUs { public static final String FILE_PATH = "data/save.txt"; - + protected static AccountList accounts; public boolean isExitEntered = false; - private Storage storage; private Ui ui; - protected static AccountList accounts; private Parser parser; /** diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 07b8dc6c60..a7c514352b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -1,14 +1,7 @@ package seedu.bankwithus; import seedu.bankwithus.exceptions.CommandNotFoundException; -import seedu.bankwithus.BankWithUs; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; - public class Parser { - private BankWithUs bwu; public Parser(BankWithUs bwu) { @@ -18,29 +11,17 @@ public Parser(BankWithUs bwu) { /** * Parses the user input into command and arguments. */ - + public void parseUserInput(String input) throws CommandNotFoundException { // Split input by space - String[] split = input.trim().split(" ", 2); + String[] split = input.trim().split("\\s+", 2); String command = split[0]; String args = split.length == 2 ? split[1] : ""; - switch (command) { - case "exit": { + if (command.equals("exit")) { bwu.isExitEntered = true; - break; - } - - case "balance" : { - for(Account acc : AccountList.accounts) { - System.out.println(acc.balance); - } - break; - } - default: + } else { throw new CommandNotFoundException(); } } - - } diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index 245e5c8a6a..c31f53fe3f 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -8,8 +8,8 @@ public class Storage { - private final File saveDir = new File("data"); protected File saveFile; + private final File saveDir = new File("data"); private Ui ui; /** From f1637ebc123020d8d301296ab5d8e002dbed416f Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Tue, 14 Mar 2023 14:23:56 +0800 Subject: [PATCH 045/368] Add save feature test --- src/test/java/seedu/bankwithus/StorageTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index ffd9af35a3..1ded681b95 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -2,6 +2,8 @@ import org.junit.jupiter.api.Test; +import java.util.Scanner; + import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; public class StorageTest { @@ -11,4 +13,11 @@ public void load_normalSaveFile_noMessage() { Storage storage = new Storage("data/save.txt"); assertDoesNotThrow(() -> storage.load()); } + + @Test + public void save_accountList_noMessage(){ + AccountList accountList = new AccountList(); + Storage storage = new Storage("data/save.txt"); + assertDoesNotThrow(() -> storage.saveToFile(accountList)); + } } From 26a714d3d16418b3fc63805e6c9fd6ed34d6a865 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Tue, 14 Mar 2023 14:33:53 +0800 Subject: [PATCH 046/368] Made changes to createAccount function in BankWithUs class --- data/save.txt | 1 + .../java/seedu/bankwithus/AccountList.java | 2 +- .../java/seedu/bankwithus/BankWithUs.java | 22 ++++++++++--------- text-ui-test/EXPECTED.TXT | 3 ++- text-ui-test/data/save.txt | 0 text-ui-test/input.txt | 5 +++-- 6 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 text-ui-test/data/save.txt diff --git a/data/save.txt b/data/save.txt index e69de29bb2..eed34ab1ea 100644 --- a/data/save.txt +++ b/data/save.txt @@ -0,0 +1 @@ +june;1000.0 diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 7adc549557..c81cae6824 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -4,7 +4,7 @@ import java.util.Scanner; public class AccountList { - protected static ArrayList accounts; + protected ArrayList accounts; private Ui ui; public AccountList() { diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 8bb89093b8..b418c5b8a5 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -8,7 +8,7 @@ public class BankWithUs { public static final String FILE_PATH = "data/save.txt"; - protected static AccountList accounts; + protected AccountList accounts; public boolean isExitEntered = false; private Storage storage; private Ui ui; @@ -55,6 +55,17 @@ public void exit(String filePath) throws IOException { ui.closeScanner(); } + /** + * Creates a new Account for a first time user + */ + public void createAccount() { + System.out.println("Whats your name?"); + String userName = ui.getNextLine(); + System.out.println("How much would you like to add as Balance?"); + String balance = ui.getNextLine(); + this.accounts.addAccount(userName, balance); + } + /** * The main command and output loop. Takes in user input line by line * and gives it to the parser to execute the command. @@ -85,13 +96,4 @@ public static void main(String[] args) { } } - public void createAccount() { - System.out.println("Whats your name?"); - ui.createScanner(); - String userName = ui.getNextLine(); - System.out.println("How much would you like to add as Balance?"); - float balance = Float.parseFloat(ui.getNextLine()); - Account myAccount = new Account(userName, balance); - AccountList.accounts.add(myAccount); - } } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index b5138c75f8..8cbf759a1d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,4 +1,5 @@ File not found, trying to create file. Savefile created successfully! -Not a valid command! +Whats your name? +How much would you like to add as Balance? Goodbye! Hope to see you again! :) diff --git a/text-ui-test/data/save.txt b/text-ui-test/data/save.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 04a8411967..60e77a6b1e 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,2 +1,3 @@ -hihi -exit +june +1000 +exit \ No newline at end of file From 6fee70a5d3fc7906d3bc482584f4e7dc9689d720 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Tue, 14 Mar 2023 14:38:43 +0800 Subject: [PATCH 047/368] Add parseSavedFile --- src/main/java/seedu/bankwithus/Parser.java | 25 ++++++++++++++----- .../java/seedu/bankwithus/StorageTest.java | 2 +- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 65e02b86a0..76b7819dfc 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -2,6 +2,8 @@ import seedu.bankwithus.exceptions.CommandNotFoundException; +import java.util.Scanner; + public class Parser { private BankWithUs bwu; @@ -13,7 +15,7 @@ public Parser(BankWithUs bwu) { /** * Parses the user input into command and arguments. */ - + public void parseUserInput(String input) throws CommandNotFoundException { // Split input by space String[] split = input.trim().split("\\s+", 2); @@ -21,11 +23,22 @@ public void parseUserInput(String input) throws CommandNotFoundException { String args = split.length == 2 ? split[1] : ""; switch (command) { - case "exit": - bwu.isExitEntered = true; - break; - default: - throw new CommandNotFoundException(); + case "exit": + bwu.isExitEntered = true; + break; + default: + throw new CommandNotFoundException(); + } + } + + public void parseSavedFile(AccountList list) { + Scanner myReader = new Scanner("data/save.txt"); + while (myReader.hasNextLine()) { + String data = myReader.nextLine(); + String[] splitDetails = data.split("\\$"); + String name = splitDetails[0]; + String balance = splitDetails[1]; + list.addAccount(name, balance); } } diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index 1ded681b95..cb31cc5934 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -15,7 +15,7 @@ public void load_normalSaveFile_noMessage() { } @Test - public void save_accountList_noMessage(){ + public void save_accountList_noMessage() { AccountList accountList = new AccountList(); Storage storage = new Storage("data/save.txt"); assertDoesNotThrow(() -> storage.saveToFile(accountList)); From df371a479477c67663dac8b015dce6eeea654db9 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Tue, 14 Mar 2023 14:38:46 +0800 Subject: [PATCH 048/368] Made changes to comply with checkstyleMain --- src/main/java/seedu/bankwithus/BankWithUs.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index b418c5b8a5..72fb8fa92d 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -8,8 +8,8 @@ public class BankWithUs { public static final String FILE_PATH = "data/save.txt"; - protected AccountList accounts; public boolean isExitEntered = false; + protected AccountList accounts; private Storage storage; private Ui ui; private Parser parser; From 4fe140e9a71610f59345463cdd74b3c10496cc75 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Tue, 14 Mar 2023 14:56:31 +0800 Subject: [PATCH 049/368] Add JavaDoc for parseSavedFile method --- src/main/java/seedu/bankwithus/Parser.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 76b7819dfc..9c14de916f 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -31,11 +31,17 @@ public void parseUserInput(String input) throws CommandNotFoundException { } } + /** + * This method reads any existing file and add the saved data + * into current programme + * + * @param list current operation AccountList + */ public void parseSavedFile(AccountList list) { Scanner myReader = new Scanner("data/save.txt"); while (myReader.hasNextLine()) { String data = myReader.nextLine(); - String[] splitDetails = data.split("\\$"); + String[] splitDetails = data.split(";"); String name = splitDetails[0]; String balance = splitDetails[1]; list.addAccount(name, balance); From f35b42d03d301695f71f3ffd8dd893de923d9a88 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Tue, 14 Mar 2023 14:23:56 +0800 Subject: [PATCH 050/368] Add save feature test --- src/test/java/seedu/bankwithus/StorageTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index ffd9af35a3..1ded681b95 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -2,6 +2,8 @@ import org.junit.jupiter.api.Test; +import java.util.Scanner; + import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; public class StorageTest { @@ -11,4 +13,11 @@ public void load_normalSaveFile_noMessage() { Storage storage = new Storage("data/save.txt"); assertDoesNotThrow(() -> storage.load()); } + + @Test + public void save_accountList_noMessage(){ + AccountList accountList = new AccountList(); + Storage storage = new Storage("data/save.txt"); + assertDoesNotThrow(() -> storage.saveToFile(accountList)); + } } From 1e582b449083fef8b7690317e24415c6d61d8f98 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Tue, 14 Mar 2023 15:21:26 +0800 Subject: [PATCH 051/368] Add deposit feature --- src/main/java/seedu/bankwithus/Account.java | 2 +- .../java/seedu/bankwithus/AccountList.java | 14 +++++++++++ .../java/seedu/bankwithus/BankWithUs.java | 23 ++++++++++++++---- src/main/java/seedu/bankwithus/Parser.java | 8 +++++-- src/main/java/seedu/bankwithus/Ui.java | 9 +++---- .../seedu/bankwithus/AccountListTest.java | 24 +++++++++++++++++++ 6 files changed, 69 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 9fd5c4a77b..d775378423 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -4,7 +4,7 @@ public class Account { protected String name; protected float balance; - + private Ui ui; /** * @param name initialise in the name of the account * @param balance initialise the balance of the account diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index ac481df27d..76ae8a8432 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -45,4 +45,18 @@ public String getAllAccountDetails() { } return temp; } + + public Account getCurrentAccount() { + return accounts.get(0); + } + + public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException { + try { + float depositAmount = Float.parseFloat(depositAmountString); + getCurrentAccount().balance += depositAmount; + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } + } + } diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 308f4aad6e..0a9a486197 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -13,7 +13,9 @@ public class BankWithUs { private Storage storage; private Ui ui; - private AccountList accounts; + private AccountList accountList; + + private Account currentAccount; private Parser parser; /** @@ -28,7 +30,7 @@ public BankWithUs(String filePath) throws IOException { storage = new Storage(filePath); parser = new Parser(this); try { - accounts = new AccountList(storage.load()); + accountList = new AccountList(storage.load()); } catch (FileNotFoundException e) { ui.showFileNotFoundError(); try { @@ -37,7 +39,7 @@ public BankWithUs(String filePath) throws IOException { ui.showIOError(); throw ioE; } - accounts = new AccountList(); + accountList = new AccountList(); } } @@ -48,7 +50,7 @@ public BankWithUs(String filePath) throws IOException { */ public void exit(String filePath) throws IOException { try { - storage.saveToFile(accounts); + storage.saveToFile(accountList); } catch (IOException e) { ui.showIOError(); throw e; @@ -76,6 +78,15 @@ public void run() throws IOException { exit(FILE_PATH); } + + public AccountList getAccountList() { + return accountList; + } + + public void setAccountList(AccountList accountList) { + this.accountList = accountList; + } + public static void main(String[] args) { try { new BankWithUs(FILE_PATH).run(); @@ -83,4 +94,8 @@ public static void main(String[] args) { return; } } + + public void setCurrentAccount(Account currentAccount) { + this.currentAccount = currentAccount; + } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 65e02b86a0..0d29eaac80 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -3,7 +3,7 @@ import seedu.bankwithus.exceptions.CommandNotFoundException; public class Parser { - + private Ui ui; private BankWithUs bwu; public Parser(BankWithUs bwu) { @@ -13,7 +13,6 @@ public Parser(BankWithUs bwu) { /** * Parses the user input into command and arguments. */ - public void parseUserInput(String input) throws CommandNotFoundException { // Split input by space String[] split = input.trim().split("\\s+", 2); @@ -24,6 +23,11 @@ public void parseUserInput(String input) throws CommandNotFoundException { case "exit": bwu.isExitEntered = true; break; + case "deposit": + bwu.getAccountList().depositMoney(args); + ui.showDepositMessage(); + break; + default: throw new CommandNotFoundException(); } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 60f3e714e8..f662599968 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -19,7 +19,7 @@ public void showIOError() { } public void showNumberFormatError() { - System.out.println("The input is not a number! Please try again."); + System.out.println("The input is not a valid number! Please try again."); } public void showCommandNotFoundError() { @@ -30,10 +30,13 @@ public void showFarewellMessage() { System.out.println("Goodbye! Hope to see you again! :)"); } + public void showDepositMessage() { + System.out.println("New deposit added!"); + } + /** * Creates a scanner in the Ui class */ - public void createScanner() { this.scanner = new Scanner(System.in); } @@ -43,7 +46,6 @@ public void createScanner() { * * @return the next of user input */ - public String getNextLine() { return scanner.nextLine(); } @@ -51,7 +53,6 @@ public String getNextLine() { /** * Closes the scanner */ - public void closeScanner() { this.scanner.close(); } diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 03fbda095c..78da15c00a 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,6 +1,8 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { @@ -13,4 +15,26 @@ void addAccount_invalidBalance_expectException() throws NullPointerException { assertThrows(NullPointerException.class, () -> accountList.addAccount(name, balanceString)); } + + @Test + void depositMoney_invalidAmount_expectException() throws NullPointerException { + String amountString = "abc"; + String name = "Bob"; + String balance = "0"; + AccountList accountList = new AccountList(); + accountList.addAccount(name, balance); + assertThrows(NullPointerException.class, + () -> accountList.depositMoney(amountString)); + } + + @Test + void depositMoney_validAmount_expectDeposit() { + String amountString = "100.5"; + String name = "Bob"; + String balance = "100.5"; + AccountList accountList = new AccountList(); + accountList.addAccount(name, balance); + accountList.depositMoney(amountString); + assertEquals(201, accountList.getCurrentAccount().getAccountBalance()); + } } From eeba4bcc484b061b686a20642e8585bbf94fab11 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Tue, 14 Mar 2023 15:45:17 +0800 Subject: [PATCH 052/368] Add parseSavedFile --- src/main/java/seedu/bankwithus/Parser.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 0ec2d51fc8..7eb75f3062 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -2,6 +2,7 @@ import seedu.bankwithus.exceptions.CommandNotFoundException; +import java.io.File; import java.io.IOException; import java.util.Scanner; @@ -41,8 +42,9 @@ public void parseUserInput(String input) throws CommandNotFoundException { * * @param list current operation AccountList */ - public void parseSavedFile(AccountList list) { - Scanner myReader = new Scanner("data/save.txt"); + public void parseSavedFile(AccountList list) throws IOException { + File f = new File("data/save.txt"); + Scanner myReader = new Scanner(f); while (myReader.hasNextLine()) { String data = myReader.nextLine(); String[] splitDetails = data.split(";"); From ae93b46591e92c7a9acda6590e2c1ab514dd1451 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Tue, 14 Mar 2023 15:47:17 +0800 Subject: [PATCH 053/368] Modify the Main block --- src/main/java/seedu/bankwithus/BankWithUs.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 610d7c4fc7..d4f88ae7c8 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -69,17 +69,19 @@ public void createAccount() { /** * 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 { ui.createScanner(); if (storage.saveFile.length() < 1) { createAccount(); - } - else { - parser.parseSavedFile(accounts); - System.out.println(accounts.getAllAccountDetails()); + } else { + try { + parser.parseSavedFile(accounts); + } catch (IOException e) { + ui.showIOError(); + } } while (!isExitEntered) { String line = ui.getNextLine(); @@ -96,8 +98,6 @@ public static void main(String[] args) { try { new BankWithUs(FILE_PATH).run(); } catch (IOException e) { - return; } } - } From e81ccb96819e02ab34a676d817923c0728623c2c Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Tue, 14 Mar 2023 16:09:23 +0800 Subject: [PATCH 054/368] Deleted data/save.txt --- data/save.txt | 1 - text-ui-test/data/save.txt | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt deleted file mode 100644 index eed34ab1ea..0000000000 --- a/data/save.txt +++ /dev/null @@ -1 +0,0 @@ -june;1000.0 diff --git a/text-ui-test/data/save.txt b/text-ui-test/data/save.txt index e69de29bb2..eed34ab1ea 100644 --- a/text-ui-test/data/save.txt +++ b/text-ui-test/data/save.txt @@ -0,0 +1 @@ +june;1000.0 From 059f3b5bcadda2efb915af9bd32d7acc4855007b Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Tue, 14 Mar 2023 16:10:17 +0800 Subject: [PATCH 055/368] Fix bugs --- data/save.txt | 1 - src/main/java/seedu/bankwithus/BankWithUs.java | 7 +++---- 2 files changed, 3 insertions(+), 5 deletions(-) delete mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt deleted file mode 100644 index eed34ab1ea..0000000000 --- a/data/save.txt +++ /dev/null @@ -1 +0,0 @@ -june;1000.0 diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index cc72333f8c..230d1df180 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -9,7 +9,6 @@ public class BankWithUs { public static final String FILE_PATH = "data/save.txt"; public boolean isExitEntered = false; - protected AccountList accounts; private Storage storage; private Ui ui; private AccountList accountList; @@ -59,18 +58,18 @@ public void exit(String filePath) throws IOException { /** * Creates a new Account for a first time user */ - public void createAccount() { + public void createAccount() { System.out.println("Whats your name?"); String userName = ui.getNextLine(); System.out.println("How much would you like to add as Balance?"); String balance = ui.getNextLine(); - this.accounts.addAccount(userName, balance); + accountList.addAccount(userName, balance); } /** * 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 { From bd23def3a15aa441203b2967513f724376812c0f Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 14 Mar 2023 16:51:06 +0800 Subject: [PATCH 056/368] Resolved checkstyle errors --- src/main/java/seedu/bankwithus/BankWithUs.java | 1 + src/main/java/seedu/bankwithus/Parser.java | 10 +++++----- src/test/java/seedu/bankwithus/StorageTest.java | 2 -- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index d4f88ae7c8..5c0866d29f 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -98,6 +98,7 @@ public static void main(String[] args) { try { new BankWithUs(FILE_PATH).run(); } catch (IOException e) { + return; } } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 7eb75f3062..2f3b72ee7c 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -27,11 +27,11 @@ public void parseUserInput(String input) throws CommandNotFoundException { bwu.isExitEntered = true; } else { switch (command) { - case "exit": - bwu.isExitEntered = true; - break; - default: - throw new CommandNotFoundException(); + case "exit": + bwu.isExitEntered = true; + break; + default: + throw new CommandNotFoundException(); } } } diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index cb31cc5934..4f05aa2f37 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -2,8 +2,6 @@ import org.junit.jupiter.api.Test; -import java.util.Scanner; - import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; public class StorageTest { From f6bd48e09fea98e6d5914a0e6dad067f3795e909 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 14 Mar 2023 16:59:21 +0800 Subject: [PATCH 057/368] Deleted the savefile in text-ui-test --- text-ui-test/data/save.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 text-ui-test/data/save.txt diff --git a/text-ui-test/data/save.txt b/text-ui-test/data/save.txt deleted file mode 100644 index e69de29bb2..0000000000 From 8cee24fa06daeb895376a3d273024334f87c60f8 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Tue, 14 Mar 2023 22:53:12 +0800 Subject: [PATCH 058/368] Added a case for View_Account to display account details as per user input --- src/main/java/seedu/bankwithus/Parser.java | 6 +++++- src/main/java/seedu/bankwithus/Ui.java | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 7eb75f3062..0185af0593 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -22,7 +22,7 @@ public void parseUserInput(String input) throws CommandNotFoundException { String[] split = input.trim().split("\\s+", 2); String command = split[0]; String args = split.length == 2 ? split[1] : ""; - + Ui screen = new Ui(); if (command.equals("exit")) { bwu.isExitEntered = true; } else { @@ -30,6 +30,10 @@ public void parseUserInput(String input) throws CommandNotFoundException { case "exit": bwu.isExitEntered = true; break; + case "View_Account": + String accDetails = bwu.accounts.getAllAccountDetails(); + screen.viewAccount(accDetails); + break; default: throw new CommandNotFoundException(); } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 60f3e714e8..9652ceb21d 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -55,4 +55,13 @@ public String getNextLine() { public void closeScanner() { this.scanner.close(); } + + public void viewAccount(String accDetails) { + String name = accDetails.split(";")[0]; + String bal = accDetails.split(";")[1]; + System.out.println("----------------------------"); + System.out.println("Name: " + name); + System.out.println("Balance: $"+bal); + System.out.println("----------------------------"); + } } From fd5fd47d7b3313b63815a0e6590203b4136ed40f Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 17:08:10 +0800 Subject: [PATCH 059/368] Formatted files more appropriately --- data/save.txt | 1 + .../java/seedu/bankwithus/BankWithUs.java | 1 + src/main/java/seedu/bankwithus/Parser.java | 24 ++++++++----------- 3 files changed, 12 insertions(+), 14 deletions(-) create mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt new file mode 100644 index 0000000000..8fe0018f1e --- /dev/null +++ b/data/save.txt @@ -0,0 +1 @@ +jane;1000.0 diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index d4f88ae7c8..5c0866d29f 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -98,6 +98,7 @@ public static void main(String[] args) { try { new BankWithUs(FILE_PATH).run(); } catch (IOException e) { + return; } } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 0185af0593..c07be22b6b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -23,20 +23,16 @@ public void parseUserInput(String input) throws CommandNotFoundException { String command = split[0]; String args = split.length == 2 ? split[1] : ""; Ui screen = new Ui(); - if (command.equals("exit")) { - bwu.isExitEntered = true; - } else { - switch (command) { - case "exit": - bwu.isExitEntered = true; - break; - case "View_Account": - String accDetails = bwu.accounts.getAllAccountDetails(); - screen.viewAccount(accDetails); - break; - default: - throw new CommandNotFoundException(); - } + switch (command) { + case "exit": + bwu.isExitEntered = true; + break; + case "View_Account": + String accDetails = bwu.accounts.getAllAccountDetails(); + screen.viewAccount(accDetails); + break; + default: + throw new CommandNotFoundException(); } } From cca54cb8ac27f6b579b014e83ba337b506e15e28 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 17:09:08 +0800 Subject: [PATCH 060/368] Changed the View_Account case to view-account --- src/main/java/seedu/bankwithus/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index c07be22b6b..36a8ef6648 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -27,7 +27,7 @@ public void parseUserInput(String input) throws CommandNotFoundException { case "exit": bwu.isExitEntered = true; break; - case "View_Account": + case "view-account": String accDetails = bwu.accounts.getAllAccountDetails(); screen.viewAccount(accDetails); break; From e60017de6b93260da0e736106d46306adabc0aa3 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 17:18:51 +0800 Subject: [PATCH 061/368] Removed the data/save.txt --- data/save.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt deleted file mode 100644 index 8fe0018f1e..0000000000 --- a/data/save.txt +++ /dev/null @@ -1 +0,0 @@ -jane;1000.0 From 92393f717b5ad9b188c78ed53c918162f1303680 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 17:56:59 +0800 Subject: [PATCH 062/368] Reformatted the switch case indentation as checkstyle condition is diff from intellij auto format --- data/save.txt | 1 + src/main/java/seedu/bankwithus/Parser.java | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt new file mode 100644 index 0000000000..06dccd5706 --- /dev/null +++ b/data/save.txt @@ -0,0 +1 @@ +jane;900.0 diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 36a8ef6648..d3111f856e 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -24,15 +24,15 @@ public void parseUserInput(String input) throws CommandNotFoundException { String args = split.length == 2 ? split[1] : ""; Ui screen = new Ui(); switch (command) { - case "exit": - bwu.isExitEntered = true; - break; - case "view-account": - String accDetails = bwu.accounts.getAllAccountDetails(); - screen.viewAccount(accDetails); - break; - default: - throw new CommandNotFoundException(); + case "exit": + bwu.isExitEntered = true; + break; + case "view-account": + String accDetails = bwu.accounts.getAllAccountDetails(); + screen.viewAccount(accDetails); + break; + default: + throw new CommandNotFoundException(); } } From cb30129580bd3aa31fd3ae7aaddf2e7947593446 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 17:58:49 +0800 Subject: [PATCH 063/368] Deleted data/save.txt --- data/save.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt deleted file mode 100644 index 06dccd5706..0000000000 --- a/data/save.txt +++ /dev/null @@ -1 +0,0 @@ -jane;900.0 From 36e01531805ea60763094fdc8d7e2e00a117b6fc Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 18:02:46 +0800 Subject: [PATCH 064/368] Removed an unused import in storageTest --- src/test/java/seedu/bankwithus/StorageTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index cb31cc5934..4f05aa2f37 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -2,8 +2,6 @@ import org.junit.jupiter.api.Test; -import java.util.Scanner; - import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; public class StorageTest { From 53396891e7f78375dd418191f372d5257cd47afd Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 18:11:19 +0800 Subject: [PATCH 065/368] extracted the printing of lines into a method called printLine in UI class --- src/main/java/seedu/bankwithus/Ui.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 9652ceb21d..98881d8f2a 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -56,12 +56,13 @@ public void closeScanner() { this.scanner.close(); } + public void printLine() {System.out.println("----------------------------");} public void viewAccount(String accDetails) { String name = accDetails.split(";")[0]; String bal = accDetails.split(";")[1]; - System.out.println("----------------------------"); + printLine(); System.out.println("Name: " + name); System.out.println("Balance: $"+bal); - System.out.println("----------------------------"); + printLine(); } } From 2ba8c0543988132a554affabfdab2743a3bb5cc3 Mon Sep 17 00:00:00 2001 From: manushridiv Date: Wed, 15 Mar 2023 18:17:25 +0800 Subject: [PATCH 066/368] Added withdraw case --- data/save.txt | 1 + src/main/java/seedu/bankwithus/Account.java | 3 +++ src/main/java/seedu/bankwithus/Parser.java | 30 +++++++++++++-------- src/main/java/seedu/bankwithus/Ui.java | 11 ++++++++ 4 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt new file mode 100644 index 0000000000..d66d674e04 --- /dev/null +++ b/data/save.txt @@ -0,0 +1 @@ +jen;900.0 diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 9fd5c4a77b..1d26aafbdf 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -25,4 +25,7 @@ public float getAccountBalance() { return balance; } + public void setBalance(float balance) { + this.balance = balance; + } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 7eb75f3062..776916eaa4 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -22,18 +22,26 @@ public void parseUserInput(String input) throws CommandNotFoundException { String[] split = input.trim().split("\\s+", 2); String command = split[0]; String args = split.length == 2 ? split[1] : ""; - - if (command.equals("exit")) { - bwu.isExitEntered = true; - } else { - switch (command) { - case "exit": - bwu.isExitEntered = true; - break; - default: - throw new CommandNotFoundException(); - } + Ui screen = new Ui(); + switch (command) { + case "exit": + bwu.isExitEntered = true; + break; + case "view-account": + String accDetails = bwu.accounts.getAllAccountDetails(); + screen.viewAccount(accDetails); + break; + case "withdraw": + float withdrawAmt = Float.parseFloat(args); + float currBal = bwu.accounts.accounts.get(0).balance; + float final_bal = currBal-withdrawAmt; + bwu.accounts.accounts.get(0).setBalance(final_bal); + System.out.println("u have $" + String.valueOf(final_bal) + " remaining!"); + break; + default: + throw new CommandNotFoundException(); } + } /** diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 60f3e714e8..c95cc8b42f 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -55,4 +55,15 @@ public String getNextLine() { public void closeScanner() { this.scanner.close(); } + + public void viewAccount(String accDetails) { + String name = accDetails.split(";")[0]; + String bal = accDetails.split(";")[1]; + System.out.println("----------------------------"); + System.out.println("Name: " + name); + System.out.println("Balance: $"+bal); + System.out.println("----------------------------"); + } } + + From 057b015d5888f0abacf1968af7bc2ee815112f1d Mon Sep 17 00:00:00 2001 From: tyuyang Date: Wed, 15 Mar 2023 19:41:42 +0800 Subject: [PATCH 067/368] Fixed checkstyle error from merge #40 --- src/main/java/seedu/bankwithus/Parser.java | 49 ++++++++++++------- src/main/java/seedu/bankwithus/Ui.java | 10 +++- .../exceptions/NegativeAmountException.java | 8 +++ 3 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/NegativeAmountException.java diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index c65e6fdd52..4e0405426b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -1,6 +1,7 @@ package seedu.bankwithus; import seedu.bankwithus.exceptions.CommandNotFoundException; +import seedu.bankwithus.exceptions.NegativeAmountException; import java.io.File; import java.io.IOException; @@ -13,11 +14,14 @@ public Parser(BankWithUs bwu) { this.bwu = bwu; } - public float parseWithdrawAmt(String args) { + public float parseWithdrawAmt(String args) throws NegativeAmountException { float withdrawAmt = Float.parseFloat(args); + if (withdrawAmt < 0) { + throw new NegativeAmountException(); + } float currBal = bwu.accounts.accounts.get(0).balance; - float final_bal = currBal-withdrawAmt; - return final_bal; + float finalBal = currBal-withdrawAmt; + return finalBal; } /** @@ -31,24 +35,30 @@ public void parseUserInput(String input) throws CommandNotFoundException { String args = split.length == 2 ? split[1] : ""; Ui screen = new Ui(); switch (command) { - case "exit": - bwu.isExitEntered = true; - break; - case "view-account": - String accDetails = bwu.accounts.getAllAccountDetails(); - screen.viewAccount(accDetails); - break; - case "withdraw": - float final_bal = parseWithdrawAmt(args); - if(final_bal > -1) { - bwu.accounts.accounts.get(0).setBalance(final_bal); - screen.showBal(final_bal); + case "exit": + bwu.isExitEntered = true; + break; + case "view-account": + String accDetails = bwu.accounts.getAllAccountDetails(); + screen.viewAccount(accDetails); + break; + case "withdraw": + try { + float finalBal = parseWithdrawAmt(args); + if(finalBal >= 0) { + bwu.accounts.accounts.get(0).setBalance(finalBal); + screen.showBal(finalBal); } else { - System.out.println("You do not have sufficient Balance"); + screen.showInsufficientBalanceMessage(); } - break; - default: - throw new CommandNotFoundException(); + } catch (NumberFormatException e) { + screen.showNumberFormatError(); + } catch (NegativeAmountException e) { + screen.showNegativeAmountError(); + } + break; + default: + throw new CommandNotFoundException(); } } @@ -71,5 +81,6 @@ public void parseSavedFile(AccountList list) throws IOException { String balance = splitDetails[1]; list.addAccount(name, balance); } + myReader.close(); } } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 3b7782bcb6..4aefc40ab6 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -72,4 +72,12 @@ public void viewAccount(String accDetails) { public void showBal(float finalBal) { System.out.println("You have $" + String.valueOf(finalBal) + " remaining!"); } -} \ No newline at end of file + + public void showNegativeAmountError() { + System.out.println("Negative number entered!"); + } + + public void showInsufficientBalanceMessage() { + System.out.println("You do not have sufficient Balance"); + } +} 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 { + +} From 97f156ab575fb1325271f126589097097bf50c1a Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Wed, 15 Mar 2023 20:37:01 +0800 Subject: [PATCH 068/368] Handle number format exceptions --- data/save.txt | 2 +- src/main/java/seedu/bankwithus/AccountList.java | 15 +++------------ src/main/java/seedu/bankwithus/BankWithUs.java | 8 +++++++- src/main/java/seedu/bankwithus/Parser.java | 12 ++++++++++-- src/main/java/seedu/bankwithus/Ui.java | 4 ++++ 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/data/save.txt b/data/save.txt index e03d8678c6..b388e3ca90 100644 --- a/data/save.txt +++ b/data/save.txt @@ -1 +1 @@ -jen;0.0 +jen;10.0 diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index ea9fd964c0..6b3df9d320 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -5,7 +5,6 @@ public class AccountList { protected ArrayList accounts; - private Ui ui; public AccountList() { accounts = new ArrayList(); @@ -22,14 +21,10 @@ public AccountList(Scanner scanner) { * @param balanceString Balance of the new account to be added in String type * @throws NumberFormatException If balanceString cannot be parsed into a float number */ - public void addAccount(String name, String balanceString) throws NumberFormatException { - try { + public void addAccount(String name, String balanceString) throws NumberFormatException, NullPointerException { float balance = Float.parseFloat(balanceString); Account newAccount = new Account(name, balance); accounts.add(newAccount); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } } /** @@ -51,11 +46,7 @@ public Account getCurrentAccount() { } public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException { - try { - float depositAmount = Float.parseFloat(depositAmountString); - getCurrentAccount().balance += depositAmount; - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } + float depositAmount = Float.parseFloat(depositAmountString); + getCurrentAccount().balance += depositAmount; } } diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 01bb89f6b0..846ed476a3 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -63,7 +63,13 @@ public void createAccount() { String userName = ui.getNextLine(); System.out.println("How much would you like to add as Balance?"); String balance = ui.getNextLine(); - accountList.addAccount(userName, balance); + try { + accountList.addAccount(userName, balance); + } catch (NullPointerException e) { + ui.showNullInputError(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } } /** diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index fd6abed210..a3d556221b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -38,8 +38,16 @@ public void parseUserInput(String input) throws CommandNotFoundException { bwu.isExitEntered = true; break; case "deposit": - bwu.getAccountList().depositMoney(args); - screen.showDepositMessage(); + try { + bwu.getAccountList().depositMoney(args); + screen.showDepositMessage(); + screen.showBal(bwu.getAccountList().accounts.get(0).getAccountBalance()); + } catch (NumberFormatException e) { + screen.showNumberFormatError(); + } catch (NullPointerException e) { + screen.showNumberFormatError(); + } + break; case "view-account": String accDetails = bwu.getAccountList().getAllAccountDetails(); screen.viewAccount(accDetails); diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index a950f5a31f..d81ddf8905 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -22,6 +22,10 @@ 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!"); } From 066e69559f49e5ae68c48152fdba26976bdfffd5 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Wed, 15 Mar 2023 20:43:33 +0800 Subject: [PATCH 069/368] Fix coding standard violations --- src/main/java/seedu/bankwithus/AccountList.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 6b3df9d320..669f3e2b24 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -22,9 +22,9 @@ public AccountList(Scanner scanner) { * @throws NumberFormatException If balanceString cannot be parsed into a float number */ public void addAccount(String name, String balanceString) throws NumberFormatException, NullPointerException { - float balance = Float.parseFloat(balanceString); - Account newAccount = new Account(name, balance); - accounts.add(newAccount); + float balance = Float.parseFloat(balanceString); + Account newAccount = new Account(name, balance); + accounts.add(newAccount); } /** From da10873424af342a4d9dcfef44551527676b307d Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Wed, 15 Mar 2023 20:47:56 +0800 Subject: [PATCH 070/368] Rewrite accountList tests --- src/test/java/seedu/bankwithus/AccountListTest.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 78da15c00a..7f7efffbd1 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,29 +1,28 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { @Test - void addAccount_invalidBalance_expectException() throws NullPointerException { + void addAccount_invalidBalance_expectException() throws NumberFormatException { String name = "Bob"; String balanceString = "abc"; AccountList accountList = new AccountList(); - assertThrows(NullPointerException.class, + assertThrows(NumberFormatException.class, () -> accountList.addAccount(name, balanceString)); } @Test - void depositMoney_invalidAmount_expectException() throws NullPointerException { + void depositMoney_invalidAmount_expectException() throws NumberFormatException { String amountString = "abc"; String name = "Bob"; String balance = "0"; AccountList accountList = new AccountList(); accountList.addAccount(name, balance); - assertThrows(NullPointerException.class, + assertThrows(NumberFormatException.class, () -> accountList.depositMoney(amountString)); } From 7596d50c7c4c9b9bff7adf0f9cad9d2143946152 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Wed, 15 Mar 2023 21:18:23 +0800 Subject: [PATCH 071/368] Fix add account bugs --- data/save.txt | 1 - src/main/java/seedu/bankwithus/AccountList.java | 11 +++++++++-- src/main/java/seedu/bankwithus/BankWithUs.java | 6 +++--- src/main/java/seedu/bankwithus/Parser.java | 10 ++++++---- src/main/java/seedu/bankwithus/Ui.java | 3 +++ src/test/java/seedu/bankwithus/AccountListTest.java | 13 ++++++++++++- 6 files changed, 33 insertions(+), 11 deletions(-) delete mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt deleted file mode 100644 index b388e3ca90..0000000000 --- a/data/save.txt +++ /dev/null @@ -1 +0,0 @@ -jen;10.0 diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 669f3e2b24..ffa93c6f67 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,5 +1,7 @@ package seedu.bankwithus; +import seedu.bankwithus.exceptions.NegativeAmountException; + import java.util.ArrayList; import java.util.Scanner; @@ -45,8 +47,13 @@ public Account getCurrentAccount() { return accounts.get(0); } - public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException { + public void depositMoney(String depositAmountString) throws NumberFormatException, + NullPointerException, NegativeAmountException { float depositAmount = Float.parseFloat(depositAmountString); - getCurrentAccount().balance += depositAmount; + if (depositAmount < 0) { + throw new NegativeAmountException(); + } else { + getCurrentAccount().balance += depositAmount; + } } } diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 846ed476a3..8454cfa363 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -65,10 +65,13 @@ public void createAccount() { String balance = ui.getNextLine(); try { accountList.addAccount(userName, balance); + ui.showAddAccountMessage(); } catch (NullPointerException e) { ui.showNullInputError(); + createAccount(); } catch (NumberFormatException e) { ui.showNumberFormatError(); + createAccount(); } } @@ -105,9 +108,6 @@ public AccountList getAccountList() { return accountList; } - public void setAccountList(AccountList accountList) { - this.accountList = accountList; - } public static void main(String[] args) { try { diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index a3d556221b..b74a42456f 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -19,7 +19,7 @@ public float parseWithdrawAmt(String args) throws NegativeAmountException { if (withdrawAmt < 0) { throw new NegativeAmountException(); } - float currBal = bwu.getAccountList().accounts.get(0).balance; + float currBal = bwu.getAccountList().getCurrentAccount().balance; float finalBal = currBal-withdrawAmt; return finalBal; } @@ -41,11 +41,13 @@ public void parseUserInput(String input) throws CommandNotFoundException { try { bwu.getAccountList().depositMoney(args); screen.showDepositMessage(); - screen.showBal(bwu.getAccountList().accounts.get(0).getAccountBalance()); + screen.showBal(bwu.getAccountList().getCurrentAccount().getAccountBalance()); } catch (NumberFormatException e) { screen.showNumberFormatError(); } catch (NullPointerException e) { - screen.showNumberFormatError(); + screen.showNullInputError(); + } catch (NegativeAmountException e) { + screen.showNegativeAmountError(); } break; case "view-account": @@ -56,7 +58,7 @@ public void parseUserInput(String input) throws CommandNotFoundException { try { float finalBal = parseWithdrawAmt(args); if(finalBal >= 0) { - bwu.getAccountList().accounts.get(0).setBalance(finalBal); + bwu.getAccountList().getCurrentAccount().setBalance(finalBal); screen.showBal(finalBal); } else { screen.showInsufficientBalanceMessage(); diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index d81ddf8905..2c2f4ed573 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -34,6 +34,9 @@ public void showFarewellMessage() { System.out.println("Goodbye! Hope to see you again! :)"); } + public void showAddAccountMessage() { + System.out.println("Account created!"); + } public void showDepositMessage() { System.out.println("New deposit added!"); } diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 7f7efffbd1..c50874f758 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,6 +1,8 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; +import seedu.bankwithus.exceptions.NegativeAmountException; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -33,7 +35,16 @@ void depositMoney_validAmount_expectDeposit() { String balance = "100.5"; AccountList accountList = new AccountList(); accountList.addAccount(name, balance); - accountList.depositMoney(amountString); + Ui screen = new Ui(); + try { + accountList.depositMoney(amountString); + } catch (NumberFormatException e) { + screen.showNumberFormatError(); + } catch (NullPointerException e) { + screen.showNullInputError(); + } catch (NegativeAmountException e) { + screen.showNegativeAmountError(); + } assertEquals(201, accountList.getCurrentAccount().getAccountBalance()); } } From b61a806b8e3fea43edce08d52cb0850caa8d8a6a Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Wed, 15 Mar 2023 21:22:35 +0800 Subject: [PATCH 072/368] Modify test-ui-test --- text-ui-test/EXPECTED.TXT | 1 + 1 file changed, 1 insertion(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 8cbf759a1d..6cfc0ad64f 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -2,4 +2,5 @@ File not found, trying to create file. Savefile created successfully! Whats your name? How much would you like to add as Balance? +Account created! Goodbye! Hope to see you again! :) From 462490d2c96ad384dcb9e8463e2c225b0a48cc4c Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 21:28:07 +0800 Subject: [PATCH 073/368] Added a JUNIT test for AccountList addAccount method --- src/test/java/seedu/bankwithus/AccountListTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 03fbda095c..c2837e98a5 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,6 +1,8 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { @@ -13,4 +15,13 @@ void addAccount_invalidBalance_expectException() throws NullPointerException { assertThrows(NullPointerException.class, () -> accountList.addAccount(name, balanceString)); } + + @Test + void testing_Add_New_account_Jane_with_1000_balance() { + AccountList TestAccountList = new AccountList(); + TestAccountList.addAccount("Jane", "1000"); + assertEquals("Jane", TestAccountList.accounts.get(0).name); + assertEquals(1000.0, TestAccountList.accounts.get(0).balance); + } + } From d16677a78a5c5fd39edaa81f27d5c988a619f8f9 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 21:56:13 +0800 Subject: [PATCH 074/368] Made small changes in naming to meet checkstyle --- src/test/java/seedu/bankwithus/AccountListTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 80f942969b..57836faf87 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -49,11 +49,10 @@ void depositMoney_validAmount_expectDeposit() { } @Test - void testing_Add_New_account_Jane_with_1000_balance() { + void testingAddAccount() { AccountList TestAccountList = new AccountList(); TestAccountList.addAccount("Jane", "1000"); assertEquals("Jane", TestAccountList.accounts.get(0).name); assertEquals(1000.0, TestAccountList.accounts.get(0).balance); } - -} \ No newline at end of file +} From a0e287f268645b3c113c29c8d0124fdd00c1ce8b Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Wed, 15 Mar 2023 22:09:53 +0800 Subject: [PATCH 075/368] Added a welcome message --- META-INF/MANIFEST.MF | 3 +++ src/main/java/seedu/bankwithus/BankWithUs.java | 1 + src/main/java/seedu/bankwithus/Ui.java | 14 ++++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 META-INF/MANIFEST.MF 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/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 8454cfa363..f8b3a13ead 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -82,6 +82,7 @@ public void createAccount() { * @throws IOException if something goes wrong while exiting the program */ public void run() throws IOException { + ui.greet(); ui.createScanner(); if (storage.saveFile.length() < 1) { createAccount(); diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 82ab771c13..6772dd2aa2 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -98,4 +98,18 @@ public void showHelp() { 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" + ); + } } From 483cd4fdb4fc7b5d3f9b94b4dd79d36bc02501d2 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 09:20:06 +0800 Subject: [PATCH 076/368] Made runtest more robust --- text-ui-test/EXPECTED.TXT | 55 +++++++++++++++++++++++++++++++++++++++ text-ui-test/input.txt | 22 +++++++++++++--- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 6cfc0ad64f..bf59ecca3a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,6 +1,61 @@ File not found, trying to create file. Savefile created successfully! +Welcome to: + + /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ +| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ +| $$ \ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$| $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$ +| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$ $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/ +| $$__ $$ /$$$$$$$| $$ \ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \ $$| $$ | $$| $$$$$$ +| $$ \ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \ $$$| $$ | $$ /$$| $$ | $$| $$ | $$ \____ $$ +| $$$$$$$/| $$$$$$$| $$ | $$| $$ \ $$| $$/ \ $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/ +|_______/ \_______/|__/ |__/|__/ \__/|__/ \__/|__/ \___/ |__/ |__/ \______/ |_______/ + Whats your name? How much would you like to add as Balance? Account created! +---------------------------- +help: displays the current menu +view-account: shows account name and balance +withdraw : withdraws from available balance +deposit : deposits and adds deposit to balance +exit: quits program and saves +---------------------------- +Not a valid command! +---------------------------- +Name: hihi +Balance: $1000.0 + +---------------------------- +You do not have sufficient Balance +Negative number entered! +The input is not a valid number! Please try again. +---------------------------- +Name: hihi +Balance: $1000.0 + +---------------------------- +You have $800.0 remaining! +---------------------------- +Name: hihi +Balance: $800.0 + +---------------------------- +You do not have sufficient Balance +Negative number entered! +The input is not a valid number! Please try again. +New deposit added! +You have $1800.0 remaining! +---------------------------- +Name: hihi +Balance: $1800.0 + +---------------------------- +New deposit added! +You have $1900.0 remaining! +---------------------------- +Name: hihi +Balance: $1900.0 + +---------------------------- Goodbye! Hope to see you again! :) diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 60e77a6b1e..33a1dcb818 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,3 +1,19 @@ -june -1000 -exit \ No newline at end of file +hihi +1000.0 +help +hihi +view-account +withdraw 1500 +withdraw -10 +withdraw a100 +view-account +withdraw 200 +view-account +withdraw 800.1 +deposit -100 +deposit bb100 +deposit 1000 +view-account +deposit 100 +view-account +exit From 41871ea791298f928cadf114c4af5c63c667cc5c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 12:40:24 +0800 Subject: [PATCH 077/368] Move create account into AccountList class, modify AccountList constructor to create account if savefile does not exist automatically --- data/save.txt | 0 .../java/seedu/bankwithus/AccountList.java | 28 +++++++++++ .../java/seedu/bankwithus/BankWithUs.java | 48 +++++-------------- .../exceptions/AccountNotFoundException.java | 5 ++ 4 files changed, 46 insertions(+), 35 deletions(-) create mode 100644 data/save.txt create mode 100644 src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java diff --git a/data/save.txt b/data/save.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index ffa93c6f67..6a65a6a277 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -7,13 +7,41 @@ public class AccountList { protected ArrayList accounts; + private Ui ui; public AccountList() { accounts = new ArrayList(); + ui = new Ui(); + createAccount(); } public AccountList(Scanner scanner) { accounts = new ArrayList(); + ui = new Ui(); + } + + /** + * Creates a new Account for a first time user + */ + public void createAccount() { + ui.createScanner(); + System.out.println("Whats your name?"); + String userName = ui.getNextLine(); + System.out.println("How much would you like to add as Balance?"); + String balance = ui.getNextLine(); + try { + addAccount(userName, balance); + ui.showAddAccountMessage(); + ui.closeScanner(); + } catch (NullPointerException e) { + ui.showNullInputError(); + createAccount(); + ui.closeScanner(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + createAccount(); + ui.closeScanner(); + } } /** diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index f8b3a13ead..ed97a9cf59 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -39,6 +39,10 @@ public BankWithUs(String filePath) throws IOException { } } + public AccountList getAccountList() { + return accountList; + } + /** * exit the programme, save the data and show farewell message * @@ -55,26 +59,6 @@ public void exit(String filePath) throws IOException { ui.closeScanner(); } - /** - * Creates a new Account for a first time user - */ - public void createAccount() { - System.out.println("Whats your name?"); - String userName = ui.getNextLine(); - System.out.println("How much would you like to add as Balance?"); - String balance = ui.getNextLine(); - try { - accountList.addAccount(userName, balance); - ui.showAddAccountMessage(); - } catch (NullPointerException e) { - ui.showNullInputError(); - createAccount(); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - createAccount(); - } - } - /** * The main command and output loop. Takes in user input line by line * and gives it to the parser to execute the command. @@ -84,15 +68,15 @@ public void createAccount() { public void run() throws IOException { ui.greet(); ui.createScanner(); - if (storage.saveFile.length() < 1) { - createAccount(); - } else { - try { - parser.parseSavedFile(accountList); - } catch (IOException e) { - ui.showIOError(); - } - } + // if (storage.saveFile.length() < 1) { + // createAccount(); + // } else { + // try { + // parser.parseSavedFile(accountList); + // } catch (IOException e) { + // ui.showIOError(); + // } + // } while (!isExitEntered) { String line = ui.getNextLine(); try { @@ -104,12 +88,6 @@ public void run() throws IOException { exit(FILE_PATH); } - - public AccountList getAccountList() { - return accountList; - } - - public static void main(String[] args) { try { new BankWithUs(FILE_PATH).run(); 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..89886b9fd1 --- /dev/null +++ b/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java @@ -0,0 +1,5 @@ +package seedu.bankwithus.exceptions; + +public class AccountNotFoundException extends Exception { + +} From 1c4081de7487678ace516739b7b7a0225d3b34c8 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 12:59:20 +0800 Subject: [PATCH 078/368] Fixed bug where blank user name can be entered during account creation --- src/main/java/seedu/bankwithus/AccountList.java | 15 +++++++++++++-- src/main/java/seedu/bankwithus/Ui.java | 8 ++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 6a65a6a277..079032a2bb 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,6 +1,7 @@ package seedu.bankwithus; import seedu.bankwithus.exceptions.NegativeAmountException; +import seedu.bankwithus.exceptions.UserNameBlankException; import java.util.ArrayList; import java.util.Scanner; @@ -20,13 +21,23 @@ public AccountList(Scanner scanner) { ui = new Ui(); } + private String getName() { + ui.askForName(); + String userName = ui.getNextLine(); + userName.trim(); + if (userName.isBlank()) { + ui.showBlankUserNameError(); + return getName(); + } + return userName; + } + /** * Creates a new Account for a first time user */ public void createAccount() { ui.createScanner(); - System.out.println("Whats your name?"); - String userName = ui.getNextLine(); + String userName = getName(); System.out.println("How much would you like to add as Balance?"); String balance = ui.getNextLine(); try { diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 6772dd2aa2..3d0ff7ecaf 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -112,4 +112,12 @@ public void greet() { "|_______/ \\_______/|__/ |__/|__/ \\__/|__/ \\__/|__/ \\___/ |__/ |__/ \\______/ |_______/ \n" ); } + + public void askForName() { + System.out.println("What's your name?"); + } + + public void showBlankUserNameError() { + System.out.println("User Name cannot be blank."); + } } From 5ec0fcbc9ece298a763be236bef68df2cfce7a27 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 12:59:54 +0800 Subject: [PATCH 079/368] Delete redundant import --- src/main/java/seedu/bankwithus/AccountList.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 079032a2bb..5fdad4a363 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,7 +1,6 @@ package seedu.bankwithus; import seedu.bankwithus.exceptions.NegativeAmountException; -import seedu.bankwithus.exceptions.UserNameBlankException; import java.util.ArrayList; import java.util.Scanner; From d964cb2b95ec2c1526ff906f39e9932f8045d498 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 14:50:54 +0800 Subject: [PATCH 080/368] Delete redundant attribute --- src/main/java/seedu/bankwithus/Account.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 4953de2415..0522c158b3 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -4,7 +4,6 @@ public class Account { protected String name; protected float balance; - private Ui ui; /** * @param name initialise in the name of the account * @param balance initialise the balance of the account From c4b6e7f85dde58aa1fa84576d7118184e0458575 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 14:52:55 +0800 Subject: [PATCH 081/368] Restructure create new account feature --- .../java/seedu/bankwithus/AccountList.java | 48 +++++----- src/main/java/seedu/bankwithus/Ui.java | 5 ++ .../seedu/bankwithus/AccountListTest.java | 89 ++++++++++--------- 3 files changed, 73 insertions(+), 69 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 5fdad4a363..5228cdf363 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -12,7 +12,7 @@ public class AccountList { public AccountList() { accounts = new ArrayList(); ui = new Ui(); - createAccount(); + createNewAccount(); } public AccountList(Scanner scanner) { @@ -20,37 +20,26 @@ public AccountList(Scanner scanner) { ui = new Ui(); } - private String getName() { + private String askUserForName() { ui.askForName(); String userName = ui.getNextLine(); userName.trim(); if (userName.isBlank()) { ui.showBlankUserNameError(); - return getName(); + return askUserForName(); } return userName; } - /** - * Creates a new Account for a first time user - */ - public void createAccount() { - ui.createScanner(); - String userName = getName(); - System.out.println("How much would you like to add as Balance?"); - String balance = ui.getNextLine(); + private float askUserForBalance() throws NumberFormatException { + ui.askForBalance(); + String balanceString = ui.getNextLine(); + balanceString.trim(); try { - addAccount(userName, balance); - ui.showAddAccountMessage(); - ui.closeScanner(); - } catch (NullPointerException e) { - ui.showNullInputError(); - createAccount(); - ui.closeScanner(); + float balance = Float.parseFloat(balanceString); + return balance; } catch (NumberFormatException e) { - ui.showNumberFormatError(); - createAccount(); - ui.closeScanner(); + return askUserForBalance(); } } @@ -58,15 +47,24 @@ public void createAccount() { * Creates a new account and adds it to the AccountList. * * @param name Name of the new account to be added - * @param balanceString Balance of the new account to be added in String type - * @throws NumberFormatException If balanceString cannot be parsed into a float number + * @param balance Balance of the new account to be added */ - public void addAccount(String name, String balanceString) throws NumberFormatException, NullPointerException { - float balance = Float.parseFloat(balanceString); + public void addAccount(String name, float balance) { Account newAccount = new Account(name, balance); accounts.add(newAccount); } + /** + * Creates a new Account for a first time user + */ + public void createNewAccount() { + ui.createScanner(); + String userName = askUserForName(); + float balance = askUserForBalance(); + addAccount(userName, balance); + ui.closeScanner(); + } + /** * name and balance are separated by $ prepared to be saved * diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 3d0ff7ecaf..628608f7bf 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -120,4 +120,9 @@ public void askForName() { 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?"); + + } } diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 57836faf87..db8ed8b1e4 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -8,51 +8,52 @@ class AccountListTest { - @Test - void addAccount_invalidBalance_expectException() throws NumberFormatException { - String name = "Bob"; - String balanceString = "abc"; - AccountList accountList = new AccountList(); - assertThrows(NumberFormatException.class, - () -> accountList.addAccount(name, balanceString)); - } + // Invalid because addAccount parameter have been changed + // @Test + // void addAccount_invalidBalance_expectException() throws NumberFormatException { + // String name = "Bob"; + // String balanceString = "abc"; + // AccountList accountList = new AccountList(); + // assertThrows(NumberFormatException.class, + // () -> accountList.addAccount(name, balanceString)); + // } - @Test - void depositMoney_invalidAmount_expectException() throws NumberFormatException { - 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_invalidAmount_expectException() throws NumberFormatException { + // 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_validAmount_expectDeposit() { - String amountString = "100.5"; - String name = "Bob"; - String balance = "100.5"; - AccountList accountList = new AccountList(); - accountList.addAccount(name, balance); - Ui screen = new Ui(); - try { - accountList.depositMoney(amountString); - } catch (NumberFormatException e) { - screen.showNumberFormatError(); - } catch (NullPointerException e) { - screen.showNullInputError(); - } catch (NegativeAmountException e) { - screen.showNegativeAmountError(); - } - assertEquals(201, accountList.getCurrentAccount().getAccountBalance()); - } + // @Test + // void depositMoney_validAmount_expectDeposit() { + // String amountString = "100.5"; + // String name = "Bob"; + // String balance = "100.5"; + // AccountList accountList = new AccountList(); + // accountList.addAccount(name, balance); + // Ui screen = new Ui(); + // try { + // accountList.depositMoney(amountString); + // } catch (NumberFormatException e) { + // screen.showNumberFormatError(); + // } catch (NullPointerException e) { + // screen.showNullInputError(); + // } catch (NegativeAmountException e) { + // screen.showNegativeAmountError(); + // } + // assertEquals(201, accountList.getCurrentAccount().getAccountBalance()); + // } - @Test - void testingAddAccount() { - AccountList TestAccountList = new AccountList(); - TestAccountList.addAccount("Jane", "1000"); - assertEquals("Jane", TestAccountList.accounts.get(0).name); - assertEquals(1000.0, TestAccountList.accounts.get(0).balance); - } + // @Test + // void testingAddAccount() { + // AccountList TestAccountList = new AccountList(); + // TestAccountList.addAccount("Jane", "1000"); + // assertEquals("Jane", TestAccountList.accounts.get(0).name); + // assertEquals(1000.0, TestAccountList.accounts.get(0).balance); + // } } From 4d719c27df8f94dabeeac09c808c6b67a14dc14a Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 17:30:59 +0800 Subject: [PATCH 082/368] Restructured startup feature --- .../java/seedu/bankwithus/AccountList.java | 35 ++++++++---- .../java/seedu/bankwithus/BankWithUs.java | 10 +++- src/main/java/seedu/bankwithus/Parser.java | 55 +++++++++++++------ src/main/java/seedu/bankwithus/Ui.java | 6 +- .../CorruptedSaveFileException.java | 5 ++ .../java/seedu/bankwithus/StorageTest.java | 12 ++-- 6 files changed, 86 insertions(+), 37 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/CorruptedSaveFileException.java diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 5228cdf363..538ebe5f13 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -6,18 +6,28 @@ import java.util.Scanner; public class AccountList { - protected ArrayList accounts; + private ArrayList accounts; + private BankWithUs bwu; private Ui ui; - - public AccountList() { + + public AccountList(BankWithUs bwu) { accounts = new ArrayList(); - ui = new Ui(); + this.bwu = bwu; + this.ui = bwu.getUi(); createNewAccount(); } - public AccountList(Scanner scanner) { + public AccountList(Scanner scanner, BankWithUs bwu) { accounts = new ArrayList(); - ui = new Ui(); + this.bwu = bwu; + this.ui = bwu.getUi(); + Parser parser = new Parser(this); + try { + parser.parseSavedFile(scanner); + } catch (Exception e) { + ui.showCorruptedSaveFileError(); + createNewAccount(); + } } private String askUserForName() { @@ -37,8 +47,13 @@ private float askUserForBalance() throws NumberFormatException { balanceString.trim(); try { float balance = Float.parseFloat(balanceString); + if (balance < 0) { + ui.showNegativeAmountError(); + return askUserForBalance(); + } return balance; } catch (NumberFormatException e) { + ui.showNumberFormatError(); return askUserForBalance(); } } @@ -46,8 +61,8 @@ private float askUserForBalance() throws NumberFormatException { /** * 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 name Name of the new account to be added + * @param balance Balance of the new account to be added */ public void addAccount(String name, float balance) { Account newAccount = new Account(name, balance); @@ -58,15 +73,13 @@ public void addAccount(String name, float balance) { * Creates a new Account for a first time user */ public void createNewAccount() { - ui.createScanner(); String userName = askUserForName(); float balance = askUserForBalance(); addAccount(userName, balance); - ui.closeScanner(); } /** - * name and balance are separated by $ prepared to be saved + * name and balance are separated by ; prepared to be saved * * @return returns all accounts details in String */ diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index ed97a9cf59..4a17469547 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -25,8 +25,9 @@ public BankWithUs(String filePath) throws IOException { ui = new Ui(); storage = new Storage(filePath); parser = new Parser(this); + ui.createScanner(); try { - accountList = new AccountList(storage.load()); + accountList = new AccountList(storage.load(), this); } catch (FileNotFoundException e) { ui.showFileNotFoundError(); try { @@ -35,7 +36,7 @@ public BankWithUs(String filePath) throws IOException { ui.showIOError(); throw ioE; } - accountList = new AccountList(); + accountList = new AccountList(this); } } @@ -43,6 +44,10 @@ public AccountList getAccountList() { return accountList; } + public Ui getUi() { + return ui; + } + /** * exit the programme, save the data and show farewell message * @@ -67,7 +72,6 @@ public void exit(String filePath) throws IOException { */ public void run() throws IOException { ui.greet(); - ui.createScanner(); // if (storage.saveFile.length() < 1) { // createAccount(); // } else { diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 230496ca92..148dd9a41b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -1,6 +1,7 @@ package seedu.bankwithus; import seedu.bankwithus.exceptions.CommandNotFoundException; +import seedu.bankwithus.exceptions.CorruptedSaveFileException; import seedu.bankwithus.exceptions.NegativeAmountException; import java.io.File; @@ -9,11 +10,16 @@ public class Parser { private BankWithUs bwu; + private AccountList accountList; public Parser(BankWithUs bwu) { this.bwu = bwu; } + public Parser(AccountList accountList) { + this.accountList = accountList; + } + public float parseWithdrawAmt(String args) throws NegativeAmountException { float withdrawAmt = Float.parseFloat(args); if (withdrawAmt < 0) { @@ -79,22 +85,39 @@ public void parseUserInput(String input) throws CommandNotFoundException { - /** - * This method reads any existing file and add the saved data - * into current programme - * - * @param list current operation AccountList - */ - public void parseSavedFile(AccountList list) throws IOException { - File f = new File("data/save.txt"); - Scanner myReader = new Scanner(f); - while (myReader.hasNextLine()) { - String data = myReader.nextLine(); - String[] splitDetails = data.split(";"); - String name = splitDetails[0]; - String balance = splitDetails[1]; - list.addAccount(name, balance); + // /** + // * This method reads any existing file and add the saved data + // * into current programme + // * + // * @param list current operation AccountList + // */ + // public void parseSavedFile(AccountList list) throws IOException { + // File f = new File("data/save.txt"); + // Scanner myReader = new Scanner(f); + // while (myReader.hasNextLine()) { + // String data = myReader.nextLine(); + // String[] splitDetails = data.split(";"); + // String name = splitDetails[0]; + // String balanceString = splitDetails[1]; + // list.addAccount(name, balanceString); + // } + // myReader.close(); + // } + + public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException { + String accountDetails = scanner.nextLine(); + accountDetails.trim(); + if (accountDetails.isBlank()) { + throw new CorruptedSaveFileException(); + } + String[] splitDetails = accountDetails.split(";"); + String name = splitDetails[0]; + String balanceString = splitDetails[1]; + try { + float balance = Float.parseFloat(balanceString); + accountList.addAccount(name, balance); + } catch (Exception e) { + throw new CorruptedSaveFileException(); } - myReader.close(); } } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 628608f7bf..15f75eeda3 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -82,7 +82,7 @@ public void showBal(float finalBal) { } public void showNegativeAmountError() { - System.out.println("Negative number entered!"); + System.out.println("Negative amount entered!"); } public void showInsufficientBalanceMessage() { @@ -125,4 +125,8 @@ 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..."); + } } 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..abf543acbd --- /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/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index 4f05aa2f37..b9db102291 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -12,10 +12,10 @@ public void load_normalSaveFile_noMessage() { assertDoesNotThrow(() -> storage.load()); } - @Test - public void save_accountList_noMessage() { - AccountList accountList = new AccountList(); - Storage storage = new Storage("data/save.txt"); - assertDoesNotThrow(() -> storage.saveToFile(accountList)); - } + // @Test + // public void save_accountList_noMessage() { + // AccountList accountList = new AccountList(); + // Storage storage = new Storage("data/save.txt"); + // assertDoesNotThrow(() -> storage.saveToFile(accountList)); + // } } From 7542017286c4d5ec9ee3e87ae6217b51bd700f03 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 17:32:46 +0800 Subject: [PATCH 083/368] Delete dead code --- .../java/seedu/bankwithus/BankWithUs.java | 9 -------- src/main/java/seedu/bankwithus/Parser.java | 23 ------------------- src/main/java/seedu/bankwithus/Ui.java | 1 - 3 files changed, 33 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 4a17469547..8837fd8f09 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -72,15 +72,6 @@ public void exit(String filePath) throws IOException { */ public void run() throws IOException { ui.greet(); - // if (storage.saveFile.length() < 1) { - // createAccount(); - // } else { - // try { - // parser.parseSavedFile(accountList); - // } catch (IOException e) { - // ui.showIOError(); - // } - // } while (!isExitEntered) { String line = ui.getNextLine(); try { diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 148dd9a41b..57a1bb9731 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -4,8 +4,6 @@ import seedu.bankwithus.exceptions.CorruptedSaveFileException; import seedu.bankwithus.exceptions.NegativeAmountException; -import java.io.File; -import java.io.IOException; import java.util.Scanner; public class Parser { @@ -83,27 +81,6 @@ public void parseUserInput(String input) throws CommandNotFoundException { } } - - - // /** - // * This method reads any existing file and add the saved data - // * into current programme - // * - // * @param list current operation AccountList - // */ - // public void parseSavedFile(AccountList list) throws IOException { - // File f = new File("data/save.txt"); - // Scanner myReader = new Scanner(f); - // while (myReader.hasNextLine()) { - // String data = myReader.nextLine(); - // String[] splitDetails = data.split(";"); - // String name = splitDetails[0]; - // String balanceString = splitDetails[1]; - // list.addAccount(name, balanceString); - // } - // myReader.close(); - // } - public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException { String accountDetails = scanner.nextLine(); accountDetails.trim(); diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 15f75eeda3..34cd311b1e 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -123,7 +123,6 @@ public void showBlankUserNameError() { public void askForBalance() { System.out.println("How much would you like to add as Balance?"); - } public void showCorruptedSaveFileError() { From 65afd3f2c7c46c8e3c65dd6f3ec1005590622743 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 17:40:47 +0800 Subject: [PATCH 084/368] Modify location of greet text --- data/save.txt | 0 src/main/java/seedu/bankwithus/BankWithUs.java | 2 +- text-ui-test/EXPECTED.TXT | 11 +++++------ 3 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 8837fd8f09..16686e32b0 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -26,6 +26,7 @@ public BankWithUs(String filePath) throws IOException { storage = new Storage(filePath); parser = new Parser(this); ui.createScanner(); + ui.greet(); try { accountList = new AccountList(storage.load(), this); } catch (FileNotFoundException e) { @@ -71,7 +72,6 @@ public void exit(String filePath) throws IOException { * @throws IOException if something goes wrong while exiting the program */ public void run() throws IOException { - ui.greet(); while (!isExitEntered) { String line = ui.getNextLine(); try { diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index bf59ecca3a..723c1ecd5f 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,5 +1,3 @@ -File not found, trying to create file. -Savefile created successfully! Welcome to: /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ @@ -11,9 +9,10 @@ Welcome to: | $$$$$$$/| $$$$$$$| $$ | $$| $$ \ $$| $$/ \ $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/ |_______/ \_______/|__/ |__/|__/ \__/|__/ \__/|__/ \___/ |__/ |__/ \______/ |_______/ -Whats your name? +File not found, trying to create file. +Savefile created successfully! +What's your name? How much would you like to add as Balance? -Account created! ---------------------------- help: displays the current menu view-account: shows account name and balance @@ -28,7 +27,7 @@ Balance: $1000.0 ---------------------------- You do not have sufficient Balance -Negative number entered! +Negative amount entered! The input is not a valid number! Please try again. ---------------------------- Name: hihi @@ -42,7 +41,7 @@ Balance: $800.0 ---------------------------- You do not have sufficient Balance -Negative number entered! +Negative amount entered! The input is not a valid number! Please try again. New deposit added! You have $1800.0 remaining! From a210dcd05caa87b68197e27b75cf60c3c77e3ed7 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 20:54:12 +0800 Subject: [PATCH 085/368] Remove unecessary attribute bwu --- src/main/java/seedu/bankwithus/AccountList.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 538ebe5f13..e7dc4fc6f9 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -7,19 +7,16 @@ public class AccountList { private ArrayList accounts; - private BankWithUs bwu; private Ui ui; - + public AccountList(BankWithUs bwu) { accounts = new ArrayList(); - this.bwu = bwu; this.ui = bwu.getUi(); createNewAccount(); } public AccountList(Scanner scanner, BankWithUs bwu) { accounts = new ArrayList(); - this.bwu = bwu; this.ui = bwu.getUi(); Parser parser = new Parser(this); try { From 25638d204b26d5d69b174ca794b9f02c45334ab2 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 21:08:58 +0800 Subject: [PATCH 086/368] Prevent user from entering ; in the userName, which will cause problems in the savefile --- src/main/java/seedu/bankwithus/AccountList.java | 4 ++++ src/main/java/seedu/bankwithus/Ui.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index e7dc4fc6f9..4d6f84f67f 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -35,6 +35,10 @@ private String askUserForName() { ui.showBlankUserNameError(); return askUserForName(); } + if (userName.contains(";")) { + ui.showForbiddenCharacterError(); + return askUserForName(); + } return userName; } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 34cd311b1e..af28584bbd 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -128,4 +128,8 @@ public void askForBalance() { public void showCorruptedSaveFileError() { System.out.println("Save file is corrupted!!! Creating new account..."); } + + public void showForbiddenCharacterError() { + System.out.println("Please do not put the chacter ';' in the name."); + } } From 8b1aef194168d9ca126dd7c974db5a31b73e0367 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 21:19:56 +0800 Subject: [PATCH 087/368] Make use of NegativeAmountException --- src/main/java/seedu/bankwithus/AccountList.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 4d6f84f67f..0c9c006887 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -49,13 +49,15 @@ private float askUserForBalance() throws NumberFormatException { try { float balance = Float.parseFloat(balanceString); if (balance < 0) { - ui.showNegativeAmountError(); - return askUserForBalance(); + throw new NegativeAmountException(); } return balance; } catch (NumberFormatException e) { ui.showNumberFormatError(); return askUserForBalance(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + return askUserForBalance(); } } From ce2a8bf858336f6e68540dd4184398cf0d9e3c7c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 21:50:29 +0800 Subject: [PATCH 088/368] Further prevent any shenanigans arising from people doing stupid stuff with their savefile --- src/main/java/seedu/bankwithus/Parser.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 57a1bb9731..c3d33e2854 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -87,10 +87,13 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException { if (accountDetails.isBlank()) { throw new CorruptedSaveFileException(); } - String[] splitDetails = accountDetails.split(";"); - String name = splitDetails[0]; - String balanceString = splitDetails[1]; try { + String[] splitDetails = accountDetails.split(";"); + String name = splitDetails[0].trim(); + String balanceString = splitDetails[1].trim(); + if (name.isEmpty() || balanceString.isEmpty()) { + throw new Exception(); + } float balance = Float.parseFloat(balanceString); accountList.addAccount(name, balance); } catch (Exception e) { From 03bb4152fe4ce5e02a08ebbbd9bb555d220c4747 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 21:51:20 +0800 Subject: [PATCH 089/368] Shifted position of methods --- src/main/java/seedu/bankwithus/BankWithUs.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 16686e32b0..8c8c88a91a 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -14,6 +14,14 @@ public class BankWithUs { private AccountList accountList; private Parser parser; + public AccountList getAccountList() { + return accountList; + } + + public Ui getUi() { + return ui; + } + /** * Creates a new instance of BankWithUs. Initialises storage, ui and * accounts. Should load data into accounts too. @@ -41,16 +49,8 @@ public BankWithUs(String filePath) throws IOException { } } - public AccountList getAccountList() { - return accountList; - } - - public Ui getUi() { - return ui; - } - /** - * exit the programme, save the data and show farewell message + * Exit the programme, save the data and show farewell message * * @throws IOException throw error if the data cannot be saved */ From 9c54f00779773befd412522102d26083e5d75039 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 21:56:16 +0800 Subject: [PATCH 090/368] Add docutmentation, tidied up code --- src/main/java/seedu/bankwithus/Account.java | 5 +- .../java/seedu/bankwithus/AccountList.java | 48 ++++++++++++++++--- .../java/seedu/bankwithus/BankWithUs.java | 6 +++ src/main/java/seedu/bankwithus/Parser.java | 17 +++++++ src/main/java/seedu/bankwithus/Ui.java | 24 ++++++---- 5 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 0522c158b3..b0752e8f4c 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -5,6 +5,8 @@ public class Account { protected float balance; /** + * Instantiates an account object + * * @param name initialise in the name of the account * @param balance initialise the balance of the account */ @@ -13,9 +15,6 @@ public Account(String name, float balance) { this.balance = balance; } - /** - * @return returns a string contains the name of the Account - */ public String getAccountName() { return name; } diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 0c9c006887..5ceed294e8 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -9,12 +9,28 @@ public class AccountList { private ArrayList accounts; private Ui ui; + /** + * Instantiates AccountList and creates a new account. + * Called only when savefile is not found + * + * @param bwu the main bankWithUs program + */ public AccountList(BankWithUs bwu) { accounts = new ArrayList(); this.ui = bwu.getUi(); createNewAccount(); } + /** + * Instantiates AccountList and either: + * 1. Load the saved information in the save file into + * the account list + * 2. Create a brand new account if the save file was + * empty + * + * @param scanner the scanner containing the information in the save file + * @param bwu the main bankWithUs program + */ public AccountList(Scanner scanner, BankWithUs bwu) { accounts = new ArrayList(); this.ui = bwu.getUi(); @@ -27,6 +43,21 @@ public AccountList(Scanner scanner, BankWithUs bwu) { } } + /** + * Returns the current account. + * @return + */ + public Account getCurrentAccount() { + return accounts.get(0); + } + + /** + * 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 + */ private String askUserForName() { ui.askForName(); String userName = ui.getNextLine(); @@ -42,7 +73,14 @@ private String askUserForName() { return userName; } - private float askUserForBalance() throws NumberFormatException { + /** + * Asks the user for their initial balance and returns it as a + * float. Will keep looping so long as the user does not give + * a valid balance. + * + * @return balance in the form of a float + */ + private float askUserForBalance() { ui.askForBalance(); String balanceString = ui.getNextLine(); balanceString.trim(); @@ -82,9 +120,9 @@ public void createNewAccount() { } /** - * name and balance are separated by ; prepared to be saved + * Name and balance are separated by ; prepared to be saved * - * @return returns all accounts details in String + * @return returns all accounts details in String format */ public String getAllAccountDetails() { String temp = ""; @@ -95,10 +133,6 @@ public String getAllAccountDetails() { return temp; } - public Account getCurrentAccount() { - return accounts.get(0); - } - public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException, NegativeAmountException { float depositAmount = Float.parseFloat(depositAmountString); diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 8c8c88a91a..018529175d 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -30,14 +30,20 @@ public Ui getUi() { * @throws IOException thrown when something goes really, really wrong */ public BankWithUs(String filePath) throws IOException { + // Main object instantiations ui = new Ui(); storage = new Storage(filePath); parser = new Parser(this); + + // Ui stuff ui.createScanner(); ui.greet(); + + // Initialising accountList try { accountList = new AccountList(storage.load(), this); } catch (FileNotFoundException e) { + // If savefile not created ui.showFileNotFoundError(); try { storage.createNewFile(); diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index c3d33e2854..f18e69f686 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -10,10 +10,20 @@ public class Parser { private BankWithUs bwu; private AccountList accountList; + /** + * Instantiates a bwu Parser object + * + * @param bwu the main bankWithUs program + */ public Parser(BankWithUs bwu) { this.bwu = bwu; } + /** + * Instatiates a accountList Parser object + * + * @param accountList the accountList + */ public Parser(AccountList accountList) { this.accountList = accountList; } @@ -81,6 +91,13 @@ public void parseUserInput(String input) throws CommandNotFoundException { } } + /** + * Parses the save file. Takes in the scanner to the save file, + * and splits the name and balance by ; character. + * + * @param scanner + * @throws CorruptedSaveFileException if any of the parameters are corrupted + */ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException { String accountDetails = scanner.nextLine(); accountDetails.trim(); diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index af28584bbd..5c90a747c0 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -102,14 +102,22 @@ public void showHelp() { public void greet() { System.out.println("Welcome to: "); System.out.println("\n" + - " /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ \n" + - "| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ \n" + - "| $$ \\ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$| $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$\n" + - "| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$ $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/\n" + - "| $$__ $$ /$$$$$$$| $$ \\ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \\ $$| $$ | $$| $$$$$$ \n" + - "| $$ \\ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \\ $$$| $$ | $$ /$$| $$ | $$| $$ | $$ \\____ $$\n" + - "| $$$$$$$/| $$$$$$$| $$ | $$| $$ \\ $$| $$/ \\ $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/\n" + - "|_______/ \\_______/|__/ |__/|__/ \\__/|__/ \\__/|__/ \\___/ |__/ |__/ \\______/ |_______/ \n" + " /$$$$$$$ /$$ /$$ /$$" + + " /$$ /$$ /$$ /$$ /$$ \n" + + "| $$__ $$ | $$ | $$ /$ | $$" + + "|__/ | $$ | $$ | $$ | $$ \n" + + "| $$ \\ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$|" + + " $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$\n" + + "| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$" + + " $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/\n" + + "| $$__ $$ /$$$$$$$| $$ \\ $$| $$$$$$/ | $$$$_ " + + "$$$$| $$ | $$ | $$ \\ $$| $$ | $$| $$$$$$ \n" + + "| $$ \\ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \\ " + + "$$$| $$ | $$ /$$| $$ | $$| $$ | $$ \\____ $$\n" + + "| $$$$$$$/| $$$$$$$| $$ | $$| $$ \\ $$| $$/ \\ " + + " $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/\n" + + "|_______/ \\_______/|__/ |__/|__/ \\__/|__/ " + + "\\__/|__/ \\___/ |__/ |__/ \\______/ |_______/ \n" ); } From 1c7a107479f9ba69d6fd539be8cba418d345e82e Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 21:59:51 +0800 Subject: [PATCH 091/368] Fix checkstyle errors, test checkstyle are generally commented out --- src/main/java/seedu/bankwithus/BankWithUs.java | 16 ++++++++-------- src/main/java/seedu/bankwithus/Ui.java | 2 +- .../java/seedu/bankwithus/AccountListTest.java | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 018529175d..738b542b25 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -14,14 +14,6 @@ public class BankWithUs { private AccountList accountList; private Parser parser; - public AccountList getAccountList() { - return accountList; - } - - public Ui getUi() { - return ui; - } - /** * Creates a new instance of BankWithUs. Initialises storage, ui and * accounts. Should load data into accounts too. @@ -55,6 +47,14 @@ public BankWithUs(String filePath) throws IOException { } } + public AccountList getAccountList() { + return accountList; + } + + public Ui getUi() { + return ui; + } + /** * Exit the programme, save the data and show farewell message * diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 5c90a747c0..d423b2eae7 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -118,7 +118,7 @@ public void greet() { " $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/\n" + "|_______/ \\_______/|__/ |__/|__/ \\__/|__/ " + "\\__/|__/ \\___/ |__/ |__/ \\______/ |_______/ \n" - ); + ); } public void askForName() { diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index db8ed8b1e4..086b53aa5c 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,10 +1,10 @@ package seedu.bankwithus; -import org.junit.jupiter.api.Test; -import seedu.bankwithus.exceptions.NegativeAmountException; +// import org.junit.jupiter.api.Test; +// import seedu.bankwithus.exceptions.NegativeAmountException; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +// import static org.junit.jupiter.api.Assertions.assertEquals; +// import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { From ff56ec16ae58203a169c00ee760fee4fab917a10 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 22:13:31 +0800 Subject: [PATCH 092/368] Migrated exit command call to parseUserInput instead of BWU --- src/main/java/seedu/bankwithus/BankWithUs.java | 8 ++++---- src/main/java/seedu/bankwithus/Parser.java | 10 ++++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 738b542b25..f497ae44d9 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -60,15 +60,16 @@ public Ui getUi() { * * @throws IOException throw error if the data cannot be saved */ - public void exit(String filePath) throws IOException { + public void exit() throws IOException { + isExitEntered = true; + ui.showFarewellMessage(); + ui.closeScanner(); try { storage.saveToFile(accountList); } catch (IOException e) { ui.showIOError(); throw e; } - ui.showFarewellMessage(); - ui.closeScanner(); } /** @@ -86,7 +87,6 @@ public void run() throws IOException { ui.showCommandNotFoundError(); } } - exit(FILE_PATH); } public static void main(String[] args) { diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index f18e69f686..9c41270c27 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -4,6 +4,7 @@ import seedu.bankwithus.exceptions.CorruptedSaveFileException; import seedu.bankwithus.exceptions.NegativeAmountException; +import java.io.IOException; import java.util.Scanner; public class Parser { @@ -40,8 +41,9 @@ public float parseWithdrawAmt(String args) throws NegativeAmountException { /** * Parses the user input into command and arguments. + * @throws IOException */ - public void parseUserInput(String input) throws CommandNotFoundException { + public void parseUserInput(String input) throws CommandNotFoundException, IOException { // Split input by space String[] split = input.trim().split("\\s+", 2); String command = split[0]; @@ -49,7 +51,11 @@ public void parseUserInput(String input) throws CommandNotFoundException { Ui screen = new Ui(); switch (command) { case "exit": - bwu.isExitEntered = true; + try { + bwu.exit(); + } catch (IOException e) { + throw e; + } break; case "deposit": try { From b950eff8388cdd206cbc672450f60cd5155f1b7f Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 22:17:17 +0800 Subject: [PATCH 093/368] Change screen to ui, made bwu's ui the ui in parser --- src/main/java/seedu/bankwithus/Parser.java | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 9c41270c27..5d5bf66330 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -10,6 +10,7 @@ public class Parser { private BankWithUs bwu; private AccountList accountList; + private Ui ui; /** * Instantiates a bwu Parser object @@ -18,6 +19,7 @@ public class Parser { */ public Parser(BankWithUs bwu) { this.bwu = bwu; + this.ui = bwu.getUi(); } /** @@ -48,7 +50,6 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce String[] split = input.trim().split("\\s+", 2); String command = split[0]; String args = split.length == 2 ? split[1] : ""; - Ui screen = new Ui(); switch (command) { case "exit": try { @@ -60,37 +61,37 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "deposit": try { bwu.getAccountList().depositMoney(args); - screen.showDepositMessage(); - screen.showBal(bwu.getAccountList().getCurrentAccount().getAccountBalance()); + ui.showDepositMessage(); + ui.showBal(bwu.getAccountList().getCurrentAccount().getAccountBalance()); } catch (NumberFormatException e) { - screen.showNumberFormatError(); + ui.showNumberFormatError(); } catch (NullPointerException e) { - screen.showNullInputError(); + ui.showNullInputError(); } catch (NegativeAmountException e) { - screen.showNegativeAmountError(); + ui.showNegativeAmountError(); } break; case "view-account": String accDetails = bwu.getAccountList().getAllAccountDetails(); - screen.viewAccount(accDetails); + ui.viewAccount(accDetails); break; case "withdraw": try { float finalBal = parseWithdrawAmt(args); if(finalBal >= 0) { bwu.getAccountList().getCurrentAccount().setBalance(finalBal); - screen.showBal(finalBal); + ui.showBal(finalBal); } else { - screen.showInsufficientBalanceMessage(); + ui.showInsufficientBalanceMessage(); } } catch (NumberFormatException e) { - screen.showNumberFormatError(); + ui.showNumberFormatError(); } catch (NegativeAmountException e) { - screen.showNegativeAmountError(); + ui.showNegativeAmountError(); } break; case "help": - screen.showHelp(); + ui.showHelp(); break; default: throw new CommandNotFoundException(); From 1713243aa96fad1e79c8372954e3853428c51644 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 22:20:28 +0800 Subject: [PATCH 094/368] Changed all occurences of bwu.getAccountList() to accountList so that it is more readable --- src/main/java/seedu/bankwithus/Parser.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 5d5bf66330..11b68d3b2f 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -20,6 +20,7 @@ public class Parser { public Parser(BankWithUs bwu) { this.bwu = bwu; this.ui = bwu.getUi(); + this.accountList = accountList; } /** @@ -36,7 +37,7 @@ public float parseWithdrawAmt(String args) throws NegativeAmountException { if (withdrawAmt < 0) { throw new NegativeAmountException(); } - float currBal = bwu.getAccountList().getCurrentAccount().balance; + float currBal = accountList.getCurrentAccount().balance; float finalBal = currBal-withdrawAmt; return finalBal; } @@ -60,9 +61,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce break; case "deposit": try { - bwu.getAccountList().depositMoney(args); + accountList.depositMoney(args); ui.showDepositMessage(); - ui.showBal(bwu.getAccountList().getCurrentAccount().getAccountBalance()); + ui.showBal(accountList.getCurrentAccount().getAccountBalance()); } catch (NumberFormatException e) { ui.showNumberFormatError(); } catch (NullPointerException e) { @@ -72,14 +73,14 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce } break; case "view-account": - String accDetails = bwu.getAccountList().getAllAccountDetails(); + String accDetails = accountList.getAllAccountDetails(); ui.viewAccount(accDetails); break; case "withdraw": try { float finalBal = parseWithdrawAmt(args); if(finalBal >= 0) { - bwu.getAccountList().getCurrentAccount().setBalance(finalBal); + accountList.getCurrentAccount().setBalance(finalBal); ui.showBal(finalBal); } else { ui.showInsufficientBalanceMessage(); From f6a0ec736c4e53e353cc71dfed28305e25a58006 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 22:32:49 +0800 Subject: [PATCH 095/368] Create showBal() function in accountList --- src/main/java/seedu/bankwithus/AccountList.java | 5 +++++ src/main/java/seedu/bankwithus/Parser.java | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 5ceed294e8..94cea77c7f 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -133,6 +133,11 @@ public String getAllAccountDetails() { return temp; } + public void showBal() { + float balance = getCurrentAccount().getAccountBalance(); + ui.showBal(balance); + } + public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException, NegativeAmountException { float depositAmount = Float.parseFloat(depositAmountString); diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 11b68d3b2f..26fc4940ff 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -20,7 +20,7 @@ public class Parser { public Parser(BankWithUs bwu) { this.bwu = bwu; this.ui = bwu.getUi(); - this.accountList = accountList; + this.accountList = bwu.getAccountList(); } /** @@ -63,10 +63,11 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce try { accountList.depositMoney(args); ui.showDepositMessage(); - ui.showBal(accountList.getCurrentAccount().getAccountBalance()); + accountList.showBal(); } catch (NumberFormatException e) { ui.showNumberFormatError(); } catch (NullPointerException e) { + // Will almost never happen, but who knows ui.showNullInputError(); } catch (NegativeAmountException e) { ui.showNegativeAmountError(); @@ -101,7 +102,8 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce /** * Parses the save file. Takes in the scanner to the save file, - * and splits the name and balance by ; character. + * and 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 From a48281fc2593cfc7ce3defc9ef8be95a1a4251e9 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 22:33:36 +0800 Subject: [PATCH 096/368] Fix error that occured due to accountList not being instantiated before Parser object --- src/main/java/seedu/bankwithus/BankWithUs.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index f497ae44d9..cfbf85178f 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -25,7 +25,6 @@ public BankWithUs(String filePath) throws IOException { // Main object instantiations ui = new Ui(); storage = new Storage(filePath); - parser = new Parser(this); // Ui stuff ui.createScanner(); @@ -45,6 +44,7 @@ public BankWithUs(String filePath) throws IOException { } accountList = new AccountList(this); } + parser = new Parser(this); } public AccountList getAccountList() { From 34265b39469d18a10ba772fbec59d7e99544193e Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:04:11 +0800 Subject: [PATCH 097/368] Add withdraw message to ui, use in withdraw command --- src/main/java/seedu/bankwithus/Parser.java | 1 + src/main/java/seedu/bankwithus/Ui.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 26fc4940ff..efba13755b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -86,6 +86,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce } else { ui.showInsufficientBalanceMessage(); } + ui.showWithdrawMessage(); } catch (NumberFormatException e) { ui.showNumberFormatError(); } catch (NegativeAmountException e) { diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index d423b2eae7..0dc464a4a1 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -37,10 +37,15 @@ public void showFarewellMessage() { public void showAddAccountMessage() { System.out.println("Account created!"); } + public void showDepositMessage() { System.out.println("New deposit added!"); } + public void showWithdrawMessage() { + System.out.println("Withdrawal successful!"); + } + /** * Creates a scanner in the Ui class */ From efead4a6d982dd6c5119e8d333d63ca9e8fedf50 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:06:22 +0800 Subject: [PATCH 098/368] Changed name and balance in account to private --- src/main/java/seedu/bankwithus/Account.java | 4 ++-- src/main/java/seedu/bankwithus/AccountList.java | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index b0752e8f4c..b12c632b21 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -1,8 +1,8 @@ package seedu.bankwithus; public class Account { - protected String name; - protected float balance; + private String name; + private float balance; /** * Instantiates an account object diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 94cea77c7f..53e66b3b48 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -127,7 +127,7 @@ public void createNewAccount() { public String getAllAccountDetails() { String temp = ""; for (Account acc : accounts) { - temp += acc.name + ";" + acc.balance; + temp += acc.getAccountName() + ";" + acc.getAccountBalance(); temp += "\n"; } return temp; @@ -144,7 +144,9 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio if (depositAmount < 0) { throw new NegativeAmountException(); } else { - getCurrentAccount().balance += depositAmount; + getCurrentAccount().addBalance(depositAmount); + } + } } } } From 09b46c3ff6d32adbd342d7dc0fc084fecce62ca7 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:06:57 +0800 Subject: [PATCH 099/368] Replace setBalance with addBalance and subtractBalance --- src/main/java/seedu/bankwithus/Account.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index b12c632b21..fe2b4ba0d5 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -23,7 +23,11 @@ public float getAccountBalance() { return balance; } - public void setBalance(float balance) { - this.balance = balance; + public void addBalance(float balance) { + this.balance += balance; + } + + public void subtractBalance(float balance) { + this.balance -= balance; } } From dc5b25f14a1b7dd670e612341707e1bd1b0fa1c4 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:08:15 +0800 Subject: [PATCH 100/368] Change parseWithdrawAmount to withdrawMoney function in accountList --- .../java/seedu/bankwithus/AccountList.java | 12 +++++++++++ .../InsufficientBalanceException.java | 5 +++++ src/main/java/seedu/bankwithus/Parser.java | 21 ++++--------------- 3 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/InsufficientBalanceException.java diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 53e66b3b48..b582fcf7be 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -147,6 +147,18 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio getCurrentAccount().addBalance(depositAmount); } } + + public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, + NegativeAmountException, InsufficientBalanceException { + float withdrawAmount = Float.parseFloat(withdrawAmountString); + if (withdrawAmount < 0) { + throw new NegativeAmountException(); + } + float currentBalance = getCurrentAccount().getAccountBalance(); + if (currentBalance < withdrawAmount) { + throw new InsufficientBalanceException(); + } else { + getCurrentAccount().subtractBalance(withdrawAmount); } } } diff --git a/src/main/java/seedu/bankwithus/InsufficientBalanceException.java b/src/main/java/seedu/bankwithus/InsufficientBalanceException.java new file mode 100644 index 0000000000..2d9b9c821f --- /dev/null +++ b/src/main/java/seedu/bankwithus/InsufficientBalanceException.java @@ -0,0 +1,5 @@ +package seedu.bankwithus; + +public class InsufficientBalanceException extends Exception { + +} diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index efba13755b..2196c05d8b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -32,16 +32,6 @@ public Parser(AccountList accountList) { this.accountList = accountList; } - public float parseWithdrawAmt(String args) throws NegativeAmountException { - float withdrawAmt = Float.parseFloat(args); - if (withdrawAmt < 0) { - throw new NegativeAmountException(); - } - float currBal = accountList.getCurrentAccount().balance; - float finalBal = currBal-withdrawAmt; - return finalBal; - } - /** * Parses the user input into command and arguments. * @throws IOException @@ -79,18 +69,15 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce break; case "withdraw": try { - float finalBal = parseWithdrawAmt(args); - if(finalBal >= 0) { - accountList.getCurrentAccount().setBalance(finalBal); - ui.showBal(finalBal); - } else { - ui.showInsufficientBalanceMessage(); - } + accountList.withdrawMoney(args); ui.showWithdrawMessage(); + accountList.showBal(); } catch (NumberFormatException e) { ui.showNumberFormatError(); } catch (NegativeAmountException e) { ui.showNegativeAmountError(); + } catch (InsufficientBalanceException e) { + ui.showInsufficientBalanceMessage(); } break; case "help": From b2f9b6b7e1fad045ecac5255810ffb85a629536f Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:08:54 +0800 Subject: [PATCH 101/368] Modify EXPECTED.TXT in lieu of new behaviour changes --- text-ui-test/EXPECTED.TXT | 1 + 1 file changed, 1 insertion(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 723c1ecd5f..468679fa85 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -34,6 +34,7 @@ Name: hihi Balance: $1000.0 ---------------------------- +Withdrawal successful! You have $800.0 remaining! ---------------------------- Name: hihi From 309cfb2c11fb8089743332e85cce593fd3bec5c6 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:18:44 +0800 Subject: [PATCH 102/368] Delete part of comment --- src/test/java/seedu/bankwithus/AccountListTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 086b53aa5c..5a89830f36 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -8,7 +8,6 @@ class AccountListTest { - // Invalid because addAccount parameter have been changed // @Test // void addAccount_invalidBalance_expectException() throws NumberFormatException { // String name = "Bob"; From 92c27ce4a1b6d569ecc2d96e42aa2dd927dd153e Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:21:05 +0800 Subject: [PATCH 103/368] Shift InsufficientBalanceException to exception package --- src/main/java/seedu/bankwithus/AccountList.java | 1 + src/main/java/seedu/bankwithus/Parser.java | 1 + .../{ => exceptions}/InsufficientBalanceException.java | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) rename src/main/java/seedu/bankwithus/{ => exceptions}/InsufficientBalanceException.java (64%) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index b582fcf7be..d479b45aee 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,5 +1,6 @@ package seedu.bankwithus; +import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; import java.util.ArrayList; diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 2196c05d8b..7660abe2fc 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -2,6 +2,7 @@ import seedu.bankwithus.exceptions.CommandNotFoundException; import seedu.bankwithus.exceptions.CorruptedSaveFileException; +import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; import java.io.IOException; diff --git a/src/main/java/seedu/bankwithus/InsufficientBalanceException.java b/src/main/java/seedu/bankwithus/exceptions/InsufficientBalanceException.java similarity index 64% rename from src/main/java/seedu/bankwithus/InsufficientBalanceException.java rename to src/main/java/seedu/bankwithus/exceptions/InsufficientBalanceException.java index 2d9b9c821f..22ba8317d4 100644 --- a/src/main/java/seedu/bankwithus/InsufficientBalanceException.java +++ b/src/main/java/seedu/bankwithus/exceptions/InsufficientBalanceException.java @@ -1,4 +1,4 @@ -package seedu.bankwithus; +package seedu.bankwithus.exceptions; public class InsufficientBalanceException extends Exception { From 2ea8ff1129fd0e2954de052b1bed26d38f1d44aa Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:27:40 +0800 Subject: [PATCH 104/368] Closed savefile scanner --- src/main/java/seedu/bankwithus/Parser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 7660abe2fc..acad8012a2 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -115,5 +115,6 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException { } catch (Exception e) { throw new CorruptedSaveFileException(); } + scanner.close(); } } From d9de9a0d8ef81eb086af1b86976b480fcfe65324 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:38:58 +0800 Subject: [PATCH 105/368] Commented out test --- src/test/java/seedu/bankwithus/StorageTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index b9db102291..4d50347d0a 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -8,8 +8,8 @@ public class StorageTest { @Test public void load_normalSaveFile_noMessage() { assertDoesNotThrow(() -> new Storage("data/save.txt")); - Storage storage = new Storage("data/save.txt"); - assertDoesNotThrow(() -> storage.load()); + // Storage storage = new Storage("data/save.txt"); + // assertDoesNotThrow(() -> storage.load()); } // @Test From afb121b35c10edce730175e9b55fb1608f85c79d Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 16 Mar 2023 23:45:50 +0800 Subject: [PATCH 106/368] Make runtest more robust --- text-ui-test/EXPECTED.TXT | 33 ++++++++++++++++++++++----------- text-ui-test/input.txt | 28 ++++++++++++++++------------ 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 468679fa85..c5c1363b3a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -12,6 +12,14 @@ Welcome to: File not found, trying to create file. Savefile created successfully! What's your name? +User Name cannot be blank. +What's your name? +Please do not put the chacter ';' 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? ---------------------------- help: displays the current menu @@ -26,7 +34,6 @@ Name: hihi Balance: $1000.0 ---------------------------- -You do not have sufficient Balance Negative amount entered! The input is not a valid number! Please try again. ---------------------------- @@ -34,28 +41,32 @@ Name: hihi Balance: $1000.0 ---------------------------- -Withdrawal successful! -You have $800.0 remaining! +New deposit added! +You have $1100.21 remaining! ---------------------------- Name: hihi -Balance: $800.0 +Balance: $1100.21 ---------------------------- -You do not have sufficient Balance Negative amount entered! +You do not have sufficient Balance +---------------------------- +Name: hihi +Balance: $1100.21 + +---------------------------- The input is not a valid number! Please try again. -New deposit added! -You have $1800.0 remaining! ---------------------------- Name: hihi -Balance: $1800.0 +Balance: $1100.21 ---------------------------- -New deposit added! -You have $1900.0 remaining! +Withdrawal successful! +You have $1000.20996 remaining! ---------------------------- Name: hihi -Balance: $1900.0 +Balance: $1000.20996 ---------------------------- +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 33a1dcb818..2ee41ed71c 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,19 +1,23 @@ + +hi;hi hihi -1000.0 -help hihi + +1000 +help +view account +view-account +deposit -1 +deposit java view-account -withdraw 1500 -withdraw -10 -withdraw a100 +deposit 100.21 view-account -withdraw 200 +withdraw -1 +withdraw 100000 view-account -withdraw 800.1 -deposit -100 -deposit bb100 -deposit 1000 +withdraw dba view-account -deposit 100 +withdraw 100 view-account -exit + +exit \ No newline at end of file From ae614c7df4368ef997b4d1eeb1a910fcab893145 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Sat, 18 Mar 2023 20:45:27 +0800 Subject: [PATCH 107/368] Add delete account feature Add showEmptySavedFile exception Add some Ui to make the program looks better Add getSize() in AccountList --- src/main/java/seedu/bankwithus/Account.java | 2 +- .../java/seedu/bankwithus/AccountList.java | 52 ++++++--- .../java/seedu/bankwithus/BankWithUs.java | 1 + src/main/java/seedu/bankwithus/Parser.java | 109 ++++++++++-------- src/main/java/seedu/bankwithus/Storage.java | 10 +- src/main/java/seedu/bankwithus/Ui.java | 41 +++++-- .../exceptions/AccountNotFoundException.java | 2 +- .../CorruptedSaveFileException.java | 2 +- .../exceptions/SaveFileIsEmpty.java | 8 ++ 9 files changed, 149 insertions(+), 78 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmpty.java diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index fe2b4ba0d5..a3cd3bbd8d 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -6,7 +6,7 @@ public class Account { /** * Instantiates an account object - * + * * @param name initialise in the name of the account * @param balance initialise the balance of the account */ diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index d479b45aee..ad91893c2c 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,5 +1,6 @@ package seedu.bankwithus; +import seedu.bankwithus.exceptions.AccountNotFoundException; import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; @@ -13,7 +14,7 @@ public class AccountList { /** * Instantiates AccountList and creates a new account. * Called only when savefile is not found - * + * * @param bwu the main bankWithUs program */ public AccountList(BankWithUs bwu) { @@ -25,10 +26,10 @@ public AccountList(BankWithUs bwu) { /** * Instantiates AccountList and either: * 1. Load the saved information in the save file into - * the account list + * the account list * 2. Create a brand new account if the save file was - * empty - * + * empty + * * @param scanner the scanner containing the information in the save file * @param bwu the main bankWithUs program */ @@ -39,13 +40,14 @@ public AccountList(Scanner scanner, BankWithUs bwu) { try { parser.parseSavedFile(scanner); } catch (Exception e) { - ui.showCorruptedSaveFileError(); + ui.showEmptyFile(); createNewAccount(); } } /** * Returns the current account. + * * @return */ public Account getCurrentAccount() { @@ -56,7 +58,7 @@ public Account getCurrentAccount() { * 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 */ private String askUserForName() { @@ -78,7 +80,7 @@ private String askUserForName() { * Asks the user for their initial balance and returns it as a * float. Will keep looping so long as the user does not give * a valid balance. - * + * * @return balance in the form of a float */ private float askUserForBalance() { @@ -103,8 +105,8 @@ private float askUserForBalance() { /** * 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 name Name of the new account to be added + * @param balance Balance of the new account to be added */ public void addAccount(String name, float balance) { Account newAccount = new Account(name, balance); @@ -125,13 +127,17 @@ public void createNewAccount() { * * @return returns all accounts details in String format */ - public String getAllAccountDetails() { - String temp = ""; - for (Account acc : accounts) { - temp += acc.getAccountName() + ";" + acc.getAccountBalance(); - temp += "\n"; + 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()); + temp.append("\n"); + } + return temp.toString(); } - return temp; } public void showBal() { @@ -162,4 +168,20 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept getCurrentAccount().subtractBalance(withdrawAmount); } } + + public void deleteAccount(String name) { + for (Account acc : accounts) { + if (acc.getAccountName().contains(name)) { + accounts.remove(acc); + ui.showAccountDeleted(name); + return; + } + } + ui.showNoAccountFound(); + } + + public int getSize() { + return accounts.size(); + } + } diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index cfbf85178f..570192d890 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -33,6 +33,7 @@ public BankWithUs(String filePath) throws IOException { // Initialising accountList try { accountList = new AccountList(storage.load(), this); + ui.showNumberOfAccount(accountList.getSize()); } catch (FileNotFoundException e) { // If savefile not created ui.showFileNotFoundError(); diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index acad8012a2..4b4fafd140 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -1,9 +1,11 @@ package seedu.bankwithus; +import seedu.bankwithus.exceptions.AccountNotFoundException; import seedu.bankwithus.exceptions.CommandNotFoundException; import seedu.bankwithus.exceptions.CorruptedSaveFileException; import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; +import seedu.bankwithus.exceptions.SaveFileIsEmpty; import java.io.IOException; import java.util.Scanner; @@ -15,7 +17,7 @@ public class Parser { /** * Instantiates a bwu Parser object - * + * * @param bwu the main bankWithUs program */ public Parser(BankWithUs bwu) { @@ -26,7 +28,7 @@ public Parser(BankWithUs bwu) { /** * Instatiates a accountList Parser object - * + * * @param accountList the accountList */ public Parser(AccountList accountList) { @@ -35,6 +37,7 @@ public Parser(AccountList accountList) { /** * Parses the user input into command and arguments. + * * @throws IOException */ public void parseUserInput(String input) throws CommandNotFoundException, IOException { @@ -43,65 +46,71 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce 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 { - accountList.depositMoney(args); - ui.showDepositMessage(); - accountList.showBal(); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NullPointerException e) { - // Will almost never happen, but who knows - ui.showNullInputError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } - break; - case "view-account": - String accDetails = accountList.getAllAccountDetails(); - ui.viewAccount(accDetails); - break; - case "withdraw": - try { - accountList.withdrawMoney(args); - ui.showWithdrawMessage(); - accountList.showBal(); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } catch (InsufficientBalanceException e) { - ui.showInsufficientBalanceMessage(); - } - break; - case "help": - ui.showHelp(); - break; - default: - throw new CommandNotFoundException(); + case "exit": + try { + bwu.exit(); + } catch (IOException e) { + throw e; + } + break; + case "deposit": + try { + accountList.depositMoney(args); + ui.showDepositMessage(); + accountList.showBal(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NullPointerException e) { + // Will almost never happen, but who knows + ui.showNullInputError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } + break; + case "view-account": + try { + String accDetails = accountList.getAllAccountDetails(); + ui.viewAccount(accDetails); + } catch (AccountNotFoundException e) { + ui.showNoAccount(); + } + break; + case "withdraw": + try { + accountList.withdrawMoney(args); + ui.showWithdrawMessage(); + accountList.showBal(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } catch (InsufficientBalanceException e) { + ui.showInsufficientBalanceMessage(); + } + break; + case "help": + ui.showHelp(); + break; + case "delete": + accountList.deleteAccount(args); + break; + default: + throw new CommandNotFoundException(); } } /** * Parses the save file. Takes in the scanner to the save file, - * and splits the name and balance by ; character. Part of + * and 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 { + public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, SaveFileIsEmpty { String accountDetails = scanner.nextLine(); - accountDetails.trim(); if (accountDetails.isBlank()) { - throw new CorruptedSaveFileException(); + throw new SaveFileIsEmpty(); } try { String[] splitDetails = accountDetails.split(";"); diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index c31f53fe3f..49c8eccec6 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -1,5 +1,7 @@ package seedu.bankwithus; +import seedu.bankwithus.exceptions.AccountNotFoundException; + import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; @@ -50,8 +52,12 @@ public void createNewFile() throws IOException { */ public void saveToFile(AccountList list) throws IOException { FileWriter fw = new FileWriter(saveFile); - fw.write(list.getAllAccountDetails()); - fw.close(); + try { + fw.write(list.getAllAccountDetails()); + fw.close(); + } catch (AccountNotFoundException e) { + fw.close(); + } } } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 0dc464a4a1..32a45f6416 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -107,21 +107,21 @@ public void showHelp() { public void greet() { System.out.println("Welcome to: "); System.out.println("\n" + - " /$$$$$$$ /$$ /$$ /$$" + + " /$$$$$$$ /$$ /$$ /$$" + " /$$ /$$ /$$ /$$ /$$ \n" + - "| $$__ $$ | $$ | $$ /$ | $$" + + "| $$__ $$ | $$ | $$ /$ | $$" + "|__/ | $$ | $$ | $$ | $$ \n" + - "| $$ \\ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$|" + + "| $$ \\ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$|" + " $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$\n" + - "| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$" + + "| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$" + " $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/\n" + - "| $$__ $$ /$$$$$$$| $$ \\ $$| $$$$$$/ | $$$$_ " + + "| $$__ $$ /$$$$$$$| $$ \\ $$| $$$$$$/ | $$$$_ " + "$$$$| $$ | $$ | $$ \\ $$| $$ | $$| $$$$$$ \n" + - "| $$ \\ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \\ " + + "| $$ \\ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \\ " + "$$$| $$ | $$ /$$| $$ | $$| $$ | $$ \\____ $$\n" + - "| $$$$$$$/| $$$$$$$| $$ | $$| $$ \\ $$| $$/ \\ " + + "| $$$$$$$/| $$$$$$$| $$ | $$| $$ \\ $$| $$/ \\ " + " $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/\n" + - "|_______/ \\_______/|__/ |__/|__/ \\__/|__/ " + + "|_______/ \\_______/|__/ |__/|__/ \\__/|__/ " + "\\__/|__/ \\___/ |__/ |__/ \\______/ |_______/ \n" ); } @@ -145,4 +145,29 @@ public void showCorruptedSaveFileError() { public void showForbiddenCharacterError() { System.out.println("Please do not put the chacter ';' in the name."); } + + public void showAccountDeleted(String name) { + System.out.println("Account: " + name + " deleted"); + printLine(); + } + + public void showNoAccountFound() { + System.out.println("Account is not found, please re-enter the account name"); + printLine(); + } + + public void showNoAccount() { + 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(); + } + + public void showNumberOfAccount(int accSize) { + System.out.println("Found " + accSize + " Account"); + } + } diff --git a/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java b/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java index 89886b9fd1..0b6f2f4378 100644 --- a/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java +++ b/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java @@ -1,5 +1,5 @@ package seedu.bankwithus.exceptions; public class AccountNotFoundException extends Exception { - + } diff --git a/src/main/java/seedu/bankwithus/exceptions/CorruptedSaveFileException.java b/src/main/java/seedu/bankwithus/exceptions/CorruptedSaveFileException.java index abf543acbd..8076887183 100644 --- a/src/main/java/seedu/bankwithus/exceptions/CorruptedSaveFileException.java +++ b/src/main/java/seedu/bankwithus/exceptions/CorruptedSaveFileException.java @@ -1,5 +1,5 @@ package seedu.bankwithus.exceptions; public class CorruptedSaveFileException extends Exception { - + } diff --git a/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmpty.java b/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmpty.java new file mode 100644 index 0000000000..a95c67803c --- /dev/null +++ b/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmpty.java @@ -0,0 +1,8 @@ +package seedu.bankwithus.exceptions; + +/** + * Thrown when the saved file has no data + */ +public class SaveFileIsEmpty extends Exception { + +} From 0b5eedcf78be38d3f8f5bb55a7351445638cf801 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Sat, 18 Mar 2023 20:52:17 +0800 Subject: [PATCH 108/368] Add showAddedAccount in Ui --- src/main/java/seedu/bankwithus/AccountList.java | 1 + src/main/java/seedu/bankwithus/Ui.java | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index ad91893c2c..bf52f96bd6 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -111,6 +111,7 @@ private float askUserForBalance() { public void addAccount(String name, float balance) { Account newAccount = new Account(name, balance); accounts.add(newAccount); + ui.showNewAddedAccount(newAccount); } /** diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 32a45f6416..4d08ea6077 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -170,4 +170,11 @@ public void showNumberOfAccount(int accSize) { System.out.println("Found " + accSize + " Account"); } + public void showNewAddedAccount(Account acc) { + printLine(); + System.out.println("Name: " + acc.getAccountName()); + System.out.println("Balance: $" + acc.getAccountBalance()); + printLine(); + } + } From 7ddace647850c57eeb2ba96704cf0d8b6bb30b88 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Sat, 18 Mar 2023 21:03:29 +0800 Subject: [PATCH 109/368] Update the text-ui-test --- text-ui-test/EXPECTED.TXT | 17 +++++++++++------ text-ui-test/input.txt | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index c5c1363b3a..2249763e31 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,13 +1,13 @@ -Welcome to: +Welcome to: - /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ -| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ + /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ +| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ | $$ \ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$| $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$ | $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$ $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/ -| $$__ $$ /$$$$$$$| $$ \ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \ $$| $$ | $$| $$$$$$ +| $$__ $$ /$$$$$$$| $$ \ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \ $$| $$ | $$| $$$$$$ | $$ \ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \ $$$| $$ | $$ /$$| $$ | $$| $$ | $$ \____ $$ | $$$$$$$/| $$$$$$$| $$ | $$| $$ \ $$| $$/ \ $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/ -|_______/ \_______/|__/ |__/|__/ \__/|__/ \__/|__/ \___/ |__/ |__/ \______/ |_______/ +|_______/ \_______/|__/ |__/|__/ \__/|__/ \__/|__/ \___/ |__/ |__/ \______/ |_______/ File not found, trying to create file. Savefile created successfully! @@ -22,6 +22,10 @@ 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? ---------------------------- +Name: hihi +Balance: $1000.0 +---------------------------- +---------------------------- help: displays the current menu view-account: shows account name and balance withdraw : withdraws from available balance @@ -48,7 +52,8 @@ Name: hihi Balance: $1100.21 ---------------------------- -Negative amount entered! +Account is not found, please re-enter the account name +---------------------------- You do not have sufficient Balance ---------------------------- Name: hihi diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 2ee41ed71c..0f8a590fd9 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -12,7 +12,7 @@ deposit java view-account deposit 100.21 view-account -withdraw -1 +delete sherlock withdraw 100000 view-account withdraw dba From 37f94aa3d44f288cc8bcecc3b25244e97894d25b Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Tue, 21 Mar 2023 13:04:13 +0800 Subject: [PATCH 110/368] change indentation level --- src/main/java/seedu/bankwithus/Parser.java | 100 ++++++++++----------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 4b4fafd140..4b4a65e44e 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -46,56 +46,56 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce 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 { - accountList.depositMoney(args); - ui.showDepositMessage(); - accountList.showBal(); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NullPointerException e) { - // Will almost never happen, but who knows - ui.showNullInputError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } - break; - case "view-account": - try { - String accDetails = accountList.getAllAccountDetails(); - ui.viewAccount(accDetails); - } catch (AccountNotFoundException e) { - ui.showNoAccount(); - } - break; - case "withdraw": - try { - accountList.withdrawMoney(args); - ui.showWithdrawMessage(); - accountList.showBal(); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } catch (InsufficientBalanceException e) { - ui.showInsufficientBalanceMessage(); - } - break; - case "help": - ui.showHelp(); - break; - case "delete": - accountList.deleteAccount(args); - break; - default: - throw new CommandNotFoundException(); + case "exit": + try { + bwu.exit(); + } catch (IOException e) { + throw e; + } + break; + case "deposit": + try { + accountList.depositMoney(args); + ui.showDepositMessage(); + accountList.showBal(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NullPointerException e) { + // Will almost never happen, but who knows + ui.showNullInputError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } + break; + case "view-account": + try { + String accDetails = accountList.getAllAccountDetails(); + ui.viewAccount(accDetails); + } catch (AccountNotFoundException e) { + ui.showNoAccount(); + } + break; + case "withdraw": + try { + accountList.withdrawMoney(args); + ui.showWithdrawMessage(); + accountList.showBal(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } catch (InsufficientBalanceException e) { + ui.showInsufficientBalanceMessage(); + } + break; + case "help": + ui.showHelp(); + break; + case "delete": + accountList.deleteAccount(args); + break; + default: + throw new CommandNotFoundException(); } } From ec224cdfaaced0c21904e62233362f534f1e8543 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Wed, 22 Mar 2023 10:50:03 +0800 Subject: [PATCH 111/368] Modify the try-catch block to show different messages when catching different exceptions --- src/main/java/seedu/bankwithus/AccountList.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index bf52f96bd6..58a2afad37 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -3,6 +3,7 @@ import seedu.bankwithus.exceptions.AccountNotFoundException; import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; +import seedu.bankwithus.exceptions.SaveFileIsEmpty; import java.util.ArrayList; import java.util.Scanner; @@ -40,7 +41,11 @@ public AccountList(Scanner scanner, BankWithUs bwu) { try { parser.parseSavedFile(scanner); } catch (Exception e) { - ui.showEmptyFile(); + if (e.equals(new SaveFileIsEmpty())) { + ui.showEmptyFile(); + } else { + ui.showCorruptedSaveFileError(); + } createNewAccount(); } } From b4daf61e835253fd4e52e840ee31e115aa9a77a7 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Wed, 22 Mar 2023 12:52:24 +0800 Subject: [PATCH 112/368] Modify the text-ui-test files --- .gitignore | 2 +- src/main/java/seedu/bankwithus/Ui.java | 4 ++-- text-ui-test/EXPECTED.TXT | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 2873e189e1..90f9b46619 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,5 @@ src/main/resources/docs/ *.iml bin/ -/text-ui-test/ACTUAL.TXT +/text-ui-test/EXPECTED.TXT text-ui-test/EXPECTED-UNIX.TXT diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 4d08ea6077..ad0fe067d2 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -116,13 +116,13 @@ public void greet() { "| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$" + " $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/\n" + "| $$__ $$ /$$$$$$$| $$ \\ $$| $$$$$$/ | $$$$_ " + - "$$$$| $$ | $$ | $$ \\ $$| $$ | $$| $$$$$$ \n" + + "$$$$| $$ | $$ | $$ \\ $$| $$ | $$| $$$$$$\n" + "| $$ \\ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \\ " + "$$$| $$ | $$ /$$| $$ | $$| $$ | $$ \\____ $$\n" + "| $$$$$$$/| $$$$$$$| $$ | $$| $$ \\ $$| $$/ \\ " + " $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/\n" + "|_______/ \\_______/|__/ |__/|__/ \\__/|__/ " + - "\\__/|__/ \\___/ |__/ |__/ \\______/ |_______/ \n" + "\\__/|__/ \\___/ |__/ |__/ \\______/ |_______/\n" ); } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 2249763e31..856109277b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,7 @@ -Welcome to: +Welcome to: - /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ -| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ + /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ +| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ | $$ \ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$| $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$ | $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$ $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/ | $$__ $$ /$$$$$$$| $$ \ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \ $$| $$ | $$| $$$$$$ From 4fc93a3c31b7850c01f22ce9332ae926effccf82 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Wed, 22 Mar 2023 13:18:34 +0800 Subject: [PATCH 113/368] add multiple-account command allows user to have more than one account modify text-ui-test files --- src/main/java/seedu/bankwithus/Parser.java | 3 +++ src/main/java/seedu/bankwithus/Ui.java | 14 ++++++---- text-ui-test/EXPECTED.TXT | 30 +++++++++++++++++----- text-ui-test/input.txt | 4 +++ 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 4b4a65e44e..744eef5e4b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -88,6 +88,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showInsufficientBalanceMessage(); } break; + case "add-account": + accountList.createNewAccount(); + break; case "help": ui.showHelp(); break; diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index ad0fe067d2..001de40f4c 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -74,12 +74,15 @@ public void printLine() { } public void viewAccount(String accDetails) { - String name = accDetails.split(";")[0]; - String bal = accDetails.split(";")[1]; - printLine(); - System.out.println("Name: " + name); - System.out.println("Balance: $" + bal); + String[] accounts = accDetails.split("\\n"); printLine(); + 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(float finalBal) { @@ -172,6 +175,7 @@ public void showNumberOfAccount(int accSize) { public void showNewAddedAccount(Account acc) { printLine(); + System.out.println("Account created!"); System.out.println("Name: " + acc.getAccountName()); System.out.println("Balance: $" + acc.getAccountBalance()); printLine(); diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 856109277b..93ab171f53 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -22,6 +22,7 @@ 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 created! Name: hihi Balance: $1000.0 ---------------------------- @@ -36,42 +37,59 @@ Not a valid command! ---------------------------- Name: hihi Balance: $1000.0 - ---------------------------- Negative amount entered! The input is not a valid number! Please try again. ---------------------------- Name: hihi Balance: $1000.0 - ---------------------------- New deposit added! You have $1100.21 remaining! ---------------------------- Name: hihi Balance: $1100.21 - ---------------------------- Account is not found, please re-enter the account name ---------------------------- +What's your name? +How much would you like to add as Balance? +---------------------------- +Account created! +Name: sherlock +Balance: $123778.1 +---------------------------- +---------------------------- +Name: hihi +Balance: $1100.21 +---------------------------- +Name: sherlock +Balance: $123778.1 +---------------------------- You do not have sufficient Balance ---------------------------- Name: hihi Balance: $1100.21 - +---------------------------- +Name: sherlock +Balance: $123778.1 ---------------------------- The input is not a valid number! Please try again. ---------------------------- Name: hihi Balance: $1100.21 - +---------------------------- +Name: sherlock +Balance: $123778.1 ---------------------------- Withdrawal successful! You have $1000.20996 remaining! ---------------------------- Name: hihi Balance: $1000.20996 - +---------------------------- +Name: sherlock +Balance: $123778.1 ---------------------------- 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 0f8a590fd9..c7cae57b2d 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -13,6 +13,10 @@ view-account deposit 100.21 view-account delete sherlock +add-account +sherlock +123778.1 +view-account withdraw 100000 view-account withdraw dba From c0b617a5c03cb4b11844e617259d73e0aa1cf6db Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Thu, 23 Mar 2023 00:08:21 +0800 Subject: [PATCH 114/368] add switch account feature in ArrayList modify text-ui-test files and Ui add NoAccountException and OnlyOneAccount Ui --- data/save.txt | 0 .../java/seedu/bankwithus/AccountList.java | 26 ++++++++++-- src/main/java/seedu/bankwithus/Parser.java | 42 ++++++++++++------- src/main/java/seedu/bankwithus/Ui.java | 15 +++++-- .../exceptions/NoAccountException.java | 7 ++++ ...pty.java => SaveFileIsEmptyException.java} | 2 +- text-ui-test/EXPECTED.TXT | 31 ++++++-------- text-ui-test/input.txt | 2 +- 8 files changed, 83 insertions(+), 42 deletions(-) create mode 100644 data/save.txt create mode 100644 src/main/java/seedu/bankwithus/exceptions/NoAccountException.java rename src/main/java/seedu/bankwithus/exceptions/{SaveFileIsEmpty.java => SaveFileIsEmptyException.java} (61%) diff --git a/data/save.txt b/data/save.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 58a2afad37..82a6373993 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -3,9 +3,11 @@ import seedu.bankwithus.exceptions.AccountNotFoundException; import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; -import seedu.bankwithus.exceptions.SaveFileIsEmpty; +import seedu.bankwithus.exceptions.NoAccountException; +import seedu.bankwithus.exceptions.SaveFileIsEmptyException; import java.util.ArrayList; +import java.util.Collections; import java.util.Scanner; public class AccountList { @@ -35,13 +37,13 @@ public AccountList(BankWithUs bwu) { * @param bwu the main bankWithUs program */ public AccountList(Scanner scanner, BankWithUs bwu) { - accounts = new ArrayList(); + accounts = new ArrayList<>(); this.ui = bwu.getUi(); Parser parser = new Parser(this); try { parser.parseSavedFile(scanner); } catch (Exception e) { - if (e.equals(new SaveFileIsEmpty())) { + if (e.equals(new SaveFileIsEmptyException())) { ui.showEmptyFile(); } else { ui.showCorruptedSaveFileError(); @@ -190,4 +192,22 @@ public int getSize() { return accounts.size(); } + 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().contains(accName)) { + Collections.swap(accounts, i, 0); + ui.showMainAccountSwitched(); + return; + } + } + ui.showNoAccountFound(); + } + + } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 744eef5e4b..4dd6529a5b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -5,7 +5,8 @@ import seedu.bankwithus.exceptions.CorruptedSaveFileException; import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; -import seedu.bankwithus.exceptions.SaveFileIsEmpty; +import seedu.bankwithus.exceptions.NoAccountException; +import seedu.bankwithus.exceptions.SaveFileIsEmptyException; import java.io.IOException; import java.util.Scanner; @@ -91,6 +92,13 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "add-account": accountList.createNewAccount(); break; + case "switch-to": + try { + accountList.switchMainAccount(args); + } catch (NoAccountException e ){ + ui.showNoAccount(); + } + break; case "help": ui.showHelp(); break; @@ -110,22 +118,24 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce * @param scanner * @throws CorruptedSaveFileException if any of the parameters are corrupted */ - public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, SaveFileIsEmpty { - String accountDetails = scanner.nextLine(); - if (accountDetails.isBlank()) { - throw new SaveFileIsEmpty(); - } + public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, SaveFileIsEmptyException { try { - String[] splitDetails = accountDetails.split(";"); - String name = splitDetails[0].trim(); - String balanceString = splitDetails[1].trim(); - if (name.isEmpty() || balanceString.isEmpty()) { - throw new Exception(); - } - float balance = Float.parseFloat(balanceString); - accountList.addAccount(name, balance); - } catch (Exception e) { - throw new CorruptedSaveFileException(); + while (scanner.hasNextLine()) { + String accountDetails = scanner.nextLine(); + if (accountDetails.isBlank()) { + throw new SaveFileIsEmptyException(); + } + String[] splitDetails = accountDetails.split(";"); + String name = splitDetails[0].trim(); + String balanceString = splitDetails[1].trim(); + if (name.isEmpty() || balanceString.isEmpty()) { + throw new Exception(); + } + float balance = Float.parseFloat(balanceString); + accountList.addAccount(name, balance); + } + } catch (Exception ex) { + throw new RuntimeException(ex); } scanner.close(); } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 001de40f4c..dd2d1e11e1 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -75,7 +75,7 @@ public void printLine() { public void viewAccount(String accDetails) { String[] accounts = accDetails.split("\\n"); - printLine(); + System.out.println("MAIN Account:"); for (String account : accounts) { String name = account.split(";")[0]; String bal = account.split(";")[1]; @@ -95,10 +95,10 @@ public void showNegativeAmountError() { 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 account name and balance"); System.out.println("withdraw : withdraws from available balance"); @@ -155,7 +155,7 @@ public void showAccountDeleted(String name) { } public void showNoAccountFound() { - System.out.println("Account is not found, please re-enter the account name"); + System.out.println("Account is not found, please rectify the name"); printLine(); } @@ -181,4 +181,13 @@ public void showNewAddedAccount(Account acc) { printLine(); } + public void showThereIsOnlyOneAccount() { + System.out.println("There is only one account"); + printLine(); + } + + public void showMainAccountSwitched() { + System.out.println("Main Account switched"); + printLine(); + } } 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..e7bfac8d56 --- /dev/null +++ b/src/main/java/seedu/bankwithus/exceptions/NoAccountException.java @@ -0,0 +1,7 @@ +package seedu.bankwithus.exceptions; + +/** + * thrown when there is no account at all + */ +public class NoAccountException extends Exception { +} diff --git a/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmpty.java b/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java similarity index 61% rename from src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmpty.java rename to src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java index a95c67803c..1c91bc65b9 100644 --- a/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmpty.java +++ b/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java @@ -3,6 +3,6 @@ /** * Thrown when the saved file has no data */ -public class SaveFileIsEmpty extends Exception { +public class SaveFileIsEmptyException extends Exception { } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 93ab171f53..b300e0b1a2 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -26,7 +26,6 @@ Account created! Name: hihi Balance: $1000.0 ---------------------------- ----------------------------- help: displays the current menu view-account: shows account name and balance withdraw : withdraws from available balance @@ -34,23 +33,23 @@ deposit : deposits and adds deposit to balance exit: quits program and saves ---------------------------- Not a valid command! ----------------------------- +MAIN Account: Name: hihi Balance: $1000.0 ---------------------------- Negative amount entered! The input is not a valid number! Please try again. ----------------------------- +MAIN Account: Name: hihi Balance: $1000.0 ---------------------------- New deposit added! You have $1100.21 remaining! ----------------------------- +MAIN Account: Name: hihi Balance: $1100.21 ---------------------------- -Account is not found, please re-enter the account name +Account is not found, please rectify the name ---------------------------- What's your name? How much would you like to add as Balance? @@ -59,7 +58,7 @@ Account created! Name: sherlock Balance: $123778.1 ---------------------------- ----------------------------- +MAIN Account: Name: hihi Balance: $1100.21 ---------------------------- @@ -68,28 +67,24 @@ Balance: $123778.1 ---------------------------- You do not have sufficient Balance ---------------------------- -Name: hihi -Balance: $1100.21 +Main Account switched ---------------------------- +MAIN Account: Name: sherlock Balance: $123778.1 ---------------------------- -The input is not a valid number! Please try again. ----------------------------- Name: hihi Balance: $1100.21 ---------------------------- -Name: sherlock -Balance: $123778.1 ----------------------------- +The input is not a valid number! Please try again. Withdrawal successful! -You have $1000.20996 remaining! +You have $123678.1 remaining! +MAIN Account: +Name: sherlock +Balance: $123678.1 ---------------------------- Name: hihi -Balance: $1000.20996 ----------------------------- -Name: sherlock -Balance: $123778.1 +Balance: $1100.21 ---------------------------- 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 c7cae57b2d..e9663229b5 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -18,9 +18,9 @@ sherlock 123778.1 view-account withdraw 100000 +switch-to sherlock view-account withdraw dba -view-account withdraw 100 view-account From d658613b718315ac72c3b9ac495332e2d4c318b9 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Thu, 23 Mar 2023 00:13:30 +0800 Subject: [PATCH 115/368] correct Checkstyle error --- src/main/java/seedu/bankwithus/Parser.java | 124 ++++++++++----------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 4dd6529a5b..dfcbb11078 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -47,66 +47,66 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce 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 { - accountList.depositMoney(args); - ui.showDepositMessage(); - accountList.showBal(); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NullPointerException e) { - // Will almost never happen, but who knows - ui.showNullInputError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } - break; - case "view-account": - try { - String accDetails = accountList.getAllAccountDetails(); - ui.viewAccount(accDetails); - } catch (AccountNotFoundException e) { - ui.showNoAccount(); - } - break; - case "withdraw": - try { - accountList.withdrawMoney(args); - ui.showWithdrawMessage(); - accountList.showBal(); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } catch (InsufficientBalanceException e) { - ui.showInsufficientBalanceMessage(); - } - break; - case "add-account": - accountList.createNewAccount(); - break; - case "switch-to": - try { - accountList.switchMainAccount(args); - } catch (NoAccountException e ){ - ui.showNoAccount(); - } - break; - case "help": - ui.showHelp(); - break; - case "delete": - accountList.deleteAccount(args); - break; - default: - throw new CommandNotFoundException(); + case "exit": + try { + bwu.exit(); + } catch (IOException e) { + throw e; + } + break; + case "deposit": + try { + accountList.depositMoney(args); + ui.showDepositMessage(); + accountList.showBal(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NullPointerException e) { + // Will almost never happen, but who knows + ui.showNullInputError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } + break; + case "view-account": + try { + String accDetails = accountList.getAllAccountDetails(); + ui.viewAccount(accDetails); + } catch (AccountNotFoundException e) { + ui.showNoAccount(); + } + break; + case "withdraw": + try { + accountList.withdrawMoney(args); + ui.showWithdrawMessage(); + accountList.showBal(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } catch (InsufficientBalanceException e) { + ui.showInsufficientBalanceMessage(); + } + break; + case "add-account": + accountList.createNewAccount(); + break; + case "switch-to": + try { + accountList.switchMainAccount(args); + } catch (NoAccountException e) { + ui.showNoAccount(); + } + break; + case "help": + ui.showHelp(); + break; + case "delete": + accountList.deleteAccount(args); + break; + default: + throw new CommandNotFoundException(); } } @@ -133,8 +133,8 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S } float balance = Float.parseFloat(balanceString); accountList.addAccount(name, balance); - } - } catch (Exception ex) { + } + } catch (Exception ex) { throw new RuntimeException(ex); } scanner.close(); From 80e87b165df72285f630411ad26b32908589c772 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Thu, 23 Mar 2023 00:16:17 +0800 Subject: [PATCH 116/368] change indentation level --- src/main/java/seedu/bankwithus/Parser.java | 120 ++++++++++----------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index dfcbb11078..a743b14ebf 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -47,66 +47,66 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce 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 { - accountList.depositMoney(args); - ui.showDepositMessage(); - accountList.showBal(); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NullPointerException e) { - // Will almost never happen, but who knows - ui.showNullInputError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } - break; - case "view-account": - try { - String accDetails = accountList.getAllAccountDetails(); - ui.viewAccount(accDetails); - } catch (AccountNotFoundException e) { - ui.showNoAccount(); - } - break; - case "withdraw": - try { - accountList.withdrawMoney(args); - ui.showWithdrawMessage(); - accountList.showBal(); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } catch (InsufficientBalanceException e) { - ui.showInsufficientBalanceMessage(); - } - break; - case "add-account": - accountList.createNewAccount(); - break; - case "switch-to": - try { - accountList.switchMainAccount(args); - } catch (NoAccountException e) { - ui.showNoAccount(); - } - break; - case "help": - ui.showHelp(); - break; - case "delete": - accountList.deleteAccount(args); - break; - default: - throw new CommandNotFoundException(); + case "exit": + try { + bwu.exit(); + } catch (IOException e) { + throw e; + } + break; + case "deposit": + try { + accountList.depositMoney(args); + ui.showDepositMessage(); + accountList.showBal(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NullPointerException e) { + // Will almost never happen, but who knows + ui.showNullInputError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } + break; + case "view-account": + try { + String accDetails = accountList.getAllAccountDetails(); + ui.viewAccount(accDetails); + } catch (AccountNotFoundException e) { + ui.showNoAccount(); + } + break; + case "withdraw": + try { + accountList.withdrawMoney(args); + ui.showWithdrawMessage(); + accountList.showBal(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } catch (InsufficientBalanceException e) { + ui.showInsufficientBalanceMessage(); + } + break; + case "add-account": + accountList.createNewAccount(); + break; + case "switch-to": + try { + accountList.switchMainAccount(args); + } catch (NoAccountException e) { + ui.showNoAccount(); + } + break; + case "help": + ui.showHelp(); + break; + case "delete": + accountList.deleteAccount(args); + break; + default: + throw new CommandNotFoundException(); } } From 096443931ec651ff8a4f4fe8aecbbc307f44816d Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Thu, 23 Mar 2023 09:55:33 +0800 Subject: [PATCH 117/368] Tidy up the codes --- .../java/seedu/bankwithus/AccountList.java | 14 ++++---- src/main/java/seedu/bankwithus/Parser.java | 33 +++++++++---------- src/main/java/seedu/bankwithus/Ui.java | 4 +-- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 82a6373993..2bc1884d2c 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -1,6 +1,7 @@ package seedu.bankwithus; import seedu.bankwithus.exceptions.AccountNotFoundException; +import seedu.bankwithus.exceptions.CorruptedSaveFileException; import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; import seedu.bankwithus.exceptions.NoAccountException; @@ -42,12 +43,11 @@ public AccountList(Scanner scanner, BankWithUs bwu) { Parser parser = new Parser(this); try { parser.parseSavedFile(scanner); - } catch (Exception e) { - if (e.equals(new SaveFileIsEmptyException())) { - ui.showEmptyFile(); - } else { - ui.showCorruptedSaveFileError(); - } + } catch (CorruptedSaveFileException e) { + ui.showCorruptedSaveFileError(); + createNewAccount(); + } catch (SaveFileIsEmptyException e) { + ui.showEmptyFile(); createNewAccount(); } } @@ -118,7 +118,7 @@ private float askUserForBalance() { public void addAccount(String name, float balance) { Account newAccount = new Account(name, balance); accounts.add(newAccount); - ui.showNewAddedAccount(newAccount); + ui.showNewAccountAdded(newAccount); } /** diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index a743b14ebf..8f7c0898dd 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -73,7 +73,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce String accDetails = accountList.getAllAccountDetails(); ui.viewAccount(accDetails); } catch (AccountNotFoundException e) { - ui.showNoAccount(); + ui.showAccountNotFound(); } break; case "withdraw": @@ -96,7 +96,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce try { accountList.switchMainAccount(args); } catch (NoAccountException e) { - ui.showNoAccount(); + ui.showAccountNotFound(); } break; case "help": @@ -119,24 +119,21 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce * @throws CorruptedSaveFileException if any of the parameters are corrupted */ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, SaveFileIsEmptyException { - try { - while (scanner.hasNextLine()) { - String accountDetails = scanner.nextLine(); - if (accountDetails.isBlank()) { - throw new SaveFileIsEmptyException(); - } - String[] splitDetails = accountDetails.split(";"); - String name = splitDetails[0].trim(); - String balanceString = splitDetails[1].trim(); - if (name.isEmpty() || balanceString.isEmpty()) { - throw new Exception(); - } - float balance = Float.parseFloat(balanceString); - accountList.addAccount(name, balance); + while (scanner.hasNextLine()) { + String accountDetails = scanner.nextLine(); + if (accountDetails.isBlank()) { + throw new SaveFileIsEmptyException(); } - } catch (Exception ex) { - throw new RuntimeException(ex); + String[] splitDetails = accountDetails.split(";"); + String name = splitDetails[0].trim(); + String balanceString = splitDetails[1].trim(); + if (name.isEmpty() || balanceString.isEmpty()) { + throw new CorruptedSaveFileException(); + } + float balance = Float.parseFloat(balanceString); + accountList.addAccount(name, balance); } + scanner.close(); } } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index dd2d1e11e1..0be1d7f455 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -159,7 +159,7 @@ public void showNoAccountFound() { printLine(); } - public void showNoAccount() { + public void showAccountNotFound() { System.out.println("There is no account"); printLine(); } @@ -173,7 +173,7 @@ public void showNumberOfAccount(int accSize) { System.out.println("Found " + accSize + " Account"); } - public void showNewAddedAccount(Account acc) { + public void showNewAccountAdded(Account acc) { printLine(); System.out.println("Account created!"); System.out.println("Name: " + acc.getAccountName()); From adcde0de062eda2a30082b3a5f671d4aa4af58e7 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Thu, 23 Mar 2023 12:38:01 +0800 Subject: [PATCH 118/368] change the attribute balance to String type --- data/save.txt | 0 src/main/java/seedu/bankwithus/Account.java | 20 ++++++++++++------- .../java/seedu/bankwithus/AccountList.java | 20 +++++++++---------- src/main/java/seedu/bankwithus/Parser.java | 7 ++++--- src/main/java/seedu/bankwithus/Ui.java | 5 +++-- text-ui-test/EXPECTED.TXT | 6 +++--- 6 files changed, 33 insertions(+), 25 deletions(-) delete mode 100644 data/save.txt diff --git a/data/save.txt b/data/save.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index a3cd3bbd8d..0ff7e2ea08 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -1,8 +1,10 @@ package seedu.bankwithus; +import java.text.DecimalFormat; + public class Account { private String name; - private float balance; + private String balance; /** * Instantiates an account object @@ -10,7 +12,7 @@ public class Account { * @param name initialise in the name of the account * @param balance initialise the balance of the account */ - public Account(String name, float balance) { + public Account(String name, String balance) { this.name = name; this.balance = balance; } @@ -19,15 +21,19 @@ public String getAccountName() { return name; } - public float getAccountBalance() { + public String getAccountBalance() { return balance; } - public void addBalance(float balance) { - this.balance += balance; + public void addBalance(float balanceToBeAdded) { + DecimalFormat df = new DecimalFormat("#.##"); + String formatted = df.format(Float.parseFloat(balance) + balanceToBeAdded); + this.balance = String.valueOf(formatted); } - public void subtractBalance(float balance) { - this.balance -= balance; + public void subtractBalance(float currentBalance, float withdrawal) { + DecimalFormat df = new DecimalFormat("#.##"); + String formatted = df.format(currentBalance - withdrawal); + this.balance = String.valueOf(formatted); } } diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 2bc1884d2c..700c17fad4 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -57,7 +57,7 @@ public AccountList(Scanner scanner, BankWithUs bwu) { * * @return */ - public Account getCurrentAccount() { + public Account getMainAccount() { return accounts.get(0); } @@ -90,16 +90,16 @@ private String askUserForName() { * * @return balance in the form of a float */ - private float askUserForBalance() { + private String askUserForBalance() { ui.askForBalance(); String balanceString = ui.getNextLine(); - balanceString.trim(); + balanceString = balanceString.trim(); try { float balance = Float.parseFloat(balanceString); if (balance < 0) { throw new NegativeAmountException(); } - return balance; + return balanceString; } catch (NumberFormatException e) { ui.showNumberFormatError(); return askUserForBalance(); @@ -115,7 +115,7 @@ private float askUserForBalance() { * @param name Name of the new account to be added * @param balance Balance of the new account to be added */ - public void addAccount(String name, float balance) { + public void addAccount(String name, String balance) { Account newAccount = new Account(name, balance); accounts.add(newAccount); ui.showNewAccountAdded(newAccount); @@ -126,7 +126,7 @@ public void addAccount(String name, float balance) { */ public void createNewAccount() { String userName = askUserForName(); - float balance = askUserForBalance(); + String balance = askUserForBalance(); addAccount(userName, balance); } @@ -149,7 +149,7 @@ public String getAllAccountDetails() throws AccountNotFoundException { } public void showBal() { - float balance = getCurrentAccount().getAccountBalance(); + String balance = getMainAccount().getAccountBalance(); ui.showBal(balance); } @@ -159,7 +159,7 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio if (depositAmount < 0) { throw new NegativeAmountException(); } else { - getCurrentAccount().addBalance(depositAmount); + getMainAccount().addBalance(depositAmount); } } @@ -169,11 +169,11 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept if (withdrawAmount < 0) { throw new NegativeAmountException(); } - float currentBalance = getCurrentAccount().getAccountBalance(); + float currentBalance = Float.parseFloat(getMainAccount().getAccountBalance()); if (currentBalance < withdrawAmount) { throw new InsufficientBalanceException(); } else { - getCurrentAccount().subtractBalance(withdrawAmount); + getMainAccount().subtractBalance(currentBalance,withdrawAmount); } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 8f7c0898dd..fdcf250373 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -130,10 +130,11 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S if (name.isEmpty() || balanceString.isEmpty()) { throw new CorruptedSaveFileException(); } - float balance = Float.parseFloat(balanceString); - accountList.addAccount(name, balance); + accountList.addAccount(name, balanceString); } - scanner.close(); + if (accountList.getSize() == 0){ + throw new SaveFileIsEmptyException(); + } } } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 0be1d7f455..2583f991dc 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -85,8 +85,8 @@ public void viewAccount(String accDetails) { } } - public void showBal(float finalBal) { - System.out.println("You have $" + String.valueOf(finalBal) + " remaining!"); + public void showBal(String finalBal) { + System.out.println("You have $" + finalBal + " remaining!"); } public void showNegativeAmountError() { @@ -171,6 +171,7 @@ public void showEmptyFile() { public void showNumberOfAccount(int accSize) { System.out.println("Found " + accSize + " Account"); + printLine(); } public void showNewAccountAdded(Account acc) { diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index b300e0b1a2..2f18acc8f1 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -24,7 +24,7 @@ How much would you like to add as Balance? ---------------------------- Account created! Name: hihi -Balance: $1000.0 +Balance: $1000 ---------------------------- help: displays the current menu view-account: shows account name and balance @@ -35,13 +35,13 @@ exit: quits program and saves Not a valid command! MAIN Account: Name: hihi -Balance: $1000.0 +Balance: $1000 ---------------------------- Negative amount entered! The input is not a valid number! Please try again. MAIN Account: Name: hihi -Balance: $1000.0 +Balance: $1000 ---------------------------- New deposit added! You have $1100.21 remaining! From 3fcc50ee1f6b4d8cc72ab070844f61d5bac50951 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 12:48:50 +0800 Subject: [PATCH 119/368] Modify git ignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 90f9b46619..bf5b078f8c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,7 @@ src/main/resources/docs/ *.iml bin/ -/text-ui-test/EXPECTED.TXT +data +data/save.txt +text-ui-test/ACTUAL.TXT text-ui-test/EXPECTED-UNIX.TXT From fc0f638c3925b444c857ab44f6be29821bc2ca16 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Thu, 23 Mar 2023 12:53:05 +0800 Subject: [PATCH 120/368] add authorship for Sherlock-YH --- src/main/java/seedu/bankwithus/Account.java | 7 ++++--- src/main/java/seedu/bankwithus/AccountList.java | 11 +++++++---- src/main/java/seedu/bankwithus/BankWithUs.java | 3 ++- src/main/java/seedu/bankwithus/Parser.java | 2 +- src/main/java/seedu/bankwithus/Storage.java | 1 + src/main/java/seedu/bankwithus/Ui.java | 14 +++++++------- .../exceptions/AccountNotFoundException.java | 1 + .../bankwithus/exceptions/NoAccountException.java | 1 + .../exceptions/SaveFileIsEmptyException.java | 1 + 9 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 0ff7e2ea08..f551f4baf1 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -6,6 +6,7 @@ public class Account { private String name; private String balance; + //@@author Sherlock-YH /** * Instantiates an account object * @@ -16,15 +17,15 @@ public Account(String name, String balance) { this.name = name; this.balance = balance; } - + //@@author Sherlock-YH public String getAccountName() { return name; } - + //@@author Sherlock-YH public String getAccountBalance() { return balance; } - + //@@author public void addBalance(float balanceToBeAdded) { DecimalFormat df = new DecimalFormat("#.##"); String formatted = df.format(Float.parseFloat(balance) + balanceToBeAdded); diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 700c17fad4..6bed9dba79 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -108,7 +108,7 @@ private String askUserForBalance() { return askUserForBalance(); } } - + //@@author Sherlock-YH /** * Creates a new account and adds it to the AccountList. * @@ -120,7 +120,7 @@ public void addAccount(String name, String balance) { accounts.add(newAccount); ui.showNewAccountAdded(newAccount); } - + //@@author /** * Creates a new Account for a first time user */ @@ -129,7 +129,7 @@ public void createNewAccount() { String balance = askUserForBalance(); addAccount(userName, balance); } - + //@@author Sherlock-YH /** * Name and balance are separated by ; prepared to be saved * @@ -147,7 +147,7 @@ public String getAllAccountDetails() throws AccountNotFoundException { return temp.toString(); } } - + //@@author public void showBal() { String balance = getMainAccount().getAccountBalance(); ui.showBal(balance); @@ -177,6 +177,7 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept } } + //@@author Sherlock-YH public void deleteAccount(String name) { for (Account acc : accounts) { if (acc.getAccountName().contains(name)) { @@ -188,10 +189,12 @@ public void deleteAccount(String name) { ui.showNoAccountFound(); } + //@@author Sherlock-YH public int getSize() { return accounts.size(); } + //@@author Sherlock-YH public void switchMainAccount(String accName) throws NoAccountException { //swap acc to the head of AccountList if (accounts.size() == 0) { diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 570192d890..62f89e952a 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -56,6 +56,7 @@ public Ui getUi() { return ui; } + //@@author Sherlock-YH /** * Exit the programme, save the data and show farewell message * @@ -72,7 +73,7 @@ public void exit() throws IOException { throw e; } } - + //@@author /** * The main command and output loop. Takes in user input line by line * and gives it to the parser to execute the command. diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index fdcf250373..d0691ab8e0 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -109,7 +109,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce throw new CommandNotFoundException(); } } - + //@@author Sherlock-YH /** * Parses the save file. Takes in the scanner to the save file, * and splits the name and balance by ; character. Part of diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/Storage.java index 49c8eccec6..237616bbca 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/Storage.java @@ -45,6 +45,7 @@ public void createNewFile() throws IOException { ui.showFileCreated(); } + //@@author Sherlock-YH /** * This method saves all account details to data/save.txt * diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 2583f991dc..6974a168f3 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -148,17 +148,17 @@ public void showCorruptedSaveFileError() { public void showForbiddenCharacterError() { System.out.println("Please do not put the chacter ';' 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(); @@ -168,12 +168,12 @@ 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) { printLine(); System.out.println("Account created!"); @@ -181,12 +181,12 @@ public void showNewAccountAdded(Account acc) { 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("Main Account switched"); printLine(); diff --git a/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java b/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java index 0b6f2f4378..b71278dfc5 100644 --- a/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java +++ b/src/main/java/seedu/bankwithus/exceptions/AccountNotFoundException.java @@ -1,5 +1,6 @@ package seedu.bankwithus.exceptions; +//@@author Sherlock-YH public class AccountNotFoundException extends Exception { } diff --git a/src/main/java/seedu/bankwithus/exceptions/NoAccountException.java b/src/main/java/seedu/bankwithus/exceptions/NoAccountException.java index e7bfac8d56..6e70aeeaf5 100644 --- a/src/main/java/seedu/bankwithus/exceptions/NoAccountException.java +++ b/src/main/java/seedu/bankwithus/exceptions/NoAccountException.java @@ -1,5 +1,6 @@ package seedu.bankwithus.exceptions; +//@@author Sherlock-YH /** * thrown when there is no account at all */ diff --git a/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java b/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java index 1c91bc65b9..d015cb7717 100644 --- a/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java +++ b/src/main/java/seedu/bankwithus/exceptions/SaveFileIsEmptyException.java @@ -1,5 +1,6 @@ package seedu.bankwithus.exceptions; +//@@author Sherlock-YH /** * Thrown when the saved file has no data */ From ea3954c7002bab5282c6fc5ebc2d3f1a47a19aae Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 17:31:41 +0800 Subject: [PATCH 121/368] Add update total amount withdrawn method --- src/main/java/seedu/bankwithus/Account.java | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index f551f4baf1..490704eed1 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -1,10 +1,13 @@ package seedu.bankwithus; import java.text.DecimalFormat; +import java.time.LocalDate; public class Account { private String name; private String balance; + private String totalAmtWithdrawn; + private LocalDate lastWithdrawnDate; //@@author Sherlock-YH /** @@ -36,5 +39,28 @@ public void subtractBalance(float currentBalance, float withdrawal) { DecimalFormat df = new DecimalFormat("#.##"); String formatted = df.format(currentBalance - withdrawal); this.balance = String.valueOf(formatted); + updateTotalAmtWithdrawn(withdrawal); + } + + //@@author tyuyang + private void updateTotalAmtWithdrawn(float withdrawal) { + LocalDate currentDate = LocalDate.now(); + DecimalFormat df = new DecimalFormat("#.##"); + if (lastWithdrawnDate == null) { + lastWithdrawnDate = currentDate; + String formatted = df.format(withdrawal); + totalAmtWithdrawn = String.valueOf(formatted); + return; + } + assert totalAmtWithdrawn != null; + if (lastWithdrawnDate.getMonth() == currentDate.getMonth() && + lastWithdrawnDate.getYear() == currentDate.getYear()) { + String formatted = df.format(Float.parseFloat(totalAmtWithdrawn) + withdrawal); + totalAmtWithdrawn = String.valueOf(formatted); + } else { + String formatted = df.format(withdrawal); + totalAmtWithdrawn = String.valueOf(formatted); + } + lastWithdrawnDate = currentDate; } } From 4f20ad903adfe1da846accc58c53305368f26c8e Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 19:51:36 +0800 Subject: [PATCH 122/368] Add authorship --- src/main/java/seedu/bankwithus/AccountList.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 6bed9dba79..bd72d73175 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -153,6 +153,7 @@ public void showBal() { ui.showBal(balance); } + //@@author xiaoge26 public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException, NegativeAmountException { float depositAmount = Float.parseFloat(depositAmountString); @@ -163,6 +164,7 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio } } + //@@author public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, NegativeAmountException, InsufficientBalanceException { float withdrawAmount = Float.parseFloat(withdrawAmountString); From 5096ae597340aef27c2a7bf0482ea7df25178d7c Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 21:08:50 +0800 Subject: [PATCH 123/368] Fix accountList tests --- src/main/java/seedu/bankwithus/Account.java | 9 ++ .../java/seedu/bankwithus/AccountList.java | 73 ++++++++++-- src/main/java/seedu/bankwithus/Parser.java | 10 +- .../seedu/bankwithus/AccountListTest.java | 109 ++++++++++-------- 4 files changed, 144 insertions(+), 57 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index f551f4baf1..d76647bdf0 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -37,4 +37,13 @@ public void subtractBalance(float currentBalance, float withdrawal) { String formatted = df.format(currentBalance - withdrawal); this.balance = String.valueOf(formatted); } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index bd72d73175..1b0d6e3ff4 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -27,6 +27,14 @@ public AccountList(BankWithUs bwu) { 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 @@ -108,27 +116,70 @@ private String askUserForBalance() { return askUserForBalance(); } } - //@@author Sherlock-YH + + public boolean isFloat(String str) { + try { + Float.parseFloat(str); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + public boolean isNegative(String str) { + return Float.parseFloat(str) < 0; + } + + public boolean isBlank(String str) { + return str.isBlank(); + } + + + //@@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 */ - public void addAccount(String name, String balance) { - Account newAccount = new Account(name, balance); - accounts.add(newAccount); - ui.showNewAccountAdded(newAccount); + public void addAccount(String name, String balance) throws NumberFormatException, + NullPointerException, NegativeAmountException { + if (isBlank(name)) { + throw new NullPointerException(); + } else if (isFloat(balance)) { + if (isNegative(balance)) { + throw new NegativeAmountException(); + } + Account newAccount = new Account(name, balance); + accounts.add(newAccount); + ui.showNewAccountAdded(newAccount); + } else { + throw new NumberFormatException(); + } + } - //@@author + + //@@author vishnuvk47 /** * Creates a new Account for a first time user */ public void createNewAccount() { String userName = askUserForName(); String balance = askUserForBalance(); - addAccount(userName, balance); + try { + addAccount(userName, balance); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + createNewAccount(); + } catch (NullPointerException e) { + ui.showBlankUserNameError(); + createNewAccount(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + createNewAccount(); + } } + //@@author Sherlock-YH /** * Name and balance are separated by ; prepared to be saved @@ -147,6 +198,7 @@ public String getAllAccountDetails() throws AccountNotFoundException { return temp.toString(); } } + //@@author public void showBal() { String balance = getMainAccount().getAccountBalance(); @@ -213,6 +265,13 @@ public void switchMainAccount(String accName) throws NoAccountException { } ui.showNoAccountFound(); } + } + public ArrayList getAccounts() { + return accounts; + } + public void setAccounts(ArrayList accounts) { + this.accounts = accounts; } + } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index d0691ab8e0..72ea630418 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -130,7 +130,15 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S if (name.isEmpty() || balanceString.isEmpty()) { throw new CorruptedSaveFileException(); } - accountList.addAccount(name, balanceString); + try { + accountList.addAccount(name, balanceString); + } catch (NumberFormatException e) { + throw new CorruptedSaveFileException(); + } catch (NegativeAmountException e) { + throw new CorruptedSaveFileException(); + } catch (NullPointerException e) { + throw new CorruptedSaveFileException(); + } } scanner.close(); if (accountList.getSize() == 0){ diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 5a89830f36..3ca4f71c79 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,58 +1,69 @@ package seedu.bankwithus; -// import org.junit.jupiter.api.Test; -// import seedu.bankwithus.exceptions.NegativeAmountException; + import org.junit.jupiter.api.Test; + import seedu.bankwithus.exceptions.CorruptedSaveFileException; + import seedu.bankwithus.exceptions.NegativeAmountException; -// import static org.junit.jupiter.api.Assertions.assertEquals; -// import static org.junit.jupiter.api.Assertions.assertThrows; + import static org.junit.jupiter.api.Assertions.assertEquals; + import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { + Ui ui = new Ui(); + @Test + void addAccount_invalidBalance_expectException() throws NumberFormatException { + String name = "Bob"; + String balanceString = "abc"; + AccountList accountList = new AccountList(); + assertThrows(NumberFormatException.class, + () -> accountList.addAccount(name, balanceString)); + } - // @Test - // void addAccount_invalidBalance_expectException() throws NumberFormatException { - // String name = "Bob"; - // String balanceString = "abc"; - // AccountList accountList = new AccountList(); - // assertThrows(NumberFormatException.class, - // () -> accountList.addAccount(name, balanceString)); - // } + @Test + void depositMoney_invalidAmount_expectException() throws NumberFormatException { + String amountString = "abc"; + String name = "Bob"; + String balance = "0"; + AccountList accountList = new AccountList(); + try { + accountList.addAccount(name, balance); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NullPointerException e) { + ui.showNullInputError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } + assertThrows(NumberFormatException.class, + () -> accountList.depositMoney(amountString)); + } - // @Test - // void depositMoney_invalidAmount_expectException() throws NumberFormatException { - // 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_validAmount_expectDeposit() { + String amountString = "100.5"; + String name = "Bob"; + String balance = "100.5"; + AccountList accountList = new AccountList(); + Ui ui = new Ui(); + try { + accountList.addAccount(name, balance); + accountList.depositMoney(amountString); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NullPointerException e) { + ui.showNullInputError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } + assertEquals("201", accountList.getMainAccount().getAccountBalance()); + } - // @Test - // void depositMoney_validAmount_expectDeposit() { - // String amountString = "100.5"; - // String name = "Bob"; - // String balance = "100.5"; - // AccountList accountList = new AccountList(); - // accountList.addAccount(name, balance); - // Ui screen = new Ui(); - // try { - // accountList.depositMoney(amountString); - // } catch (NumberFormatException e) { - // screen.showNumberFormatError(); - // } catch (NullPointerException e) { - // screen.showNullInputError(); - // } catch (NegativeAmountException e) { - // screen.showNegativeAmountError(); - // } - // assertEquals(201, accountList.getCurrentAccount().getAccountBalance()); - // } - - // @Test - // void testingAddAccount() { - // AccountList TestAccountList = new AccountList(); - // TestAccountList.addAccount("Jane", "1000"); - // assertEquals("Jane", TestAccountList.accounts.get(0).name); - // assertEquals(1000.0, TestAccountList.accounts.get(0).balance); - // } + /** + @Test + void testingAddAccount() { + AccountList TestAccountList = new AccountList(); + TestAccountList.addAccount("Jane", "1000"); + assertEquals("Jane", TestAccountList.getMainAccount().getName()); + assertEquals("1000", TestAccountList.getMainAccount().getAccountBalance()); + } + **/ } From 2f03a6a6185140f98d4510e1fdee2120b1a9656a Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 21:16:34 +0800 Subject: [PATCH 124/368] Extract withdrawal checker class, add documentation and tests --- src/main/java/seedu/bankwithus/Account.java | 36 ++++------- .../seedu/bankwithus/WithdrawalChecker.java | 60 +++++++++++++++++++ .../bankwithus/WithdrawalCheckerTest.java | 29 +++++++++ 3 files changed, 101 insertions(+), 24 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/WithdrawalChecker.java create mode 100644 src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 490704eed1..f5903cb553 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -6,8 +6,7 @@ public class Account { private String name; private String balance; - private String totalAmtWithdrawn; - private LocalDate lastWithdrawnDate; + private WithdrawalChecker withdrawalChecker; //@@author Sherlock-YH /** @@ -19,6 +18,15 @@ public class Account { public Account(String name, String balance) { this.name = name; this.balance = balance; + this.withdrawalChecker = new WithdrawalChecker(); + } + + //@@author tyuyang + public Account(String name, String balance, String totalAmtWithdrawn, + LocalDate lastWithdrawnDate) { + this.name = name; + this.balance = balance; + this.withdrawalChecker = new WithdrawalChecker(totalAmtWithdrawn, lastWithdrawnDate); } //@@author Sherlock-YH public String getAccountName() { @@ -39,28 +47,8 @@ public void subtractBalance(float currentBalance, float withdrawal) { DecimalFormat df = new DecimalFormat("#.##"); String formatted = df.format(currentBalance - withdrawal); this.balance = String.valueOf(formatted); - updateTotalAmtWithdrawn(withdrawal); - } - //@@author tyuyang - private void updateTotalAmtWithdrawn(float withdrawal) { - LocalDate currentDate = LocalDate.now(); - DecimalFormat df = new DecimalFormat("#.##"); - if (lastWithdrawnDate == null) { - lastWithdrawnDate = currentDate; - String formatted = df.format(withdrawal); - totalAmtWithdrawn = String.valueOf(formatted); - return; - } - assert totalAmtWithdrawn != null; - if (lastWithdrawnDate.getMonth() == currentDate.getMonth() && - lastWithdrawnDate.getYear() == currentDate.getYear()) { - String formatted = df.format(Float.parseFloat(totalAmtWithdrawn) + withdrawal); - totalAmtWithdrawn = String.valueOf(formatted); - } else { - String formatted = df.format(withdrawal); - totalAmtWithdrawn = String.valueOf(formatted); - } - lastWithdrawnDate = currentDate; + withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); } + } diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java new file mode 100644 index 0000000000..9aca352312 --- /dev/null +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -0,0 +1,60 @@ +package seedu.bankwithus; + +import java.text.DecimalFormat; +import java.time.LocalDate; + +public class WithdrawalChecker { + private String totalAmtWithdrawn; + private LocalDate lastWithdrawnDate; + + /** + * Instantiates withdrawalChecker without any amount withdrawn + */ + public WithdrawalChecker() { + this.totalAmtWithdrawn = "0"; + } + + /** + * 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) { + this.totalAmtWithdrawn = totalAmtWithdrawn; + this.lastWithdrawnDate = lastWithdrawnDate; + } + + 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(float withdrawal) { + LocalDate currentDate = LocalDate.now(); + DecimalFormat df = new DecimalFormat("#.##"); + if (lastWithdrawnDate == null) { + lastWithdrawnDate = currentDate; + String formatted = df.format(withdrawal); + totalAmtWithdrawn = String.valueOf(formatted); + return; + } + assert totalAmtWithdrawn != null; + if (lastWithdrawnDate.getMonth() == currentDate.getMonth() && + lastWithdrawnDate.getYear() == currentDate.getYear()) { + String formatted = df.format(Float.parseFloat(totalAmtWithdrawn) + withdrawal); + totalAmtWithdrawn = String.valueOf(formatted); + } else { + String formatted = df.format(withdrawal); + totalAmtWithdrawn = String.valueOf(formatted); + } + lastWithdrawnDate = currentDate; + } +} diff --git a/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java b/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java new file mode 100644 index 0000000000..55fcdb58cc --- /dev/null +++ b/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java @@ -0,0 +1,29 @@ +package seedu.bankwithus; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; + +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((float) 10.1)); + assertEquals("10.1", wcNoWithdrawals.getTotalAmtWithdrawn()); + + //test with prior withdrawals + assertDoesNotThrow(() -> wcNoWithdrawals.updateTotalAmtWithdrawn((float) 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((float) 1.11)); + assertEquals("1.11", wcWithWithdrawals.getTotalAmtWithdrawn()); + } +} From de207d4f3fd6047da9e1f35c4580337e3b782441 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Thu, 23 Mar 2023 21:22:52 +0800 Subject: [PATCH 125/368] Changed MAIN account to Current Account and added a method in UI to display which account user switched to --- src/main/java/seedu/bankwithus/AccountList.java | 1 + src/main/java/seedu/bankwithus/Ui.java | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 6bed9dba79..37d479fc08 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -206,6 +206,7 @@ public void switchMainAccount(String accName) throws NoAccountException { if (accounts.get(i).getAccountName().contains(accName)) { Collections.swap(accounts, i, 0); ui.showMainAccountSwitched(); + ui.showCurrentAccount(accounts.get(0)); return; } } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 6974a168f3..7bfa271a2b 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -75,7 +75,7 @@ public void printLine() { public void viewAccount(String accDetails) { String[] accounts = accDetails.split("\\n"); - System.out.println("MAIN Account:"); + System.out.println("Current Account:"); for (String account : accounts) { String name = account.split(";")[0]; String bal = account.split(";")[1]; @@ -188,7 +188,16 @@ public void showThereIsOnlyOneAccount() { } //@@author Sherlock-YH public void showMainAccountSwitched() { - System.out.println("Main Account switched"); + printLine(); + 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(); } } From cdb34933d09f9a0b7042f0503a7ebe43f3a9d8d4 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 21:54:06 +0800 Subject: [PATCH 126/368] Add feature to save withdrawal information into savefile --- src/main/java/seedu/bankwithus/Account.java | 8 +++++++- src/main/java/seedu/bankwithus/AccountList.java | 13 +++++++++++++ src/main/java/seedu/bankwithus/Parser.java | 17 +++++++++++++++-- .../seedu/bankwithus/WithdrawalChecker.java | 9 +++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index f5903cb553..9d01d435a4 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -36,13 +36,19 @@ public String getAccountName() { public String getAccountBalance() { return balance; } - //@@author + + //@@author tyuyang + public WithdrawalChecker getWithdrawalChecker() { + return withdrawalChecker; + } + //@@author xiaoge26 public void addBalance(float balanceToBeAdded) { DecimalFormat df = new DecimalFormat("#.##"); String formatted = df.format(Float.parseFloat(balance) + balanceToBeAdded); this.balance = String.valueOf(formatted); } + //@@author manushridiv public void subtractBalance(float currentBalance, float withdrawal) { DecimalFormat df = new DecimalFormat("#.##"); String formatted = df.format(currentBalance - withdrawal); diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 6bed9dba79..9ed2a2a22f 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -7,6 +7,7 @@ import seedu.bankwithus.exceptions.NoAccountException; import seedu.bankwithus.exceptions.SaveFileIsEmptyException; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Collections; import java.util.Scanner; @@ -120,6 +121,14 @@ public void addAccount(String name, String balance) { accounts.add(newAccount); ui.showNewAccountAdded(newAccount); } + + //@@author tyuyang + public void addAccount(String name, String balance, String totalAmtWithdrawn, + LocalDate lastWithdrawnDate) { + Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate); + accounts.add(newAccount); + ui.showNewAccountAdded(newAccount); + } //@@author /** * Creates a new Account for a first time user @@ -142,6 +151,8 @@ public String getAllAccountDetails() throws AccountNotFoundException { 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()); temp.append("\n"); } return temp.toString(); @@ -153,6 +164,7 @@ public void showBal() { ui.showBal(balance); } + //@@author xiaoge26 public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException, NegativeAmountException { float depositAmount = Float.parseFloat(depositAmountString); @@ -163,6 +175,7 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio } } + //@@author manushridiv public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, NegativeAmountException, InsufficientBalanceException { float withdrawAmount = Float.parseFloat(withdrawAmountString); diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index d0691ab8e0..ca951549ee 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -9,6 +9,7 @@ import seedu.bankwithus.exceptions.SaveFileIsEmptyException; import java.io.IOException; +import java.time.LocalDate; import java.util.Scanner; public class Parser { @@ -127,10 +128,22 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S String[] splitDetails = accountDetails.split(";"); String name = splitDetails[0].trim(); String balanceString = splitDetails[1].trim(); - if (name.isEmpty() || balanceString.isEmpty()) { + String totalAmtWithdrawn = splitDetails[2].trim(); + String lastWithdrawnDate = splitDetails[3].trim(); + if (name.isEmpty() || balanceString.isEmpty() || totalAmtWithdrawn.isEmpty()) { throw new CorruptedSaveFileException(); } - accountList.addAccount(name, balanceString); + try { + if (lastWithdrawnDate.isEmpty()) { + //if no history of withdrawing + accountList.addAccount(name, balanceString); + } else { + accountList.addAccount(name, balanceString, totalAmtWithdrawn, + LocalDate.parse(lastWithdrawnDate)); + } + } catch (Exception e) { + throw new CorruptedSaveFileException(); + } } scanner.close(); if (accountList.getSize() == 0){ diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java index 9aca352312..21fbf75a2a 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -57,4 +57,13 @@ public void updateTotalAmtWithdrawn(float withdrawal) { } lastWithdrawnDate = currentDate; } + + @Override + public String toString() { + if (lastWithdrawnDate == null) { + return totalAmtWithdrawn; + } else { + return totalAmtWithdrawn + ";" + lastWithdrawnDate.toString(); + } + } } From f96f927b5bf0631559140d4b07d7d5af3dff7f83 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 21:58:54 +0800 Subject: [PATCH 127/368] Add more tests for accountList class --- .../java/seedu/bankwithus/AccountList.java | 48 ++--------------- src/main/java/seedu/bankwithus/Parser.java | 11 +--- .../seedu/bankwithus/AccountListTest.java | 51 +++++++++---------- 3 files changed, 30 insertions(+), 80 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 1b0d6e3ff4..094b564cc2 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -76,7 +76,7 @@ public Account getMainAccount() { * * @return the userName String */ - private String askUserForName() { + public String askUserForName() { ui.askForName(); String userName = ui.getNextLine(); userName.trim(); @@ -98,7 +98,7 @@ private String askUserForName() { * * @return balance in the form of a float */ - private String askUserForBalance() { + public String askUserForBalance() { ui.askForBalance(); String balanceString = ui.getNextLine(); balanceString = balanceString.trim(); @@ -117,24 +117,6 @@ private String askUserForBalance() { } } - public boolean isFloat(String str) { - try { - Float.parseFloat(str); - return true; - } catch (NumberFormatException e) { - return false; - } - } - - public boolean isNegative(String str) { - return Float.parseFloat(str) < 0; - } - - public boolean isBlank(String str) { - return str.isBlank(); - } - - //@@author xiaoge26 /** * Creates a new account and adds it to the AccountList. @@ -142,21 +124,10 @@ public boolean isBlank(String str) { * @param name Name of the new account to be added * @param balance Balance of the new account to be added */ - public void addAccount(String name, String balance) throws NumberFormatException, - NullPointerException, NegativeAmountException { - if (isBlank(name)) { - throw new NullPointerException(); - } else if (isFloat(balance)) { - if (isNegative(balance)) { - throw new NegativeAmountException(); - } + public void addAccount(String name, String balance) { Account newAccount = new Account(name, balance); accounts.add(newAccount); ui.showNewAccountAdded(newAccount); - } else { - throw new NumberFormatException(); - } - } //@@author vishnuvk47 @@ -166,18 +137,7 @@ public void addAccount(String name, String balance) throws NumberFormatException public void createNewAccount() { String userName = askUserForName(); String balance = askUserForBalance(); - try { - addAccount(userName, balance); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - createNewAccount(); - } catch (NullPointerException e) { - ui.showBlankUserNameError(); - createNewAccount(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - createNewAccount(); - } + addAccount(userName, balance); } //@@author Sherlock-YH diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 72ea630418..eb925e3a67 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -109,6 +109,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce throw new CommandNotFoundException(); } } + //@@author Sherlock-YH /** * Parses the save file. Takes in the scanner to the save file, @@ -130,15 +131,7 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S if (name.isEmpty() || balanceString.isEmpty()) { throw new CorruptedSaveFileException(); } - try { - accountList.addAccount(name, balanceString); - } catch (NumberFormatException e) { - throw new CorruptedSaveFileException(); - } catch (NegativeAmountException e) { - throw new CorruptedSaveFileException(); - } catch (NullPointerException e) { - throw new CorruptedSaveFileException(); - } + accountList.addAccount(name, balanceString); } scanner.close(); if (accountList.getSize() == 0){ diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 3ca4f71c79..c806ef2641 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,51 +1,49 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; - import seedu.bankwithus.exceptions.CorruptedSaveFileException; import seedu.bankwithus.exceptions.NegativeAmountException; + import java.io.ByteArrayInputStream; + import java.io.InputStream; + import java.util.Scanner; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { Ui ui = new Ui(); - @Test - void addAccount_invalidBalance_expectException() throws NumberFormatException { - String name = "Bob"; - String balanceString = "abc"; - AccountList accountList = new AccountList(); - assertThrows(NumberFormatException.class, - () -> accountList.addAccount(name, balanceString)); - } - @Test - void depositMoney_invalidAmount_expectException() throws NumberFormatException { + @Test + void depositMoney_notANumber_expectException() { String amountString = "abc"; String name = "Bob"; String balance = "0"; AccountList accountList = new AccountList(); - try { - accountList.addAccount(name, balance); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NullPointerException e) { - ui.showNullInputError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } + 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)); + } + @Test - void depositMoney_validAmount_expectDeposit() { - String amountString = "100.5"; + void depositMoney_largeAmount_expectDeposit() { + String amountString = "12345678.85"; String name = "Bob"; - String balance = "100.5"; + String balance = "100.05"; AccountList accountList = new AccountList(); Ui ui = new Ui(); + accountList.addAccount(name, balance); try { - accountList.addAccount(name, balance); accountList.depositMoney(amountString); } catch (NumberFormatException e) { ui.showNumberFormatError(); @@ -54,10 +52,10 @@ void depositMoney_validAmount_expectDeposit() { } catch (NegativeAmountException e) { ui.showNegativeAmountError(); } - assertEquals("201", accountList.getMainAccount().getAccountBalance()); + assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); } - /** + @Test void testingAddAccount() { AccountList TestAccountList = new AccountList(); @@ -65,5 +63,4 @@ void testingAddAccount() { assertEquals("Jane", TestAccountList.getMainAccount().getName()); assertEquals("1000", TestAccountList.getMainAccount().getAccountBalance()); } - **/ } From 93cd14c79febfc3b6a2f740288875fe8f666c59b Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 22:04:34 +0800 Subject: [PATCH 128/368] Fix exception that occurs if too little semicolons are in account details --- src/main/java/seedu/bankwithus/Parser.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index ca951549ee..58bc3f7189 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -126,14 +126,14 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S throw new SaveFileIsEmptyException(); } String[] splitDetails = accountDetails.split(";"); - String name = splitDetails[0].trim(); - String balanceString = splitDetails[1].trim(); - String totalAmtWithdrawn = splitDetails[2].trim(); - String lastWithdrawnDate = splitDetails[3].trim(); - if (name.isEmpty() || balanceString.isEmpty() || totalAmtWithdrawn.isEmpty()) { - throw new CorruptedSaveFileException(); - } try { + String name = splitDetails[0].trim(); + String balanceString = splitDetails[1].trim(); + String totalAmtWithdrawn = splitDetails[2].trim(); + String lastWithdrawnDate = splitDetails.length == 4 ? splitDetails[3].trim() : ""; + if (name.isEmpty() || balanceString.isEmpty() || totalAmtWithdrawn.isEmpty()) { + throw new CorruptedSaveFileException(); + } if (lastWithdrawnDate.isEmpty()) { //if no history of withdrawing accountList.addAccount(name, balanceString); @@ -143,7 +143,7 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S } } catch (Exception e) { throw new CorruptedSaveFileException(); - } + } } scanner.close(); if (accountList.getSize() == 0){ From 6e7986787c1c8724dc9a0708e7afd6e24aa16457 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 22:06:02 +0800 Subject: [PATCH 129/368] Fix Checkstyle errors --- src/main/java/seedu/bankwithus/AccountList.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 094b564cc2..31326cf0ba 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -125,9 +125,9 @@ public String askUserForBalance() { * @param balance Balance of the new account to be added */ public void addAccount(String name, String balance) { - Account newAccount = new Account(name, balance); - accounts.add(newAccount); - ui.showNewAccountAdded(newAccount); + Account newAccount = new Account(name, balance); + accounts.add(newAccount); + ui.showNewAccountAdded(newAccount); } //@@author vishnuvk47 From 161e90c5a9d3ba76ef5f22a8edaee31ed5cd0706 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 22:11:26 +0800 Subject: [PATCH 130/368] Delete unused lines --- src/test/java/seedu/bankwithus/AccountListTest.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index c806ef2641..f8c32f1d56 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -3,15 +3,10 @@ import org.junit.jupiter.api.Test; import seedu.bankwithus.exceptions.NegativeAmountException; - import java.io.ByteArrayInputStream; - import java.io.InputStream; - import java.util.Scanner; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { - Ui ui = new Ui(); @Test void depositMoney_notANumber_expectException() { From bb47ae97444c9301124cadb46e614b5b3d60130f Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Thu, 23 Mar 2023 22:14:51 +0800 Subject: [PATCH 131/368] trying to add a save goal feature --- src/main/java/seedu/bankwithus/Account.java | 10 ++++++++++ src/main/java/seedu/bankwithus/Parser.java | 2 ++ src/main/java/seedu/bankwithus/Ui.java | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index f551f4baf1..8235222055 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -6,6 +6,8 @@ public class Account { private String name; private String balance; + private float amtToSave = 0; + //@@author Sherlock-YH /** * Instantiates an account object @@ -37,4 +39,12 @@ public void subtractBalance(float currentBalance, float withdrawal) { String formatted = df.format(currentBalance - withdrawal); this.balance = String.valueOf(formatted); } + + public float getAmtToSave() { + return this.amtToSave; + } + + public void setAmtToSave(float amt) { + this.amtToSave = amt; + } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index d0691ab8e0..40e1c278e5 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -102,6 +102,8 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "help": ui.showHelp(); break; + case "save": + case "delete": accountList.deleteAccount(args); break; diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 7bfa271a2b..90e1854f5f 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -146,7 +146,7 @@ public void showCorruptedSaveFileError() { } public void showForbiddenCharacterError() { - System.out.println("Please do not put the chacter ';' in the name."); + System.out.println("Please do not put the character ';' in the name."); } //@@author Sherlock-YH public void showAccountDeleted(String name) { From 22e5f6c6ab456b8eefe48be631656c624cb7c413 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 22:17:34 +0800 Subject: [PATCH 132/368] Fix indentation errors --- .../seedu/bankwithus/AccountListTest.java | 78 +++++++++---------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index f8c32f1d56..0df89b9867 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,22 +1,21 @@ package seedu.bankwithus; - import org.junit.jupiter.api.Test; - import seedu.bankwithus.exceptions.NegativeAmountException; +import org.junit.jupiter.api.Test; +import seedu.bankwithus.exceptions.NegativeAmountException; - import static org.junit.jupiter.api.Assertions.assertEquals; - import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { - @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)); + 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 @@ -29,33 +28,32 @@ void depositMoney_negativeNumber_expectException() { assertThrows(NegativeAmountException.class, () -> accountList.depositMoney(amountString)); } - - @Test - void depositMoney_largeAmount_expectDeposit() { - String amountString = "12345678.85"; - String name = "Bob"; - String balance = "100.05"; - AccountList accountList = new AccountList(); - Ui ui = new Ui(); - accountList.addAccount(name, balance); - try { - accountList.depositMoney(amountString); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NullPointerException e) { - ui.showNullInputError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } - assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); - } + @Test + void depositMoney_largeAmount_expectDeposit() { + String amountString = "12345678.85"; + String name = "Bob"; + String balance = "100.05"; + AccountList accountList = new AccountList(); + Ui ui = new Ui(); + accountList.addAccount(name, balance); + try { + accountList.depositMoney(amountString); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NullPointerException e) { + ui.showNullInputError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } + assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); + } - @Test - void testingAddAccount() { - AccountList TestAccountList = new AccountList(); - TestAccountList.addAccount("Jane", "1000"); - assertEquals("Jane", TestAccountList.getMainAccount().getName()); - assertEquals("1000", TestAccountList.getMainAccount().getAccountBalance()); - } + @Test + void testingAddAccount() { + AccountList TestAccountList = new AccountList(); + TestAccountList.addAccount("Jane", "1000"); + assertEquals("Jane", TestAccountList.getMainAccount().getName()); + assertEquals("1000", TestAccountList.getMainAccount().getAccountBalance()); + } } From cf780f487f236b0c281469da39e56c82e9ad797a Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 22:23:04 +0800 Subject: [PATCH 133/368] Change test name --- src/test/java/seedu/bankwithus/AccountListTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 0df89b9867..25bc514c7b 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -16,7 +16,7 @@ void depositMoney_notANumber_expectException() { accountList.addAccount(name, balance); assertThrows(NumberFormatException.class, () -> accountList.depositMoney(amountString)); - } + } @Test void depositMoney_negativeNumber_expectException() { @@ -50,7 +50,7 @@ void depositMoney_largeAmount_expectDeposit() { @Test - void testingAddAccount() { + void testingAddAccount_validInput_expectNewAccount() { AccountList TestAccountList = new AccountList(); TestAccountList.addAccount("Jane", "1000"); assertEquals("Jane", TestAccountList.getMainAccount().getName()); From f0e3e55587ee80501106825a0a52cdc0a5c64692 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 22:27:29 +0800 Subject: [PATCH 134/368] Change save detail format --- src/main/java/seedu/bankwithus/Parser.java | 2 +- src/main/java/seedu/bankwithus/WithdrawalChecker.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 58bc3f7189..fb204dc1b2 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -130,7 +130,7 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S String name = splitDetails[0].trim(); String balanceString = splitDetails[1].trim(); String totalAmtWithdrawn = splitDetails[2].trim(); - String lastWithdrawnDate = splitDetails.length == 4 ? splitDetails[3].trim() : ""; + String lastWithdrawnDate = splitDetails[3].trim(); if (name.isEmpty() || balanceString.isEmpty() || totalAmtWithdrawn.isEmpty()) { throw new CorruptedSaveFileException(); } diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java index 21fbf75a2a..9cbcbfddd4 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -61,7 +61,7 @@ public void updateTotalAmtWithdrawn(float withdrawal) { @Override public String toString() { if (lastWithdrawnDate == null) { - return totalAmtWithdrawn; + return totalAmtWithdrawn + ";"; } else { return totalAmtWithdrawn + ";" + lastWithdrawnDate.toString(); } From 167706e1454735abec95d4be891fc51152f443e4 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 22:31:33 +0800 Subject: [PATCH 135/368] Remove a test temporarily --- src/test/java/seedu/bankwithus/AccountListTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 25bc514c7b..7981828e4c 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -28,6 +28,11 @@ void depositMoney_negativeNumber_expectException() { assertThrows(NegativeAmountException.class, () -> accountList.depositMoney(amountString)); } + /** + * This test tests the depositMoney method in AccountList.java when a large + * amount is deposited. The expected result is that the correct amount is deposited. + * + * Uncomment this test when the bug is fixed. @Test void depositMoney_largeAmount_expectDeposit() { String amountString = "12345678.85"; @@ -47,6 +52,7 @@ void depositMoney_largeAmount_expectDeposit() { } assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); } + */ @Test From e30e778929abaf287e2d4490bf96c4a495def7f0 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 22:57:08 +0800 Subject: [PATCH 136/368] Fix checkstyle errors --- .../seedu/bankwithus/AccountListTest.java | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 7981828e4c..2b37ec4ae6 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -28,31 +28,28 @@ void depositMoney_negativeNumber_expectException() { assertThrows(NegativeAmountException.class, () -> accountList.depositMoney(amountString)); } - /** - * This test tests the depositMoney method in AccountList.java when a large - * amount is deposited. The expected result is that the correct amount is deposited. - * - * Uncomment this test when the bug is fixed. - @Test - void depositMoney_largeAmount_expectDeposit() { - String amountString = "12345678.85"; - String name = "Bob"; - String balance = "100.05"; - AccountList accountList = new AccountList(); - Ui ui = new Ui(); - accountList.addAccount(name, balance); - try { - accountList.depositMoney(amountString); - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } catch (NullPointerException e) { - ui.showNullInputError(); - } catch (NegativeAmountException e) { - ui.showNegativeAmountError(); - } - assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); - } - */ + //This test tests the depositMoney method in AccountList.java when a large amount is deposited. + // The expected result is that the correct amount is deposited. + // Uncomment this test when the bug is fixed. +// @Test +// void depositMoney_largeAmount_expectDeposit() { +// String amountString = "12345678.85"; +// String name = "Bob"; +// String balance = "100.05"; +// AccountList accountList = new AccountList(); +// Ui ui = new Ui(); +// accountList.addAccount(name, balance); +// try { +// accountList.depositMoney(amountString); +// } catch (NumberFormatException e) { +// ui.showNumberFormatError(); +// } catch (NullPointerException e) { +// ui.showNullInputError(); +// } catch (NegativeAmountException e) { +// ui.showNegativeAmountError(); +// } +// assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); +// } @Test From deab713dbb07dba4d74e8a925c517f645742c864 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 23 Mar 2023 23:01:42 +0800 Subject: [PATCH 137/368] Change indentation --- .../seedu/bankwithus/AccountListTest.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 2b37ec4ae6..1250bba848 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -31,25 +31,25 @@ void depositMoney_negativeNumber_expectException() { //This test tests the depositMoney method in AccountList.java when a large amount is deposited. // The expected result is that the correct amount is deposited. // Uncomment this test when the bug is fixed. -// @Test -// void depositMoney_largeAmount_expectDeposit() { -// String amountString = "12345678.85"; -// String name = "Bob"; -// String balance = "100.05"; -// AccountList accountList = new AccountList(); -// Ui ui = new Ui(); -// accountList.addAccount(name, balance); -// try { -// accountList.depositMoney(amountString); -// } catch (NumberFormatException e) { -// ui.showNumberFormatError(); -// } catch (NullPointerException e) { -// ui.showNullInputError(); -// } catch (NegativeAmountException e) { -// ui.showNegativeAmountError(); -// } -// assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); -// } + // @Test + // void depositMoney_largeAmount_expectDeposit() { + // String amountString = "12345678.85"; + // String name = "Bob"; + // String balance = "100.05"; + // AccountList accountList = new AccountList(); + // Ui ui = new Ui(); + // accountList.addAccount(name, balance); + // try { + // accountList.depositMoney(amountString); + // } catch (NumberFormatException e) { + // ui.showNumberFormatError(); + // } catch (NullPointerException e) { + // ui.showNullInputError(); + // } catch (NegativeAmountException e) { + // ui.showNegativeAmountError(); + // } + // assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); + // } @Test From 2f7584094665e0326e6bf246944df748b76f1e8e Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 23:07:28 +0800 Subject: [PATCH 138/368] Add logging --- .../java/seedu/bankwithus/WithdrawalChecker.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java index 9cbcbfddd4..c0c49825ad 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -1,17 +1,23 @@ package seedu.bankwithus; +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.INFO, "Default WithdrawalChecker contructor called"); this.totalAmtWithdrawn = "0"; + logger.log(Level.INFO, "totalAmtWithdrawn set to " + totalAmtWithdrawn); } /** @@ -21,8 +27,11 @@ public WithdrawalChecker() { * @param lastWithdrawnDate last known withdrawal date */ public WithdrawalChecker(String totalAmtWithdrawn, LocalDate lastWithdrawnDate) { + logger.log(Level.INFO, "WithdrawalChecker contructer with set withdrawals called"); this.totalAmtWithdrawn = totalAmtWithdrawn; this.lastWithdrawnDate = lastWithdrawnDate; + logger.log(Level.INFO, "totalAntWithdrawn set to " + totalAmtWithdrawn); + logger.log(Level.INFO, "lastWithdrawnDate set to " + lastWithdrawnDate.toString()); } public String getTotalAmtWithdrawn() { @@ -38,9 +47,12 @@ public String getTotalAmtWithdrawn() { * @param withdrawal the amount that was just withdrawn */ public void updateTotalAmtWithdrawn(float withdrawal) { + logger.log(Level.INFO, "updateTotalAmtWithdrawn in WithdrawalChecker called"); LocalDate currentDate = LocalDate.now(); DecimalFormat df = new DecimalFormat("#.##"); + logger.log(Level.INFO, "Checking if account has withdrawal history"); if (lastWithdrawnDate == null) { + logger.log(Level.INFO, "No withdrawal history found, setting values now"); lastWithdrawnDate = currentDate; String formatted = df.format(withdrawal); totalAmtWithdrawn = String.valueOf(formatted); @@ -49,9 +61,11 @@ public void updateTotalAmtWithdrawn(float withdrawal) { assert totalAmtWithdrawn != null; if (lastWithdrawnDate.getMonth() == currentDate.getMonth() && lastWithdrawnDate.getYear() == currentDate.getYear()) { + logger.log(Level.INFO, "Previous withdrawal in the same month, adding to total"); String formatted = df.format(Float.parseFloat(totalAmtWithdrawn) + withdrawal); totalAmtWithdrawn = String.valueOf(formatted); } else { + logger.log(Level.INFO, "Previous withdrawal in previous months, setting to new value"); String formatted = df.format(withdrawal); totalAmtWithdrawn = String.valueOf(formatted); } From 0a3918a53ff37d13b9d089e1c589c33838add94c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 23:09:37 +0800 Subject: [PATCH 139/368] Add command to set withdrawal limit --- .../java/seedu/bankwithus/AccountList.java | 21 +++++++++++++++++++ src/main/java/seedu/bankwithus/Parser.java | 8 +++++++ .../seedu/bankwithus/WithdrawalChecker.java | 6 ++++++ 3 files changed, 35 insertions(+) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 9ed2a2a22f..2442f85125 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -224,6 +224,27 @@ public void switchMainAccount(String accName) throws NoAccountException { } 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 { + float withdrawalLimit; + try { + withdrawalLimit = Float.parseFloat(args); + } catch (Exception e) { + throw new NumberFormatException(); + } + if (withdrawalLimit < 0) { + throw new NegativeAmountException(); + } + getMainAccount().getWithdrawalChecker().setWithdrawalLimit(withdrawalLimit); } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index fb204dc1b2..820fa39e7b 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -100,6 +100,14 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showAccountNotFound(); } break; + case "set-wl": + try { + accountList.setWithdrawalLimit(args); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); + } case "help": ui.showHelp(); break; diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java index c0c49825ad..a549cd61d1 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -72,6 +72,12 @@ public void updateTotalAmtWithdrawn(float withdrawal) { lastWithdrawnDate = currentDate; } + public void setWithdrawalLimit(float withdrawalLimit) { + DecimalFormat df = new DecimalFormat("#.##"); + String formatted = df.format(withdrawalLimit); + this.withdrawalLimit = String.valueOf(formatted); + } + @Override public String toString() { if (lastWithdrawnDate == null) { From f5da38e5bc1ba2d8c8eee9d76456b45131b5c81f Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 23:11:10 +0800 Subject: [PATCH 140/368] Update help mesaage --- src/main/java/seedu/bankwithus/Ui.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 6974a168f3..0666d52e2c 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -103,6 +103,7 @@ public void showHelp() { System.out.println("view-account: shows account 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-wl : sets to be the withdrawal limit"); System.out.println("exit: quits program and saves"); printLine(); } From ced8e3d67fa263ff01711adbb334ef55d115603f Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 23:14:53 +0800 Subject: [PATCH 141/368] Fix fallthrough error --- src/main/java/seedu/bankwithus/Parser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 820fa39e7b..229129b030 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -108,6 +108,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce } catch (NegativeAmountException e) { ui.showNegativeAmountError(); } + break; case "help": ui.showHelp(); break; From 15b5dee31fc5f0a9380d5019ae1f7cf9104187e0 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 23 Mar 2023 23:22:37 +0800 Subject: [PATCH 142/368] Update EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 1 + 1 file changed, 1 insertion(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 2f18acc8f1..9ffbb266d9 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -30,6 +30,7 @@ help: displays the current menu view-account: shows account name and balance withdraw : withdraws from available balance deposit : deposits and adds deposit to balance +set-wl : sets to be the withdrawal limit exit: quits program and saves ---------------------------- Not a valid command! From 5906510629d02eacda0c76d401483e76fef12f2f Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Thu, 23 Mar 2023 23:42:47 +0800 Subject: [PATCH 143/368] Added a SaveGoal class --- src/main/java/seedu/bankwithus/Account.java | 8 +++++++ src/main/java/seedu/bankwithus/Parser.java | 7 ++++-- src/main/java/seedu/bankwithus/SaveGoal.java | 24 ++++++++++++++++++++ src/main/java/seedu/bankwithus/Ui.java | 5 ++++ 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/SaveGoal.java diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 856c4c6429..e49f717c5e 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -6,6 +6,7 @@ public class Account { private String name; private String balance; + private SaveGoal saveGoal; private WithdrawalChecker withdrawalChecker; private float amtToSave = 0; @@ -52,4 +53,11 @@ public void subtractBalance(float currentBalance, float withdrawal) { withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); } + + public void setSaveGoal(SaveGoal saveGoal) { + this.saveGoal = saveGoal; + } + public SaveGoal getSaveGoal() { + return this.saveGoal; + } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 40e1c278e5..c8b4afbfcb 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -45,7 +45,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce // Split input by space String[] split = input.trim().split("\\s+", 2); String command = split[0]; - String args = split.length == 2 ? split[1] : ""; + String args = split.length > 1 ? split[1] : ""; switch (command) { case "exit": try { @@ -103,7 +103,10 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showHelp(); break; case "save": - + float toSave = Float.parseFloat(args); + String untilWhenStr = split[2]; + SaveGoal saveGoal = new SaveGoal(toSave, untilWhenStr); + accountList.getMainAccount().setSaveGoal(saveGoal); case "delete": accountList.deleteAccount(args); break; diff --git a/src/main/java/seedu/bankwithus/SaveGoal.java b/src/main/java/seedu/bankwithus/SaveGoal.java new file mode 100644 index 0000000000..810d8f0703 --- /dev/null +++ b/src/main/java/seedu/bankwithus/SaveGoal.java @@ -0,0 +1,24 @@ +package seedu.bankwithus; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.util.Date; + +public class SaveGoal { + public float amtToSave; + public Date untilWhen; + + public SaveGoal(float amtToSave, String untilWhenStr) { + this.amtToSave = amtToSave; + + DateFormat format = new SimpleDateFormat("dd-MM-yyyy"); + try { + this.untilWhen = format.parse(untilWhenStr); + } catch (ParseException e) { + System.out.println("Please enter Date in DD-MM-YYYY format and retry"); + e.printStackTrace(); + } + } +} diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 90e1854f5f..70c4970efc 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -200,4 +200,9 @@ public void showCurrentAccount(Account acc){ System.out.println("Balance: $" + acc.getAccountBalance()); printLine(); } + + 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)"); + } } From 4d73aae75791abe584da9a3479fd2629355d4bb1 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 24 Mar 2023 10:25:41 +0800 Subject: [PATCH 144/368] Add ui improvement for checking and setting withdrawal limit --- .../java/seedu/bankwithus/AccountList.java | 9 +++++++++ src/main/java/seedu/bankwithus/Parser.java | 11 +++++++++++ src/main/java/seedu/bankwithus/Ui.java | 18 ++++++++++++++++++ .../seedu/bankwithus/WithdrawalChecker.java | 4 ++++ 4 files changed, 42 insertions(+) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index e4cc2c81bb..f92bd3e769 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -268,4 +268,13 @@ public void setAccounts(ArrayList accounts) { this.accounts = accounts; } + //@@author tyuyang + public String[] checkWithdrawalLimit() { + String[] wlInfo = new String[2]; + WithdrawalChecker withdrawalChecker = this.getMainAccount().getWithdrawalChecker(); + withdrawalChecker.updateTotalAmtWithdrawn(0); + wlInfo[0] = withdrawalChecker.getWithdrawalLimit(); + wlInfo[1] = withdrawalChecker.getTotalAmtWithdrawn(); + return wlInfo; + } } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 26bc9f01ae..9b218628bd 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -82,6 +82,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce accountList.withdrawMoney(args); ui.showWithdrawMessage(); accountList.showBal(); + ui.printLine(); } catch (NumberFormatException e) { ui.showNumberFormatError(); } catch (NegativeAmountException e) { @@ -103,12 +104,22 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "set-wl": 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; diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 0666d52e2c..9c3f22b205 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -104,6 +104,8 @@ public void showHelp() { System.out.println("withdraw : withdraws from available balance"); System.out.println("deposit : deposits and adds deposit to balance"); 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"); + System.out.println(" this month."); System.out.println("exit: quits program and saves"); printLine(); } @@ -192,4 +194,20 @@ public void showMainAccountSwitched() { System.out.println("Main Account switched"); printLine(); } + //@@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."); + } } diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java index a549cd61d1..b6be1051df 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -72,6 +72,10 @@ public void updateTotalAmtWithdrawn(float withdrawal) { lastWithdrawnDate = currentDate; } + public String getWithdrawalLimit() { + return this.withdrawalLimit; + } + public void setWithdrawalLimit(float withdrawalLimit) { DecimalFormat df = new DecimalFormat("#.##"); String formatted = df.format(withdrawalLimit); From dfbd6eb18ce18e0507f317442c6ccc3d6995e63e Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 24 Mar 2023 10:26:09 +0800 Subject: [PATCH 145/368] Update input to test for set-wl and check-wl commands --- text-ui-test/EXPECTED.TXT | 22 ++++++++++++++++++++++ text-ui-test/input.txt | 8 ++++++++ 2 files changed, 30 insertions(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9ffbb266d9..56ba4972c1 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -31,6 +31,8 @@ view-account: shows account name and balance withdraw : withdraws from available balance deposit : deposits and adds deposit to balance set-wl : sets to be the withdrawal limit +check-wl: shows the withdrawal limit and the amount of money withdrawn + this month. exit: quits program and saves ---------------------------- Not a valid command! @@ -80,6 +82,7 @@ Balance: $1100.21 The input is not a valid number! Please try again. Withdrawal successful! You have $123678.1 remaining! +---------------------------- MAIN Account: Name: sherlock Balance: $123678.1 @@ -87,5 +90,24 @@ Balance: $123678.1 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. +---------------------------- +Withdrawal successful! +You have $123668.1 remaining! +---------------------------- +Withdrawal limit is currently 100. +You have withdrawn 110 this month. +---------------------------- 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 e9663229b5..b2e3176f63 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -23,5 +23,13 @@ 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 +check-wl exit \ No newline at end of file From bc94df7f83d0e04440e0751dd9d8a04785605533 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 24 Mar 2023 10:32:54 +0800 Subject: [PATCH 146/368] Modify withdrawalChecker toString function to save wl information into save file --- .../java/seedu/bankwithus/WithdrawalChecker.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java index b6be1051df..f9b2645fe1 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -84,10 +84,18 @@ public void setWithdrawalLimit(float withdrawalLimit) { @Override public String toString() { + String lastWithdrawnDateString; if (lastWithdrawnDate == null) { - return totalAmtWithdrawn + ";"; + lastWithdrawnDateString = ""; } else { - return totalAmtWithdrawn + ";" + lastWithdrawnDate.toString(); + lastWithdrawnDateString = lastWithdrawnDate.toString(); } + String withdrawalLimitString; + if (withdrawalLimit == null) { + withdrawalLimitString = ""; + } else { + withdrawalLimitString = withdrawalLimit; + } + return totalAmtWithdrawn + ";" + lastWithdrawnDateString + ";" + withdrawalLimitString; } } From 4134dc67603f74e053c2df024e30c29936c57808 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 24 Mar 2023 11:00:05 +0800 Subject: [PATCH 147/368] Add parsing of withdrawal limit in parse saved file method --- src/main/java/seedu/bankwithus/AccountList.java | 14 +++++++++++--- src/main/java/seedu/bankwithus/Parser.java | 5 +++-- .../java/seedu/bankwithus/WithdrawalChecker.java | 4 ++-- .../java/seedu/bankwithus/AccountListTest.java | 6 +++--- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index f92bd3e769..cde68b65d7 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -125,16 +125,24 @@ public String askUserForBalance() { * @param name Name of the new account to be added * @param balance Balance of the new account to be added */ - public void addAccount(String name, String balance) { + public void addAccount(String name, String balance, String withdrawalLimit) { Account newAccount = new Account(name, balance); + if (!withdrawalLimit.isBlank()) { + Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); + newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat); + } accounts.add(newAccount); ui.showNewAccountAdded(newAccount); } //@@author tyuyang public void addAccount(String name, String balance, String totalAmtWithdrawn, - LocalDate lastWithdrawnDate) { + LocalDate lastWithdrawnDate, String withdrawalLimit) { Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate); + if (!withdrawalLimit.isBlank()) { + Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); + newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat); + } accounts.add(newAccount); ui.showNewAccountAdded(newAccount); } @@ -146,7 +154,7 @@ public void addAccount(String name, String balance, String totalAmtWithdrawn, public void createNewAccount() { String userName = askUserForName(); String balance = askUserForBalance(); - addAccount(userName, balance); + addAccount(userName, balance, ""); } //@@author Sherlock-YH diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 9b218628bd..252145f0c1 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -152,15 +152,16 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S String balanceString = splitDetails[1].trim(); String totalAmtWithdrawn = splitDetails[2].trim(); String lastWithdrawnDate = splitDetails[3].trim(); + String withdrawalLimit = splitDetails[4].trim(); if (name.isEmpty() || balanceString.isEmpty() || totalAmtWithdrawn.isEmpty()) { throw new CorruptedSaveFileException(); } if (lastWithdrawnDate.isEmpty()) { //if no history of withdrawing - accountList.addAccount(name, balanceString); + accountList.addAccount(name, balanceString, withdrawalLimit); } else { accountList.addAccount(name, balanceString, totalAmtWithdrawn, - LocalDate.parse(lastWithdrawnDate)); + LocalDate.parse(lastWithdrawnDate), withdrawalLimit); } } catch (Exception e) { throw new CorruptedSaveFileException(); diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java index f9b2645fe1..5f5f9ecc73 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -86,13 +86,13 @@ public void setWithdrawalLimit(float withdrawalLimit) { public String toString() { String lastWithdrawnDateString; if (lastWithdrawnDate == null) { - lastWithdrawnDateString = ""; + lastWithdrawnDateString = " "; } else { lastWithdrawnDateString = lastWithdrawnDate.toString(); } String withdrawalLimitString; if (withdrawalLimit == null) { - withdrawalLimitString = ""; + withdrawalLimitString = " "; } else { withdrawalLimitString = withdrawalLimit; } diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 1250bba848..b6fe32aa9a 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -13,7 +13,7 @@ void depositMoney_notANumber_expectException() { String name = "Bob"; String balance = "0"; AccountList accountList = new AccountList(); - accountList.addAccount(name, balance); + accountList.addAccount(name, balance, ""); assertThrows(NumberFormatException.class, () -> accountList.depositMoney(amountString)); } @@ -24,7 +24,7 @@ void depositMoney_negativeNumber_expectException() { String name = "Bob"; String balance = "100"; AccountList accountList = new AccountList(); - accountList.addAccount(name, balance); + accountList.addAccount(name, balance, ""); assertThrows(NegativeAmountException.class, () -> accountList.depositMoney(amountString)); } @@ -55,7 +55,7 @@ void depositMoney_negativeNumber_expectException() { @Test void testingAddAccount_validInput_expectNewAccount() { AccountList TestAccountList = new AccountList(); - TestAccountList.addAccount("Jane", "1000"); + TestAccountList.addAccount("Jane", "1000", ""); assertEquals("Jane", TestAccountList.getMainAccount().getName()); assertEquals("1000", TestAccountList.getMainAccount().getAccountBalance()); } From 7aa1ad7c603d3e8f2f14f2b3e43263fced2c9fe8 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Fri, 24 Mar 2023 11:56:40 +0800 Subject: [PATCH 148/368] Add documentation and tests --- .../java/seedu/bankwithus/AccountList.java | 15 ++++- .../java/seedu/bankwithus/BankWithUs.java | 2 +- .../seedu/bankwithus/AccountListTest.java | 65 +++++++++++++++++-- .../bankwithus/WithdrawalCheckerTest.java | 19 ++++++ 4 files changed, 93 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index cde68b65d7..26937de89e 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -122,8 +122,9 @@ public String askUserForBalance() { /** * 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 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); @@ -136,6 +137,15 @@ public void addAccount(String name, String balance, String withdrawalLimit) { } //@@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) { Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate); @@ -268,6 +278,7 @@ public void setWithdrawalLimit(String args) throws NegativeAmountException { getMainAccount().getWithdrawalChecker().setWithdrawalLimit(withdrawalLimit); } + //@@author Sherlock-YH public ArrayList getAccounts() { return accounts; } diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 62f89e952a..d3bc385bd2 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -73,7 +73,7 @@ public void exit() throws IOException { throw e; } } - //@@author + //@@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. diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index b6fe32aa9a..8c8f66a29e 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.Test; import seedu.bankwithus.exceptions.NegativeAmountException; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -51,12 +52,66 @@ void depositMoney_negativeNumber_expectException() { // assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); // } - + //@@author xiaoge26 @Test void testingAddAccount_validInput_expectNewAccount() { - AccountList TestAccountList = new AccountList(); - TestAccountList.addAccount("Jane", "1000", ""); - assertEquals("Jane", TestAccountList.getMainAccount().getName()); - assertEquals("1000", TestAccountList.getMainAccount().getAccountBalance()); + AccountList testAccountList = new AccountList(); + testAccountList.addAccount("Jane", "1000", ""); + assertEquals("Jane", testAccountList.getMainAccount().getName()); + assertEquals("1000", 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()); } } diff --git a/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java b/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java index 55fcdb58cc..fe6f2fce1d 100644 --- a/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java +++ b/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java @@ -26,4 +26,23 @@ public void updateTotalAmtWithdrawn_validInput_noException() { assertDoesNotThrow(() -> wcWithWithdrawals.updateTotalAmtWithdrawn((float) 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((float) 10.10)); + 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((float) 100.10)); + assertEquals("1000;2023-01-10;100.1", wc2.toString()); + } } From 7f7dc5d021a0edc560338472a7b6eda634eea065 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 13:22:07 +0800 Subject: [PATCH 149/368] Add saveGoal feature and restricted withdrawal based on savegoal deadline --- src/main/java/seedu/bankwithus/Account.java | 1 + .../java/seedu/bankwithus/AccountList.java | 58 ++++++++++++++++++- src/main/java/seedu/bankwithus/Parser.java | 16 +++-- src/main/java/seedu/bankwithus/SaveGoal.java | 23 ++++---- src/main/java/seedu/bankwithus/Ui.java | 17 +++++- 5 files changed, 95 insertions(+), 20 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index e49f717c5e..2864b8b80b 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -22,6 +22,7 @@ public Account(String name, String balance) { this.name = name; this.balance = balance; this.withdrawalChecker = new WithdrawalChecker(); + this.saveGoal = new SaveGoal(0, "01-01-2001"); } //@@author tyuyang diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 9cdbcb35ae..403dba3869 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -7,9 +7,13 @@ import seedu.bankwithus.exceptions.NoAccountException; import seedu.bankwithus.exceptions.SaveFileIsEmptyException; +import java.time.DateTimeException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.Scanner; +import java.util.regex.PatternSyntaxException; public class AccountList { private ArrayList accounts; @@ -176,6 +180,12 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio } } + 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); + } //@@author public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, NegativeAmountException, InsufficientBalanceException { @@ -184,10 +194,18 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept throw new NegativeAmountException(); } float currentBalance = Float.parseFloat(getMainAccount().getAccountBalance()); + float expectedBal = currentBalance - withdrawAmount; + LocalDate tdy = LocalDate.now(); + LocalDate tdyDate = handleDate(tdy); if (currentBalance < withdrawAmount) { throw new InsufficientBalanceException(); + } else if(getMainAccount().getSaveGoal().amtToSave > expectedBal && !getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate)) { + System.out.println("Withdrawing the specified amount would lead to failing to meet Save Goal"); + System.out.println("would you like to proceed? (Y/N)"); + handleProceed(withdrawAmount, currentBalance); } else { - getMainAccount().subtractBalance(currentBalance,withdrawAmount); + getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); + ui.showWithdrawMessage(); } } @@ -235,4 +253,42 @@ public void setAccounts(ArrayList accounts) { this.accounts = accounts; } + public void handleProceed(float withdrawAmount, float currentBalance) { + 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().setSaveGoal(new SaveGoal(0, "01-01-2001")); + ui.showWithdrawMessage(); + + } else { + ui.showWithdrawCancelled(); + } + } + + public void handleSaveGoal(String args, String untilWhenStr) { + try { + float toSave = Float.parseFloat(args); + if (isDateFormatValid(untilWhenStr)) { + SaveGoal saveGoal = new SaveGoal(toSave, untilWhenStr); + getMainAccount().setSaveGoal(saveGoal); + } + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } + } + public boolean isDateFormatValid(String date) { + String regex = "\\d{2}-\\d{2}-\\d{4}"; + try { + return date.matches(regex); + } catch ( DateTimeException e) { + System.out.println("Date is not in the correct format."); + return false; + } + + } + } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 7ca29c799f..08eddbb5e4 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -9,6 +9,7 @@ import seedu.bankwithus.exceptions.SaveFileIsEmptyException; import java.io.IOException; +import java.time.LocalDate; import java.util.Scanner; public class Parser { @@ -43,7 +44,7 @@ public Parser(AccountList accountList) { */ public void parseUserInput(String input) throws CommandNotFoundException, IOException { // Split input by space - String[] split = input.trim().split("\\s+", 2); + String[] split = input.trim().split("\\s+", 3); String command = split[0]; String args = split.length > 1 ? split[1] : ""; switch (command) { @@ -79,7 +80,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "withdraw": try { accountList.withdrawMoney(args); - ui.showWithdrawMessage(); + //need to make amends here to only show if withdrawn when no savegoal accountList.showBal(); } catch (NumberFormatException e) { ui.showNumberFormatError(); @@ -103,10 +104,13 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showHelp(); break; case "save": - float toSave = Float.parseFloat(args); - String untilWhenStr = split[2]; - SaveGoal saveGoal = new SaveGoal(toSave, untilWhenStr); - accountList.getMainAccount().setSaveGoal(saveGoal); + if(split.length > 2) { + String untilWhenStr = split[2]; + accountList.handleSaveGoal(args, untilWhenStr); + } else { + ui.showInsufficientArgsEntered(); + } + break; case "delete": accountList.deleteAccount(args); break; diff --git a/src/main/java/seedu/bankwithus/SaveGoal.java b/src/main/java/seedu/bankwithus/SaveGoal.java index 810d8f0703..f8bfea4332 100644 --- a/src/main/java/seedu/bankwithus/SaveGoal.java +++ b/src/main/java/seedu/bankwithus/SaveGoal.java @@ -1,24 +1,23 @@ package seedu.bankwithus; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; +import java.time.DateTimeException; import java.time.LocalDate; -import java.util.Date; +import java.time.format.DateTimeFormatter; public class SaveGoal { public float amtToSave; - public Date untilWhen; + public LocalDate untilWhen; public SaveGoal(float amtToSave, String untilWhenStr) { - this.amtToSave = amtToSave; - - DateFormat format = new SimpleDateFormat("dd-MM-yyyy"); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); try { - this.untilWhen = format.parse(untilWhenStr); - } catch (ParseException e) { - System.out.println("Please enter Date in DD-MM-YYYY format and retry"); - e.printStackTrace(); + this.untilWhen = LocalDate.parse(untilWhenStr, formatter); + this.amtToSave = amtToSave; + Ui.showSaveGoalCreated(Float.toString(amtToSave), untilWhenStr); + } catch (DateTimeException e) { + System.out.println("Incorrect Date format, Try again following dd-MM-YYYY format!"); } } + + } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 70c4970efc..516cf5b5c5 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -6,6 +6,10 @@ public class Ui { private Scanner scanner; + public static 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."); } @@ -48,9 +52,12 @@ public void showWithdrawMessage() { /** * Creates a scanner in the Ui class + * + * @return */ - public void createScanner() { + public Scanner createScanner() { this.scanner = new Scanner(System.in); + return null; } /** @@ -201,6 +208,14 @@ public void showCurrentAccount(Account acc){ 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)"); From 4c3f1af764c65cad775ef8c87720d729f886a34c Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 14:42:39 +0800 Subject: [PATCH 150/368] fixed bugs and handled exception in saveGoal and resolved checkstyle --- src/main/java/seedu/bankwithus/Account.java | 10 ++--- .../java/seedu/bankwithus/AccountList.java | 40 ++++++++++++------- src/main/java/seedu/bankwithus/Parser.java | 5 ++- src/main/java/seedu/bankwithus/SaveGoal.java | 1 - src/main/java/seedu/bankwithus/Ui.java | 11 +++++ 5 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 2864b8b80b..bc152f99e7 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -4,13 +4,11 @@ import java.time.LocalDate; public class Account { + + public SaveGoal saveGoal; private String name; private String balance; - private SaveGoal saveGoal; private WithdrawalChecker withdrawalChecker; - - private float amtToSave = 0; - //@@author Sherlock-YH /** * Instantiates an account object @@ -55,8 +53,10 @@ public void subtractBalance(float currentBalance, float withdrawal) { withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); } - public void setSaveGoal(SaveGoal saveGoal) { + public void setSaveGoal(SaveGoal saveGoal, String args, String untilWhenStr) { + this.saveGoal = saveGoal; + Ui.showSaveGoalCreated(args, untilWhenStr); } public SaveGoal getSaveGoal() { return this.saveGoal; diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 403dba3869..8ecb6d0b35 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -13,7 +13,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Scanner; -import java.util.regex.PatternSyntaxException; + public class AccountList { private ArrayList accounts; @@ -199,9 +199,8 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept LocalDate tdyDate = handleDate(tdy); if (currentBalance < withdrawAmount) { throw new InsufficientBalanceException(); - } else if(getMainAccount().getSaveGoal().amtToSave > expectedBal && !getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate)) { - System.out.println("Withdrawing the specified amount would lead to failing to meet Save Goal"); - System.out.println("would you like to proceed? (Y/N)"); + } else if(isFailsSaveGoal(expectedBal, tdyDate)) { + ui.failToMeetSaveGoal(); handleProceed(withdrawAmount, currentBalance); } else { getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); @@ -254,14 +253,14 @@ public void setAccounts(ArrayList accounts) { } public void handleProceed(float withdrawAmount, float currentBalance) { - String YesOrNo = ui.getNextLine(); - while(!(YesOrNo.equalsIgnoreCase("y") || YesOrNo.equalsIgnoreCase("n"))) { + 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(); + yesOrNo = ui.getNextLine(); } - if(YesOrNo.equalsIgnoreCase("y")) { + if(yesOrNo.equalsIgnoreCase("y")) { getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); - getMainAccount().setSaveGoal(new SaveGoal(0, "01-01-2001")); + getMainAccount().saveGoal.amtToSave = 0; ui.showWithdrawMessage(); } else { @@ -274,21 +273,34 @@ public void handleSaveGoal(String args, String untilWhenStr) { float toSave = Float.parseFloat(args); if (isDateFormatValid(untilWhenStr)) { SaveGoal saveGoal = new SaveGoal(toSave, untilWhenStr); - getMainAccount().setSaveGoal(saveGoal); + getMainAccount().setSaveGoal(saveGoal, args, untilWhenStr); } } catch (NumberFormatException e) { ui.showNumberFormatError(); } } public boolean isDateFormatValid(String date) { - String regex = "\\d{2}-\\d{2}-\\d{4}"; + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); try { - return date.matches(regex); - } catch ( DateTimeException e) { - System.out.println("Date is not in the correct format."); + LocalDate.parse(date, formatter); + return true; + } catch (DateTimeException e) { + System.out.println("Incorrect Date format, Try again following dd-MM-YYYY format!"); return false; } } + public void showGoal() { + SaveGoal goal = getMainAccount().getSaveGoal(); + ui.showGoal(goal); + } + + public Boolean isFailsSaveGoal(float expectedBal, LocalDate tdyDate) { + boolean exceedsSaveGoal = getMainAccount().getSaveGoal().amtToSave > expectedBal; + boolean deadlinePassed = getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate); + return (exceedsSaveGoal && !deadlinePassed); + } + } diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 08eddbb5e4..166a6f7a0a 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -9,7 +9,6 @@ import seedu.bankwithus.exceptions.SaveFileIsEmptyException; import java.io.IOException; -import java.time.LocalDate; import java.util.Scanner; public class Parser { @@ -80,7 +79,6 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "withdraw": try { accountList.withdrawMoney(args); - //need to make amends here to only show if withdrawn when no savegoal accountList.showBal(); } catch (NumberFormatException e) { ui.showNumberFormatError(); @@ -111,6 +109,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showInsufficientArgsEntered(); } break; + case "show-saveGoal": + accountList.showGoal(); + break; case "delete": accountList.deleteAccount(args); break; diff --git a/src/main/java/seedu/bankwithus/SaveGoal.java b/src/main/java/seedu/bankwithus/SaveGoal.java index f8bfea4332..73adcdc457 100644 --- a/src/main/java/seedu/bankwithus/SaveGoal.java +++ b/src/main/java/seedu/bankwithus/SaveGoal.java @@ -13,7 +13,6 @@ public SaveGoal(float amtToSave, String untilWhenStr) { try { this.untilWhen = LocalDate.parse(untilWhenStr, formatter); this.amtToSave = amtToSave; - Ui.showSaveGoalCreated(Float.toString(amtToSave), untilWhenStr); } catch (DateTimeException e) { System.out.println("Incorrect Date format, Try again following dd-MM-YYYY format!"); } diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 516cf5b5c5..f477da0760 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -220,4 +220,15 @@ 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) { + printLine(); + System.out.println("Min amount to save: $" + Float.toString(goal.amtToSave)); + System.out.println("Deadline: "+goal.untilWhen); + printLine(); + } + + public void showArgsWrongFormat() { + System.out.println("please try again with a valid float and/or dd-mm-yy format"); + } } From 68325df7145e9a4caadc94dfe468409b8a7426dd Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 14:46:21 +0800 Subject: [PATCH 151/368] Add all the commands to the ui.showHelp() method --- src/main/java/seedu/bankwithus/Ui.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index f477da0760..dc9af61a69 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -110,6 +110,9 @@ public void showHelp() { System.out.println("view-account: shows account name and balance"); System.out.println("withdraw : withdraws from available balance"); System.out.println("deposit : deposits and adds deposit to balance"); + System.out.println("save : sets a saveGoal of until "); + System.out.println("add-account: adds a new account"); + System.out.println("switch-to : switches to account"); System.out.println("exit: quits program and saves"); printLine(); } From 8ba23be1288c44883125b0443e36051cc2f4ea81 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 14:47:02 +0800 Subject: [PATCH 152/368] Add new printLine() to ui.showHelp() --- src/main/java/seedu/bankwithus/Ui.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index dc9af61a69..08bcf33869 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -106,6 +106,7 @@ public void showInsufficientBalanceMessage() { } public void showHelp() { + printLine(); System.out.println("help: displays the current menu"); System.out.println("view-account: shows account name and balance"); System.out.println("withdraw : withdraws from available balance"); From d54bb40ecebddb9261b058b7e3ed2144cba93d85 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 15:37:18 +0800 Subject: [PATCH 153/368] Cleaned up code --- .../java/seedu/bankwithus/AccountList.java | 48 +++++++++++++++++-- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 8ecb6d0b35..838efe539a 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -180,6 +180,11 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio } } + /** + * checks if date is in the DD-MM-YYYY format + * @param date + * @return true is date in correct format and false if not + */ public LocalDate handleDate(LocalDate date) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); String formattedDate = date.format(formatter); @@ -208,14 +213,21 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept } } + public void findAccount(String name, Account acc) { + if (acc.getAccountName().contains(name)) { + accounts.remove(acc); + ui.showAccountDeleted(name); + if(accounts.size() < 1) { + createNewAccount(); + } + } + } + //@@author Sherlock-YH public void deleteAccount(String name) { for (Account acc : accounts) { - if (acc.getAccountName().contains(name)) { - accounts.remove(acc); - ui.showAccountDeleted(name); - return; - } + findAccount(name, acc); + return; } ui.showNoAccountFound(); } @@ -252,6 +264,11 @@ public void setAccounts(ArrayList accounts) { this.accounts = accounts; } + /** + * handles overwriting of saveGoal at users own discretion + * @param withdrawAmount + * @param currentBalance + */ public void handleProceed(float withdrawAmount, float currentBalance) { String yesOrNo = ui.getNextLine(); while(!(yesOrNo.equalsIgnoreCase("y") || yesOrNo.equalsIgnoreCase("n"))) { @@ -268,6 +285,12 @@ public void handleProceed(float withdrawAmount, float currentBalance) { } } + /** + * 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 { float toSave = Float.parseFloat(args); @@ -279,6 +302,12 @@ public void handleSaveGoal(String args, String untilWhenStr) { ui.showNumberFormatError(); } } + + /** + * 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) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); @@ -292,11 +321,20 @@ public boolean isDateFormatValid(String date) { } + /** + * Prints to UI the save goal that the user has set for himself + */ public void showGoal() { SaveGoal goal = getMainAccount().getSaveGoal(); ui.showGoal(goal); } + /** + * checks to see if the amount being withdrawn exeeds save Goal requirements + * @param expectedBal + * @param tdyDate + * @return True if fails to meet save Goal and False if meets save Goal requirements + */ public Boolean isFailsSaveGoal(float expectedBal, LocalDate tdyDate) { boolean exceedsSaveGoal = getMainAccount().getSaveGoal().amtToSave > expectedBal; boolean deadlinePassed = getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate); From ba1e6985a3a944082187ed198f518d5c6835b4b8 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 15:57:07 +0800 Subject: [PATCH 154/368] add new method getName in account to comply with one of teh accountlist test that was added --- src/main/java/seedu/bankwithus/Account.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index bc152f99e7..68a2042947 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -58,6 +58,10 @@ public void setSaveGoal(SaveGoal saveGoal, String args, String untilWhenStr) { this.saveGoal = saveGoal; Ui.showSaveGoalCreated(args, untilWhenStr); } + + public String getName() { + return this.name; + } public SaveGoal getSaveGoal() { return this.saveGoal; } From 5c109b3d74e3231001a3a03c19d82ea1a6001679 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 17:33:41 +0800 Subject: [PATCH 155/368] Formatted code --- src/main/java/seedu/bankwithus/Account.java | 2 +- .../java/seedu/bankwithus/AccountList.java | 5 +-- src/main/java/seedu/bankwithus/Parser.java | 6 ++-- src/main/java/seedu/bankwithus/Ui.java | 15 ++++---- text-ui-test/EXPECTED.TXT | 35 ++++++++----------- text-ui-test/input.txt | 2 -- 6 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index edc32e5da9..6936d95002 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -29,6 +29,7 @@ public Account(String name, String balance, String totalAmtWithdrawn, this.name = name; this.balance = balance; this.withdrawalChecker = new WithdrawalChecker(totalAmtWithdrawn, lastWithdrawnDate); + this.saveGoal = new SaveGoal(0, "01-01-2001"); } //@@author Sherlock-YH public String getAccountName() { @@ -62,7 +63,6 @@ public void subtractBalance(float currentBalance, float withdrawal) { public void setSaveGoal(SaveGoal saveGoal, String args, String untilWhenStr) { this.saveGoal = saveGoal; - Ui.showSaveGoalCreated(args, untilWhenStr); } public String getName() { diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 1888753dda..25aa25cd56 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -225,7 +225,7 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept } } - public void findAccount(String name, Account acc) { + public void findAccountToDelete(String name, Account acc) { if (acc.getAccountName().contains(name)) { accounts.remove(acc); ui.showAccountDeleted(name); @@ -238,7 +238,7 @@ public void findAccount(String name, Account acc) { //@@author Sherlock-YH public void deleteAccount(String name) { for (Account acc : accounts) { - findAccount(name, acc); + findAccountToDelete(name, acc); return; } ui.showNoAccountFound(); @@ -332,6 +332,7 @@ public void handleSaveGoal(String args, String untilWhenStr) { if (isDateFormatValid(untilWhenStr)) { SaveGoal saveGoal = new SaveGoal(toSave, untilWhenStr); getMainAccount().setSaveGoal(saveGoal, args, untilWhenStr); + ui.showSaveGoalCreated(args, untilWhenStr); } } catch (NumberFormatException e) { ui.showNumberFormatError(); diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 5494454286..daaf80d480 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -46,7 +46,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce // Split input by space String[] split = input.trim().split("\\s+", 3); String command = split[0]; - String args = split.length > 1 ? split[1] : ""; + String args = split.length == 2 ? split[1] : ""; switch (command) { case "exit": try { @@ -112,8 +112,8 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showHelp(); break; case "save": - if(split.length > 2) { - String untilWhenStr = split[2]; + if(args.length() > 0) { + String untilWhenStr = ui.getDeadline(); accountList.handleSaveGoal(args, untilWhenStr); } else { ui.showInsufficientArgsEntered(); diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 542d4dce5c..55b01b629f 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -6,7 +6,7 @@ public class Ui { private Scanner scanner; - public static void showSaveGoalCreated(String args, String untilWhenStr) { + 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!"); } @@ -23,7 +23,7 @@ public void showIOError() { } public void showNumberFormatError() { - System.out.println("The input is not a valid number! Please try again."); + System.out.println("either The amount or deadline input is not a valid number! Please try again."); } public void showNullInputError() { @@ -55,9 +55,8 @@ public void showWithdrawMessage() { * * @return */ - public Scanner createScanner() { + public void createScanner() { this.scanner = new Scanner(System.in); - return null; } /** @@ -187,7 +186,6 @@ public void showNumberOfAccount(int accSize) { } //@@author Sherlock-YH public void showNewAccountAdded(Account acc) { - printLine(); System.out.println("Account created!"); System.out.println("Name: " + acc.getAccountName()); System.out.println("Balance: $" + acc.getAccountBalance()); @@ -200,7 +198,6 @@ public void showThereIsOnlyOneAccount() { } //@@author Sherlock-YH public void showMainAccountSwitched() { - printLine(); System.out.println("Current Account switched"); printLine(); System.out.println("Current Account is:"); @@ -227,7 +224,6 @@ public void failToMeetSaveGoal() { } public void showGoal(SaveGoal goal) { - printLine(); System.out.println("Min amount to save: $" + Float.toString(goal.amtToSave)); System.out.println("Deadline: "+goal.untilWhen); printLine(); @@ -236,4 +232,9 @@ public void showGoal(SaveGoal goal) { 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(); + } } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9ffbb266d9..71321c6c79 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -12,9 +12,7 @@ Welcome to: File not found, trying to create file. Savefile created successfully! What's your name? -User Name cannot be blank. -What's your name? -Please do not put the chacter ';' in the 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. @@ -26,32 +24,23 @@ Account created! Name: hihi Balance: $1000 ---------------------------- -help: displays the current menu -view-account: shows account name and balance -withdraw : withdraws from available balance -deposit : deposits and adds deposit to balance -set-wl : sets to be the withdrawal limit -exit: quits program and saves ----------------------------- Not a valid command! -MAIN Account: +Current Account: Name: hihi Balance: $1000 ---------------------------- Negative amount entered! The input is not a valid number! Please try again. -MAIN Account: +Current Account: Name: hihi Balance: $1000 ---------------------------- New deposit added! You have $1100.21 remaining! -MAIN Account: +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? ---------------------------- @@ -59,7 +48,7 @@ Account created! Name: sherlock Balance: $123778.1 ---------------------------- -MAIN Account: +Current Account: Name: hihi Balance: $1100.21 ---------------------------- @@ -68,9 +57,15 @@ Balance: $123778.1 ---------------------------- You do not have sufficient Balance ---------------------------- -Main Account switched ---------------------------- -MAIN Account: +Current Account switched +---------------------------- +Current Account is: +---------------------------- +Name: sherlock +Balance: $123778.1 +---------------------------- +Current Account: Name: sherlock Balance: $123778.1 ---------------------------- @@ -80,7 +75,7 @@ Balance: $1100.21 The input is not a valid number! Please try again. Withdrawal successful! You have $123678.1 remaining! -MAIN Account: +Current Account: Name: sherlock Balance: $123678.1 ---------------------------- @@ -88,4 +83,4 @@ Name: hihi Balance: $1100.21 ---------------------------- 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 e9663229b5..90561a6816 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,10 +1,8 @@ - hi;hi hihi hihi 1000 -help view account view-account deposit -1 From 843f0c3a130a21e5667faeb2c354a26037bd9340 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 17:39:00 +0800 Subject: [PATCH 156/368] modified expected.txt to fit new style of inputs --- text-ui-test/EXPECTED.TXT | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 71321c6c79..93cac75cc5 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -15,11 +15,10 @@ 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. +either The amount or deadline 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. +either The amount or deadline input is not a valid number! Please try again. How much would you like to add as Balance? ----------------------------- Account created! Name: hihi Balance: $1000 @@ -30,7 +29,7 @@ Name: hihi Balance: $1000 ---------------------------- Negative amount entered! -The input is not a valid number! Please try again. +either The amount or deadline input is not a valid number! Please try again. Current Account: Name: hihi Balance: $1000 @@ -43,7 +42,6 @@ Balance: $1100.21 ---------------------------- What's your name? How much would you like to add as Balance? ----------------------------- Account created! Name: sherlock Balance: $123778.1 @@ -57,7 +55,6 @@ Balance: $123778.1 ---------------------------- You do not have sufficient Balance ---------------------------- ----------------------------- Current Account switched ---------------------------- Current Account is: @@ -72,7 +69,7 @@ Balance: $123778.1 Name: hihi Balance: $1100.21 ---------------------------- -The input is not a valid number! Please try again. +either The amount or deadline input is not a valid number! Please try again. Withdrawal successful! You have $123678.1 remaining! Current Account: @@ -83,4 +80,4 @@ Name: hihi Balance: $1100.21 ---------------------------- Not a valid command! - +Goodbye! Hope to see you again! :) From 09b25b4b3be2cf3de2979d794af20a606eca9d45 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 18:25:13 +0800 Subject: [PATCH 157/368] Reverted the exception handling for the invalid number Format and the split back to 2 --- src/main/java/seedu/bankwithus/Parser.java | 2 +- src/main/java/seedu/bankwithus/Ui.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index daaf80d480..e3c6d666a8 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -44,7 +44,7 @@ public Parser(AccountList accountList) { */ public void parseUserInput(String input) throws CommandNotFoundException, IOException { // Split input by space - String[] split = input.trim().split("\\s+", 3); + String[] split = input.trim().split("\\s+", 2); String command = split[0]; String args = split.length == 2 ? split[1] : ""; switch (command) { diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 55b01b629f..822cdb2263 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -23,7 +23,7 @@ public void showIOError() { } public void showNumberFormatError() { - System.out.println("either The amount or deadline input is not a valid number! Please try again."); + System.out.println("The input is not a valid number! Please try again."); } public void showNullInputError() { From a1b254e4439c055b1369278f995ba33a7bb88bcb Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 18:31:08 +0800 Subject: [PATCH 158/368] Fixed expected.txt --- text-ui-test/EXPECTED.TXT | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 93cac75cc5..ee0fa975c6 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -15,9 +15,9 @@ 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? -either The amount or deadline input is not a valid number! Please try again. +The input is not a valid number! Please try again. How much would you like to add as Balance? -either The amount or deadline input is not a valid number! Please try again. +The input is not a valid number! Please try again. How much would you like to add as Balance? Account created! Name: hihi @@ -29,7 +29,7 @@ Name: hihi Balance: $1000 ---------------------------- Negative amount entered! -either The amount or deadline input is not a valid number! Please try again. +The input is not a valid number! Please try again. Current Account: Name: hihi Balance: $1000 @@ -69,7 +69,7 @@ Balance: $123778.1 Name: hihi Balance: $1100.21 ---------------------------- -either The amount or deadline input is not a valid number! Please try again. +The input is not a valid number! Please try again. Withdrawal successful! You have $123678.1 remaining! Current Account: From a66e8ea43e28c8fd0c82ccf396b38ef0507ad87a Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 20:49:16 +0800 Subject: [PATCH 159/368] Add Dev Guide --- docs/DeveloperGuide.md | 149 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 139 insertions(+), 10 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 64e1f0ed2b..fb86326ded 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,5 +1,34 @@ # Developer Guide +* [Acknowledgements](#acknowledgements) +* [Setting up, getting started](#setting-up-getting-started) +* [Design](#design) + * [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) +* [Implementation](#implementation) + * [Account related Feature](#Account-feature) + * [saveGoal related Feature](#SaveGoal-feature) + * [transaction Related Feature](#transaction-feature) + +* [Appendix: Requirements](#appendix-requirements) + * [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) + +--- + + + ## Acknowledgements {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} @@ -8,22 +37,73 @@ {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +### Design -## Product scope -### Target user profile +### Architecture -{Describe the target user profile} -### Value proposition +### 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: + +* Is an ArrayList 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 teh AccountList array + +### 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: -{Describe the value proposition: what problem does it solve?} +* Handles storing data in sa save file and also loading data, if any, when program opens. -## User Stories +### Withdraw-Limit-Checker-Component +Class: `WithdrawalChecker.java` -|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| +--- + +## Implementation +* [Account related Feature](#account-feature) +* [saveGoal related Feature](#savegoal-feature) +* [transaction Related Feature](#transaction-feature) + +--- ## Non-Functional Requirements @@ -33,6 +113,55 @@ * *glossary item* - Definition +## Appendix: Requirements + +### 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. + + +### 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 + +Fast typers 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 + +| 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 spendings 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 finacnials | +| v2.0 | user | list all the command that can be used | have a basic overview of the apps functionalities | + + +### Non-Functional Requirements + +{Give non-functional requirements} + +### Glossary + +* *glossary item* - Definition + ## Instructions for manual testing {Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing} From 95660fb7723afba408d77418a18fc8d0819b174d Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 20:50:32 +0800 Subject: [PATCH 160/368] Add a setting up, getting started heading --- docs/DeveloperGuide.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index fb86326ded..a963621e2b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -33,6 +33,10 @@ {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} +## Setting up, getting started + +--- + ## Design & implementation {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} From b8b364024e8ba88e06d5ebc483775610a52609ba Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 24 Mar 2023 20:51:25 +0800 Subject: [PATCH 161/368] Made Dev guide more consistent for the user stories --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a963621e2b..e5905cd17f 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -155,7 +155,7 @@ minimalism of a CLI interface, as it provides only the essential information and | v2.0 | user | add a savings goal | so that i can keep track of my spendings 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 finacnials | -| v2.0 | user | list all the command that can be used | have a basic overview of the apps functionalities | +| v2.0 | user | list all the command that can be used | so that i can have a basic overview of the apps functionalities | ### Non-Functional Requirements From 66b1a2387cb514f17372580df1206208cc4461a5 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Sat, 25 Mar 2023 10:28:11 +0800 Subject: [PATCH 162/368] Added @@author for vishnu in accountList class, shifted certain lines from withdraw method to isFailsSaveGoal method --- src/main/java/seedu/bankwithus/AccountList.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 5c4d2cf093..000fa53f0c 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -209,6 +209,7 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio } } + //@@author vishnuvk47 /** * checks if date is in the DD-MM-YYYY format * @param date @@ -229,12 +230,9 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept throw new NegativeAmountException(); } float currentBalance = Float.parseFloat(getMainAccount().getAccountBalance()); - float expectedBal = currentBalance - withdrawAmount; - LocalDate tdy = LocalDate.now(); - LocalDate tdyDate = handleDate(tdy); if (currentBalance < withdrawAmount) { throw new InsufficientBalanceException(); - } else if(isFailsSaveGoal(expectedBal, tdyDate)) { + } else if(isFailsSaveGoal(currentBalance, withdrawAmount)) { ui.failToMeetSaveGoal(); handleProceed(withdrawAmount, currentBalance); } else { @@ -318,6 +316,7 @@ public void setAccounts(ArrayList accounts) { this.accounts = accounts; } + //@@author vishnuvk47 /** * handles overwriting of saveGoal at users own discretion * @param withdrawAmount @@ -390,7 +389,10 @@ public void showGoal() { * @param tdyDate * @return True if fails to meet save Goal and False if meets save Goal requirements */ - public Boolean isFailsSaveGoal(float expectedBal, LocalDate tdyDate) { + public Boolean isFailsSaveGoal(float currentBalance, float withdrawAmount) { + float expectedBal = currentBalance - withdrawAmount; + LocalDate tdy = LocalDate.now(); + LocalDate tdyDate = handleDate(tdy); boolean exceedsSaveGoal = getMainAccount().getSaveGoal().amtToSave > expectedBal; boolean deadlinePassed = getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate); return (exceedsSaveGoal && !deadlinePassed); From 9d5924de2024d1d9471205ea1bb240eacc239752 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Sat, 25 Mar 2023 10:28:48 +0800 Subject: [PATCH 163/368] Add @@author for vishnu in Account class --- src/main/java/seedu/bankwithus/Account.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 6936d95002..42f17861bb 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -60,6 +60,7 @@ public void subtractBalance(float currentBalance, float withdrawal) { withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); } + //@@author vishnuvk47 public void setSaveGoal(SaveGoal saveGoal, String args, String untilWhenStr) { this.saveGoal = saveGoal; From cf50329b27478b92b852920d7c24e745a845b312 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Sat, 25 Mar 2023 10:29:25 +0800 Subject: [PATCH 164/368] Add logic to prevent withdrawals when it will exceed wl --- .../java/seedu/bankwithus/AccountList.java | 5 ++- src/main/java/seedu/bankwithus/Parser.java | 7 ++++ src/main/java/seedu/bankwithus/Ui.java | 9 +++-- .../seedu/bankwithus/WithdrawalChecker.java | 9 +++++ .../ExceedsWithdrawalLimitException.java | 5 +++ text-ui-test/EXPECTED.TXT | 34 +++++++++++++++++++ text-ui-test/input.txt | 2 ++ 7 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/ExceedsWithdrawalLimitException.java diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 000fa53f0c..5bae8bb4c7 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -2,6 +2,7 @@ import seedu.bankwithus.exceptions.AccountNotFoundException; 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; @@ -224,7 +225,7 @@ public LocalDate handleDate(LocalDate date) { //@@author manushridiv public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, - NegativeAmountException, InsufficientBalanceException { + NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException { float withdrawAmount = Float.parseFloat(withdrawAmountString); if (withdrawAmount < 0) { throw new NegativeAmountException(); @@ -232,6 +233,8 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept float currentBalance = Float.parseFloat(getMainAccount().getAccountBalance()); if (currentBalance < withdrawAmount) { throw new InsufficientBalanceException(); + } else if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(withdrawAmount)) { + throw new ExceedsWithdrawalLimitException(); } else if(isFailsSaveGoal(currentBalance, withdrawAmount)) { ui.failToMeetSaveGoal(); handleProceed(withdrawAmount, currentBalance); diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index c6f0b809b8..5dee590494 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -3,6 +3,7 @@ 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; @@ -88,6 +89,12 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce 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(); } break; case "add-account": diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/Ui.java index 8ecdc51d7e..cf9b10e4a3 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/Ui.java @@ -247,13 +247,18 @@ public void showWithdrawalLimitSet(String withdrawalLimit) { public void showWithdrawalLimit(String withdrawalLimit) { if (withdrawalLimit != null) { - System.out.println("Withdrawal limit is currently " + withdrawalLimit + "."); + 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."); + 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!"); } } diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java index 5f5f9ecc73..2ab8f76e38 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -82,6 +82,15 @@ public void setWithdrawalLimit(float withdrawalLimit) { this.withdrawalLimit = String.valueOf(formatted); } + public boolean willExceedWithdrawalLimit(float withdrawAmount) { + if (totalAmtWithdrawn.isBlank() || withdrawalLimit == null) { + return false; + } + float totalAmtWithdrawnFloat = Float.parseFloat(totalAmtWithdrawn); + float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); + return ((totalAmtWithdrawnFloat + withdrawAmount) > withdrawalLimitFloat); + } + @Override public String toString() { String lastWithdrawnDateString; 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/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index ee0fa975c6..6a3d487596 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -72,6 +72,40 @@ Balance: $1100.21 The input is not a valid number! Please try again. Withdrawal successful! You have $123678.1 remaining! +---------------------------- +Current Account: +Name: sherlock +Balance: $123678.1 +---------------------------- +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. +---------------------------- +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.1 diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index fb87b2634f..fb55a5975f 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -29,5 +29,7 @@ set-wl 100 check-wl withdraw 10 check-wl +withdraw 100 +view-account exit \ No newline at end of file From 83bc2b4b9abfe2a512025bf1d6e948fa4132c36b Mon Sep 17 00:00:00 2001 From: tyuyang Date: Sat, 25 Mar 2023 10:31:53 +0800 Subject: [PATCH 165/368] Fix checkstyle errors --- src/main/java/seedu/bankwithus/AccountList.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 5bae8bb4c7..720ecead1f 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -388,8 +388,8 @@ public void showGoal() { /** * checks to see if the amount being withdrawn exeeds save Goal requirements - * @param expectedBal - * @param tdyDate + * @param currentBalance + * @param withdrawAmount * @return True if fails to meet save Goal and False if meets save Goal requirements */ public Boolean isFailsSaveGoal(float currentBalance, float withdrawAmount) { From a9b3309d074561059a5b2658ae99f96d07077b72 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Sat, 25 Mar 2023 10:35:31 +0800 Subject: [PATCH 166/368] Add documentation for willExceedWithdrawalLimit --- src/main/java/seedu/bankwithus/WithdrawalChecker.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/WithdrawalChecker.java index 2ab8f76e38..45e8ccd56c 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/WithdrawalChecker.java @@ -82,6 +82,12 @@ public void setWithdrawalLimit(float 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(float withdrawAmount) { if (totalAmtWithdrawn.isBlank() || withdrawalLimit == null) { return false; From 4fafcd0524ce7ebea73e38cdac374e1c35e5567c Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sat, 25 Mar 2023 14:50:22 +0800 Subject: [PATCH 167/368] Add view transaction feature --- src/main/java/seedu/bankwithus/Account.java | 1 + .../java/seedu/bankwithus/AccountList.java | 2 +- src/main/java/seedu/bankwithus/Parser.java | 13 +++++ .../java/seedu/bankwithus/Transaction.java | 43 ++++++++++++++++ .../seedu/bankwithus/TransactionList.java | 50 +++++++++++++++++++ 5 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/main/java/seedu/bankwithus/Transaction.java create mode 100644 src/main/java/seedu/bankwithus/TransactionList.java diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 42f17861bb..a9791977e3 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -44,6 +44,7 @@ public String getAccountBalance() { public WithdrawalChecker getWithdrawalChecker() { return withdrawalChecker; } + //@@author xiaoge26 public void addBalance(float balanceToBeAdded) { DecimalFormat df = new DecimalFormat("#.##"); diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 720ecead1f..b7a98bbbaa 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -387,7 +387,7 @@ public void showGoal() { } /** - * checks to see if the amount being withdrawn exeeds save Goal requirements + * 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 diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 5dee590494..5eda0f9d2a 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -16,6 +16,7 @@ public class Parser { private BankWithUs bwu; private AccountList accountList; + private TransactionList transactionList; private Ui ui; /** @@ -27,6 +28,8 @@ public Parser(BankWithUs bwu) { this.bwu = bwu; this.ui = bwu.getUi(); this.accountList = bwu.getAccountList(); + this.transactionList = new TransactionList(); + //this.transactionList = bwu.getTransactionList(); } /** @@ -36,6 +39,7 @@ public Parser(BankWithUs bwu) { */ public Parser(AccountList accountList) { this.accountList = accountList; + this.transactionList = new TransactionList(); } /** @@ -59,6 +63,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "deposit": try { accountList.depositMoney(args); + Transaction transaction = new Transaction(accountList.getMainAccount().getAccountName(), + args, LocalDate.now(), "deposit"); + transactionList.addTransaction(transaction); ui.showDepositMessage(); accountList.showBal(); } catch (NumberFormatException e) { @@ -81,6 +88,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "withdraw": try { accountList.withdrawMoney(args); + Transaction transaction = new Transaction(accountList.getMainAccount().getAccountName(), + args, LocalDate.now(), "withdraw"); + transactionList.addTransaction(transaction); accountList.showBal(); ui.printLine(); } catch (NumberFormatException e) { @@ -143,6 +153,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "delete": accountList.deleteAccount(args); break; + case "view-transactions": + transactionList.printAllTransactions(); + break; default: throw new CommandNotFoundException(); } diff --git a/src/main/java/seedu/bankwithus/Transaction.java b/src/main/java/seedu/bankwithus/Transaction.java new file mode 100644 index 0000000000..890a6e962e --- /dev/null +++ b/src/main/java/seedu/bankwithus/Transaction.java @@ -0,0 +1,43 @@ +package seedu.bankwithus; + +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 amount, LocalDate date, String type) { + this.AccountName = AccountName; + this.amount = amount; + this.date = LocalDate.now(); + this.type = type; + } + + @Override + public String toString() { + 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 LocalDate getDate() { + return date; + } + + public String getType() { + return type; + } +} diff --git a/src/main/java/seedu/bankwithus/TransactionList.java b/src/main/java/seedu/bankwithus/TransactionList.java new file mode 100644 index 0000000000..0af87f63d0 --- /dev/null +++ b/src/main/java/seedu/bankwithus/TransactionList.java @@ -0,0 +1,50 @@ +package seedu.bankwithus; + +import java.time.LocalDate; +import java.util.ArrayList; + +public class TransactionList { + private ArrayList transactions; + private int size; + + public TransactionList() { + this.transactions = new ArrayList<>(); + this.size = 0; + } + + public void addTransaction(Transaction transaction) { + transactions.add(transaction); + size++; + } + + public Transaction getTransaction(int index) { + return transactions.get(index); + } + public int getSize() { + return size; + } + + public void clearTransactionList() { + transactions.clear(); + size = 0; + } + + public void printAllTransactions() { + for (int i = 0; i < size; i++) { + System.out.println(transactions.get(i).toString()); + } + } + + public void printTransactionListByType(String type) { + for (int i = 0; i < size; i++) { + if (transactions.get(i).getType().equals(type)) + System.out.println(transactions.get(i).toString()); + } + } + public void printTransactionListByDate(LocalDate date) { + for (int i = 0; i < size; i++) { + if (transactions.get(i).getDate().isBefore(date)) + System.out.println(transactions.get(i).toString()); + } + } +} From 52c1876c1341accbb158210098530bb51538791e Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sat, 25 Mar 2023 15:27:31 +0800 Subject: [PATCH 168/368] Create packages for all classes --- src/main/java/seedu/bankwithus/Account.java | 76 ---- .../java/seedu/bankwithus/AccountList.java | 413 ------------------ .../java/seedu/bankwithus/BankWithUs.java | 4 + .../java/seedu/bankwithus/Transaction.java | 43 -- .../seedu/bankwithus/TransactionList.java | 50 --- .../bankwithus/{ => common}/SaveGoal.java | 2 +- .../{ => common}/WithdrawalChecker.java | 2 +- .../seedu/bankwithus/{ => parser}/Parser.java | 7 +- .../bankwithus/{ => storage}/Storage.java | 4 +- .../java/seedu/bankwithus/{ => ui}/Ui.java | 5 +- .../seedu/bankwithus/AccountListTest.java | 1 + .../java/seedu/bankwithus/StorageTest.java | 1 + .../bankwithus/WithdrawalCheckerTest.java | 1 + 13 files changed, 22 insertions(+), 587 deletions(-) delete mode 100644 src/main/java/seedu/bankwithus/Account.java delete mode 100644 src/main/java/seedu/bankwithus/AccountList.java delete mode 100644 src/main/java/seedu/bankwithus/Transaction.java delete mode 100644 src/main/java/seedu/bankwithus/TransactionList.java rename src/main/java/seedu/bankwithus/{ => common}/SaveGoal.java (94%) rename src/main/java/seedu/bankwithus/{ => common}/WithdrawalChecker.java (99%) rename src/main/java/seedu/bankwithus/{ => parser}/Parser.java (97%) rename src/main/java/seedu/bankwithus/{ => storage}/Storage.java (94%) rename src/main/java/seedu/bankwithus/{ => ui}/Ui.java (98%) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java deleted file mode 100644 index a9791977e3..0000000000 --- a/src/main/java/seedu/bankwithus/Account.java +++ /dev/null @@ -1,76 +0,0 @@ -package seedu.bankwithus; - -import java.text.DecimalFormat; -import java.time.LocalDate; - -public class Account { - - public SaveGoal saveGoal; - private String name; - private String 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) { - this.name = name; - this.balance = balance; - this.withdrawalChecker = new WithdrawalChecker(); - this.saveGoal = new SaveGoal(0, "01-01-2001"); - } - - //@@author tyuyang - public Account(String name, String balance, String totalAmtWithdrawn, - LocalDate lastWithdrawnDate) { - this.name = name; - this.balance = balance; - this.withdrawalChecker = new WithdrawalChecker(totalAmtWithdrawn, lastWithdrawnDate); - this.saveGoal = new SaveGoal(0, "01-01-2001"); - } - //@@author Sherlock-YH - public String getAccountName() { - return name; - } - //@@author Sherlock-YH - public String getAccountBalance() { - return balance; - } - - //@@author tyuyang - public WithdrawalChecker getWithdrawalChecker() { - return withdrawalChecker; - } - - //@@author xiaoge26 - public void addBalance(float balanceToBeAdded) { - DecimalFormat df = new DecimalFormat("#.##"); - String formatted = df.format(Float.parseFloat(balance) + balanceToBeAdded); - this.balance = String.valueOf(formatted); - } - - //@@author manushridiv - public void subtractBalance(float currentBalance, float withdrawal) { - DecimalFormat df = new DecimalFormat("#.##"); - String formatted = df.format(currentBalance - withdrawal); - this.balance = String.valueOf(formatted); - - 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/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java deleted file mode 100644 index b7a98bbbaa..0000000000 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ /dev/null @@ -1,413 +0,0 @@ -package seedu.bankwithus; - -import seedu.bankwithus.exceptions.AccountNotFoundException; -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.SaveFileIsEmptyException; - -import java.time.DateTimeException; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Scanner; - - -public class AccountList { - private ArrayList accounts; - private Ui ui; - - /** - * Instantiates AccountList and creates a new account. - * Called only when savefile 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 brand new account if the save file was - * empty - * - * @param scanner the scanner containing the information in 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); - } catch (CorruptedSaveFileException e) { - ui.showCorruptedSaveFileError(); - createNewAccount(); - } catch (SaveFileIsEmptyException e) { - ui.showEmptyFile(); - createNewAccount(); - } - } - - /** - * Returns the current account. - * - * @return - */ - public Account getMainAccount() { - return accounts.get(0); - } - - /** - * 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 - * float. Will keep looping so long as the user does not give - * a valid balance. - * - * @return balance in the form of a float - */ - public String askUserForBalance() { - ui.askForBalance(); - String balanceString = ui.getNextLine(); - balanceString = balanceString.trim(); - try { - float balance = Float.parseFloat(balanceString); - if (balance < 0) { - throw new NegativeAmountException(); - } - return balanceString; - } 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); - if (!withdrawalLimit.isBlank()) { - Float withdrawalLimitFloat = Float.parseFloat(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) { - Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate); - if (!withdrawalLimit.isBlank()) { - Float withdrawalLimitFloat = Float.parseFloat(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(); - 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()); - temp.append("\n"); - } - return temp.toString(); - } - } - - //@@author - public void showBal() { - String balance = getMainAccount().getAccountBalance(); - ui.showBal(balance); - } - - //@@author xiaoge26 - public void depositMoney(String depositAmountString) throws NumberFormatException, - NullPointerException, NegativeAmountException { - float depositAmount = Float.parseFloat(depositAmountString); - if (depositAmount < 0) { - throw new NegativeAmountException(); - } else { - getMainAccount().addBalance(depositAmount); - } - } - - //@@author vishnuvk47 - /** - * checks if date is in the DD-MM-YYYY format - * @param date - * @return true is date in correct format and false if not - */ - 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); - } - - //@@author manushridiv - public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, - NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException { - float withdrawAmount = Float.parseFloat(withdrawAmountString); - if (withdrawAmount < 0) { - throw new NegativeAmountException(); - } - float currentBalance = Float.parseFloat(getMainAccount().getAccountBalance()); - if (currentBalance < withdrawAmount) { - throw new InsufficientBalanceException(); - } else if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(withdrawAmount)) { - throw new ExceedsWithdrawalLimitException(); - } else if(isFailsSaveGoal(currentBalance, withdrawAmount)) { - ui.failToMeetSaveGoal(); - handleProceed(withdrawAmount, currentBalance); - } else { - getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); - ui.showWithdrawMessage(); - } - } - - public void findAccountToDelete(String name, Account acc) { - if (acc.getAccountName().contains(name)) { - accounts.remove(acc); - ui.showAccountDeleted(name); - if(accounts.size() < 1) { - createNewAccount(); - } - } - } - - //@@author Sherlock-YH - public void deleteAccount(String name) { - for (Account acc : accounts) { - findAccountToDelete(name, acc); - return; - } - ui.showNoAccountFound(); - } - - //@@author Sherlock-YH - public int getSize() { - return accounts.size(); - } - - //@@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().contains(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 { - float withdrawalLimit; - try { - withdrawalLimit = Float.parseFloat(args); - } catch (Exception e) { - throw new NumberFormatException(); - } - if (withdrawalLimit < 0) { - 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(float withdrawAmount, float currentBalance) { - 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 = 0; - ui.showWithdrawMessage(); - - } else { - ui.showWithdrawCancelled(); - } - } - - /** - * 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 { - float toSave = Float.parseFloat(args); - if (isDateFormatValid(untilWhenStr)) { - SaveGoal saveGoal = new SaveGoal(toSave, untilWhenStr); - getMainAccount().setSaveGoal(saveGoal, args, untilWhenStr); - ui.showSaveGoalCreated(args, untilWhenStr); - } - } catch (NumberFormatException e) { - ui.showNumberFormatError(); - } - } - - /** - * 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) { - - 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(); - 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 isFailsSaveGoal(float currentBalance, float withdrawAmount) { - float expectedBal = currentBalance - withdrawAmount; - LocalDate tdy = LocalDate.now(); - LocalDate tdyDate = handleDate(tdy); - boolean exceedsSaveGoal = getMainAccount().getSaveGoal().amtToSave > expectedBal; - boolean deadlinePassed = getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate); - return (exceedsSaveGoal && !deadlinePassed); - } - - //@@author tyuyang - public String[] checkWithdrawalLimit() { - String[] wlInfo = new String[2]; - WithdrawalChecker withdrawalChecker = this.getMainAccount().getWithdrawalChecker(); - withdrawalChecker.updateTotalAmtWithdrawn(0); - wlInfo[0] = withdrawalChecker.getWithdrawalLimit(); - wlInfo[1] = withdrawalChecker.getTotalAmtWithdrawn(); - return wlInfo; - } -} diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index d3bc385bd2..fc346391f7 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -3,7 +3,11 @@ import java.io.FileNotFoundException; import java.io.IOException; +import seedu.bankwithus.data.AccountList; import seedu.bankwithus.exceptions.CommandNotFoundException; +import seedu.bankwithus.parser.Parser; +import seedu.bankwithus.storage.Storage; +import seedu.bankwithus.ui.Ui; public class BankWithUs { diff --git a/src/main/java/seedu/bankwithus/Transaction.java b/src/main/java/seedu/bankwithus/Transaction.java deleted file mode 100644 index 890a6e962e..0000000000 --- a/src/main/java/seedu/bankwithus/Transaction.java +++ /dev/null @@ -1,43 +0,0 @@ -package seedu.bankwithus; - -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 amount, LocalDate date, String type) { - this.AccountName = AccountName; - this.amount = amount; - this.date = LocalDate.now(); - this.type = type; - } - - @Override - public String toString() { - 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 LocalDate getDate() { - return date; - } - - public String getType() { - return type; - } -} diff --git a/src/main/java/seedu/bankwithus/TransactionList.java b/src/main/java/seedu/bankwithus/TransactionList.java deleted file mode 100644 index 0af87f63d0..0000000000 --- a/src/main/java/seedu/bankwithus/TransactionList.java +++ /dev/null @@ -1,50 +0,0 @@ -package seedu.bankwithus; - -import java.time.LocalDate; -import java.util.ArrayList; - -public class TransactionList { - private ArrayList transactions; - private int size; - - public TransactionList() { - this.transactions = new ArrayList<>(); - this.size = 0; - } - - public void addTransaction(Transaction transaction) { - transactions.add(transaction); - size++; - } - - public Transaction getTransaction(int index) { - return transactions.get(index); - } - public int getSize() { - return size; - } - - public void clearTransactionList() { - transactions.clear(); - size = 0; - } - - public void printAllTransactions() { - for (int i = 0; i < size; i++) { - System.out.println(transactions.get(i).toString()); - } - } - - public void printTransactionListByType(String type) { - for (int i = 0; i < size; i++) { - if (transactions.get(i).getType().equals(type)) - System.out.println(transactions.get(i).toString()); - } - } - public void printTransactionListByDate(LocalDate date) { - for (int i = 0; i < size; i++) { - if (transactions.get(i).getDate().isBefore(date)) - System.out.println(transactions.get(i).toString()); - } - } -} diff --git a/src/main/java/seedu/bankwithus/SaveGoal.java b/src/main/java/seedu/bankwithus/common/SaveGoal.java similarity index 94% rename from src/main/java/seedu/bankwithus/SaveGoal.java rename to src/main/java/seedu/bankwithus/common/SaveGoal.java index 73adcdc457..fd4bcf8905 100644 --- a/src/main/java/seedu/bankwithus/SaveGoal.java +++ b/src/main/java/seedu/bankwithus/common/SaveGoal.java @@ -1,4 +1,4 @@ -package seedu.bankwithus; +package seedu.bankwithus.common; import java.time.DateTimeException; import java.time.LocalDate; diff --git a/src/main/java/seedu/bankwithus/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java similarity index 99% rename from src/main/java/seedu/bankwithus/WithdrawalChecker.java rename to src/main/java/seedu/bankwithus/common/WithdrawalChecker.java index 45e8ccd56c..8b54e72495 100644 --- a/src/main/java/seedu/bankwithus/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java @@ -1,4 +1,4 @@ -package seedu.bankwithus; +package seedu.bankwithus.common; import java.util.logging.Level; import java.util.logging.Logger; diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java similarity index 97% rename from src/main/java/seedu/bankwithus/Parser.java rename to src/main/java/seedu/bankwithus/parser/Parser.java index 5eda0f9d2a..7bc8b1ddae 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -1,5 +1,10 @@ -package seedu.bankwithus; +package seedu.bankwithus.parser; +import seedu.bankwithus.data.AccountList; +import seedu.bankwithus.BankWithUs; +import seedu.bankwithus.data.Transaction; +import seedu.bankwithus.data.TransactionList; +import seedu.bankwithus.ui.Ui; import seedu.bankwithus.exceptions.AccountNotFoundException; import seedu.bankwithus.exceptions.CommandNotFoundException; import seedu.bankwithus.exceptions.CorruptedSaveFileException; diff --git a/src/main/java/seedu/bankwithus/Storage.java b/src/main/java/seedu/bankwithus/storage/Storage.java similarity index 94% rename from src/main/java/seedu/bankwithus/Storage.java rename to src/main/java/seedu/bankwithus/storage/Storage.java index 237616bbca..97776d6976 100644 --- a/src/main/java/seedu/bankwithus/Storage.java +++ b/src/main/java/seedu/bankwithus/storage/Storage.java @@ -1,5 +1,7 @@ -package seedu.bankwithus; +package seedu.bankwithus.storage; +import seedu.bankwithus.data.AccountList; +import seedu.bankwithus.ui.Ui; import seedu.bankwithus.exceptions.AccountNotFoundException; import java.io.File; diff --git a/src/main/java/seedu/bankwithus/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java similarity index 98% rename from src/main/java/seedu/bankwithus/Ui.java rename to src/main/java/seedu/bankwithus/ui/Ui.java index cf9b10e4a3..d477d95935 100644 --- a/src/main/java/seedu/bankwithus/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -1,4 +1,7 @@ -package seedu.bankwithus; +package seedu.bankwithus.ui; + +import seedu.bankwithus.data.Account; +import seedu.bankwithus.common.SaveGoal; import java.util.Scanner; diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 8c8f66a29e..ca5e58679c 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,6 +1,7 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; +import seedu.bankwithus.data.AccountList; import seedu.bankwithus.exceptions.NegativeAmountException; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index 4d50347d0a..bb3995bf4c 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -1,6 +1,7 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; +import seedu.bankwithus.storage.Storage; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; diff --git a/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java b/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java index fe6f2fce1d..4d81465511 100644 --- a/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java +++ b/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java @@ -6,6 +6,7 @@ import java.time.LocalDate; import org.junit.jupiter.api.Test; +import seedu.bankwithus.common.WithdrawalChecker; public class WithdrawalCheckerTest { @Test From 04e124641e8a49058536da97d312fbd33c91175a Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sat, 25 Mar 2023 20:43:19 +0800 Subject: [PATCH 169/368] Add transaction feature --- build.gradle | 1 + .../java/seedu/bankwithus/BankWithUs.java | 3 ++ .../TransactionNotFoundException.java | 7 +++++ .../java/seedu/bankwithus/parser/Parser.java | 6 ++-- .../seedu/bankwithus/storage/Storage.java | 28 +++++++++++++---- .../storage/TransactionDecoder.java | 27 +++++++++++++++++ .../storage/TransactionEncoder.java | 30 +++++++++++++++++++ 7 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/TransactionNotFoundException.java create mode 100644 src/main/java/seedu/bankwithus/storage/TransactionDecoder.java create mode 100644 src/main/java/seedu/bankwithus/storage/TransactionEncoder.java diff --git a/build.gradle b/build.gradle index fb5d6dd6d5..df273ad0eb 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,7 @@ repositories { } dependencies { + implementation 'org.jetbrains:annotations:23.0.0' testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.5.0' } diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index fc346391f7..21c126d88f 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -4,6 +4,7 @@ import java.io.IOException; import seedu.bankwithus.data.AccountList; +import seedu.bankwithus.data.TransactionList; import seedu.bankwithus.exceptions.CommandNotFoundException; import seedu.bankwithus.parser.Parser; import seedu.bankwithus.storage.Storage; @@ -16,6 +17,7 @@ public class BankWithUs { private Storage storage; private Ui ui; private AccountList accountList; + private TransactionList transactionList; private Parser parser; /** @@ -72,6 +74,7 @@ public void exit() throws IOException { ui.closeScanner(); try { storage.saveToFile(accountList); + //storage.saveTransactionsToFile(transactionList); } catch (IOException e) { ui.showIOError(); throw e; 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/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 7bc8b1ddae..ea44611525 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -17,13 +17,13 @@ import java.io.IOException; import java.time.LocalDate; import java.util.Scanner; +import java.util.regex.Pattern; public class Parser { private BankWithUs bwu; private AccountList accountList; private TransactionList transactionList; private Ui ui; - /** * Instantiates a bwu Parser object * @@ -69,7 +69,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce try { accountList.depositMoney(args); Transaction transaction = new Transaction(accountList.getMainAccount().getAccountName(), - args, LocalDate.now(), "deposit"); + "deposit", args, LocalDate.now()); transactionList.addTransaction(transaction); ui.showDepositMessage(); accountList.showBal(); @@ -94,7 +94,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce try { accountList.withdrawMoney(args); Transaction transaction = new Transaction(accountList.getMainAccount().getAccountName(), - args, LocalDate.now(), "withdraw"); + "withdraw", args, LocalDate.now()); transactionList.addTransaction(transaction); accountList.showBal(); ui.printLine(); diff --git a/src/main/java/seedu/bankwithus/storage/Storage.java b/src/main/java/seedu/bankwithus/storage/Storage.java index 97776d6976..03162d8eb4 100644 --- a/src/main/java/seedu/bankwithus/storage/Storage.java +++ b/src/main/java/seedu/bankwithus/storage/Storage.java @@ -1,6 +1,9 @@ package seedu.bankwithus.storage; import seedu.bankwithus.data.AccountList; +import seedu.bankwithus.data.Transaction; +import seedu.bankwithus.data.TransactionList; +import seedu.bankwithus.exceptions.TransactionNotFoundException; import seedu.bankwithus.ui.Ui; import seedu.bankwithus.exceptions.AccountNotFoundException; @@ -12,9 +15,12 @@ public class Storage { - protected File saveFile; + protected File accountFile; + protected File TransactionFile; private final File saveDir = new File("data"); + private Ui ui; + private static final String DELIMITER = "|"; /** * Creates a new instance of Storage. Initialises ui and saveFile. @@ -22,7 +28,8 @@ public class Storage { * @param filepath the filepath. Should be data/save.txt by default */ public Storage(String filepath) { - this.saveFile = new File(filepath); + this.accountFile = new File(filepath); + this.TransactionFile = new File("data/transaction.txt"); this.ui = new Ui(); } @@ -33,7 +40,7 @@ public Storage(String filepath) { * @throws FileNotFoundException if file is not found */ public Scanner load() throws FileNotFoundException { - return new Scanner(saveFile); + return new Scanner(accountFile); } /** @@ -43,7 +50,7 @@ public Scanner load() throws FileNotFoundException { */ public void createNewFile() throws IOException { saveDir.mkdir(); - saveFile.createNewFile(); + accountFile.createNewFile(); ui.showFileCreated(); } @@ -54,7 +61,7 @@ public void createNewFile() throws IOException { * @param list The AccountList that stores all accounts */ public void saveToFile(AccountList list) throws IOException { - FileWriter fw = new FileWriter(saveFile); + FileWriter fw = new FileWriter(accountFile); try { fw.write(list.getAllAccountDetails()); fw.close(); @@ -63,4 +70,15 @@ public void saveToFile(AccountList list) throws IOException { } } + //@@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(accountFile); + 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..e6af078dc4 --- /dev/null +++ b/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java @@ -0,0 +1,27 @@ +package seedu.bankwithus.storage; + +import seedu.bankwithus.data.Transaction; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TransactionDecoder { + private static final String PATTERN_STRING = "(\\w+) t/(\\w+) a/(\\w+) d/(\\w+)"; + + private static final Pattern PATTERN = Pattern.compile(PATTERN_STRING); + + public static Transaction decodeTransaction(String encodedTransaction) { + Matcher matcher = PATTERN.matcher(encodedTransaction); + if (matcher.matches()) { + String accountName = matcher.group(1); + String type = matcher.group(2); + String amount = matcher.group(3); + LocalDate date = LocalDate.parse(matcher.group(4), 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..5abcd83e4e --- /dev/null +++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java @@ -0,0 +1,30 @@ +package seedu.bankwithus.storage; + +import seedu.bankwithus.data.Transaction; +import seedu.bankwithus.data.TransactionList; + +class TransactionEncoder { + public static String encodeTransaction(Transaction transaction) { + final StringBuilder encodedTransactionBuilder = new StringBuilder(); + + encodedTransactionBuilder.append(transaction.getAccountName()); + encodedTransactionBuilder.append(" t/").append(transaction.getType()); + encodedTransactionBuilder.append(" a/").append(transaction.getAmount()); + encodedTransactionBuilder.append(" d/").append(transaction.getDateStr()); + + return encodedTransactionBuilder.toString(); + } + + public static String encodeTransactionList(TransactionList 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(); + } + } +} From 6518ecab0d8ab15252762880d875b8c551e17220 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sat, 25 Mar 2023 23:27:30 +0800 Subject: [PATCH 170/368] Add save and load transactions feature --- .../java/seedu/bankwithus/BankWithUs.java | 43 ++++++++++++++----- .../java/seedu/bankwithus/parser/Parser.java | 27 +++++++++--- .../seedu/bankwithus/storage/Storage.java | 39 +++++++++++------ .../storage/TransactionDecoder.java | 18 +++----- .../storage/TransactionEncoder.java | 6 +-- .../java/seedu/bankwithus/BankWithUsTest.java | 3 +- .../java/seedu/bankwithus/StorageTest.java | 2 +- 7 files changed, 94 insertions(+), 44 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 21c126d88f..c9f9f54a6f 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -12,25 +12,28 @@ public class BankWithUs { - public static final String FILE_PATH = "data/save.txt"; + 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 and - * accounts. Should load data into accounts too. + * Creates a new instance of BankWithUs. Initialises storage, ui, + * accounts and transactions. Should load data into accounts and transaction list too. * - * @param filePath the filepath. Should be data/save.txt by default + * @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 filePath) throws IOException { + public BankWithUs(String accountsFilePath, String transactionsFilePath) throws IOException { // Main object instantiations ui = new Ui(); - storage = new Storage(filePath); + storage = new Storage(accountsFilePath, transactionsFilePath); // Ui stuff ui.createScanner(); @@ -38,19 +41,33 @@ public BankWithUs(String filePath) throws IOException { // Initialising accountList try { - accountList = new AccountList(storage.load(), this); + accountList = new AccountList(storage.loadAccounts(), this); ui.showNumberOfAccount(accountList.getSize()); } catch (FileNotFoundException e) { - // If savefile not created + // If saveFile not created ui.showFileNotFoundError(); try { - storage.createNewFile(); + storage.createNewAccountsFile(); } 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); } @@ -58,6 +75,10 @@ public AccountList getAccountList() { return accountList; } + public TransactionList getTransactionList() { + return transactionList; + } + public Ui getUi() { return ui; } @@ -74,7 +95,7 @@ public void exit() throws IOException { ui.closeScanner(); try { storage.saveToFile(accountList); - //storage.saveTransactionsToFile(transactionList); + storage.saveTransactionsToFile(transactionList); } catch (IOException e) { ui.showIOError(); throw e; @@ -100,7 +121,7 @@ public void run() throws IOException { public static void main(String[] args) { try { - new BankWithUs(FILE_PATH).run(); + new BankWithUs(ACCOUNTS_FILE_PATH, TRANSACTIONS_FILE_PATH).run(); } catch (IOException e) { return; } diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index ea44611525..780383ff4b 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -4,6 +4,7 @@ import seedu.bankwithus.BankWithUs; import seedu.bankwithus.data.Transaction; import seedu.bankwithus.data.TransactionList; +import seedu.bankwithus.storage.TransactionDecoder; import seedu.bankwithus.ui.Ui; import seedu.bankwithus.exceptions.AccountNotFoundException; import seedu.bankwithus.exceptions.CommandNotFoundException; @@ -17,7 +18,6 @@ import java.io.IOException; import java.time.LocalDate; import java.util.Scanner; -import java.util.regex.Pattern; public class Parser { private BankWithUs bwu; @@ -33,8 +33,7 @@ public Parser(BankWithUs bwu) { this.bwu = bwu; this.ui = bwu.getUi(); this.accountList = bwu.getAccountList(); - this.transactionList = new TransactionList(); - //this.transactionList = bwu.getTransactionList(); + this.transactionList = bwu.getTransactionList(); } /** @@ -44,7 +43,10 @@ public Parser(BankWithUs bwu) { */ public Parser(AccountList accountList) { this.accountList = accountList; - this.transactionList = new TransactionList(); + } + + public Parser(TransactionList transactionList) { + this.transactionList = transactionList; } /** @@ -158,7 +160,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "delete": accountList.deleteAccount(args); break; - case "view-transactions": + case "view-transactions-all": transactionList.printAllTransactions(); break; default: @@ -207,4 +209,19 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S throw new SaveFileIsEmptyException(); } } + + public void parseTransactionFile(Scanner scanner) throws CorruptedSaveFileException, SaveFileIsEmptyException { + while (scanner.hasNextLine()) { + String transactionDetails = scanner.nextLine(); + if (transactionDetails.isBlank()) { + throw new SaveFileIsEmptyException(); + } + Transaction temp = TransactionDecoder.decodeTransaction(transactionDetails); + transactionList.addTransaction(temp); + } + scanner.close(); + if (transactionList.getSize() == 0){ + throw new SaveFileIsEmptyException(); + } + } } diff --git a/src/main/java/seedu/bankwithus/storage/Storage.java b/src/main/java/seedu/bankwithus/storage/Storage.java index 03162d8eb4..21bcb08b8f 100644 --- a/src/main/java/seedu/bankwithus/storage/Storage.java +++ b/src/main/java/seedu/bankwithus/storage/Storage.java @@ -1,9 +1,7 @@ package seedu.bankwithus.storage; import seedu.bankwithus.data.AccountList; -import seedu.bankwithus.data.Transaction; import seedu.bankwithus.data.TransactionList; -import seedu.bankwithus.exceptions.TransactionNotFoundException; import seedu.bankwithus.ui.Ui; import seedu.bankwithus.exceptions.AccountNotFoundException; @@ -16,20 +14,21 @@ public class Storage { protected File accountFile; - protected File TransactionFile; + protected File transactionFile; private final File saveDir = new File("data"); private Ui ui; - private static final String DELIMITER = "|"; + /** - * Creates a new instance of Storage. Initialises ui and saveFile. + * Creates a new instance of Storage. Initialises the saveFile. * - * @param filepath the filepath. Should be data/save.txt by default + * @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 filepath) { - this.accountFile = new File(filepath); - this.TransactionFile = new File("data/transaction.txt"); + public Storage(String accountsFilepath, String transactionsFilepath) { + this.accountFile = new File(accountsFilepath); + this.transactionFile = new File(transactionsFilepath); this.ui = new Ui(); } @@ -39,21 +38,37 @@ public Storage(String filepath) { * @return the scanner containing the contents of the saveFile * @throws FileNotFoundException if file is not found */ - public Scanner load() throws FileNotFoundException { + 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 createNewFile() throws IOException { + public void createNewAccountsFile() throws IOException { saveDir.mkdir(); accountFile.createNewFile(); ui.showFileCreated(); } + + //@@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 @@ -77,7 +92,7 @@ public void saveToFile(AccountList list) throws IOException { * @param transactionList The TransactionList that stores all transactions */ public void saveTransactionsToFile(TransactionList transactionList) throws IOException { - FileWriter fw = new FileWriter(accountFile); + FileWriter fw = new FileWriter(transactionFile); 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 index e6af078dc4..d93ddd8e11 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java @@ -4,21 +4,17 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -public class TransactionDecoder { - private static final String PATTERN_STRING = "(\\w+) t/(\\w+) a/(\\w+) d/(\\w+)"; - private static final Pattern PATTERN = Pattern.compile(PATTERN_STRING); +public class TransactionDecoder { public static Transaction decodeTransaction(String encodedTransaction) { - Matcher matcher = PATTERN.matcher(encodedTransaction); - if (matcher.matches()) { - String accountName = matcher.group(1); - String type = matcher.group(2); - String amount = matcher.group(3); - LocalDate date = LocalDate.parse(matcher.group(4), DateTimeFormatter.ofPattern("dd-MM-yyyy")); + String[] 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 index 5abcd83e4e..80f5271ca8 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java @@ -8,9 +8,9 @@ public static String encodeTransaction(Transaction transaction) { final StringBuilder encodedTransactionBuilder = new StringBuilder(); encodedTransactionBuilder.append(transaction.getAccountName()); - encodedTransactionBuilder.append(" t/").append(transaction.getType()); - encodedTransactionBuilder.append(" a/").append(transaction.getAmount()); - encodedTransactionBuilder.append(" d/").append(transaction.getDateStr()); + encodedTransactionBuilder.append(" /").append(transaction.getType()); + encodedTransactionBuilder.append(" /").append(transaction.getAmount()); + encodedTransactionBuilder.append(" /").append(transaction.getDateStr()); return encodedTransactionBuilder.toString(); } diff --git a/src/test/java/seedu/bankwithus/BankWithUsTest.java b/src/test/java/seedu/bankwithus/BankWithUsTest.java index 8092890f16..fb2b0a0be1 100644 --- a/src/test/java/seedu/bankwithus/BankWithUsTest.java +++ b/src/test/java/seedu/bankwithus/BankWithUsTest.java @@ -7,8 +7,9 @@ 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("")); + assertThrows(IOException.class, () -> new BankWithUs("", "")); } } diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java index bb3995bf4c..613e8cd14e 100644 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ b/src/test/java/seedu/bankwithus/StorageTest.java @@ -8,7 +8,7 @@ public class StorageTest { @Test public void load_normalSaveFile_noMessage() { - assertDoesNotThrow(() -> new Storage("data/save.txt")); + assertDoesNotThrow(() -> new Storage("data/save.txt", "data/transaction.txt")); // Storage storage = new Storage("data/save.txt"); // assertDoesNotThrow(() -> storage.load()); } From 465e7c3ed6b605a635d35c12797f0aedd5bde5f9 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sat, 25 Mar 2023 23:44:32 +0800 Subject: [PATCH 171/368] Create user package --- .../java/seedu/bankwithus/BankWithUs.java | 4 +- .../java/seedu/bankwithus/parser/Parser.java | 6 +- .../seedu/bankwithus/storage/Storage.java | 4 +- .../storage/TransactionDecoder.java | 2 +- .../storage/TransactionEncoder.java | 4 +- src/main/java/seedu/bankwithus/ui/Ui.java | 2 +- .../java/seedu/bankwithus/user/Account.java | 78 ++++ .../seedu/bankwithus/user/AccountList.java | 420 ++++++++++++++++++ .../seedu/bankwithus/user/Transaction.java | 46 ++ .../bankwithus/user/TransactionList.java | 73 +++ .../seedu/bankwithus/AccountListTest.java | 2 +- 11 files changed, 629 insertions(+), 12 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/user/Account.java create mode 100644 src/main/java/seedu/bankwithus/user/AccountList.java create mode 100644 src/main/java/seedu/bankwithus/user/Transaction.java create mode 100644 src/main/java/seedu/bankwithus/user/TransactionList.java diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index c9f9f54a6f..50b5200fcb 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -3,8 +3,8 @@ import java.io.FileNotFoundException; import java.io.IOException; -import seedu.bankwithus.data.AccountList; -import seedu.bankwithus.data.TransactionList; +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; diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 780383ff4b..7ebf863ed9 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -1,9 +1,9 @@ package seedu.bankwithus.parser; -import seedu.bankwithus.data.AccountList; +import seedu.bankwithus.user.AccountList; import seedu.bankwithus.BankWithUs; -import seedu.bankwithus.data.Transaction; -import seedu.bankwithus.data.TransactionList; +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; diff --git a/src/main/java/seedu/bankwithus/storage/Storage.java b/src/main/java/seedu/bankwithus/storage/Storage.java index 21bcb08b8f..72cbc9160f 100644 --- a/src/main/java/seedu/bankwithus/storage/Storage.java +++ b/src/main/java/seedu/bankwithus/storage/Storage.java @@ -1,7 +1,7 @@ package seedu.bankwithus.storage; -import seedu.bankwithus.data.AccountList; -import seedu.bankwithus.data.TransactionList; +import seedu.bankwithus.user.AccountList; +import seedu.bankwithus.user.TransactionList; import seedu.bankwithus.ui.Ui; import seedu.bankwithus.exceptions.AccountNotFoundException; diff --git a/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java b/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java index d93ddd8e11..35410c4a56 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java @@ -1,6 +1,6 @@ package seedu.bankwithus.storage; -import seedu.bankwithus.data.Transaction; +import seedu.bankwithus.user.Transaction; import java.time.LocalDate; import java.time.format.DateTimeFormatter; diff --git a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java index 80f5271ca8..864d541f1f 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java @@ -1,7 +1,7 @@ package seedu.bankwithus.storage; -import seedu.bankwithus.data.Transaction; -import seedu.bankwithus.data.TransactionList; +import seedu.bankwithus.user.Transaction; +import seedu.bankwithus.user.TransactionList; class TransactionEncoder { public static String encodeTransaction(Transaction transaction) { diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index d477d95935..ef6c448310 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -1,6 +1,6 @@ package seedu.bankwithus.ui; -import seedu.bankwithus.data.Account; +import seedu.bankwithus.user.Account; import seedu.bankwithus.common.SaveGoal; import java.util.Scanner; 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..24dc1ec415 --- /dev/null +++ b/src/main/java/seedu/bankwithus/user/Account.java @@ -0,0 +1,78 @@ +package seedu.bankwithus.user; + +import seedu.bankwithus.common.SaveGoal; +import seedu.bankwithus.common.WithdrawalChecker; + +import java.text.DecimalFormat; +import java.time.LocalDate; + +public class Account { + public SaveGoal saveGoal; + private String name; + private String 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) { + this.name = name; + this.balance = balance; + this.withdrawalChecker = new WithdrawalChecker(); + this.saveGoal = new SaveGoal(0, "01-01-2001"); + } + + //@@author tyuyang + public Account(String name, String balance, String totalAmtWithdrawn, + LocalDate lastWithdrawnDate) { + this.name = name; + this.balance = balance; + this.withdrawalChecker = new WithdrawalChecker(totalAmtWithdrawn, lastWithdrawnDate); + this.saveGoal = new SaveGoal(0, "01-01-2001"); + } + //@@author Sherlock-YH + public String getAccountName() { + return name; + } + //@@author Sherlock-YH + public String getAccountBalance() { + return balance; + } + + //@@author tyuyang + public WithdrawalChecker getWithdrawalChecker() { + return withdrawalChecker; + } + + //@@author xiaoge26 + public void addBalance(float balanceToBeAdded) { + DecimalFormat df = new DecimalFormat("#.##"); + String formatted = df.format(Float.parseFloat(balance) + balanceToBeAdded); + this.balance = String.valueOf(formatted); + } + + //@@author manushridiv + public void subtractBalance(float currentBalance, float withdrawal) { + DecimalFormat df = new DecimalFormat("#.##"); + String formatted = df.format(currentBalance - withdrawal); + this.balance = String.valueOf(formatted); + + 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..735bbf3fdd --- /dev/null +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -0,0 +1,420 @@ +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.NegativeAmountException; +import seedu.bankwithus.exceptions.NoAccountException; +import seedu.bankwithus.exceptions.SaveFileIsEmptyException; +import seedu.bankwithus.parser.Parser; +import seedu.bankwithus.ui.Ui; + +import java.time.DateTimeException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Scanner; + + +public class AccountList { + private ArrayList accounts; + private Ui ui; + + /** + * Instantiates AccountList and creates a new account. + * Called only when savefile 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 brand 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); + } catch (CorruptedSaveFileException e) { + ui.showCorruptedSaveFileError(); + createNewAccount(); + } catch (SaveFileIsEmptyException e) { + ui.showEmptyFile(); + createNewAccount(); + } + } + + //@@author xiaoge26 + /** + * Returns the current account. + * + * @return + */ + 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 + * float. Will keep looping so long as the user does not give + * a valid balance. + * + * @return balance in the form of a float + */ + public String askUserForBalance() { + ui.askForBalance(); + String balanceString = ui.getNextLine(); + balanceString = balanceString.trim(); + try { + float balance = Float.parseFloat(balanceString); + if (balance < 0) { + throw new NegativeAmountException(); + } + return balanceString; + } 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); + if (!withdrawalLimit.isBlank()) { + Float withdrawalLimitFloat = Float.parseFloat(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) { + Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate); + if (!withdrawalLimit.isBlank()) { + Float withdrawalLimitFloat = Float.parseFloat(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(); + 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()); + temp.append("\n"); + } + return temp.toString(); + } + } + + //@@author + public void showBal() { + String balance = getMainAccount().getAccountBalance(); + ui.showBal(balance); + } + + //@@author xiaoge26 + public void depositMoney(String depositAmountString) throws NumberFormatException, + NullPointerException, NegativeAmountException { + float depositAmount = Float.parseFloat(depositAmountString); + if (depositAmount < 0) { + throw new NegativeAmountException(); + } else { + getMainAccount().addBalance(depositAmount); + } + } + + //@@author vishnuvk47 + /** + * checks if date is in the DD-MM-YYYY format + * @param date + * @return true is date in correct format and false if not + */ + 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); + } + + //@@author manushridiv + public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, + NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException { + float withdrawAmount = Float.parseFloat(withdrawAmountString); + if (withdrawAmount < 0) { + throw new NegativeAmountException(); + } + float currentBalance = Float.parseFloat(getMainAccount().getAccountBalance()); + if (currentBalance < withdrawAmount) { + throw new InsufficientBalanceException(); + } else if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(withdrawAmount)) { + throw new ExceedsWithdrawalLimitException(); + } else if(isFailsSaveGoal(currentBalance, withdrawAmount)) { + ui.failToMeetSaveGoal(); + handleProceed(withdrawAmount, currentBalance); + } else { + getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); + ui.showWithdrawMessage(); + } + } + + public void findAccountToDelete(String name, Account acc) { + if (acc.getAccountName().contains(name)) { + accounts.remove(acc); + ui.showAccountDeleted(name); + if(accounts.size() < 1) { + createNewAccount(); + } + } + } + + //@@author Sherlock-YH + public void deleteAccount(String name) { + for (Account acc : accounts) { + findAccountToDelete(name, acc); + return; + } + ui.showNoAccountFound(); + } + + //@@author Sherlock-YH + public int getSize() { + return accounts.size(); + } + + //@@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().contains(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 { + float withdrawalLimit; + try { + withdrawalLimit = Float.parseFloat(args); + } catch (Exception e) { + throw new NumberFormatException(); + } + if (withdrawalLimit < 0) { + 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(float withdrawAmount, float currentBalance) { + 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 = 0; + ui.showWithdrawMessage(); + + } else { + ui.showWithdrawCancelled(); + } + } + + /** + * 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 { + float toSave = Float.parseFloat(args); + if (isDateFormatValid(untilWhenStr)) { + SaveGoal saveGoal = new SaveGoal(toSave, untilWhenStr); + getMainAccount().setSaveGoal(saveGoal, args, untilWhenStr); + ui.showSaveGoalCreated(args, untilWhenStr); + } + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } + } + + /** + * 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) { + + 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(); + 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 isFailsSaveGoal(float currentBalance, float withdrawAmount) { + float expectedBal = currentBalance - withdrawAmount; + LocalDate tdy = LocalDate.now(); + LocalDate tdyDate = handleDate(tdy); + boolean exceedsSaveGoal = getMainAccount().getSaveGoal().amtToSave > expectedBal; + boolean deadlinePassed = getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate); + return (exceedsSaveGoal && !deadlinePassed); + } + + //@@author tyuyang + public String[] checkWithdrawalLimit() { + String[] wlInfo = new String[2]; + WithdrawalChecker withdrawalChecker = this.getMainAccount().getWithdrawalChecker(); + withdrawalChecker.updateTotalAmtWithdrawn(0); + wlInfo[0] = withdrawalChecker.getWithdrawalLimit(); + wlInfo[1] = withdrawalChecker.getTotalAmtWithdrawn(); + return wlInfo; + } +} 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..58a1ed0dae --- /dev/null +++ b/src/main/java/seedu/bankwithus/user/Transaction.java @@ -0,0 +1,46 @@ +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 = LocalDate.now(); + } + + @Override + public String toString() { + 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 LocalDate getDate() { + return date; + } + public String getDateStr() { + return date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")); + } + + public String getType() { + return type; + } +} 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..0e474e68c7 --- /dev/null +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -0,0 +1,73 @@ +package seedu.bankwithus.user; + +import seedu.bankwithus.exceptions.CorruptedSaveFileException; +import seedu.bankwithus.exceptions.SaveFileIsEmptyException; +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; + } + + public TransactionList(Scanner scanner) { + this.size = 0; + transactions = new ArrayList<>(); + Ui ui = new Ui(); + Parser parser = new Parser(this); + try { + parser.parseTransactionFile(scanner); + } catch (CorruptedSaveFileException e) { + ui.showCorruptedSaveFileError(); + } catch (SaveFileIsEmptyException e) { + ui.showEmptyFile(); + } + } + + public void addTransaction(Transaction transaction) { + transactions.add(transaction); + size++; + } + + public ArrayList getTransactions() { + return transactions; + } + public Transaction getTransaction(int index) { + return transactions.get(index); + } + public int getSize() { + return size; + } + + public void clearTransactionList() { + transactions.clear(); + size = 0; + } + public void printAllTransactions() { + for (int i = 0; i < size; i++) { + System.out.println(transactions.get(i).toString()); + } + } + + public void printTransactionListByType(String type) { + for (int i = 0; i < size; i++) { + if (transactions.get(i).getType().equals(type)) + System.out.println(transactions.get(i).toString()); + } + } + public void printTransactionListByDate(LocalDate date) { + for (int i = 0; i < size; i++) { + if (transactions.get(i).getDate().isBefore(date)) + System.out.println(transactions.get(i).toString()); + } + } +} diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index ca5e58679c..380ad62dda 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,7 +1,7 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; -import seedu.bankwithus.data.AccountList; +import seedu.bankwithus.user.AccountList; import seedu.bankwithus.exceptions.NegativeAmountException; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; From d5db1a7e1525010b0cdce69e86c9a1eecbbaee65 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sat, 25 Mar 2023 23:51:37 +0800 Subject: [PATCH 172/368] Fix checkstyle errors --- .../java/seedu/bankwithus/user/TransactionList.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 0e474e68c7..d9cfed5bc8 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -60,14 +60,16 @@ public void printAllTransactions() { public void printTransactionListByType(String type) { for (int i = 0; i < size; i++) { - if (transactions.get(i).getType().equals(type)) - System.out.println(transactions.get(i).toString()); + if (transactions.get(i).getType().equals(type)) { + System.out.println(transactions.get(i).toString()); + } } } public void printTransactionListByDate(LocalDate date) { for (int i = 0; i < size; i++) { - if (transactions.get(i).getDate().isBefore(date)) - System.out.println(transactions.get(i).toString()); + if (transactions.get(i).getDate().isBefore(date)) { + System.out.println(transactions.get(i).toString()); + } } } } From 6f03a54452b660d101e90157ed3bb12a2726e623 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sun, 26 Mar 2023 00:01:54 +0800 Subject: [PATCH 173/368] Add savegoal to be able to be stored and also added a JUNIT test --- src/main/java/seedu/bankwithus/Account.java | 8 ++-- .../java/seedu/bankwithus/AccountList.java | 24 +++++++++-- src/main/java/seedu/bankwithus/Parser.java | 15 ++++++- .../seedu/bankwithus/AccountListTest.java | 42 +++++++++---------- 4 files changed, 57 insertions(+), 32 deletions(-) diff --git a/src/main/java/seedu/bankwithus/Account.java b/src/main/java/seedu/bankwithus/Account.java index 42f17861bb..976705c4b1 100644 --- a/src/main/java/seedu/bankwithus/Account.java +++ b/src/main/java/seedu/bankwithus/Account.java @@ -16,20 +16,20 @@ public class Account { * @param name initialise in the name of the account * @param balance initialise the balance of the account */ - public Account(String name, String balance) { + public Account(String name, String balance, String amtToSave, String untilWhen) { this.name = name; this.balance = balance; this.withdrawalChecker = new WithdrawalChecker(); - this.saveGoal = new SaveGoal(0, "01-01-2001"); + this.saveGoal = new SaveGoal(Float.parseFloat(amtToSave), untilWhen); } //@@author tyuyang public Account(String name, String balance, String totalAmtWithdrawn, - LocalDate lastWithdrawnDate) { + LocalDate lastWithdrawnDate, String amtToSave, String untilWhen) { this.name = name; this.balance = balance; this.withdrawalChecker = new WithdrawalChecker(totalAmtWithdrawn, lastWithdrawnDate); - this.saveGoal = new SaveGoal(0, "01-01-2001"); + this.saveGoal = new SaveGoal(Float.parseFloat(amtToSave), untilWhen); } //@@author Sherlock-YH public String getAccountName() { diff --git a/src/main/java/seedu/bankwithus/AccountList.java b/src/main/java/seedu/bankwithus/AccountList.java index 720ecead1f..fbaa524dc5 100644 --- a/src/main/java/seedu/bankwithus/AccountList.java +++ b/src/main/java/seedu/bankwithus/AccountList.java @@ -132,7 +132,17 @@ public String askUserForBalance() { * @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); + Account newAccount = new Account(name, balance, "0", "01-01-2001"); + if (!withdrawalLimit.isBlank()) { + Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); + newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat); + } + accounts.add(newAccount); + ui.showNewAccountAdded(newAccount); + } + + public void addAccount(String name, String balance, String withdrawalLimit, String amtToSave, String untilWhen) { + Account newAccount = new Account(name, balance, amtToSave, untilWhen); if (!withdrawalLimit.isBlank()) { Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat); @@ -152,8 +162,8 @@ public void addAccount(String name, String balance, String withdrawalLimit) { * @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) { - Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate); + LocalDate lastWithdrawnDate, String withdrawalLimit, String amtToSave, String untilWhen) { + Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate, amtToSave, untilWhen); if (!withdrawalLimit.isBlank()) { Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat); @@ -187,6 +197,10 @@ public String getAllAccountDetails() throws AccountNotFoundException { 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(); @@ -350,7 +364,9 @@ public void handleProceed(float withdrawAmount, float currentBalance) { public void handleSaveGoal(String args, String untilWhenStr) { try { float toSave = Float.parseFloat(args); - if (isDateFormatValid(untilWhenStr)) { + if (toSave < 0) { + ui.showNegativeAmountError(); + } else if (isDateFormatValid(untilWhenStr)) { SaveGoal saveGoal = new SaveGoal(toSave, untilWhenStr); getMainAccount().setSaveGoal(saveGoal, args, untilWhenStr); ui.showSaveGoalCreated(args, untilWhenStr); diff --git a/src/main/java/seedu/bankwithus/Parser.java b/src/main/java/seedu/bankwithus/Parser.java index 5dee590494..d85583b8e7 100644 --- a/src/main/java/seedu/bankwithus/Parser.java +++ b/src/main/java/seedu/bankwithus/Parser.java @@ -170,15 +170,26 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S String totalAmtWithdrawn = splitDetails[2].trim(); String lastWithdrawnDate = splitDetails[3].trim(); String withdrawalLimit = splitDetails[4].trim(); + String amtToSave; + String untilWhen; + if (splitDetails.length > 5) { + amtToSave = splitDetails[5].trim(); + untilWhen = splitDetails[6].trim(); + } else { + amtToSave = "0"; + untilWhen = "2001-01-01"; + } + StringBuilder tempStr = new StringBuilder(untilWhen); + untilWhen = tempStr.reverse().toString(); if (name.isEmpty() || balanceString.isEmpty() || totalAmtWithdrawn.isEmpty()) { throw new CorruptedSaveFileException(); } if (lastWithdrawnDate.isEmpty()) { //if no history of withdrawing - accountList.addAccount(name, balanceString, withdrawalLimit); + accountList.addAccount(name, balanceString, withdrawalLimit, amtToSave, untilWhen); } else { accountList.addAccount(name, balanceString, totalAmtWithdrawn, - LocalDate.parse(lastWithdrawnDate), withdrawalLimit); + LocalDate.parse(lastWithdrawnDate), withdrawalLimit, amtToSave, untilWhen); } } catch (Exception e) { throw new CorruptedSaveFileException(); diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 8c8f66a29e..06511cc524 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,6 +1,8 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; +import seedu.bankwithus.exceptions.ExceedsWithdrawalLimitException; +import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -29,28 +31,24 @@ void depositMoney_negativeNumber_expectException() { assertThrows(NegativeAmountException.class, () -> accountList.depositMoney(amountString)); } - //This test tests the depositMoney method in AccountList.java when a large amount is deposited. - // The expected result is that the correct amount is deposited. - // Uncomment this test when the bug is fixed. - // @Test - // void depositMoney_largeAmount_expectDeposit() { - // String amountString = "12345678.85"; - // String name = "Bob"; - // String balance = "100.05"; - // AccountList accountList = new AccountList(); - // Ui ui = new Ui(); - // accountList.addAccount(name, balance); - // try { - // accountList.depositMoney(amountString); - // } catch (NumberFormatException e) { - // ui.showNumberFormatError(); - // } catch (NullPointerException e) { - // ui.showNullInputError(); - // } catch (NegativeAmountException e) { - // ui.showNegativeAmountError(); - // } - // assertEquals("12345778.9", accountList.getMainAccount().getAccountBalance()); - // } + + @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 From 1c6bfb90e814ecb7e9495aebf651dc8f5ebb030b Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sun, 26 Mar 2023 12:32:54 +0800 Subject: [PATCH 174/368] Fix bugs and refactor code --- build.gradle | 1 - .../java/seedu/bankwithus/parser/Parser.java | 12 ++++----- .../seedu/bankwithus/storage/Storage.java | 3 ++- .../storage/TransactionDecoder.java | 4 +-- .../storage/TransactionEncoder.java | 10 ++++---- .../seedu/bankwithus/user/Transaction.java | 2 +- .../bankwithus/user/TransactionList.java | 25 +++++-------------- text-ui-test/EXPECTED.TXT | 1 + 8 files changed, 23 insertions(+), 35 deletions(-) diff --git a/build.gradle b/build.gradle index df273ad0eb..fb5d6dd6d5 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,6 @@ repositories { } dependencies { - implementation 'org.jetbrains:annotations:23.0.0' testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.5.0' } diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 7ebf863ed9..3d2c2d0bf3 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -70,9 +70,8 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "deposit": try { accountList.depositMoney(args); - Transaction transaction = new Transaction(accountList.getMainAccount().getAccountName(), + transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(), "deposit", args, LocalDate.now()); - transactionList.addTransaction(transaction); ui.showDepositMessage(); accountList.showBal(); } catch (NumberFormatException e) { @@ -95,9 +94,8 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "withdraw": try { accountList.withdrawMoney(args); - Transaction transaction = new Transaction(accountList.getMainAccount().getAccountName(), + transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(), "withdraw", args, LocalDate.now()); - transactionList.addTransaction(transaction); accountList.showBal(); ui.printLine(); } catch (NumberFormatException e) { @@ -210,13 +208,15 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S } } - public void parseTransactionFile(Scanner scanner) throws CorruptedSaveFileException, SaveFileIsEmptyException { + public void parseTransactionFile(Scanner scanner) throws CorruptedSaveFileException, + SaveFileIsEmptyException { while (scanner.hasNextLine()) { String transactionDetails = scanner.nextLine(); if (transactionDetails.isBlank()) { throw new SaveFileIsEmptyException(); } - Transaction temp = TransactionDecoder.decodeTransaction(transactionDetails); + TransactionDecoder decoder = new TransactionDecoder(); + Transaction temp = decoder.decodeTransaction(transactionDetails); transactionList.addTransaction(temp); } scanner.close(); diff --git a/src/main/java/seedu/bankwithus/storage/Storage.java b/src/main/java/seedu/bankwithus/storage/Storage.java index 72cbc9160f..fedfb56022 100644 --- a/src/main/java/seedu/bankwithus/storage/Storage.java +++ b/src/main/java/seedu/bankwithus/storage/Storage.java @@ -93,7 +93,8 @@ public void saveToFile(AccountList list) throws IOException { */ public void saveTransactionsToFile(TransactionList transactionList) throws IOException { FileWriter fw = new FileWriter(transactionFile); - fw.write(TransactionEncoder.encodeTransactionList(transactionList)); + 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 index 35410c4a56..6db02246db 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java @@ -8,8 +8,8 @@ public class TransactionDecoder { - public static Transaction decodeTransaction(String encodedTransaction) { - String[] split = encodedTransaction.split(" /"); + public Transaction decodeTransaction(String encodedTransaction) { + String[] split = encodedTransaction.split(";"); if (split.length == 4) { String accountName = split[0]; String type = split[1]; diff --git a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java index 864d541f1f..0cbd5ef6eb 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java @@ -4,18 +4,18 @@ import seedu.bankwithus.user.TransactionList; class TransactionEncoder { - public static String encodeTransaction(Transaction transaction) { + public String encodeTransaction(Transaction transaction) { final StringBuilder encodedTransactionBuilder = new StringBuilder(); encodedTransactionBuilder.append(transaction.getAccountName()); - encodedTransactionBuilder.append(" /").append(transaction.getType()); - encodedTransactionBuilder.append(" /").append(transaction.getAmount()); - encodedTransactionBuilder.append(" /").append(transaction.getDateStr()); + encodedTransactionBuilder.append(";").append(transaction.getType()); + encodedTransactionBuilder.append(";").append(transaction.getAmount()); + encodedTransactionBuilder.append(";").append(transaction.getDateStr()); return encodedTransactionBuilder.toString(); } - public static String encodeTransactionList(TransactionList transactionList) { + public String encodeTransactionList(TransactionList transactionList) { if (transactionList.getSize() == 0) { return ""; } else { diff --git a/src/main/java/seedu/bankwithus/user/Transaction.java b/src/main/java/seedu/bankwithus/user/Transaction.java index 58a1ed0dae..faf6913433 100644 --- a/src/main/java/seedu/bankwithus/user/Transaction.java +++ b/src/main/java/seedu/bankwithus/user/Transaction.java @@ -15,7 +15,7 @@ public Transaction(String accountName, String type, String amount, LocalDate dat this.accountName = accountName; this.type = type; this.amount = amount; - this.date = LocalDate.now(); + this.date = date; } @Override diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index d9cfed5bc8..384069db43 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -33,6 +33,12 @@ public TransactionList(Scanner scanner) { } } + public void createNewTransaction(String accountName, String type, String amount, LocalDate date) { + Transaction transaction = new Transaction(accountName, type, amount, date); + transactions.add(transaction); + size++; + } + public void addTransaction(Transaction transaction) { transactions.add(transaction); size++; @@ -48,28 +54,9 @@ public int getSize() { return size; } - public void clearTransactionList() { - transactions.clear(); - size = 0; - } public void printAllTransactions() { for (int i = 0; i < size; i++) { System.out.println(transactions.get(i).toString()); } } - - public void printTransactionListByType(String type) { - for (int i = 0; i < size; i++) { - if (transactions.get(i).getType().equals(type)) { - System.out.println(transactions.get(i).toString()); - } - } - } - public void printTransactionListByDate(LocalDate date) { - for (int i = 0; i < size; i++) { - if (transactions.get(i).getDate().isBefore(date)) { - System.out.println(transactions.get(i).toString()); - } - } - } } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 6a3d487596..e19c8345a7 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -23,6 +23,7 @@ Account created! Name: hihi Balance: $1000 ---------------------------- +File not found, trying to create file. Not a valid command! Current Account: Name: hihi From 8c2c8ff8fb648849c038f380f6fd58635b642863 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sun, 26 Mar 2023 17:32:00 +0800 Subject: [PATCH 175/368] Add text ui test for view transactions feature --- text-ui-test/EXPECTED.TXT | 2 ++ text-ui-test/input.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index e19c8345a7..4d9e2b21d3 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -114,5 +114,7 @@ Balance: $123678.1 Name: hihi Balance: $1100.21 ---------------------------- +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 26/03/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 26/03/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 fb55a5975f..9990037425 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -31,5 +31,6 @@ withdraw 10 check-wl withdraw 100 view-account +view-transactions-all exit \ No newline at end of file From cb6a1298ee15072c761aa1badde26a864b66be8b Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sun, 26 Mar 2023 19:11:28 +0800 Subject: [PATCH 176/368] Remove unused imports --- src/test/java/seedu/bankwithus/AccountListTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index ab468a50e0..fa30f68769 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -2,8 +2,6 @@ import org.junit.jupiter.api.Test; import seedu.bankwithus.user.AccountList; -import seedu.bankwithus.exceptions.ExceedsWithdrawalLimitException; -import seedu.bankwithus.exceptions.InsufficientBalanceException; import seedu.bankwithus.exceptions.NegativeAmountException; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; From 12af972d030bdedce0a2436939bac022a0837678 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sun, 26 Mar 2023 19:27:54 +0800 Subject: [PATCH 177/368] Add a line to remove leading zeroes in askUserForBalance method --- src/main/java/seedu/bankwithus/user/AccountList.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 82d14041a8..f529e23f2c 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -114,6 +114,7 @@ public String askUserForName() { public String askUserForBalance() { ui.askForBalance(); String balanceString = ui.getNextLine(); + balanceString = balanceString.replaceFirst("^0+(?!$)", ""); balanceString = balanceString.trim(); try { float balance = Float.parseFloat(balanceString); From f66c9ca8d74ad5661ee9c35f15d1c4075d9f7254 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sun, 26 Mar 2023 21:33:17 +0800 Subject: [PATCH 178/368] Made template for User Guide and added most baseline infos --- docs/UserGuide.md | 216 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 193 insertions(+), 23 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index abd9fbe891..e437d4291a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,42 +1,212 @@ -# User Guide +### BankWithUs User Guide -## Introduction +-------------------------------------------------------------------------------------------------------------------- -{Give a product intro} +## Quick start -## Quick Start +1. Ensure you have Java `11` or above installed in your Computer. -{Give steps to get started quickly} +1. Download the latest `BankWithUs.jar` from [here](https://github.com/AY2223S2-CS2113-T13-3/tp/releases). -1. Ensure that you have Java 11 or above installed. -1. Down the latest version of `Duke` from [here](http://link.to/duke). +2. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. -## Features +3. 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.
-{Give detailed description of each feature} +4. 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: -### Adding a todo: `todo` -Adds a new item to the list of todo items. + * `view-transactions-all` : Lists all transactions. -Format: `todo n/TODO_NAME d/DEADLINE` + * `withdraw 300` : withdraws $300 from teh current balance. -* The `DEADLINE` can be in a natural language format. -* The `TODO_NAME` cannot contain punctuation. + * `delete` : deletes the current account the user is on. -Example of usage: + * `deposit 100` : Deposits $100 into the users account. -`todo n/Write the rest of the User Guide d/next week` + * `exit` : Exits the app. -`todo n/Refactor the User Guide to remove passive voice d/13/04/2020` +1. Refer to the [Features](#features) below for details of each command. -## FAQ +-------------------------------------------------------------------------------------------------------------------- + +## 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 which can be used as `deposit 300`. + +* 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`) will be ignored.
+ e.g. if the command specifies `help 123`, it will be interpreted as `help`. + +
+ +### Viewing help : `help` + +Shows a list of all the commands available and what they attempt to do. + +Format: `help` + + +### Adding an account: `add-account` + +Initiates Adding a new account. When calling the command there is no requirement for any parameter. +However, once the command starts, it will lead you through the process of a new account creation +prompting your name and balance to be stored. + +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.
+ + +Examples: + +```agsl +add-account +>>What is your name? +Steve +>>How much would you like to add as Balance? +1000 +``` + + +### List all transactions: `view-transactions-all` + +Shows a list of all the transactions processed by the **current** account. + +Format: `view-transactions-all` + +Example: +```agsl +>>view-transactions-all +Account Name: jenson Transaction Type: deposit Amount: 100 Date: 26/03/2023 +Account Name: jenson Transaction Type: withdraw Amount: 10 Date: 26/03/2023 +``` + + +### Depositing amount : `deposit` + +Deposits AMOUNT into the users account. + +Format: `deposit AMOUNT` + +Examples: +`deposit 100` + +### switch current account: `switch-to` + +Switches current account to the new requested account, if it exists. -**Q**: How do I transfer my data to another computer? +Format: `switch-to NAME` + +* The search is case-insensitive. e.g `jane` will match `Jane` +* Only the name is searched. +* Only full words will be matched e.g. `Ben` will not match `Benjamin` + +Examples: +``` +switch-to jenson +``` + + +### Add a savings Goal to the current account: `save` + +Adds a savings goal to teh current account.
+will raise an alert when attempting to withdraw more than the savings goal, if attempt is before deadline + +Format: `save AMOUNT` >> will then prompt the user for the deadline. + +* The amount to save has to be a number, -ve numbers alloed -- 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: +``` +save 300 +>>What would be the end date for the duration of your Saving goal? +11-11-2011 +>>try saving a Minimum of $300 until 11-11-2011 +>>Save Goal has been created, Have fun staying frugal! +``` + +### Deleting an account : `delete` + + +Format: `delete` + +* Deletes the current account. +* if you want to delete a different account, switch to that account and run delete. + +Examples: +``` +Current Account is: +---------------------------- +Name: jameson +Balance: $1000 +---------------------------- +>>delete +``` +Deletes the jameson account. + + +### Withdraw : `withdraw` + +Withdraws AMOUNT from the users balance. + +Format: `withdraw AMOUNT` + +Example: +```agsl +withdraw 500 +``` + +* cannot withdraw more than balance. +* cannot withdraw negative or non numbers. + + +### Exiting the program : `exit` + +Exits the program. + +Format: `exit` + +### Saving the data + +BankWithUs data is automatically stored when user exist the program and there is no manual inteference required. + +### Editing the data file + +Editing the savefile data is highly not recommended, and users should attempt to only do so at their own discretion. + +
:exclamation: **Caution:** +If you attempt to manipulate the saveFile and corrupted data is being parsed, you will be thrown exceptions. +if this inhibits the program from running, please delete the exisiting savefile and run program again +
+ +-------------------------------------------------------------------------------------------------------------------- + +## FAQ -**A**: {your answer here} +**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. -## Command Summary +-------------------------------------------------------------------------------------------------------------------- -{Give a 'cheat sheet' of commands here} +## Command summary -* Add todo `todo n/TODO_NAME d/DEADLINE` +| Action | Format, Examples | +|-----------------------------|----------------------| +| **Add an Account** | `add-account` | +| **swicth to a new account** | `switch-to ACC_NAME` | +| **Delete an account** | `delete` | +| **withdraw some amount** | `withdraw AMOUNT` | +| **Add a savings goal** | `save AMOUNT` | +| **Add a withdraw Limit** | `set-wl` | +| **Help** | `help` | \ No newline at end of file From fc2229d61e329f3c74822d3da9b49a6dffae69b5 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sun, 26 Mar 2023 22:51:58 +0800 Subject: [PATCH 179/368] Change position of method to remove leading zeroes to after .trim --- src/main/java/seedu/bankwithus/user/AccountList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index f529e23f2c..9793dfdf08 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -114,8 +114,8 @@ public String askUserForName() { public String askUserForBalance() { ui.askForBalance(); String balanceString = ui.getNextLine(); - balanceString = balanceString.replaceFirst("^0+(?!$)", ""); balanceString = balanceString.trim(); + balanceString = balanceString.replaceFirst("^0+(?!$)", ""); try { float balance = Float.parseFloat(balanceString); if (balance < 0) { From 0e87498632b59c00fc659c2c8d755b5975785526 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 27 Mar 2023 12:41:33 +0800 Subject: [PATCH 180/368] Change order of code to remove leading zeroes to after .trim() --- src/main/java/seedu/bankwithus/user/AccountList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index f529e23f2c..9793dfdf08 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -114,8 +114,8 @@ public String askUserForName() { public String askUserForBalance() { ui.askForBalance(); String balanceString = ui.getNextLine(); - balanceString = balanceString.replaceFirst("^0+(?!$)", ""); balanceString = balanceString.trim(); + balanceString = balanceString.replaceFirst("^0+(?!$)", ""); try { float balance = Float.parseFloat(balanceString); if (balance < 0) { From 082194592027e86db7f7ee9db74799f65b590e05 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 27 Mar 2023 12:43:33 +0800 Subject: [PATCH 181/368] Changed the expected.txt command to match todays date --- text-ui-test/EXPECTED.TXT | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 4d9e2b21d3..447f2668a7 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -114,7 +114,7 @@ Balance: $123678.1 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 26/03/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 26/03/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 27/03/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 27/03/2023 Not a valid command! Goodbye! Hope to see you again! :) From 65d1a79d2a653785b30ba93b17e091b380b80f15 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 27 Mar 2023 13:55:52 +0800 Subject: [PATCH 182/368] Corrected minor typo in userGuide --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e437d4291a..19cd3267e3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -8,7 +8,7 @@ 1. Download the latest `BankWithUs.jar` from [here](https://github.com/AY2223S2-CS2113-T13-3/tp/releases). -2. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. +2. Copy the file to the folder you want to use as the _home folder_ for your BankWithUs app. 3. 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.
From dd3dab9f5f0694d7718b6c7a60c27a726d1cba42 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 27 Mar 2023 15:23:53 +0800 Subject: [PATCH 183/368] Made minor grammatical and spelling changes as per the PR review --- docs/UserGuide.md | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 19cd3267e3..ef75a6acef 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -118,14 +118,14 @@ switch-to jenson ### Add a savings Goal to the current account: `save` -Adds a savings goal to teh current account.
-will raise an alert when attempting to withdraw more than the savings goal, if attempt is before deadline +Adds a savings goal to the current account.
+Will raise an alert when attempting to withdraw more than the savings goal, if attempt is before deadline Format: `save AMOUNT` >> will then prompt the user for the deadline. -* The amount to save has to be a number, -ve numbers alloed -- 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. +* 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: ``` @@ -171,6 +171,25 @@ withdraw 500 * cannot withdraw negative or non numbers. +### View Accounts : `view-account` + +Shows a list of all the available accounts--account name and balance. + +Format: `view-account` + +Example: +``` +view-account +Current Account: +Name: james +Balance: $1000 +---------------------------- +Name: john +Balance: $300 +---------------------------- +``` + + ### Exiting the program : `exit` Exits the program. From e678625aec6067075c7a0cc9e2234945ad10a766 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 27 Mar 2023 17:32:03 +0800 Subject: [PATCH 184/368] Solved issue so that 0.10 gets saved as 0.10 and not .10 --- src/main/java/seedu/bankwithus/ui/Ui.java | 2 +- src/main/java/seedu/bankwithus/user/AccountList.java | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index ef6c448310..13c0025386 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -10,7 +10,7 @@ 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("Try saving a minimum of $"+args+" until "+untilWhenStr); System.out.println("Save Goal has been created, Have fun staying frugal!"); } public void showFileNotFoundError() { diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 9793dfdf08..93bbbd29b3 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -116,6 +116,10 @@ public String askUserForBalance() { String balanceString = ui.getNextLine(); balanceString = balanceString.trim(); balanceString = balanceString.replaceFirst("^0+(?!$)", ""); + float bal = Float.parseFloat(balanceString); + if (bal < 1) { + balanceString = "0"+balanceString; + } try { float balance = Float.parseFloat(balanceString); if (balance < 0) { @@ -218,7 +222,9 @@ public String getAllAccountDetails() throws AccountNotFoundException { //@@author public void showBal() { String balance = getMainAccount().getAccountBalance(); + float bal = Float.parseFloat(balance); ui.showBal(balance); + } //@@author xiaoge26 From 1a1732602439b49a7582487ee29cc13541ab8de1 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 27 Mar 2023 17:35:26 +0800 Subject: [PATCH 185/368] Changed spelling in the save goal porton of userGuide --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index ef75a6acef..76b1518cbe 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -132,7 +132,7 @@ Examples: save 300 >>What would be the end date for the duration of your Saving goal? 11-11-2011 ->>try saving a Minimum of $300 until 11-11-2011 +>>Try saving a minimum of $300 until 11-11-2011 >>Save Goal has been created, Have fun staying frugal! ``` From 94cbed0f50809354a42fb1e95e22d426a7c5238b Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 27 Mar 2023 17:49:33 +0800 Subject: [PATCH 186/368] Update expected.txt to comply with io redir --- src/main/java/seedu/bankwithus/user/AccountList.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 93bbbd29b3..3a15a9898d 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -116,12 +116,11 @@ public String askUserForBalance() { String balanceString = ui.getNextLine(); balanceString = balanceString.trim(); balanceString = balanceString.replaceFirst("^0+(?!$)", ""); - float bal = Float.parseFloat(balanceString); - if (bal < 1) { - balanceString = "0"+balanceString; - } try { float balance = Float.parseFloat(balanceString); + if (balance < 1) { + balanceString = "0"+balanceString; + } if (balance < 0) { throw new NegativeAmountException(); } From a2f399d8c25eff5568e2249b41e67be95f1d5e39 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Tue, 28 Mar 2023 14:26:52 +0800 Subject: [PATCH 187/368] Change logic and name of SaveGoal command --- src/main/java/seedu/bankwithus/parser/Parser.java | 2 +- src/main/java/seedu/bankwithus/user/AccountList.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 87b24f1c31..a860ed6122 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -144,7 +144,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "help": ui.showHelp(); break; - case "save": + case "set-save-goal": if(args.length() > 0) { String untilWhenStr = ui.getDeadline(); accountList.handleSaveGoal(args, untilWhenStr); diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 3a15a9898d..1552fdd79e 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -426,8 +426,8 @@ public Boolean isFailsSaveGoal(float currentBalance, float withdrawAmount) { LocalDate tdy = LocalDate.now(); LocalDate tdyDate = handleDate(tdy); boolean exceedsSaveGoal = getMainAccount().getSaveGoal().amtToSave > expectedBal; - boolean deadlinePassed = getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate); - return (exceedsSaveGoal && !deadlinePassed); + boolean deadlineNotPassed = getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate); + return (exceedsSaveGoal && deadlineNotPassed); } //@@author tyuyang From 9a7230a7b2deff4cf6db4123cfb1b708a66b2256 Mon Sep 17 00:00:00 2001 From: manushridiv Date: Tue, 28 Mar 2023 14:38:59 +0800 Subject: [PATCH 188/368] changes to UG and storage files --- docs/UserGuide.md | 27 ++++++++++--------- .../storage/TransactionDecoder.java | 5 ++-- .../storage/TransactionEncoder.java | 5 +++- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 76b1518cbe..22efd5b960 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -2,28 +2,28 @@ -------------------------------------------------------------------------------------------------------------------- -## Quick start +## Quick start guide 1. Ensure you have Java `11` or above installed in your Computer. -1. Download the latest `BankWithUs.jar` from [here](https://github.com/AY2223S2-CS2113-T13-3/tp/releases). +2. Download the latest `BankWithUs.jar` from [here](https://github.com/AY2223S2-CS2113-T13-3/tp/releases). -2. Copy the file to the folder you want to use as the _home folder_ for your BankWithUs app. +3. Copy the file to the folder you want to use as the _home folder_ for your BankWithUs app. -3. 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.
+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.
-4. Follow the instruction as per the CLI and create your new account. e.g. typing **`help`** and pressing Enter will open the help option.
+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: - * `view-transactions-all` : Lists all transactions. + * `view-transactions-all` : Lists all transactions which has been committed in the app (a record) - * `withdraw 300` : withdraws $300 from teh current balance. + * `withdraw 300` : withdraws $300 from the current balance. (subsitute 300 for other numbers) - * `delete` : deletes the current account the user is on. + * `delete` : deletes the current account which the user has initially created. - * `deposit 100` : Deposits $100 into the users account. + * `deposit 100` : Deposits $100 into the users account. (subsitute 100 for other numbers) - * `exit` : Exits the app. + * `exit` : Exits the application 1. Refer to the [Features](#features) below for details of each command. @@ -51,8 +51,6 @@ Shows a list of all the commands available and what they attempt to do. Format: `help` - - ### Adding an account: `add-account` Initiates Adding a new account. When calling the command there is no requirement for any parameter. @@ -66,6 +64,8 @@ CLI prompts: "How much would you like to add as Balance?"
your input: `BALANCE` Note: Balance has to be a valid number.
+ + Examples: ```agsl @@ -100,6 +100,7 @@ Format: `deposit AMOUNT` Examples: `deposit 100` + ### switch current account: `switch-to` Switches current account to the new requested account, if it exists. @@ -110,6 +111,8 @@ Format: `switch-to NAME` * Only the name is searched. * Only full words will be matched e.g. `Ben` will not match `Benjamin` + + Examples: ``` switch-to jenson diff --git a/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java b/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java index 6db02246db..1c2f5fd17f 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionDecoder.java @@ -1,7 +1,6 @@ package seedu.bankwithus.storage; import seedu.bankwithus.user.Transaction; - import java.time.LocalDate; import java.time.format.DateTimeFormatter; @@ -9,7 +8,9 @@ public class TransactionDecoder { public Transaction decodeTransaction(String encodedTransaction) { - String[] split = encodedTransaction.split(";"); + //code quality recs + String[] split; + split = encodedTransaction.split(";"); if (split.length == 4) { String accountName = split[0]; String type = split[1]; diff --git a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java index 0cbd5ef6eb..2e8b09780a 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java @@ -5,7 +5,10 @@ class TransactionEncoder { public String encodeTransaction(Transaction transaction) { - final StringBuilder encodedTransactionBuilder = new StringBuilder(); + + //minor fix in the code, buggy + final StringBuilder encodedTransactionBuilder; + encodedTransactionBuilder = new StringBuilder(); encodedTransactionBuilder.append(transaction.getAccountName()); encodedTransactionBuilder.append(";").append(transaction.getType()); From 1253080e3b69f402faff48417bfe6975d4c5438a Mon Sep 17 00:00:00 2001 From: manushridiv Date: Tue, 28 Mar 2023 14:50:45 +0800 Subject: [PATCH 189/368] changes to UG, storage and fix date bugs --- src/main/java/seedu/bankwithus/ui/Ui.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 13c0025386..aea588eab0 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -3,6 +3,8 @@ import seedu.bankwithus.user.Account; import seedu.bankwithus.common.SaveGoal; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.Scanner; public class Ui { @@ -230,7 +232,10 @@ public void failToMeetSaveGoal() { public void showGoal(SaveGoal goal) { System.out.println("Min amount to save: $" + Float.toString(goal.amtToSave)); - System.out.println("Deadline: "+goal.untilWhen); + LocalDate date = goal.untilWhen; + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); + String untilwhen = date.format(formatter); + System.out.println("Deadline: "+untilwhen); printLine(); } From cdf6108a4df691c52d84f60a88419d7df42c9474 Mon Sep 17 00:00:00 2001 From: manushridiv Date: Tue, 28 Mar 2023 14:55:29 +0800 Subject: [PATCH 190/368] changes to date --- text-ui-test/EXPECTED.TXT | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 447f2668a7..5ae164a886 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -114,7 +114,7 @@ Balance: $123678.1 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 27/03/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 27/03/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 28/03/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 28/03/2023 Not a valid command! Goodbye! Hope to see you again! :) From 8c789da6bd6918f9d4db1bb4b13c3570b709cc6d Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 15:02:03 +0800 Subject: [PATCH 191/368] Fix transaction history not having feedback if there are no transactions --- .../exceptions/NoTransactionsFoundException.java | 5 +++++ src/main/java/seedu/bankwithus/parser/Parser.java | 7 ++++++- src/main/java/seedu/bankwithus/ui/Ui.java | 5 +++++ src/main/java/seedu/bankwithus/user/TransactionList.java | 6 +++++- 4 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/NoTransactionsFoundException.java 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/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index a860ed6122..bd078c8ea3 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -13,6 +13,7 @@ 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 java.io.IOException; @@ -159,7 +160,11 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce accountList.deleteAccount(args); break; case "view-transactions-all": - transactionList.printAllTransactions(); + try { + transactionList.printAllTransactions(); + } catch (NoTransactionsFoundException e) { + ui.noTransactionsFoundError(); + } break; default: throw new CommandNotFoundException(); diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 13c0025386..69114ee782 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -264,4 +264,9 @@ 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 noTransactionsFoundError() { + System.out.println("No transactions found!"); + printLine(); + } } diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 384069db43..a9d1fa3489 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -1,6 +1,7 @@ package seedu.bankwithus.user; import seedu.bankwithus.exceptions.CorruptedSaveFileException; +import seedu.bankwithus.exceptions.NoTransactionsFoundException; import seedu.bankwithus.exceptions.SaveFileIsEmptyException; import seedu.bankwithus.parser.Parser; import seedu.bankwithus.ui.Ui; @@ -54,7 +55,10 @@ public int getSize() { return size; } - public void printAllTransactions() { + public void printAllTransactions() throws NoTransactionsFoundException { + if (size == 0) { + throw new NoTransactionsFoundException(); + } for (int i = 0; i < size; i++) { System.out.println(transactions.get(i).toString()); } From ca08a7f18182785698222e9d42fcaf56f6b9c8f2 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 15:02:31 +0800 Subject: [PATCH 192/368] Add printLine function after show-transactions is complete --- src/main/java/seedu/bankwithus/parser/Parser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index bd078c8ea3..65a4055bee 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -162,6 +162,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "view-transactions-all": try { transactionList.printAllTransactions(); + ui.printLine(); } catch (NoTransactionsFoundException e) { ui.noTransactionsFoundError(); } From 9375f04e597689369428df4ed84664ce8b3796cb Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Tue, 28 Mar 2023 15:06:55 +0800 Subject: [PATCH 193/368] Modified User Guide and Developer Guide --- docs/DeveloperGuide.md | 18 +++++++++++++++++- docs/UserGuide.md | 17 ++++++++++------- .../bankwithus/storage/TransactionEncoder.java | 5 +++++ .../seedu/bankwithus/user/Transaction.java | 1 + .../seedu/bankwithus/user/TransactionList.java | 1 + 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index e5905cd17f..bf879bec0d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -12,6 +12,8 @@ * [SaveGoal Component](#saveGoal-component) * [Storage Component](#storage-component) * [Withdrawal Limit Component](#withdraw limit checker-Component) + * [Transaction Component](#transaction-Component) + * [TransactionList Component](#transactionlist-component) * [Implementation](#implementation) * [Account related Feature](#Account-feature) * [saveGoal related Feature](#SaveGoal-feature) @@ -95,11 +97,25 @@ Class: `Storage.java` The `Storage` component: -* Handles storing data in sa save file and also loading data, if any, when program opens. +* Handles storing data in the save files and also loading data, if any, when program opens. ### Withdraw-Limit-Checker-Component Class: `WithdrawalChecker.java` +### 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. +* Has methods to add and view transactions + --- ## Implementation diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 76b1518cbe..5eb1f23d6c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -79,7 +79,7 @@ Steve ### List all transactions: `view-transactions-all` -Shows a list of all the transactions processed by the **current** account. +Shows a list of all the transactions processed by all the accounts of the user. Format: `view-transactions-all` @@ -93,7 +93,7 @@ Account Name: jenson Transaction Type: withdraw Amount: 10 Date: 26/03/2023 ### Depositing amount : `deposit` -Deposits AMOUNT into the users account. +Deposits AMOUNT into the *current account*. Format: `deposit AMOUNT` @@ -102,7 +102,7 @@ Examples: ### switch current account: `switch-to` -Switches current account to the new requested account, if it exists. +Switches from the *current account* to the new requested account, if it exists. Format: `switch-to NAME` @@ -118,7 +118,7 @@ switch-to jenson ### Add a savings Goal to the current account: `save` -Adds a savings goal to the current account.
+Adds a savings goal to the *current account*.
Will raise an alert when attempting to withdraw more than the savings goal, if attempt is before deadline Format: `save AMOUNT` >> will then prompt the user for the deadline. @@ -200,15 +200,18 @@ Format: `exit` BankWithUs data is automatically stored when user exist the program and there is no manual inteference required. -### Editing the data file +### Editing the data files Editing the savefile data is highly not recommended, and users should attempt to only do so at their own discretion. -
:exclamation: **Caution:** +
+Warning:
If you attempt to manipulate the saveFile and corrupted data is being parsed, you will be thrown exceptions. -if this inhibits the program from running, please delete the exisiting savefile and run program again +If this inhibits the program from running, please delete the exisiting savefile and run program again
+ + -------------------------------------------------------------------------------------------------------------------- ## FAQ diff --git a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java index 0cbd5ef6eb..d9c4a9e64e 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java @@ -2,8 +2,12 @@ import seedu.bankwithus.user.Transaction; import seedu.bankwithus.user.TransactionList; +import java.util.logging.*; + class TransactionEncoder { + private static final Logger logger = + Logger.getLogger(TransactionEncoder.class.getName()); public String encodeTransaction(Transaction transaction) { final StringBuilder encodedTransactionBuilder = new StringBuilder(); @@ -16,6 +20,7 @@ public String encodeTransaction(Transaction transaction) { } public String encodeTransactionList(TransactionList transactionList) { + logger.log(Level.INFO, "Encoding TransactionList"); if (transactionList.getSize() == 0) { return ""; } else { diff --git a/src/main/java/seedu/bankwithus/user/Transaction.java b/src/main/java/seedu/bankwithus/user/Transaction.java index faf6913433..c813e32346 100644 --- a/src/main/java/seedu/bankwithus/user/Transaction.java +++ b/src/main/java/seedu/bankwithus/user/Transaction.java @@ -20,6 +20,7 @@ public Transaction(String accountName, String type, String amount, LocalDate dat @Override public String toString() { + assert date != null; return "Account Name: " + accountName + " Transaction Type: " + type + " Amount: " + amount diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 384069db43..63561c962b 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -35,6 +35,7 @@ public TransactionList(Scanner scanner) { 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++; } From 1ae38a0ce30d9abf38adcdb5d5d14ed9d0d32320 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Tue, 28 Mar 2023 15:11:27 +0800 Subject: [PATCH 194/368] Fix checkstyle errors --- src/main/java/seedu/bankwithus/storage/TransactionEncoder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java index d9c4a9e64e..5db0503714 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java @@ -2,7 +2,8 @@ import seedu.bankwithus.user.Transaction; import seedu.bankwithus.user.TransactionList; -import java.util.logging.*; +import java.util.logging.Level; +import java.util.logging.Logger; class TransactionEncoder { From db3becc0ebabe684f145cd2de2794a13369e9c1c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 15:14:05 +0800 Subject: [PATCH 195/368] Fix checkstyle issues --- src/main/java/seedu/bankwithus/parser/Parser.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 65a4055bee..ef4ae58c0a 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -160,12 +160,12 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce accountList.deleteAccount(args); break; case "view-transactions-all": - try { - transactionList.printAllTransactions(); - ui.printLine(); - } catch (NoTransactionsFoundException e) { - ui.noTransactionsFoundError(); - } + try { + transactionList.printAllTransactions(); + ui.printLine(); + } catch (NoTransactionsFoundException e) { + ui.noTransactionsFoundError(); + } break; default: throw new CommandNotFoundException(); From 7dd49c6673ec1e196c15218291512bceb4790822 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 15:18:24 +0800 Subject: [PATCH 196/368] Modify expected.txt --- text-ui-test/EXPECTED.TXT | 1 + 1 file changed, 1 insertion(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 5ae164a886..3c2e92dd92 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -116,5 +116,6 @@ Balance: $1100.21 ---------------------------- Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 28/03/2023 Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 28/03/2023 +---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 0a8547e62952c89c9536ee19bc5b711800a03c4e Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Tue, 28 Mar 2023 15:22:40 +0800 Subject: [PATCH 197/368] Fix typos --- docs/UserGuide.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 5eb1f23d6c..e620439d3f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -206,8 +206,11 @@ Editing the savefile data is highly not recommended, and users should attempt to
Warning:
-If you attempt to manipulate the saveFile and corrupted data is being parsed, you will be thrown exceptions. -If this inhibits the program from running, please delete the exisiting savefile and run program again +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.
From e5219cdbca693971d6269a85414785c3a4848a94 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 15:34:53 +0800 Subject: [PATCH 198/368] Update show help --- src/main/java/seedu/bankwithus/parser/Parser.java | 2 +- src/main/java/seedu/bankwithus/ui/Ui.java | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index ef4ae58c0a..3fc8a07318 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -153,7 +153,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showInsufficientArgsEntered(); } break; - case "show-saveGoal": + case "show-save-goal": accountList.showGoal(); break; case "delete": diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 6068b6d7c0..c774fda043 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -112,15 +112,17 @@ public void showInsufficientBalanceMessage() { public void showHelp() { printLine(); System.out.println("help: displays the current menu"); - System.out.println("view-account: shows account name and balance"); + 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("save : sets a saveGoal of until "); + 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"); - System.out.println(" this month."); + 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("exit: quits program and saves"); printLine(); } From 2b3073c317f8bbe34d7b04a6e932765eb0eb434b Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 15:39:41 +0800 Subject: [PATCH 199/368] Fix checkstyle --- src/main/java/seedu/bankwithus/ui/Ui.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index c774fda043..ae12646866 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -115,13 +115,16 @@ public void showHelp() { 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("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("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("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("exit: quits program and saves"); printLine(); From 19a32b56bdbf7e2c31e5ed8f53c73caaab43ffb4 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 15:44:38 +0800 Subject: [PATCH 200/368] Fixed 2 small bugs: no printline after deposit, and set-wl no $ sign --- src/main/java/seedu/bankwithus/parser/Parser.java | 1 + src/main/java/seedu/bankwithus/ui/Ui.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 3fc8a07318..d15b4b9ff4 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -75,6 +75,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce "deposit", args, LocalDate.now()); ui.showDepositMessage(); accountList.showBal(); + ui.printLine(); } catch (NumberFormatException e) { ui.showNumberFormatError(); } catch (NullPointerException e) { diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index ae12646866..91ebb10042 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -255,7 +255,7 @@ public String getDeadline() { //@@author tyuyang public void showWithdrawalLimitSet(String withdrawalLimit) { - System.out.println("Withdrawal limit set to " + withdrawalLimit + "!"); + System.out.println("Withdrawal limit set to $" + withdrawalLimit + "!"); } public void showWithdrawalLimit(String withdrawalLimit) { From 5a741a08ab810db3c0d24d1064eafea49315f4f1 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 15:48:52 +0800 Subject: [PATCH 201/368] Update expected.txt --- text-ui-test/EXPECTED.TXT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 3c2e92dd92..1cc122e6e9 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -89,7 +89,7 @@ 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 set to $100! ---------------------------- Withdrawal limit is currently $100. You have withdrawn $100 this month. From 6fb84a4af27c73f14550e4ec99b6d067eeef6829 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 15:52:56 +0800 Subject: [PATCH 202/368] Update expected.txt --- text-ui-test/EXPECTED.TXT | 1 + 1 file changed, 1 insertion(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 1cc122e6e9..8c7a742cf9 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -37,6 +37,7 @@ Balance: $1000 ---------------------------- New deposit added! You have $1100.21 remaining! +---------------------------- Current Account: Name: hihi Balance: $1100.21 From 95336d103139d193e4a382cf99c83a8907baac8d Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 16:53:34 +0800 Subject: [PATCH 203/368] Shifted ui.showFileCreated() to BWU since that is the only use of Ui in storage --- src/main/java/seedu/bankwithus/BankWithUs.java | 1 + src/main/java/seedu/bankwithus/storage/Storage.java | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 50b5200fcb..9d1199769e 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -48,6 +48,7 @@ public BankWithUs(String accountsFilePath, String transactionsFilePath) throws I ui.showFileNotFoundError(); try { storage.createNewAccountsFile(); + ui.showFileCreated(); } catch (IOException ioE) { ui.showIOError(); throw ioE; diff --git a/src/main/java/seedu/bankwithus/storage/Storage.java b/src/main/java/seedu/bankwithus/storage/Storage.java index fedfb56022..8bb371f28b 100644 --- a/src/main/java/seedu/bankwithus/storage/Storage.java +++ b/src/main/java/seedu/bankwithus/storage/Storage.java @@ -17,8 +17,6 @@ public class Storage { protected File transactionFile; private final File saveDir = new File("data"); - private Ui ui; - /** * Creates a new instance of Storage. Initialises the saveFile. @@ -29,7 +27,6 @@ public class Storage { public Storage(String accountsFilepath, String transactionsFilepath) { this.accountFile = new File(accountsFilepath); this.transactionFile = new File(transactionsFilepath); - this.ui = new Ui(); } /** @@ -56,7 +53,6 @@ public Scanner loadTransactions() throws FileNotFoundException { public void createNewAccountsFile() throws IOException { saveDir.mkdir(); accountFile.createNewFile(); - ui.showFileCreated(); } From 0d9d0d29ee78287f2ca6c9f964482fcd83f2e0a6 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 16:55:21 +0800 Subject: [PATCH 204/368] Add tentative puml diagram for main architecture --- docs/diagrams/main_architecture.puml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docs/diagrams/main_architecture.puml diff --git a/docs/diagrams/main_architecture.puml b/docs/diagrams/main_architecture.puml new file mode 100644 index 0000000000..ae14f514af --- /dev/null +++ b/docs/diagrams/main_architecture.puml @@ -0,0 +1,20 @@ +@startuml +class BankWithUs +class Storage +class AccountList +class Ui +class TransactionList +class Parser +BankWithUs --> Storage +Storage --> AccountList +Storage --> TransactionList +BankWithUs --> Parser +BankWithUs --> AccountList +BankWithUs --> TransactionList +BankWithUs --> Ui +Parser --> Ui +Parser --> AccountList +Parser --> TransactionList +AccountList --> Ui +TransactionList --> Ui +@enduml \ No newline at end of file From b64a0bbf2cd5ca5c4b19a0d91c6a1cc737d9a487 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 17:15:44 +0800 Subject: [PATCH 205/368] Refine puml main diagram --- docs/diagrams/main_architecture.puml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/diagrams/main_architecture.puml b/docs/diagrams/main_architecture.puml index ae14f514af..1f74102015 100644 --- a/docs/diagrams/main_architecture.puml +++ b/docs/diagrams/main_architecture.puml @@ -6,15 +6,17 @@ class Ui class TransactionList class Parser BankWithUs --> Storage -Storage --> AccountList -Storage --> TransactionList +AccountList ..> Storage +TransactionList ..> Storage BankWithUs --> Parser BankWithUs --> AccountList +AccountList ..> BankWithUs BankWithUs --> TransactionList BankWithUs --> Ui Parser --> Ui -Parser --> AccountList -Parser --> TransactionList +Parser <--> AccountList +Parser <--> TransactionList AccountList --> Ui TransactionList --> Ui + @enduml \ No newline at end of file From 98ad6e89cc3020efc2399eecb34bdcd80bae424c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 17:29:30 +0800 Subject: [PATCH 206/368] Add temporary sequence uml diagram --- docs/diagrams/example_sequence_diagram.puml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/diagrams/example_sequence_diagram.puml diff --git a/docs/diagrams/example_sequence_diagram.puml b/docs/diagrams/example_sequence_diagram.puml new file mode 100644 index 0000000000..8d88454775 --- /dev/null +++ b/docs/diagrams/example_sequence_diagram.puml @@ -0,0 +1,14 @@ +@startuml +actor Shawn +participant Ui +participant BWU +participant Parser +participant AccountList +participant Account +activate BWU +BWU -> Ui:getN +activate Ui + + + +@enduml \ No newline at end of file From 6f4acf10f5b28d8a6404143f0c165beaf00df4be Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 17:29:55 +0800 Subject: [PATCH 207/368] Removed unused import --- src/main/java/seedu/bankwithus/storage/Storage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/storage/Storage.java b/src/main/java/seedu/bankwithus/storage/Storage.java index 8bb371f28b..27d6bc6b03 100644 --- a/src/main/java/seedu/bankwithus/storage/Storage.java +++ b/src/main/java/seedu/bankwithus/storage/Storage.java @@ -2,7 +2,6 @@ import seedu.bankwithus.user.AccountList; import seedu.bankwithus.user.TransactionList; -import seedu.bankwithus.ui.Ui; import seedu.bankwithus.exceptions.AccountNotFoundException; import java.io.File; From a1c18d08d4b91b830d45195114090d998e82e9c7 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 28 Mar 2023 17:57:50 +0800 Subject: [PATCH 208/368] Continued on example sequence diagram --- docs/diagrams/example_sequence_diagram.puml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/diagrams/example_sequence_diagram.puml b/docs/diagrams/example_sequence_diagram.puml index 8d88454775..bec9ddc332 100644 --- a/docs/diagrams/example_sequence_diagram.puml +++ b/docs/diagrams/example_sequence_diagram.puml @@ -6,9 +6,25 @@ participant Parser participant AccountList participant Account activate BWU -BWU -> Ui:getN +BWU -> Ui:getNextLine() activate Ui - +Shawn -> Ui:deposit 100 +Ui --> BWU:"deposit 100" +deactivate Ui +BWU -> BWU:line = "deposit 100" +BWU -> Parser:parseUserInput(line) +activate Parser +Parser -> Parser:command = "deposit"\nargs = "100" +alt deposit +Parser -> AccountList:depositMoney(args) +activate AccountList +AccountList -> AccountList:depositAmount = \nparseFloat("args") +AccountList -> Account:addBalance() +activate Account +Account -> Account:balance = "100" +Account --> AccountList +deactivate Account +end @enduml \ No newline at end of file From 7035cdd3143d1063e72ac13df93f49a388e89b3b Mon Sep 17 00:00:00 2001 From: tyuyang Date: Wed, 29 Mar 2023 12:28:22 +0800 Subject: [PATCH 209/368] Finished example seq diagram --- docs/diagrams/example_sequence_diagram.puml | 56 ++++++++++++++++++--- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/docs/diagrams/example_sequence_diagram.puml b/docs/diagrams/example_sequence_diagram.puml index bec9ddc332..4ec94c1160 100644 --- a/docs/diagrams/example_sequence_diagram.puml +++ b/docs/diagrams/example_sequence_diagram.puml @@ -5,26 +5,70 @@ participant BWU participant Parser participant AccountList participant Account +participant TransactionList +participant Transaction +activate Ui activate BWU +activate Parser +activate AccountList +activate Account +activate TransactionList +loop if exit not entered BWU -> Ui:getNextLine() activate Ui Shawn -> Ui:deposit 100 Ui --> BWU:"deposit 100" deactivate Ui -BWU -> BWU:line = "deposit 100" BWU -> Parser:parseUserInput(line) activate Parser -Parser -> Parser:command = "deposit"\nargs = "100" alt deposit Parser -> AccountList:depositMoney(args) activate AccountList -AccountList -> AccountList:depositAmount = \nparseFloat("args") AccountList -> Account:addBalance() activate Account -Account -> Account:balance = "100" +Account -> Account:balance += 100 Account --> AccountList deactivate Account +AccountList --> Parser +deactivate AccountList +Parser -> TransactionList:createNewTransaction() +activate TransactionList +TransactionList -> Transaction:new Transaction() +activate Transaction +Transaction --> TransactionList +deactivate Transaction +TransactionList -> TransactionList:add(transaction) +activate TransactionList +TransactionList --> TransactionList +deactivate TransactionList +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:getMainAccount() +Account -> Account:getAccountBalance() +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 From 9a1f634478e7ce8bf29fd4e5a7afc4d662e37056 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Wed, 29 Mar 2023 12:48:24 +0800 Subject: [PATCH 210/368] Added tentative puml diagrams to Developer guide --- docs/DeveloperGuide.md | 7 +++++++ docs/diagrams/example_sequence_diagram.puml | 2 +- docs/diagrams/main_architecture.puml | 2 +- docs/images/MainArchitecture.png | Bin 0 -> 26201 bytes docs/images/deposit100SeqDiagram.png | Bin 0 -> 73306 bytes 5 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 docs/images/MainArchitecture.png create mode 100644 docs/images/deposit100SeqDiagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index bf879bec0d..37d4b424f9 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -46,6 +46,13 @@ ### Design ### Architecture + + +**Interactions** + +The sequence diagram below shows how components interact with each other when the user issues the command `deposit 100`. + + ### UI-Component diff --git a/docs/diagrams/example_sequence_diagram.puml b/docs/diagrams/example_sequence_diagram.puml index 4ec94c1160..5aec8e02d6 100644 --- a/docs/diagrams/example_sequence_diagram.puml +++ b/docs/diagrams/example_sequence_diagram.puml @@ -1,4 +1,4 @@ -@startuml +@startuml deposit100SeqDiagram actor Shawn participant Ui participant BWU diff --git a/docs/diagrams/main_architecture.puml b/docs/diagrams/main_architecture.puml index 1f74102015..156ea10ced 100644 --- a/docs/diagrams/main_architecture.puml +++ b/docs/diagrams/main_architecture.puml @@ -1,4 +1,4 @@ -@startuml +@startuml MainArchitecture class BankWithUs class Storage class AccountList diff --git a/docs/images/MainArchitecture.png b/docs/images/MainArchitecture.png new file mode 100644 index 0000000000000000000000000000000000000000..0184c7036468c70270a7883a485246aaf28b6874 GIT binary patch literal 26201 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 I;LQX72UD%zW&i*H literal 0 HcmV?d00001 diff --git a/docs/images/deposit100SeqDiagram.png b/docs/images/deposit100SeqDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..4815797d2668d67f01eb7b2c0566edf3cde5626c GIT binary patch literal 73306 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 Date: Wed, 29 Mar 2023 12:58:56 +0800 Subject: [PATCH 211/368] Change the stupid 2 lines --- text-ui-test/EXPECTED.TXT | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 8c7a742cf9..cc35ac5d26 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -115,8 +115,8 @@ Balance: $123678.1 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 28/03/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 28/03/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 29/03/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 29/03/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 57b048479d7e7af0bf61ebbd6921795678213d9a Mon Sep 17 00:00:00 2001 From: tyuyang Date: Wed, 29 Mar 2023 14:11:38 +0800 Subject: [PATCH 212/368] Make lots of changes: 1. Fix spelling mistakes 2. Rephrase certain lines 3. Change the order of features 4. Add set-wl and check-wl feature --- docs/UserGuide.md | 216 +++++++++++++++++++++++++++++++--------------- 1 file changed, 148 insertions(+), 68 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 042e5d62e4..c7d473889b 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -15,13 +15,13 @@ 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: - * `view-transactions-all` : Lists all transactions which has been committed in the app (a record) + * `view-transactions-all` : Lists all recorded transactions - * `withdraw 300` : withdraws $300 from the current balance. (subsitute 300 for other numbers) + * `withdraw 300` : Withdraws $300 from the current balance. (Subsitute 300 for other numbers) - * `delete` : deletes the current account which the user has initially created. + * `delete` : Deletes the current account which the user has initially created. - * `deposit 100` : Deposits $100 into the users account. (subsitute 100 for other numbers) + * `deposit 100` : Deposits $100 into the users account. (Subsitute 100 for other numbers) * `exit` : Exits the application @@ -36,7 +36,7 @@ **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 which can be used as `deposit 300`. + e.g. in `deposit AMOUNT`, `AMOUNT` is a parameter. `deposit 300` is an example of a valid command syntax. * Parameters MUST be in the specified order for the command to take appropriate effect.
@@ -48,14 +48,33 @@ ### Viewing help : `help` -Shows a list of all the commands available and what they attempt to do. +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 +exit: quits program and saves +``` + ### Adding an account: `add-account` -Initiates Adding a new account. When calling the command there is no requirement for any parameter. -However, once the command starts, it will lead you through the process of a new account creation -prompting your name and balance to be stored. +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?"
@@ -74,50 +93,121 @@ add-account Steve >>How much would you like to add as Balance? 1000 +Account created! +Name: Steve +Balance: $1000 ``` +### Switch current account: `switch-to` -### List all transactions: `view-transactions-all` +Switches from the *current account* to the new requested account, if it exists. -Shows a list of all the transactions processed by all the accounts of the user. +Format: `switch-to NAME` -Format: `view-transactions-all` +* The search is not case-sensitive. e.g `jane` will match `Jane` +* Only the name is searched. +* Only full words will be matched e.g. `Ben` will not match `Benjamin` -Example: -```agsl ->>view-transactions-all -Account Name: jenson Transaction Type: deposit Amount: 100 Date: 26/03/2023 -Account Name: jenson Transaction Type: withdraw Amount: 10 Date: 26/03/2023 + + +Examples: +``` +switch-to jenson +Current Account switched +---------------------------- +Current Account is: +---------------------------- +Name: jenson +Balance: $90 ``` -### Depositing amount : `deposit` +### Deleting an account : `delete` -Deposits AMOUNT into the *current account*. -Format: `deposit AMOUNT` +Format: `delete` + +* Deletes the current account. +* If you want to delete a different account, switch to that account and run delete. Examples: -`deposit 100` +``` +Current Account is: +---------------------------- +Name: jameson +Balance: $1000 +---------------------------- +>>delete +``` +Deletes the jameson account. +### View Accounts : `view-account` -### switch current account: `switch-to` +Shows a list of all the available accounts with their account name and balance. -Switches from the *current account* to the new requested account, if it exists. +Format: `view-account` -Format: `switch-to NAME` +Example: +``` +view-account +Current Account: +Name: james +Balance: $1000 +---------------------------- +Name: john +Balance: $300 +``` -* The search is case-insensitive. e.g `jane` will match `Jane` -* Only the name is searched. -* Only full words will be matched e.g. `Ben` will not match `Benjamin` +### Depositing amount : `deposit` +Deposits AMOUNT into the *current account*. +Format: `deposit AMOUNT` -Examples: +Example: +```agsl +deposit 100 +New deposit added! +You have $190 remaining! ``` -switch-to jenson + +* Cannot deposit negative numbers. +* Cannot deposit arguments that are not numbers. + +Attempting to do so will show error messages. + + +### Withdraw : `withdraw` + +Withdraws AMOUNT from the users balance. + +Format: `withdraw AMOUNT` + +Example: +```agsl +withdraw 500 ``` +* Cannot withdraw more than balance. +* Cannot withdraw negative numbers. +* Cannot withdraw arguments that are not numbers. + +Attempting to do so will show error messages. + +See [saving goals](#add-a-savings-goal-to-the-current-account-save) and [withdrawal limit]() for more information. + +### 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: +```agsl +>>view-transactions-all +Account Name: jenson Transaction Type: deposit Amount: 100 Date: 26/03/2023 +Account Name: jenson Transaction Type: withdraw Amount: 10 Date: 26/03/2023 +``` ### Add a savings Goal to the current account: `save` @@ -139,60 +229,50 @@ save 300 >>Save Goal has been created, Have fun staying frugal! ``` -### Deleting an account : `delete` +### 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: `delete` +Format: `set-wl AMOUNT` will set `AMOUNT` as the withdrawal limit. -* Deletes the current account. -* if you want to delete a different account, switch to that account and run delete. +* AMOUNT must be a valid number. If AMOUNT is not valid, an error message will be shown. -Examples: ``` -Current Account is: ----------------------------- -Name: jameson -Balance: $1000 +set-wl 100 +Withdrawal limit set to $100! ---------------------------- ->>delete -``` -Deletes the jameson account. - - -### Withdraw : `withdraw` - -Withdraws AMOUNT from the users balance. - -Format: `withdraw AMOUNT` - -Example: -```agsl -withdraw 500 +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. ``` -* cannot withdraw more than balance. -* cannot withdraw negative or non numbers. +### Check the current withdrawal limit: `check-wl` +Shows the current withdrawal limit and the total amount of money withdrawn in the current month. -### View Accounts : `view-account` - -Shows a list of all the available accounts--account name and balance. - -Format: `view-account` +Format: `check-wl` Example: ``` -view-account -Current Account: -Name: james -Balance: $1000 +set-wl 100 +Withdrawal limit set to $100! ---------------------------- -Name: john -Balance: $300 +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. ``` - ### Exiting the program : `exit` Exits the program. @@ -201,11 +281,11 @@ Format: `exit` ### Saving the data -BankWithUs data is automatically stored when user exist the program and there is no manual inteference required. +BankWithUs data is automatically stored when user exits the program. No manual inteference is required. ### Editing the data files -Editing the savefile data is highly not recommended, and users should attempt to only do so at their own discretion. +Please do not edit the data files.
Warning:
From 2b5f70434bed63e453cda40cef41450605df2479 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 30 Mar 2023 00:41:40 +0800 Subject: [PATCH 213/368] Remove empty transaction file exception message --- src/main/java/seedu/bankwithus/BankWithUs.java | 3 +-- src/main/java/seedu/bankwithus/user/TransactionList.java | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 9d1199769e..d72940e07a 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -59,8 +59,7 @@ public BankWithUs(String accountsFilePath, String transactionsFilePath) throws I try { transactionList = new TransactionList(storage.loadTransactions()); } catch (FileNotFoundException e) { - // If transactionFile not created - ui.showFileNotFoundError(); + // If transactionFile not created, show nothing try { storage.createNewTransactionsFile(); } catch (IOException ioE) { diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 010e8754e1..cd54cb1eda 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -52,6 +52,7 @@ public ArrayList getTransactions() { public Transaction getTransaction(int index) { return transactions.get(index); } + public int getSize() { return size; } From 4d1dff76cab36bb3f3e7ec160e6e7137717f06e1 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 30 Mar 2023 01:09:58 +0800 Subject: [PATCH 214/368] Fix text ui test --- src/main/java/seedu/bankwithus/user/TransactionList.java | 2 +- text-ui-test/EXPECTED.TXT | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index cd54cb1eda..317189f733 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -52,7 +52,7 @@ public ArrayList getTransactions() { public Transaction getTransaction(int index) { return transactions.get(index); } - + public int getSize() { return size; } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index cc35ac5d26..acf9a365a7 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -23,7 +23,6 @@ Account created! Name: hihi Balance: $1000 ---------------------------- -File not found, trying to create file. Not a valid command! Current Account: Name: hihi @@ -115,8 +114,8 @@ Balance: $123678.1 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 29/03/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 29/03/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 30/03/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 30/03/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 0fc541f5ccb65035c2884deb1053ec6abeb8458b Mon Sep 17 00:00:00 2001 From: tyuyang Date: Thu, 30 Mar 2023 09:10:41 +0800 Subject: [PATCH 215/368] Fixed logging messages --- .../bankwithus/common/WithdrawalChecker.java | 20 +++++++++---------- .../storage/TransactionEncoder.java | 3 ++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java index 8b54e72495..15b0b9d3fb 100644 --- a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java @@ -15,9 +15,9 @@ public class WithdrawalChecker { * Instantiates withdrawalChecker without any amount withdrawn */ public WithdrawalChecker() { - logger.log(Level.INFO, "Default WithdrawalChecker contructor called"); + logger.log(Level.FINE, "Default WithdrawalChecker contructor called"); this.totalAmtWithdrawn = "0"; - logger.log(Level.INFO, "totalAmtWithdrawn set to " + totalAmtWithdrawn); + logger.log(Level.FINE, "totalAmtWithdrawn set to " + totalAmtWithdrawn); } /** @@ -27,11 +27,11 @@ public WithdrawalChecker() { * @param lastWithdrawnDate last known withdrawal date */ public WithdrawalChecker(String totalAmtWithdrawn, LocalDate lastWithdrawnDate) { - logger.log(Level.INFO, "WithdrawalChecker contructer with set withdrawals called"); + logger.log(Level.FINE, "WithdrawalChecker contructer with set withdrawals called"); this.totalAmtWithdrawn = totalAmtWithdrawn; this.lastWithdrawnDate = lastWithdrawnDate; - logger.log(Level.INFO, "totalAntWithdrawn set to " + totalAmtWithdrawn); - logger.log(Level.INFO, "lastWithdrawnDate set to " + lastWithdrawnDate.toString()); + logger.log(Level.FINE, "totalAntWithdrawn set to " + totalAmtWithdrawn); + logger.log(Level.FINE, "lastWithdrawnDate set to " + lastWithdrawnDate.toString()); } public String getTotalAmtWithdrawn() { @@ -47,12 +47,12 @@ public String getTotalAmtWithdrawn() { * @param withdrawal the amount that was just withdrawn */ public void updateTotalAmtWithdrawn(float withdrawal) { - logger.log(Level.INFO, "updateTotalAmtWithdrawn in WithdrawalChecker called"); + logger.log(Level.FINE, "updateTotalAmtWithdrawn in WithdrawalChecker called"); LocalDate currentDate = LocalDate.now(); DecimalFormat df = new DecimalFormat("#.##"); - logger.log(Level.INFO, "Checking if account has withdrawal history"); + logger.log(Level.FINE, "Checking if account has withdrawal history"); if (lastWithdrawnDate == null) { - logger.log(Level.INFO, "No withdrawal history found, setting values now"); + logger.log(Level.FINE, "No withdrawal history found, setting values now"); lastWithdrawnDate = currentDate; String formatted = df.format(withdrawal); totalAmtWithdrawn = String.valueOf(formatted); @@ -61,11 +61,11 @@ public void updateTotalAmtWithdrawn(float withdrawal) { assert totalAmtWithdrawn != null; if (lastWithdrawnDate.getMonth() == currentDate.getMonth() && lastWithdrawnDate.getYear() == currentDate.getYear()) { - logger.log(Level.INFO, "Previous withdrawal in the same month, adding to total"); + logger.log(Level.FINE, "Previous withdrawal in the same month, adding to total"); String formatted = df.format(Float.parseFloat(totalAmtWithdrawn) + withdrawal); totalAmtWithdrawn = String.valueOf(formatted); } else { - logger.log(Level.INFO, "Previous withdrawal in previous months, setting to new value"); + logger.log(Level.FINE, "Previous withdrawal in previous months, setting to new value"); String formatted = df.format(withdrawal); totalAmtWithdrawn = String.valueOf(formatted); } diff --git a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java index 68090258e4..55f05e6f7e 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java @@ -23,8 +23,9 @@ public String encodeTransaction(Transaction transaction) { return encodedTransactionBuilder.toString(); } + //@@author xiaoge26 public String encodeTransactionList(TransactionList transactionList) { - logger.log(Level.INFO, "Encoding TransactionList"); + logger.log(Level.FINE, "Encoding TransactionList"); if (transactionList.getSize() == 0) { return ""; } else { From 839b25a9df3818bf03db49e1945e6a66191eccf5 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 30 Mar 2023 11:50:28 +0800 Subject: [PATCH 216/368] Remove empty transaction file exception message --- src/main/java/seedu/bankwithus/BankWithUs.java | 3 ++- src/main/java/seedu/bankwithus/user/TransactionList.java | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index d72940e07a..9d1199769e 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -59,7 +59,8 @@ public BankWithUs(String accountsFilePath, String transactionsFilePath) throws I try { transactionList = new TransactionList(storage.loadTransactions()); } catch (FileNotFoundException e) { - // If transactionFile not created, show nothing + // If transactionFile not created + ui.showFileNotFoundError(); try { storage.createNewTransactionsFile(); } catch (IOException ioE) { diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 317189f733..6832516dbf 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -30,7 +30,6 @@ public TransactionList(Scanner scanner) { } catch (CorruptedSaveFileException e) { ui.showCorruptedSaveFileError(); } catch (SaveFileIsEmptyException e) { - ui.showEmptyFile(); } } From a89dc57977a59799f4c8cc0ea525c0b782052ce8 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 30 Mar 2023 11:58:57 +0800 Subject: [PATCH 217/368] Add no transaction message --- src/main/java/seedu/bankwithus/ui/Ui.java | 3 +++ src/main/java/seedu/bankwithus/user/TransactionList.java | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 91ebb10042..012e37cc93 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -46,6 +46,9 @@ public void showFarewellMessage() { 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!"); diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 6832516dbf..51a6ece28d 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -30,6 +30,8 @@ public TransactionList(Scanner scanner) { } catch (CorruptedSaveFileException e) { ui.showCorruptedSaveFileError(); } catch (SaveFileIsEmptyException e) { + //shows "No transactions found!" as this catch block + ui.showNoTransactionsFoundMessage(); } } From f84da914d8217cb245bf556933bf20a273e96f8f Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 30 Mar 2023 12:00:22 +0800 Subject: [PATCH 218/368] Change EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 1 + 1 file changed, 1 insertion(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index acf9a365a7..9e817b9bb8 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -23,6 +23,7 @@ Account created! Name: hihi Balance: $1000 ---------------------------- +File not found, trying to create file. Not a valid command! Current Account: Name: hihi From 23d02ca1bc0c10f28f04947429bce248557b3c5b Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 31 Mar 2023 22:49:37 +0800 Subject: [PATCH 219/368] Add a save goal amount check before showing save goal --- src/main/java/seedu/bankwithus/ui/Ui.java | 2 +- .../java/seedu/bankwithus/user/AccountList.java | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 13c0025386..37219532c5 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -10,7 +10,7 @@ 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("Try saving a minimum of $" + args + " until " + untilWhenStr); System.out.println("Save Goal has been created, Have fun staying frugal!"); } public void showFileNotFoundError() { diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 1552fdd79e..8ac1185469 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -119,7 +119,7 @@ public String askUserForBalance() { try { float balance = Float.parseFloat(balanceString); if (balance < 1) { - balanceString = "0"+balanceString; + balanceString = "0" + balanceString; } if (balance < 0) { throw new NegativeAmountException(); @@ -239,9 +239,9 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio //@@author vishnuvk47 /** - * checks if date is in the DD-MM-YYYY format + * Formats the date into the dd-MM-yyyy format * @param date - * @return true is date in correct format and false if not + * @return teh date in the dd-MM-yyyy format */ public LocalDate handleDate(LocalDate date) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); @@ -262,7 +262,7 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept throw new InsufficientBalanceException(); } else if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(withdrawAmount)) { throw new ExceedsWithdrawalLimitException(); - } else if(isFailsSaveGoal(currentBalance, withdrawAmount)) { + } else if(willFailsSaveGoal(currentBalance, withdrawAmount)) { ui.failToMeetSaveGoal(); handleProceed(withdrawAmount, currentBalance); } else { @@ -373,7 +373,6 @@ public void handleProceed(float withdrawAmount, float currentBalance) { * @param args * @param untilWhenStr */ - public void handleSaveGoal(String args, String untilWhenStr) { try { float toSave = Float.parseFloat(args); @@ -412,7 +411,11 @@ public boolean isDateFormatValid(String date) { */ public void showGoal() { SaveGoal goal = getMainAccount().getSaveGoal(); - ui.showGoal(goal); + if(goal.amtToSave <= 0) { + System.out.println("you do not have any Save Goal"); + } else { + ui.showGoal(goal); + } } /** @@ -421,7 +424,7 @@ public void showGoal() { * @param withdrawAmount * @return True if fails to meet save Goal and False if meets save Goal requirements */ - public Boolean isFailsSaveGoal(float currentBalance, float withdrawAmount) { + public Boolean willFailsSaveGoal(float currentBalance, float withdrawAmount) { float expectedBal = currentBalance - withdrawAmount; LocalDate tdy = LocalDate.now(); LocalDate tdyDate = handleDate(tdy); From 0859a20433d89b570b43e9099efc31f57000f1ba Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 31 Mar 2023 22:58:16 +0800 Subject: [PATCH 220/368] Made changes as per TA code review --- .../java/seedu/bankwithus/parser/Parser.java | 10 ++- .../seedu/bankwithus/user/AccountList.java | 62 ++++++++++++++++--- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index a860ed6122..976530fbcc 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -169,8 +169,8 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce //@@author Sherlock-YH /** * Parses the save file. Takes in the scanner to the save file, - * and splits the name and balance by ; character. Part of - * accountList parser, not bwu parser + * 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 @@ -219,6 +219,12 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S } } + /** + * Reads the transaction data from the transaction save file + * @param scanner + * @throws CorruptedSaveFileException + * @throws SaveFileIsEmptyException + */ public void parseTransactionFile(Scanner scanner) throws CorruptedSaveFileException, SaveFileIsEmptyException { while (scanner.hasNextLine()) { diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 8ac1185469..02f347b876 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -84,8 +84,8 @@ public Account getMainAccount() { //@@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 + * S string. Will keep looping so long as the user does not + * Give a valid name * * @return the userName String */ @@ -106,8 +106,8 @@ public String askUserForName() { /** * Asks the user for their initial balance and returns it as a - * float. Will keep looping so long as the user does not give - * a valid balance. + * Float. Will keep looping so long as the user does not give + * A valid balance. * * @return balance in the form of a float */ @@ -152,6 +152,14 @@ public void addAccount(String name, String balance, String withdrawalLimit) { 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, String untilWhen) { Account newAccount = new Account(name, balance, amtToSave, untilWhen); if (!withdrawalLimit.isBlank()) { @@ -218,6 +226,9 @@ public String getAllAccountDetails() throws AccountNotFoundException { } } + /** + * Prints to the UI the available balance of the current user + */ //@@author public void showBal() { String balance = getMainAccount().getAccountBalance(); @@ -226,6 +237,13 @@ public void showBal() { } + /** + * Deposits a user specified amount to the current account's balance + * @param depositAmountString - amount to be deposited + * @throws NumberFormatException + * @throws NullPointerException + * @throws NegativeAmountException + */ //@@author xiaoge26 public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException, NegativeAmountException { @@ -249,7 +267,16 @@ public LocalDate handleDate(LocalDate date) { 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 + * @param withdrawAmountString - amount to be withdrawn + * @throws NumberFormatException + * @throws NegativeAmountException + * @throws InsufficientBalanceException + * @throws ExceedsWithdrawalLimitException + */ //@@author manushridiv public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException { @@ -271,6 +298,12 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept } } + /** + * 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 delet + * @param acc - the account to be checked if it matches the account name to be deleted + */ public void findAccountToDelete(String name, Account acc) { if (acc.getAccountName().contains(name)) { accounts.remove(acc); @@ -281,6 +314,10 @@ public void findAccountToDelete(String name, Account acc) { } } + /** + * Baseline method for the delete account command + * @param name - name of the account to be deleted + */ //@@author Sherlock-YH public void deleteAccount(String name) { for (Account acc : accounts) { @@ -295,6 +332,11 @@ public int getSize() { return accounts.size(); } + /** + * Method that allows 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 @@ -318,7 +360,7 @@ public void switchMainAccount(String accName) throws NoAccountException { //@@author tyuyang /** * Sets the withdrawal limit of the main account. Modifies the attribute - * withdrawalLimit in the WithdrawalChecker class directly + * WithdrawalLimit in the WithdrawalChecker class directly * * @param args the user input * @@ -348,7 +390,7 @@ public void setAccounts(ArrayList accounts) { //@@author vishnuvk47 /** - * handles overwriting of saveGoal at users own discretion + * Handles overwriting of saveGoal at users own discretion * @param withdrawAmount * @param currentBalance */ @@ -369,7 +411,7 @@ public void handleProceed(float withdrawAmount, float currentBalance) { } /** - * primary function that handles the setting and exception handling when saveGoal is called + * Primary function that handles the setting and exception handling when saveGoal is called * @param args * @param untilWhenStr */ @@ -389,7 +431,7 @@ public void handleSaveGoal(String args, String untilWhenStr) { } /** - * checks if the date is entered in teh valid DD-MM-YYYY format + * 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 */ @@ -419,7 +461,7 @@ public void showGoal() { } /** - * checks to see if the amount being withdrawn exceeds save Goal requirements + * 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 From ac916ca3a0df71a8c61eb9d4298196f261eca6e7 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Fri, 31 Mar 2023 23:56:33 +0800 Subject: [PATCH 221/368] Change deleteAccount method to show ui message and resolve bug where deleting len-1 crashes pgm --- .../java/seedu/bankwithus/parser/Parser.java | 8 +++-- .../seedu/bankwithus/user/AccountList.java | 32 +++++++++++++------ .../seedu/bankwithus/AccountListTest.java | 4 +-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 976530fbcc..d40de2fb96 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -93,9 +93,11 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce break; case "withdraw": try { - accountList.withdrawMoney(args); - transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(), - "withdraw", args, LocalDate.now()); + boolean hasWithdrawn = accountList.hasWithdrawMoney(args); + if(hasWithdrawn) { + transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(), + "withdraw", args, LocalDate.now()); + } accountList.showBal(); ui.printLine(); } catch (NumberFormatException e) { diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 02f347b876..83f3f43b4a 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -271,14 +271,16 @@ public LocalDate handleDate(LocalDate date) { /** * Withdraws a user specified amount from the current account * Also checks if user meets their withdrawal limit and save goal requirement + * Checks if a Valid withdrawal occured * @param withdrawAmountString - amount to be withdrawn * @throws NumberFormatException * @throws NegativeAmountException * @throws InsufficientBalanceException * @throws ExceedsWithdrawalLimitException + * @return true if money was withdrawn successfully and false otherwise */ //@@author manushridiv - public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, + public Boolean hasWithdrawMoney(String withdrawAmountString) throws NumberFormatException, NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException { float withdrawAmount = Float.parseFloat(withdrawAmountString); if (withdrawAmount < 0) { @@ -291,10 +293,11 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept throw new ExceedsWithdrawalLimitException(); } else if(willFailsSaveGoal(currentBalance, withdrawAmount)) { ui.failToMeetSaveGoal(); - handleProceed(withdrawAmount, currentBalance); + return handleProceed(withdrawAmount, currentBalance); } else { getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); ui.showWithdrawMessage(); + return true; } } @@ -304,14 +307,16 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept * @param name - name of the account to delet * @param acc - the account to be checked if it matches the account name to be deleted */ - public void findAccountToDelete(String name, Account acc) { - if (acc.getAccountName().contains(name)) { + public Boolean foundAccountToDelete(String name, Account acc) { + if (acc.getAccountName().equals(name)) { accounts.remove(acc); ui.showAccountDeleted(name); if(accounts.size() < 1) { createNewAccount(); } + return true; } + return false; } /** @@ -320,13 +325,20 @@ public void findAccountToDelete(String name, Account acc) { */ //@@author Sherlock-YH public void deleteAccount(String name) { - for (Account acc : accounts) { - findAccountToDelete(name, acc); - return; + boolean accountDeleted = false; + for (int i = 0; i < accounts.size(); i++) { + if(foundAccountToDelete(name, accounts.get(i))) { + accountDeleted = true; + i--; + } + } + if (!accountDeleted) { + ui.showNoAccountFound(); } - ui.showNoAccountFound(); } + + //@@author Sherlock-YH public int getSize() { return accounts.size(); @@ -394,7 +406,7 @@ public void setAccounts(ArrayList accounts) { * @param withdrawAmount * @param currentBalance */ - public void handleProceed(float withdrawAmount, float currentBalance) { + public Boolean handleProceed(float withdrawAmount, float currentBalance) { 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."); @@ -404,9 +416,11 @@ public void handleProceed(float withdrawAmount, float currentBalance) { getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); getMainAccount().saveGoal.amtToSave = 0; ui.showWithdrawMessage(); + return true; } else { ui.showWithdrawCancelled(); + return false; } } diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index fa30f68769..a1769ca331 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -36,7 +36,7 @@ void withdrawNegativeAmount() { AccountList accountList = new AccountList(); accountList.addAccount("James", "1000", ""); assertThrows(NegativeAmountException.class, () -> { - accountList.withdrawMoney("-100"); + accountList.hasWithdrawMoney("-100"); }); } @@ -45,7 +45,7 @@ void withdrawNegativeAmountWithDecimal() { AccountList accountList = new AccountList(); accountList.addAccount("James", "1000", ""); assertThrows(NegativeAmountException.class, () -> { - accountList.withdrawMoney("-21.67"); + accountList.hasWithdrawMoney("-21.67"); }); } From 8630e273623433df18d6644ac276576671576a15 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 00:16:08 +0800 Subject: [PATCH 222/368] Made a hashmap to chack that a username only exists once --- src/main/java/seedu/bankwithus/ui/Ui.java | 4 ++++ src/main/java/seedu/bankwithus/user/AccountList.java | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 37219532c5..5bdc2fb8da 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -264,4 +264,8 @@ 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 exist, try again!"); + } } diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 83f3f43b4a..7d3f881746 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -19,12 +19,14 @@ 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. @@ -197,6 +199,11 @@ public void addAccount(String name, String balance, String totalAmtWithdrawn, */ 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, ""); } From eae0b5dd4472425ce85e1c96914e2aa6b0843f82 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 00:21:53 +0800 Subject: [PATCH 223/368] Format to meet checkstyle and update expectedl.txt --- src/main/java/seedu/bankwithus/user/AccountList.java | 6 ++---- text-ui-test/EXPECTED.TXT | 6 ++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 7d3f881746..4c0b1df0bf 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -75,9 +75,7 @@ public AccountList(Scanner scanner, BankWithUs bwu) { //@@author xiaoge26 /** - * Returns the current account. - * - * @return + * @return - Returns the current account. */ public Account getMainAccount() { return accounts.get(0); @@ -280,11 +278,11 @@ public LocalDate handleDate(LocalDate date) { * Also checks if user meets their withdrawal limit and save goal requirement * Checks if a Valid withdrawal occured * @param withdrawAmountString - amount to be withdrawn + * @return true if money was withdrawn successfully and false otherwise * @throws NumberFormatException * @throws NegativeAmountException * @throws InsufficientBalanceException * @throws ExceedsWithdrawalLimitException - * @return true if money was withdrawn successfully and false otherwise */ //@@author manushridiv public Boolean hasWithdrawMoney(String withdrawAmountString) throws NumberFormatException, diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 447f2668a7..108bbfc928 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -41,6 +41,8 @@ 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 created! @@ -114,7 +116,7 @@ Balance: $123678.1 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 27/03/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 27/03/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 01/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 01/04/2023 Not a valid command! Goodbye! Hope to see you again! :) From b583164ceb04ccaf13eda689fc22c8e20a36890b Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 00:32:51 +0800 Subject: [PATCH 224/368] Solved bug where /bin/zsh balance saved as /bin/zsh --- src/main/java/seedu/bankwithus/user/AccountList.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 4c0b1df0bf..d82da5ba6b 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -118,7 +118,7 @@ public String askUserForBalance() { balanceString = balanceString.replaceFirst("^0+(?!$)", ""); try { float balance = Float.parseFloat(balanceString); - if (balance < 1) { + if (balance < 1 && balance != 0) { balanceString = "0" + balanceString; } if (balance < 0) { @@ -429,6 +429,7 @@ public Boolean handleProceed(float withdrawAmount, float currentBalance) { } } + //@@author Vishnu /** * Primary function that handles the setting and exception handling when saveGoal is called * @param args @@ -449,6 +450,7 @@ public void handleSaveGoal(String args, String untilWhenStr) { } } + //@@author Vishnu /** * Checks if the date is entered in teh valid DD-MM-YYYY format * @param date From 405a4db62e74ee3694fe0ec48da3d48d7595fb14 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 00:35:52 +0800 Subject: [PATCH 225/368] Change .contains to .equals in switchmain accoutn method resolves bug #63 --- src/main/java/seedu/bankwithus/user/AccountList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index d82da5ba6b..90866a2861 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -363,7 +363,7 @@ public void switchMainAccount(String accName) throws NoAccountException { ui.showThereIsOnlyOneAccount(); } else { for (int i = 0; i < accounts.size(); i++) { - if (accounts.get(i).getAccountName().contains(accName)) { + if (accounts.get(i).getAccountName().equals(accName)) { Collections.swap(accounts, i, 0); ui.showMainAccountSwitched(); ui.showCurrentAccount(accounts.get(0)); From 368902a143348439cf7e979540004ac6035ed260 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 00:52:35 +0800 Subject: [PATCH 226/368] Formatted some typos in the JavaDocs --- src/main/java/seedu/bankwithus/parser/Parser.java | 6 +++--- src/main/java/seedu/bankwithus/user/AccountList.java | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index d40de2fb96..e8ca6c75e9 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -170,9 +170,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce //@@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 + * 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 diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 90866a2861..49043f732b 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -84,7 +84,7 @@ public Account getMainAccount() { //@@author /** * Asks the user for the name and returns it in the form of - * S string. Will keep looping so long as the user does not + * a string. Will keep looping so long as the user does not * Give a valid name * * @return the userName String @@ -105,8 +105,8 @@ public String askUserForName() { } /** - * Asks the user for their initial balance and returns it as a - * Float. Will keep looping so long as the user does not give + * Asks the user for their initial balance and returns it as a float + * Will keep looping so long as the user does not give * A valid balance. * * @return balance in the form of a float @@ -264,7 +264,7 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio /** * Formats the date into the dd-MM-yyyy format * @param date - * @return teh date in the dd-MM-yyyy format + * @return the date in the dd-MM-yyyy format */ public LocalDate handleDate(LocalDate date) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); @@ -350,7 +350,7 @@ public int getSize() { } /** - * Method that allows that handles switching between users + * Method that handles switching between users * @param accName - account to be switched into * @throws NoAccountException */ From 8239cd4c088b6ea9ab970ed062feecb07082fa40 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 00:58:21 +0800 Subject: [PATCH 227/368] Fix typos in javadocs --- src/main/java/seedu/bankwithus/ui/Ui.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index d5833d4574..1e74ecb433 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -278,7 +278,7 @@ public void showExceedsWithdrawalLimitError() { System.out.println("in you exceeding your withdrawal limit!"); } public void accountAlreadyExists() { - System.out.println("Account already exist, try again!"); + System.out.println("Account already exists, try again!"); } public void noTransactionsFoundError() { System.out.println("No transactions found!"); From 6585cf80e27d1d1bfa018e1001b7d414416fc696 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 01:05:58 +0800 Subject: [PATCH 228/368] Changed date in expected.txt 3rd last line --- text-ui-test/EXPECTED.TXT | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index f7534b9dd6..8a858bf78d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -117,7 +117,7 @@ Balance: $123678.1 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 01/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 01/04/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 31/03/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 31/03/2023 Not a valid command! Goodbye! Hope to see you again! :) From f4acaed3058a8027261260d53e89b08179fde5d6 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 01:08:36 +0800 Subject: [PATCH 229/368] Changed date style in expected.txt --- text-ui-test/EXPECTED.TXT | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 8a858bf78d..f7534b9dd6 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -117,7 +117,7 @@ Balance: $123678.1 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 31/03/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 31/03/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 01/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 01/04/2023 Not a valid command! Goodbye! Hope to see you again! :) From 4702ddd6961696f71d9c1554f62573fc382d7569 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 13:05:33 +0800 Subject: [PATCH 230/368] Resolve IO redir --- text-ui-test/EXPECTED.TXT | 1 + 1 file changed, 1 insertion(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index f7534b9dd6..0af956bbd7 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -119,5 +119,6 @@ Balance: $1100.21 ---------------------------- Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 01/04/2023 Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 01/04/2023 +---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 707f816a9f0ef973bcb22f35ae9b4c1550b1ea71 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 16:22:14 +0800 Subject: [PATCH 231/368] Added . to all javadocs and changed the saveGoal command in UG --- docs/UserGuide.md | 44 +++++++------- .../java/seedu/bankwithus/BankWithUs.java | 2 +- .../bankwithus/common/WithdrawalChecker.java | 6 +- .../java/seedu/bankwithus/parser/Parser.java | 8 +-- .../seedu/bankwithus/storage/Storage.java | 6 +- src/main/java/seedu/bankwithus/ui/Ui.java | 6 +- .../java/seedu/bankwithus/user/Account.java | 2 +- .../seedu/bankwithus/user/AccountList.java | 58 +++++++++---------- 8 files changed, 67 insertions(+), 65 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index c7d473889b..a12b8d4ed6 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,4 +1,4 @@ -### BankWithUs User Guide +# BankWithUs User Guide -------------------------------------------------------------------------------------------------------------------- @@ -15,7 +15,7 @@ 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: - * `view-transactions-all` : Lists all recorded transactions + * `view-transactions-all` : Lists all recorded transactions. * `withdraw 300` : Withdraws $300 from the current balance. (Subsitute 300 for other numbers) @@ -23,7 +23,7 @@ * `deposit 100` : Deposits $100 into the users account. (Subsitute 100 for other numbers) - * `exit` : Exits the application + * `exit` : Exits the application. 1. Refer to the [Features](#features) below for details of each command. @@ -41,8 +41,8 @@ * 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`) will be ignored.
- e.g. if the command specifies `help 123`, it will be interpreted as `help`. +* 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`.
@@ -87,7 +87,7 @@ your input: `BALANCE` Note: Balance has to be a valid number.
Examples: -```agsl +``` add-account >>What is your name? Steve @@ -104,7 +104,7 @@ Switches from the *current account* to the new requested account, if it exists. Format: `switch-to NAME` -* The search is not case-sensitive. e.g `jane` will match `Jane` +* 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` @@ -165,7 +165,7 @@ Deposits AMOUNT into the *current account*. Format: `deposit AMOUNT` Example: -```agsl +``` deposit 100 New deposit added! You have $190 remaining! @@ -184,7 +184,7 @@ Withdraws AMOUNT from the users balance. Format: `withdraw AMOUNT` Example: -```agsl +``` withdraw 500 ``` @@ -203,18 +203,18 @@ Shows a list of all the transactions processed by all the accounts of the user. Format: `view-transactions-all` Example: -```agsl +``` >>view-transactions-all Account Name: jenson Transaction Type: deposit Amount: 100 Date: 26/03/2023 Account Name: jenson Transaction Type: withdraw Amount: 10 Date: 26/03/2023 ``` -### Add a savings Goal to the current account: `save` +### Add a savings Goal to the current account: `set-save-goal` Adds a savings goal to the *current account*.
Will raise an alert when attempting to withdraw more than the savings goal, if attempt is before deadline -Format: `save AMOUNT` >> will then prompt the user for the deadline. +Format: `set-save-goal AMOUNT` >> 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 @@ -309,12 +309,14 @@ Please keep in mind that this will result in irreversible data loss. ## Command summary -| Action | Format, Examples | -|-----------------------------|----------------------| -| **Add an Account** | `add-account` | -| **swicth to a new account** | `switch-to ACC_NAME` | -| **Delete an account** | `delete` | -| **withdraw some amount** | `withdraw AMOUNT` | -| **Add a savings goal** | `save AMOUNT` | -| **Add a withdraw Limit** | `set-wl` | -| **Help** | `help` | \ No newline at end of file +| Action | Format, Examples | +|-------------------------------|-------------------------| +| **Add an Account** | `add-account` | +| **switch to a new account** | `switch-to ACC_NAME` | +| **Delete an account** | `delete` | +| **withdraw some amount** | `withdraw AMOUNT` | +| **Add a savings goal** | `set-save-goal` | +| **Show the save Goal** | `show-saveGoal` | +| **Add a withdraw Limit** | `set-wl` | +| **View all the transactions** | `view-transactions-all` | +| **Help** | `help` | \ No newline at end of file diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 9d1199769e..5e9087e566 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -86,7 +86,7 @@ public Ui getUi() { //@@author Sherlock-YH /** - * Exit the programme, save the data and show farewell message + * Exit the programme, save the data and show farewell message. * * @throws IOException throw error if the data cannot be saved */ diff --git a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java index 15b0b9d3fb..85eedd740a 100644 --- a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java @@ -12,7 +12,7 @@ public class WithdrawalChecker { private Logger logger = Logger.getLogger("Foo"); /** - * Instantiates withdrawalChecker without any amount withdrawn + * Instantiates withdrawalChecker without any amount withdrawn. */ public WithdrawalChecker() { logger.log(Level.FINE, "Default WithdrawalChecker contructor called"); @@ -22,7 +22,7 @@ public WithdrawalChecker() { /** * Instantiates withdrawalChecker with amount withdrawn and - * last known withdrawal date + * last known withdrawal date. * @param totalAmtWithdrawn amount withdrawn * @param lastWithdrawnDate last known withdrawal date */ @@ -83,7 +83,7 @@ public void setWithdrawalLimit(float withdrawalLimit) { } /** - * Checks if the amount withdrawn will exceed the withdrawal limit + * Checks if the amount withdrawn will exceed the withdrawal limit. * * @param withdrawAmount the amount withdrawn * @return true if will exceed, false otherwise diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 1f0665523f..b727488827 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -26,7 +26,7 @@ public class Parser { private TransactionList transactionList; private Ui ui; /** - * Instantiates a bwu Parser object + * Instantiates a bwu Parser object. * * @param bwu the main bankWithUs program */ @@ -38,7 +38,7 @@ public Parser(BankWithUs bwu) { } /** - * Instatiates a accountList Parser object + * Instantiates a accountList Parser object. * * @param accountList the accountList */ @@ -179,7 +179,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce /** * 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 + * Part of AccountList parser, not bwu parser. * * @param scanner * @throws CorruptedSaveFileException if any of the parameters are corrupted @@ -229,7 +229,7 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S } /** - * Reads the transaction data from the transaction save file + * Reads the transaction data from the transaction save file. * @param scanner * @throws CorruptedSaveFileException * @throws SaveFileIsEmptyException diff --git a/src/main/java/seedu/bankwithus/storage/Storage.java b/src/main/java/seedu/bankwithus/storage/Storage.java index 27d6bc6b03..9c18bd6bf7 100644 --- a/src/main/java/seedu/bankwithus/storage/Storage.java +++ b/src/main/java/seedu/bankwithus/storage/Storage.java @@ -45,7 +45,7 @@ public Scanner loadTransactions() throws FileNotFoundException { //@@author /** - * Creates a new saveFile if file is not found. Also creates the data directory + * 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 */ @@ -66,7 +66,7 @@ public void createNewTransactionsFile() throws IOException { //@@author Sherlock-YH /** - * This method saves all account details to data/save.txt + * This method saves all account details to data/save.txt. * * @param list The AccountList that stores all accounts */ @@ -82,7 +82,7 @@ public void saveToFile(AccountList list) throws IOException { //@@author xiaoge26 /** - * This method saves all transaction details to data/save.txt + * This method saves all transaction details to data/save.txt. * * @param transactionList The TransactionList that stores all transactions */ diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 1e74ecb433..08f749c33e 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -59,7 +59,7 @@ public void showWithdrawMessage() { } /** - * Creates a scanner in the Ui class + * Creates a scanner in the Ui class. * * @return */ @@ -68,7 +68,7 @@ public void createScanner() { } /** - * Gets the next line of user input + * Gets the next line of user input. * * @return the next of user input */ @@ -77,7 +77,7 @@ public String getNextLine() { } /** - * Closes the scanner + * Closes the scanner. */ public void closeScanner() { this.scanner.close(); diff --git a/src/main/java/seedu/bankwithus/user/Account.java b/src/main/java/seedu/bankwithus/user/Account.java index 94e6bd9bb5..026a06eebf 100644 --- a/src/main/java/seedu/bankwithus/user/Account.java +++ b/src/main/java/seedu/bankwithus/user/Account.java @@ -13,7 +13,7 @@ public class Account { private WithdrawalChecker withdrawalChecker; //@@author Sherlock-YH /** - * Instantiates an account object + * Instantiates an account object. * * @param name initialise in the name of the account * @param balance initialise the balance of the account diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 49043f732b..1a21b0763c 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -30,7 +30,7 @@ public class AccountList { /** * Instantiates AccountList and creates a new account. - * Called only when savefile is not found + * Called only when save file is not found. * * @param bwu the main bankWithUs program */ @@ -41,7 +41,7 @@ public AccountList(BankWithUs bwu) { } /** - * Instantiates AccountList for unit testing + * Instantiates AccountList for unit testing. */ public AccountList() { accounts = new ArrayList(); @@ -51,9 +51,9 @@ public AccountList() { /** * Instantiates AccountList and either: * 1. Load the saved information in the save file into - * the account list - * 2. Create a brand new account if the save file was - * empty + * 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 @@ -85,7 +85,7 @@ public Account getMainAccount() { /** * 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 + * give a valid name. * * @return the userName String */ @@ -105,9 +105,9 @@ public String askUserForName() { } /** - * Asks the user for their initial balance and returns it as a float + * Asks the user for their initial balance and returns it as a float. * Will keep looping so long as the user does not give - * A valid balance. + * a valid balance. * * @return balance in the form of a float */ @@ -153,7 +153,7 @@ public void addAccount(String name, String balance, String withdrawalLimit) { } /** - * Simple method that adds an account + * Simple method that adds an account. * @param name - Name of the account * @param balance -The available balance * @param withdrawalLimit - withdrawal limit to be set @@ -172,7 +172,7 @@ public void addAccount(String name, String balance, String withdrawalLimit, Stri //@@author tyuyang /** - * Creates a new account with withdrawal info and adds it to the AccountList + * 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 @@ -193,7 +193,7 @@ public void addAccount(String name, String balance, String totalAmtWithdrawn, //@@author vishnuvk47 /** - * Creates a new Account for a first time user + * Creates a new Account for a first time user. */ public void createNewAccount() { String userName = askUserForName(); @@ -208,7 +208,7 @@ public void createNewAccount() { //@@author Sherlock-YH /** - * Name and balance are separated by ; prepared to be saved + * Name and balance are separated by ; prepared to be saved. * * @return returns all accounts details in String format */ @@ -232,7 +232,7 @@ public String getAllAccountDetails() throws AccountNotFoundException { } /** - * Prints to the UI the available balance of the current user + * Prints to the UI the available balance of the current user. */ //@@author public void showBal() { @@ -243,7 +243,7 @@ public void showBal() { } /** - * Deposits a user specified amount to the current account's balance + * Deposits a user specified amount to the current account's balance. * @param depositAmountString - amount to be deposited * @throws NumberFormatException * @throws NullPointerException @@ -262,7 +262,7 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio //@@author vishnuvk47 /** - * Formats the date into the dd-MM-yyyy format + * Formats the date into the dd-MM-yyyy format. * @param date * @return the date in the dd-MM-yyyy format */ @@ -274,9 +274,9 @@ public LocalDate handleDate(LocalDate date) { } /** - * Withdraws a user specified amount from the current account - * Also checks if user meets their withdrawal limit and save goal requirement - * Checks if a Valid withdrawal occured + * Withdraws a user specified amount from the current account. + * Also checks if user meets their withdrawal limit and save goal requirement. + * Checks if a Valid withdrawal occurred. * @param withdrawAmountString - amount to be withdrawn * @return true if money was withdrawn successfully and false otherwise * @throws NumberFormatException @@ -307,9 +307,9 @@ public Boolean hasWithdrawMoney(String withdrawAmountString) throws NumberFormat } /** - * 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 delet + * 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) { @@ -325,7 +325,7 @@ public Boolean foundAccountToDelete(String name, Account acc) { } /** - * Baseline method for the delete account command + * Baseline method for the delete account command. * @param name - name of the account to be deleted */ //@@author Sherlock-YH @@ -350,7 +350,7 @@ public int getSize() { } /** - * Method that handles switching between users + * Method that handles switching between users. * @param accName - account to be switched into * @throws NoAccountException */ @@ -377,7 +377,7 @@ public void switchMainAccount(String accName) throws NoAccountException { //@@author tyuyang /** * Sets the withdrawal limit of the main account. Modifies the attribute - * WithdrawalLimit in the WithdrawalChecker class directly + * withdrawalLimit in the WithdrawalChecker class directly. * * @param args the user input * @@ -407,7 +407,7 @@ public void setAccounts(ArrayList accounts) { //@@author vishnuvk47 /** - * Handles overwriting of saveGoal at users own discretion + * Handles overwriting of saveGoal at users own discretion. * @param withdrawAmount * @param currentBalance */ @@ -431,7 +431,7 @@ public Boolean handleProceed(float withdrawAmount, float currentBalance) { //@@author Vishnu /** - * Primary function that handles the setting and exception handling when saveGoal is called + * Primary function that handles the setting and exception handling when saveGoal is called. * @param args * @param untilWhenStr */ @@ -452,7 +452,7 @@ public void handleSaveGoal(String args, String untilWhenStr) { //@@author Vishnu /** - * Checks if the date is entered in teh valid DD-MM-YYYY format + * 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 */ @@ -470,7 +470,7 @@ public boolean isDateFormatValid(String date) { } /** - * Prints to UI the save goal that the user has set for himself + * Prints to UI the save goal that the user has set for himself. */ public void showGoal() { SaveGoal goal = getMainAccount().getSaveGoal(); @@ -482,7 +482,7 @@ public void showGoal() { } /** - * Checks to see if the amount being withdrawn exceeds save Goal requirements + * 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 From c94c7eeb3f2ffb08065cee23daa09f0292c8ab5f Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 16:34:03 +0800 Subject: [PATCH 232/368] Made change in askUserForBalance to strip -ve sign in -0 --- src/main/java/seedu/bankwithus/user/AccountList.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 1a21b0763c..f4e4c0b877 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -22,6 +22,8 @@ import java.util.HashMap; import java.util.Scanner; +import static java.lang.Math.abs; + public class AccountList { private ArrayList accounts; @@ -118,12 +120,15 @@ public String askUserForBalance() { balanceString = balanceString.replaceFirst("^0+(?!$)", ""); try { float balance = Float.parseFloat(balanceString); - if (balance < 1 && balance != 0) { - balanceString = "0" + balanceString; - } if (balance < 0) { throw new NegativeAmountException(); } + if (balance < 1 && abs(balance) != 0) { + balanceString = "0" + balanceString; + return balanceString; + } + float absBalance = abs(balance); //to strip -ve sign if user enters -0. + balanceString = Float.toString(absBalance); return balanceString; } catch (NumberFormatException e) { ui.showNumberFormatError(); From fa84f6c24b18b71ff6e6cb1f091b7352c1465fb4 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 16:38:35 +0800 Subject: [PATCH 233/368] Changed expected.txt to match the new change --- text-ui-test/EXPECTED-UNIX 2.TXT | 120 +++++++++++++++++++++++++++++++ text-ui-test/EXPECTED.TXT | 6 +- 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 text-ui-test/EXPECTED-UNIX 2.TXT diff --git a/text-ui-test/EXPECTED-UNIX 2.TXT b/text-ui-test/EXPECTED-UNIX 2.TXT new file mode 100644 index 0000000000..5ae164a886 --- /dev/null +++ b/text-ui-test/EXPECTED-UNIX 2.TXT @@ -0,0 +1,120 @@ +Welcome to: + + /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ +| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ +| $$ \ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$| $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$ +| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$ $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/ +| $$__ $$ /$$$$$$$| $$ \ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \ $$| $$ | $$| $$$$$$ +| $$ \ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \ $$$| $$ | $$ /$$| $$ | $$| $$ | $$ \____ $$ +| $$$$$$$/| $$$$$$$| $$ | $$| $$ \ $$| $$/ \ $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/ +|_______/ \_______/|__/ |__/|__/ \__/|__/ \__/|__/ \___/ |__/ |__/ \______/ |_______/ + +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 created! +Name: hihi +Balance: $1000 +---------------------------- +File not found, trying to create file. +Not a valid command! +Current Account: +Name: hihi +Balance: $1000 +---------------------------- +Negative amount entered! +The input is not a valid number! Please try again. +Current Account: +Name: hihi +Balance: $1000 +---------------------------- +New deposit added! +You have $1100.21 remaining! +Current Account: +Name: hihi +Balance: $1100.21 +---------------------------- +What's your name? +How much would you like to add as Balance? +Account created! +Name: sherlock +Balance: $123778.1 +---------------------------- +Current Account: +Name: hihi +Balance: $1100.21 +---------------------------- +Name: sherlock +Balance: $123778.1 +---------------------------- +You do not have sufficient Balance +---------------------------- +Current Account switched +---------------------------- +Current Account is: +---------------------------- +Name: sherlock +Balance: $123778.1 +---------------------------- +Current Account: +Name: sherlock +Balance: $123778.1 +---------------------------- +Name: hihi +Balance: $1100.21 +---------------------------- +The input is not a valid number! Please try again. +Withdrawal successful! +You have $123678.1 remaining! +---------------------------- +Current Account: +Name: sherlock +Balance: $123678.1 +---------------------------- +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. +---------------------------- +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.1 +---------------------------- +Name: hihi +Balance: $1100.21 +---------------------------- +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 28/03/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 28/03/2023 +Not a valid command! +Goodbye! Hope to see you again! :) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 0af956bbd7..5baa5340b9 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -21,19 +21,19 @@ The input is not a valid number! Please try again. How much would you like to add as Balance? Account created! Name: hihi -Balance: $1000 +Balance: $1000.0 ---------------------------- File not found, trying to create file. Not a valid command! Current Account: Name: hihi -Balance: $1000 +Balance: $1000.0 ---------------------------- Negative amount entered! The input is not a valid number! Please try again. Current Account: Name: hihi -Balance: $1000 +Balance: $1000.0 ---------------------------- New deposit added! You have $1100.21 remaining! From 0c61d0bada63cc84df45dacda3b71e5d71d8a9fa Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Sat, 1 Apr 2023 23:02:48 +0800 Subject: [PATCH 234/368] Added code to parse names into hashmap if savefile exists --- src/main/java/seedu/bankwithus/user/AccountList.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index f4e4c0b877..82f9e05023 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -66,6 +66,9 @@ public AccountList(Scanner scanner, BankWithUs bwu) { Parser parser = new Parser(this); try { parser.parseSavedFile(scanner); + for(Account acc : accounts) { + doesNameExist.put(acc.getName(), true); + } } catch (CorruptedSaveFileException e) { ui.showCorruptedSaveFileError(); createNewAccount(); From 8baed005dbfade5780ed67f3f473d002a8a13356 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 3 Apr 2023 11:13:44 +0800 Subject: [PATCH 235/368] Delete expected-unix 2.txt --- text-ui-test/EXPECTED-UNIX 2.TXT | 120 ------------------------------- 1 file changed, 120 deletions(-) delete mode 100644 text-ui-test/EXPECTED-UNIX 2.TXT diff --git a/text-ui-test/EXPECTED-UNIX 2.TXT b/text-ui-test/EXPECTED-UNIX 2.TXT deleted file mode 100644 index 5ae164a886..0000000000 --- a/text-ui-test/EXPECTED-UNIX 2.TXT +++ /dev/null @@ -1,120 +0,0 @@ -Welcome to: - - /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ -| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ -| $$ \ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$| $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$ -| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$ $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/ -| $$__ $$ /$$$$$$$| $$ \ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \ $$| $$ | $$| $$$$$$ -| $$ \ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \ $$$| $$ | $$ /$$| $$ | $$| $$ | $$ \____ $$ -| $$$$$$$/| $$$$$$$| $$ | $$| $$ \ $$| $$/ \ $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/ -|_______/ \_______/|__/ |__/|__/ \__/|__/ \__/|__/ \___/ |__/ |__/ \______/ |_______/ - -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 created! -Name: hihi -Balance: $1000 ----------------------------- -File not found, trying to create file. -Not a valid command! -Current Account: -Name: hihi -Balance: $1000 ----------------------------- -Negative amount entered! -The input is not a valid number! Please try again. -Current Account: -Name: hihi -Balance: $1000 ----------------------------- -New deposit added! -You have $1100.21 remaining! -Current Account: -Name: hihi -Balance: $1100.21 ----------------------------- -What's your name? -How much would you like to add as Balance? -Account created! -Name: sherlock -Balance: $123778.1 ----------------------------- -Current Account: -Name: hihi -Balance: $1100.21 ----------------------------- -Name: sherlock -Balance: $123778.1 ----------------------------- -You do not have sufficient Balance ----------------------------- -Current Account switched ----------------------------- -Current Account is: ----------------------------- -Name: sherlock -Balance: $123778.1 ----------------------------- -Current Account: -Name: sherlock -Balance: $123778.1 ----------------------------- -Name: hihi -Balance: $1100.21 ----------------------------- -The input is not a valid number! Please try again. -Withdrawal successful! -You have $123678.1 remaining! ----------------------------- -Current Account: -Name: sherlock -Balance: $123678.1 ----------------------------- -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. ----------------------------- -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.1 ----------------------------- -Name: hihi -Balance: $1100.21 ----------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 28/03/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 28/03/2023 -Not a valid command! -Goodbye! Hope to see you again! :) From 58f4cfa86d8642fb2a95b21b7c418a11b7c97324 Mon Sep 17 00:00:00 2001 From: vishnuvk47 Date: Mon, 3 Apr 2023 11:15:09 +0800 Subject: [PATCH 236/368] Changed date in expected.tct --- text-ui-test/EXPECTED.TXT | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 5baa5340b9..ca83ba8bce 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -117,8 +117,8 @@ Balance: $123678.1 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 01/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 01/04/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 03/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 03/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 3f7993d0ee71745523b5f4d8fb367ef845231218 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 14:35:15 +0800 Subject: [PATCH 237/368] Added withdrawal cancelled exception. Made it unique to save goals --- .../exceptions/WithdrawalCancelledFromSaveGoal.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledFromSaveGoal.java diff --git a/src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledFromSaveGoal.java b/src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledFromSaveGoal.java new file mode 100644 index 0000000000..90f5425ddd --- /dev/null +++ b/src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledFromSaveGoal.java @@ -0,0 +1,5 @@ +package seedu.bankwithus.exceptions; + +public class WithdrawalCancelledFromSaveGoal extends Exception { + +} From ee9b343c32967368387ee0f6e1d685f2928c683f Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 14:38:58 +0800 Subject: [PATCH 238/368] Changed handleProceed back to void type, and using exceptions to detect if withdrawal cancelled instead --- .../exceptions/WithdrawalCancelledException.java | 5 +++++ .../exceptions/WithdrawalCancelledFromSaveGoal.java | 5 ----- src/main/java/seedu/bankwithus/user/AccountList.java | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledException.java delete mode 100644 src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledFromSaveGoal.java 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/exceptions/WithdrawalCancelledFromSaveGoal.java b/src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledFromSaveGoal.java deleted file mode 100644 index 90f5425ddd..0000000000 --- a/src/main/java/seedu/bankwithus/exceptions/WithdrawalCancelledFromSaveGoal.java +++ /dev/null @@ -1,5 +0,0 @@ -package seedu.bankwithus.exceptions; - -public class WithdrawalCancelledFromSaveGoal extends Exception { - -} diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 82f9e05023..e5f28dce14 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -10,6 +10,7 @@ import seedu.bankwithus.exceptions.NegativeAmountException; import seedu.bankwithus.exceptions.NoAccountException; import seedu.bankwithus.exceptions.SaveFileIsEmptyException; +import seedu.bankwithus.exceptions.WithdrawalCancelledException; import seedu.bankwithus.parser.Parser; import seedu.bankwithus.ui.Ui; @@ -419,7 +420,8 @@ public void setAccounts(ArrayList accounts) { * @param withdrawAmount * @param currentBalance */ - public Boolean handleProceed(float withdrawAmount, float currentBalance) { + public void handleProceed(float withdrawAmount, float 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."); @@ -429,11 +431,10 @@ public Boolean handleProceed(float withdrawAmount, float currentBalance) { getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); getMainAccount().saveGoal.amtToSave = 0; ui.showWithdrawMessage(); - return true; } else { ui.showWithdrawCancelled(); - return false; + throw new WithdrawalCancelledException(); } } From cf90ff4ad2d2cdfdfcd540322344072b21266318 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 14:43:09 +0800 Subject: [PATCH 239/368] Changed hasWithdrawMoney back to withdrawMoney, used WithdrawalCancelledException to prevent logging of transaction --- src/main/java/seedu/bankwithus/user/AccountList.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index e5f28dce14..40bd46304a 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -292,10 +292,12 @@ public LocalDate handleDate(LocalDate date) { * @throws NegativeAmountException * @throws InsufficientBalanceException * @throws ExceedsWithdrawalLimitException + * @throws WithdrawalCancelledException */ //@@author manushridiv - public Boolean hasWithdrawMoney(String withdrawAmountString) throws NumberFormatException, - NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException { + public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, + NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException, + WithdrawalCancelledException { float withdrawAmount = Float.parseFloat(withdrawAmountString); if (withdrawAmount < 0) { throw new NegativeAmountException(); @@ -307,11 +309,10 @@ public Boolean hasWithdrawMoney(String withdrawAmountString) throws NumberFormat throw new ExceedsWithdrawalLimitException(); } else if(willFailsSaveGoal(currentBalance, withdrawAmount)) { ui.failToMeetSaveGoal(); - return handleProceed(withdrawAmount, currentBalance); + handleProceed(withdrawAmount, currentBalance); } else { getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); ui.showWithdrawMessage(); - return true; } } @@ -427,11 +428,11 @@ public void handleProceed(float withdrawAmount, float currentBalance) throws 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 = 0; ui.showWithdrawMessage(); - } else { ui.showWithdrawCancelled(); throw new WithdrawalCancelledException(); From 7d5c0a5662676ba3e5debe0b4d787ee277821afd Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 14:46:22 +0800 Subject: [PATCH 240/368] Update parseCommand method to account for cancelled withdrawal --- src/main/java/seedu/bankwithus/parser/Parser.java | 12 +++++++----- src/main/java/seedu/bankwithus/user/AccountList.java | 1 - 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index b727488827..ce93205443 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -15,6 +15,7 @@ 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; @@ -95,11 +96,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce break; case "withdraw": try { - boolean hasWithdrawn = accountList.hasWithdrawMoney(args); - if(hasWithdrawn) { - transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(), - "withdraw", args, LocalDate.now()); - } + accountList.withdrawMoney(args); + transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(), + "withdraw", args, LocalDate.now()); accountList.showBal(); ui.printLine(); } catch (NumberFormatException e) { @@ -114,6 +113,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showWithdrawalLimit(wlInfo[0]); //print wl ui.showTotalAmountWithdrawn(wlInfo[1]); //print total amt withdrawn ui.printLine(); + } catch (WithdrawalCancelledException e) { + ui.showWithdrawCancelled(); + ui.printLine(); } break; case "add-account": diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 40bd46304a..87edfddbb6 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -434,7 +434,6 @@ public void handleProceed(float withdrawAmount, float currentBalance) throws getMainAccount().saveGoal.amtToSave = 0; ui.showWithdrawMessage(); } else { - ui.showWithdrawCancelled(); throw new WithdrawalCancelledException(); } } From 5a23b0d226cf53ec6d73109272c70bff51c3be44 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 14:50:18 +0800 Subject: [PATCH 241/368] Updated tests in AccountlistTest and also credited vishnu --- src/test/java/seedu/bankwithus/AccountListTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index a1769ca331..bca921fc18 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -31,12 +31,13 @@ void depositMoney_negativeNumber_expectException() { () -> accountList.depositMoney(amountString)); } + //@@author vishnuvk47 @Test void withdrawNegativeAmount() { AccountList accountList = new AccountList(); accountList.addAccount("James", "1000", ""); assertThrows(NegativeAmountException.class, () -> { - accountList.hasWithdrawMoney("-100"); + accountList.withdrawMoney("-100"); }); } @@ -45,7 +46,7 @@ void withdrawNegativeAmountWithDecimal() { AccountList accountList = new AccountList(); accountList.addAccount("James", "1000", ""); assertThrows(NegativeAmountException.class, () -> { - accountList.hasWithdrawMoney("-21.67"); + accountList.withdrawMoney("-21.67"); }); } From 3a408def5ffe231d9b2b77fff0c96b64587e1eb7 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 14:59:47 +0800 Subject: [PATCH 242/368] Added new constructor to SaveGoal class --- src/main/java/seedu/bankwithus/common/SaveGoal.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/common/SaveGoal.java b/src/main/java/seedu/bankwithus/common/SaveGoal.java index fd4bcf8905..72f054412c 100644 --- a/src/main/java/seedu/bankwithus/common/SaveGoal.java +++ b/src/main/java/seedu/bankwithus/common/SaveGoal.java @@ -4,6 +4,7 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; +//@@author vishnuvk47 public class SaveGoal { public float amtToSave; public LocalDate untilWhen; @@ -18,5 +19,8 @@ public SaveGoal(float amtToSave, String untilWhenStr) { } } - + public SaveGoal(float amtToSave, LocalDate untilWhen) { + this.amtToSave = amtToSave; + this.untilWhen = untilWhen; + } } From af80f15cbcd1da7f100ffeea968e884bec3b7bce Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 15:00:40 +0800 Subject: [PATCH 243/368] Changed how localDate was parsed in the savefile --- src/main/java/seedu/bankwithus/parser/Parser.java | 9 ++++----- src/main/java/seedu/bankwithus/user/Account.java | 4 ++-- src/main/java/seedu/bankwithus/user/AccountList.java | 6 +++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index ce93205443..3fb23942f3 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -200,16 +200,15 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S String lastWithdrawnDate = splitDetails[3].trim(); String withdrawalLimit = splitDetails[4].trim(); String amtToSave; - String untilWhen; + String untilWhenStr; if (splitDetails.length > 5) { amtToSave = splitDetails[5].trim(); - untilWhen = splitDetails[6].trim(); + untilWhenStr = splitDetails[6].trim(); } else { amtToSave = "0"; - untilWhen = "2001-01-01"; + untilWhenStr = "2001-01-01"; } - StringBuilder tempStr = new StringBuilder(untilWhen); - untilWhen = tempStr.reverse().toString(); + LocalDate untilWhen = LocalDate.parse(untilWhenStr); if (name.isEmpty() || balanceString.isEmpty() || totalAmtWithdrawn.isEmpty()) { throw new CorruptedSaveFileException(); } diff --git a/src/main/java/seedu/bankwithus/user/Account.java b/src/main/java/seedu/bankwithus/user/Account.java index 026a06eebf..f2c81cba0c 100644 --- a/src/main/java/seedu/bankwithus/user/Account.java +++ b/src/main/java/seedu/bankwithus/user/Account.java @@ -18,7 +18,7 @@ public class Account { * @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, String untilWhen) { + public Account(String name, String balance, String amtToSave, LocalDate untilWhen) { this.name = name; this.balance = balance; this.withdrawalChecker = new WithdrawalChecker(); @@ -27,7 +27,7 @@ public Account(String name, String balance, String amtToSave, String untilWhen) //@@author tyuyang public Account(String name, String balance, String totalAmtWithdrawn, - LocalDate lastWithdrawnDate, String amtToSave, String untilWhen) { + LocalDate lastWithdrawnDate, String amtToSave, LocalDate untilWhen) { this.name = name; this.balance = balance; this.withdrawalChecker = new WithdrawalChecker(totalAmtWithdrawn, lastWithdrawnDate); diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 87edfddbb6..8d09b172e3 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -152,7 +152,7 @@ public String askUserForBalance() { * @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", "01-01-2001"); + Account newAccount = new Account(name, balance, "0", LocalDate.parse("2001-01-01")); if (!withdrawalLimit.isBlank()) { Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat); @@ -169,7 +169,7 @@ public void addAccount(String name, String balance, String withdrawalLimit) { * @param amtToSave - save Goal amount * @param untilWhen - deadline for save goal amount */ - public void addAccount(String name, String balance, String withdrawalLimit, String amtToSave, String untilWhen) { + public void addAccount(String name, String balance, String withdrawalLimit, String amtToSave, LocalDate untilWhen) { Account newAccount = new Account(name, balance, amtToSave, untilWhen); if (!withdrawalLimit.isBlank()) { Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); @@ -190,7 +190,7 @@ public void addAccount(String name, String balance, String withdrawalLimit, Stri * @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, String untilWhen) { + LocalDate lastWithdrawnDate, String withdrawalLimit, String amtToSave, LocalDate untilWhen) { Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate, amtToSave, untilWhen); if (!withdrawalLimit.isBlank()) { Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); From e3748f82a297d99303a1a5e698138dbcd9694cf9 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 15:08:44 +0800 Subject: [PATCH 244/368] Fixed checkstyle --- src/main/java/seedu/bankwithus/user/AccountList.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 8d09b172e3..336cc2660e 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -285,9 +285,8 @@ public LocalDate handleDate(LocalDate date) { /** * Withdraws a user specified amount from the current account. * Also checks if user meets their withdrawal limit and save goal requirement. - * Checks if a Valid withdrawal occurred. + * Throws exceptions if withdrawal does not go through. * @param withdrawAmountString - amount to be withdrawn - * @return true if money was withdrawn successfully and false otherwise * @throws NumberFormatException * @throws NegativeAmountException * @throws InsufficientBalanceException From 87af21ba249e0eb20ed1f035c1ad10a5301860c1 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 17:19:51 +0800 Subject: [PATCH 245/368] Remove johndoe.md file --- docs/team/johndoe.md | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 docs/team/johndoe.md 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 From a75c503184910a248d6233f1cc79f0c7279d67fa Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 17:20:05 +0800 Subject: [PATCH 246/368] Add tyuyang.md file --- docs/team/tyuyang.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/team/tyuyang.md diff --git a/docs/team/tyuyang.md b/docs/team/tyuyang.md new file mode 100644 index 0000000000..e69de29bb2 From 671fcdb45482fd7385e3025702a8abf8b2b08360 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 3 Apr 2023 19:00:03 +0800 Subject: [PATCH 247/368] Add PPP for tyuyang --- docs/AboutUs.md | 2 +- docs/team/tyuyang.md | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 6633f92d3c..2742158a78 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,7 @@ Display | Name | Github Profile | Portfolio --------|:-----------:|:---------------------------------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](docs/team/johndoe.md) - | Tay Yu Yang | [Github](https://github.com/tyuyang) | No portfolio to speak of. + | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](docs/team/tyuyang.md) ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | N.A. ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | No portfolio>>>>>>> master diff --git a/docs/team/tyuyang.md b/docs/team/tyuyang.md index e69de29bb2..08066ce804 100644 --- a/docs/team/tyuyang.md +++ b/docs/team/tyuyang.md @@ -0,0 +1,33 @@ +# 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. 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 (aside from limit overflow) and works as expected in all tested situations. + +### 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 the main architecture and the example sequence diagram. + + +### 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 in the PED were already pointed out 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. From 70d716eaf0e837ecea4d4b894ed1130d84f3e6fa Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 3 Apr 2023 21:41:47 +0800 Subject: [PATCH 248/368] add MoreThanTwoDecimalPlace detection when user try to withdraw or deposit --- .../exceptions/MoreThanTwoDecimalPlace.java | 6 ++ .../java/seedu/bankwithus/parser/Parser.java | 5 ++ src/main/java/seedu/bankwithus/ui/Ui.java | 6 ++ .../seedu/bankwithus/user/AccountList.java | 90 +++++++++++++------ 4 files changed, 82 insertions(+), 25 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/MoreThanTwoDecimalPlace.java 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/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 3fb23942f3..1b4bcb7ff9 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -1,5 +1,6 @@ package seedu.bankwithus.parser; +import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace; import seedu.bankwithus.user.AccountList; import seedu.bankwithus.BankWithUs; import seedu.bankwithus.user.Transaction; @@ -84,6 +85,8 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showNullInputError(); } catch (NegativeAmountException e) { ui.showNegativeAmountError(); + } catch (MoreThanTwoDecimalPlace e) { + ui.showDecimalPlacesError(); } break; case "view-account": @@ -116,6 +119,8 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce } catch (WithdrawalCancelledException e) { ui.showWithdrawCancelled(); ui.printLine(); + } catch (MoreThanTwoDecimalPlace e) { + ui.showDecimalPlacesError(); } break; case "add-account": diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 08f749c33e..379b363f0d 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -284,4 +284,10 @@ 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(); + } } diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 336cc2660e..7a8aaece0a 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -7,6 +7,7 @@ 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.SaveFileIsEmptyException; @@ -14,6 +15,7 @@ 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; @@ -67,7 +69,7 @@ public AccountList(Scanner scanner, BankWithUs bwu) { Parser parser = new Parser(this); try { parser.parseSavedFile(scanner); - for(Account acc : accounts) { + for (Account acc : accounts) { doesNameExist.put(acc.getName(), true); } } catch (CorruptedSaveFileException e) { @@ -80,6 +82,7 @@ public AccountList(Scanner scanner, BankWithUs bwu) { } //@@author xiaoge26 + /** * @return - Returns the current account. */ @@ -88,6 +91,7 @@ public Account getMainAccount() { } //@@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 @@ -144,6 +148,7 @@ public String askUserForBalance() { } //@@author xiaoge26 + /** * Creates a new account and adds it to the AccountList. * @@ -163,11 +168,12 @@ public void addAccount(String name, String balance, String withdrawalLimit) { /** * Simple method that adds an account. - * @param name - Name of the account - * @param balance -The available balance + * + * @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 + * @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); @@ -180,9 +186,10 @@ public void addAccount(String name, String balance, String withdrawalLimit, Stri } //@@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 @@ -190,7 +197,7 @@ public void addAccount(String name, String balance, String withdrawalLimit, Stri * @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) { + LocalDate lastWithdrawnDate, String withdrawalLimit, String amtToSave, LocalDate untilWhen) { Account newAccount = new Account(name, balance, totalAmtWithdrawn, lastWithdrawnDate, amtToSave, untilWhen); if (!withdrawalLimit.isBlank()) { Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); @@ -199,8 +206,9 @@ public void addAccount(String name, String balance, String totalAmtWithdrawn, accounts.add(newAccount); ui.showNewAccountAdded(newAccount); } - + //@@author vishnuvk47 + /** * Creates a new Account for a first time user. */ @@ -216,6 +224,7 @@ public void createNewAccount() { } //@@author Sherlock-YH + /** * Name and balance are separated by ; prepared to be saved. * @@ -253,6 +262,7 @@ public void showBal() { /** * Deposits a user specified amount to the current account's balance. + * * @param depositAmountString - amount to be deposited * @throws NumberFormatException * @throws NullPointerException @@ -260,18 +270,23 @@ public void showBal() { */ //@@author xiaoge26 public void depositMoney(String depositAmountString) throws NumberFormatException, - NullPointerException, NegativeAmountException { + NullPointerException, NegativeAmountException, MoreThanTwoDecimalPlace { float depositAmount = Float.parseFloat(depositAmountString); if (depositAmount < 0) { throw new NegativeAmountException(); } else { + if (isMoreThanTwoDecimalPlaces(depositAmount)) { + throw new MoreThanTwoDecimalPlace(); + } getMainAccount().addBalance(depositAmount); } } //@@author vishnuvk47 + /** * Formats the date into the dd-MM-yyyy format. + * * @param date * @return the date in the dd-MM-yyyy format */ @@ -286,6 +301,7 @@ public LocalDate handleDate(LocalDate date) { * 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 @@ -295,9 +311,10 @@ public LocalDate handleDate(LocalDate date) { */ //@@author manushridiv public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, - NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException, - WithdrawalCancelledException { + NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException, + WithdrawalCancelledException, MoreThanTwoDecimalPlace { float withdrawAmount = Float.parseFloat(withdrawAmountString); + if (withdrawAmount < 0) { throw new NegativeAmountException(); } @@ -306,11 +323,13 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept throw new InsufficientBalanceException(); } else if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(withdrawAmount)) { throw new ExceedsWithdrawalLimitException(); - } else if(willFailsSaveGoal(currentBalance, withdrawAmount)) { + } else if (willFailsSaveGoal(currentBalance, withdrawAmount)) { ui.failToMeetSaveGoal(); handleProceed(withdrawAmount, currentBalance); + } else if (isMoreThanTwoDecimalPlaces(withdrawAmount)) { + throw new MoreThanTwoDecimalPlace(); } else { - getMainAccount( ).subtractBalance(currentBalance,withdrawAmount); + getMainAccount().subtractBalance(currentBalance, withdrawAmount); ui.showWithdrawMessage(); } } @@ -318,14 +337,15 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept /** * 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 + * @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); ui.showAccountDeleted(name); - if(accounts.size() < 1) { + if (accounts.size() < 1) { createNewAccount(); } return true; @@ -335,13 +355,14 @@ public Boolean foundAccountToDelete(String name, Account acc) { /** * 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))) { + if (foundAccountToDelete(name, accounts.get(i))) { accountDeleted = true; i--; } @@ -352,7 +373,6 @@ public void deleteAccount(String name) { } - //@@author Sherlock-YH public int getSize() { return accounts.size(); @@ -360,6 +380,7 @@ public int getSize() { /** * Method that handles switching between users. + * * @param accName - account to be switched into * @throws NoAccountException */ @@ -384,12 +405,12 @@ public void switchMainAccount(String accName) throws NoAccountException { } //@@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 { @@ -404,7 +425,7 @@ public void setWithdrawalLimit(String args) throws NegativeAmountException { } getMainAccount().getWithdrawalChecker().setWithdrawalLimit(withdrawalLimit); } - + //@@author Sherlock-YH public ArrayList getAccounts() { return accounts; @@ -415,21 +436,23 @@ public void setAccounts(ArrayList accounts) { } //@@author vishnuvk47 + /** * Handles overwriting of saveGoal at users own discretion. + * * @param withdrawAmount * @param currentBalance */ - public void handleProceed(float withdrawAmount, float currentBalance) throws + public void handleProceed(float withdrawAmount, float currentBalance) throws WithdrawalCancelledException { String yesOrNo = ui.getNextLine(); - while(!(yesOrNo.equalsIgnoreCase("y") || yesOrNo.equalsIgnoreCase("n"))) { + 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); + if (yesOrNo.equalsIgnoreCase("y")) { + getMainAccount().subtractBalance(currentBalance, withdrawAmount); getMainAccount().saveGoal.amtToSave = 0; ui.showWithdrawMessage(); } else { @@ -438,8 +461,10 @@ public void handleProceed(float withdrawAmount, float currentBalance) throws } //@@author Vishnu + /** * Primary function that handles the setting and exception handling when saveGoal is called. + * * @param args * @param untilWhenStr */ @@ -459,8 +484,10 @@ public void handleSaveGoal(String args, String untilWhenStr) { } //@@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 */ @@ -482,7 +509,7 @@ public boolean isDateFormatValid(String date) { */ public void showGoal() { SaveGoal goal = getMainAccount().getSaveGoal(); - if(goal.amtToSave <= 0) { + if (goal.amtToSave <= 0) { System.out.println("you do not have any Save Goal"); } else { ui.showGoal(goal); @@ -491,6 +518,7 @@ public void showGoal() { /** * 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 @@ -513,4 +541,16 @@ public String[] checkWithdrawalLimit() { wlInfo[1] = withdrawalChecker.getTotalAmtWithdrawn(); return wlInfo; } + + //@@author Sherlock-YH + public static boolean isMoreThanTwoDecimalPlaces(float num) { + String numStr = Float.toString(num); + int decimalIndex = numStr.indexOf('.'); + if (decimalIndex == -1) { + // No decimal point found, so the number has zero decimal places + return false; + } + int numDecimals = numStr.length() - decimalIndex - 1; + return numDecimals > 2; + } } From df7730df77f015392420b7c38c3bcbf569c07826 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 3 Apr 2023 21:42:01 +0800 Subject: [PATCH 249/368] update text-ui-test --- .gitignore | 2 +- text-ui-test/EXPECTED.TXT | 9 ++++++++- text-ui-test/input.txt | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index bf5b078f8c..5f279f9082 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,5 @@ bin/ data data/save.txt -text-ui-test/ACTUAL.TXT +text-ui-test/EXPECTED.TXT text-ui-test/EXPECTED-UNIX.TXT diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index ca83ba8bce..9e873bff26 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -102,6 +102,12 @@ 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.2 remaining! +---------------------------- Withdrawal limit is currently $100. You have withdrawn $100 this month. ---------------------------- @@ -112,13 +118,14 @@ You have withdrawn $100 this month. ---------------------------- Current Account: Name: sherlock -Balance: $123678.1 +Balance: $123678.2 ---------------------------- Name: hihi Balance: $1100.21 ---------------------------- Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 03/04/2023 Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 03/04/2023 +Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 03/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 9990037425..2ae6391018 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -27,7 +27,9 @@ set-wl bal check-wl set-wl 100 check-wl -withdraw 10 +withdraw 10.111 +deposit 9.112 +deposit 0.1 check-wl withdraw 100 view-account From d97726e5446ba31730b5f7663413bbec456d7cb2 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 3 Apr 2023 21:46:09 +0800 Subject: [PATCH 250/368] remove unused Class --- src/main/java/seedu/bankwithus/user/AccountList.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 7a8aaece0a..c916ff4f35 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -15,7 +15,6 @@ 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; From e154061f9ae6e671c064b467c364dd9ea24f7829 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 3 Apr 2023 22:03:04 +0800 Subject: [PATCH 251/368] add test for AccountList withdraw and deposit method --- .../seedu/bankwithus/AccountListTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index bca921fc18..19835085ee 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,6 +1,7 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; +import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace; import seedu.bankwithus.user.AccountList; import seedu.bankwithus.exceptions.NegativeAmountException; @@ -31,6 +32,32 @@ void depositMoney_negativeNumber_expectException() { () -> 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() { From c16350b429d8dc7f987ef4f8a2e528a8604a29db Mon Sep 17 00:00:00 2001 From: vishnu Date: Tue, 4 Apr 2023 01:11:20 +0800 Subject: [PATCH 252/368] Changed Floats to BigDecimal where calculations were involved --- .../seedu/bankwithus/common/SaveGoal.java | 7 ++-- src/main/java/seedu/bankwithus/ui/Ui.java | 8 +++-- .../java/seedu/bankwithus/user/Account.java | 29 +++++++-------- .../seedu/bankwithus/user/AccountList.java | 36 ++++++++++--------- 4 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/main/java/seedu/bankwithus/common/SaveGoal.java b/src/main/java/seedu/bankwithus/common/SaveGoal.java index 72f054412c..8a2d072290 100644 --- a/src/main/java/seedu/bankwithus/common/SaveGoal.java +++ b/src/main/java/seedu/bankwithus/common/SaveGoal.java @@ -1,15 +1,16 @@ 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 float amtToSave; + public BigDecimal amtToSave; public LocalDate untilWhen; - public SaveGoal(float amtToSave, String untilWhenStr) { + public SaveGoal(BigDecimal amtToSave, String untilWhenStr) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); try { this.untilWhen = LocalDate.parse(untilWhenStr, formatter); @@ -19,7 +20,7 @@ public SaveGoal(float amtToSave, String untilWhenStr) { } } - public SaveGoal(float amtToSave, LocalDate untilWhen) { + public SaveGoal(BigDecimal amtToSave, LocalDate untilWhen) { this.amtToSave = amtToSave; this.untilWhen = untilWhen; } diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 379b363f0d..03ea21ef9d 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -3,6 +3,8 @@ 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; @@ -99,8 +101,8 @@ public void viewAccount(String accDetails) { } } - public void showBal(String finalBal) { - System.out.println("You have $" + finalBal + " remaining!"); + public void showBal(BigDecimal finalBal) { + System.out.println("You have $" + finalBal.setScale(2, RoundingMode.CEILING) + " remaining!"); } public void showNegativeAmountError() { @@ -239,7 +241,7 @@ public void failToMeetSaveGoal() { } public void showGoal(SaveGoal goal) { - System.out.println("Min amount to save: $" + Float.toString(goal.amtToSave)); + 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); diff --git a/src/main/java/seedu/bankwithus/user/Account.java b/src/main/java/seedu/bankwithus/user/Account.java index f2c81cba0c..ecee8681de 100644 --- a/src/main/java/seedu/bankwithus/user/Account.java +++ b/src/main/java/seedu/bankwithus/user/Account.java @@ -3,13 +3,15 @@ import seedu.bankwithus.common.SaveGoal; import seedu.bankwithus.common.WithdrawalChecker; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.text.DecimalFormat; import java.time.LocalDate; public class Account { public SaveGoal saveGoal; private String name; - private String balance; + private BigDecimal balance; private WithdrawalChecker withdrawalChecker; //@@author Sherlock-YH /** @@ -20,25 +22,25 @@ public class Account { */ public Account(String name, String balance, String amtToSave, LocalDate untilWhen) { this.name = name; - this.balance = balance; + this.balance = new BigDecimal(balance).setScale(2, RoundingMode.CEILING);; this.withdrawalChecker = new WithdrawalChecker(); - this.saveGoal = new SaveGoal(Float.parseFloat(amtToSave), untilWhen); + 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 = balance; + this.balance = new BigDecimal(balance).setScale(2, RoundingMode.CEILING);; this.withdrawalChecker = new WithdrawalChecker(totalAmtWithdrawn, lastWithdrawnDate); - this.saveGoal = new SaveGoal(Float.parseFloat(amtToSave), untilWhen); + this.saveGoal = new SaveGoal(new BigDecimal(amtToSave), untilWhen); } //@@author Sherlock-YH public String getAccountName() { return name; } //@@author Sherlock-YH - public String getAccountBalance() { + public BigDecimal getAccountBalance() { return balance; } @@ -48,19 +50,14 @@ public WithdrawalChecker getWithdrawalChecker() { } //@@author xiaoge26 - public void addBalance(float balanceToBeAdded) { - DecimalFormat df = new DecimalFormat("#.##"); - String formatted = df.format(Float.parseFloat(balance) + balanceToBeAdded); - this.balance = String.valueOf(formatted); + public void addBalance(BigDecimal balanceToBeAdded) { + this.balance = this.balance.add(balanceToBeAdded).setScale(2, RoundingMode.CEILING); } //@@author manushridiv - public void subtractBalance(float currentBalance, float withdrawal) { - DecimalFormat df = new DecimalFormat("#.##"); - String formatted = df.format(currentBalance - withdrawal); - this.balance = String.valueOf(formatted); - - withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); + public void subtractBalance(BigDecimal currentBalance, BigDecimal withdrawal) { + this.balance = currentBalance.subtract(withdrawal); +// withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); //check later } //@@author vishnuvk47 diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index c916ff4f35..877c8b72e3 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -15,6 +15,7 @@ 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; @@ -253,8 +254,7 @@ public String getAllAccountDetails() throws AccountNotFoundException { */ //@@author public void showBal() { - String balance = getMainAccount().getAccountBalance(); - float bal = Float.parseFloat(balance); + BigDecimal balance = getMainAccount().getAccountBalance(); ui.showBal(balance); } @@ -270,14 +270,15 @@ public void showBal() { //@@author xiaoge26 public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException, NegativeAmountException, MoreThanTwoDecimalPlace { - float depositAmount = Float.parseFloat(depositAmountString); + float depositAmount = Float.parseFloat(depositAmountString);//floats are still used, but only for comparison + BigDecimal AmtToDeposit = new BigDecimal(depositAmountString); if (depositAmount < 0) { throw new NegativeAmountException(); } else { if (isMoreThanTwoDecimalPlaces(depositAmount)) { throw new MoreThanTwoDecimalPlace(); } - getMainAccount().addBalance(depositAmount); + getMainAccount().addBalance(AmtToDeposit); } } @@ -313,22 +314,22 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException, WithdrawalCancelledException, MoreThanTwoDecimalPlace { float withdrawAmount = Float.parseFloat(withdrawAmountString); - + BigDecimal amtToDraw = new BigDecimal(withdrawAmount); if (withdrawAmount < 0) { throw new NegativeAmountException(); } - float currentBalance = Float.parseFloat(getMainAccount().getAccountBalance()); - if (currentBalance < withdrawAmount) { + BigDecimal currentBalance = getMainAccount().getAccountBalance(); + if (currentBalance.compareTo(amtToDraw) < 0) { throw new InsufficientBalanceException(); } else if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(withdrawAmount)) { throw new ExceedsWithdrawalLimitException(); - } else if (willFailsSaveGoal(currentBalance, withdrawAmount)) { + } else if (willFailsSaveGoal(currentBalance, amtToDraw)) { ui.failToMeetSaveGoal(); - handleProceed(withdrawAmount, currentBalance); + handleProceed(amtToDraw, currentBalance); } else if (isMoreThanTwoDecimalPlaces(withdrawAmount)) { throw new MoreThanTwoDecimalPlace(); } else { - getMainAccount().subtractBalance(currentBalance, withdrawAmount); + getMainAccount().subtractBalance(currentBalance, amtToDraw); ui.showWithdrawMessage(); } } @@ -442,7 +443,7 @@ public void setAccounts(ArrayList accounts) { * @param withdrawAmount * @param currentBalance */ - public void handleProceed(float withdrawAmount, float currentBalance) throws + public void handleProceed(BigDecimal withdrawAmount, BigDecimal currentBalance) throws WithdrawalCancelledException { String yesOrNo = ui.getNextLine(); while (!(yesOrNo.equalsIgnoreCase("y") || yesOrNo.equalsIgnoreCase("n"))) { @@ -452,7 +453,7 @@ public void handleProceed(float withdrawAmount, float currentBalance) throws if (yesOrNo.equalsIgnoreCase("y")) { getMainAccount().subtractBalance(currentBalance, withdrawAmount); - getMainAccount().saveGoal.amtToSave = 0; + getMainAccount().saveGoal.amtToSave = new BigDecimal(0); ui.showWithdrawMessage(); } else { throw new WithdrawalCancelledException(); @@ -473,7 +474,7 @@ public void handleSaveGoal(String args, String untilWhenStr) { if (toSave < 0) { ui.showNegativeAmountError(); } else if (isDateFormatValid(untilWhenStr)) { - SaveGoal saveGoal = new SaveGoal(toSave, untilWhenStr); + SaveGoal saveGoal = new SaveGoal(new BigDecimal(toSave), untilWhenStr); getMainAccount().setSaveGoal(saveGoal, args, untilWhenStr); ui.showSaveGoalCreated(args, untilWhenStr); } @@ -508,7 +509,8 @@ public boolean isDateFormatValid(String date) { */ public void showGoal() { SaveGoal goal = getMainAccount().getSaveGoal(); - if (goal.amtToSave <= 0) { + 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); @@ -522,11 +524,11 @@ public void showGoal() { * @param withdrawAmount * @return True if fails to meet save Goal and False if meets save Goal requirements */ - public Boolean willFailsSaveGoal(float currentBalance, float withdrawAmount) { - float expectedBal = currentBalance - withdrawAmount; + public Boolean willFailsSaveGoal(BigDecimal currentBalance, BigDecimal withdrawAmount) { + BigDecimal expectedBal = currentBalance.subtract(withdrawAmount); LocalDate tdy = LocalDate.now(); LocalDate tdyDate = handleDate(tdy); - boolean exceedsSaveGoal = getMainAccount().getSaveGoal().amtToSave > expectedBal; + boolean exceedsSaveGoal = (getMainAccount().getSaveGoal().amtToSave.compareTo(expectedBal) == 1); boolean deadlineNotPassed = getMainAccount().getSaveGoal().untilWhen.isAfter(tdyDate); return (exceedsSaveGoal && deadlineNotPassed); } From 8a17b647733f0e5e137681b31bb888b7f3ebe5cd Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 4 Apr 2023 11:57:56 +0800 Subject: [PATCH 253/368] Revert gitignore --- .gitignore | 2 +- text-ui-test/EXPECTED.TXT | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 5f279f9082..bf5b078f8c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,5 @@ bin/ data data/save.txt -text-ui-test/EXPECTED.TXT +text-ui-test/ACTUAL.TXT text-ui-test/EXPECTED-UNIX.TXT diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9e873bff26..5514cfc72a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -123,9 +123,9 @@ Balance: $123678.2 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 03/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 03/04/2023 -Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 03/04/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 04/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 04/04/2023 +Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 04/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 40488332d5be7ce733b321c5e8a02f0e9e9c6a88 Mon Sep 17 00:00:00 2001 From: vishnu Date: Tue, 4 Apr 2023 14:03:02 +0800 Subject: [PATCH 254/368] Changed relevant floats to BigDecimal where calcs are involved --- .../bankwithus/common/WithdrawalChecker.java | 5 +++-- .../java/seedu/bankwithus/user/Account.java | 5 ++--- .../seedu/bankwithus/user/AccountList.java | 20 +++++++++---------- .../seedu/bankwithus/AccountListTest.java | 4 +++- .../bankwithus/WithdrawalCheckerTest.java | 11 +++++----- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java index 85eedd740a..dfe236e6d8 100644 --- a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java @@ -1,5 +1,6 @@ package seedu.bankwithus.common; +import java.math.BigDecimal; import java.util.logging.Level; import java.util.logging.Logger; import java.text.DecimalFormat; @@ -46,7 +47,7 @@ public String getTotalAmtWithdrawn() { * * @param withdrawal the amount that was just withdrawn */ - public void updateTotalAmtWithdrawn(float withdrawal) { + public void updateTotalAmtWithdrawn(BigDecimal withdrawal) { logger.log(Level.FINE, "updateTotalAmtWithdrawn in WithdrawalChecker called"); LocalDate currentDate = LocalDate.now(); DecimalFormat df = new DecimalFormat("#.##"); @@ -62,7 +63,7 @@ public void updateTotalAmtWithdrawn(float withdrawal) { 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(Float.parseFloat(totalAmtWithdrawn) + withdrawal); + 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"); diff --git a/src/main/java/seedu/bankwithus/user/Account.java b/src/main/java/seedu/bankwithus/user/Account.java index ecee8681de..9eeb8355d6 100644 --- a/src/main/java/seedu/bankwithus/user/Account.java +++ b/src/main/java/seedu/bankwithus/user/Account.java @@ -5,7 +5,6 @@ import java.math.BigDecimal; import java.math.RoundingMode; -import java.text.DecimalFormat; import java.time.LocalDate; public class Account { @@ -22,7 +21,7 @@ public class Account { */ public Account(String name, String balance, String amtToSave, LocalDate untilWhen) { this.name = name; - this.balance = new BigDecimal(balance).setScale(2, RoundingMode.CEILING);; + this.balance = new BigDecimal(balance).setScale(2, RoundingMode.CEILING); this.withdrawalChecker = new WithdrawalChecker(); this.saveGoal = new SaveGoal(new BigDecimal(amtToSave), untilWhen); } @@ -57,7 +56,7 @@ public void addBalance(BigDecimal balanceToBeAdded) { //@@author manushridiv public void subtractBalance(BigDecimal currentBalance, BigDecimal withdrawal) { this.balance = currentBalance.subtract(withdrawal); -// withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); //check later + withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); //check later } //@@author vishnuvk47 diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 877c8b72e3..5d51257022 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -25,7 +25,6 @@ import java.util.HashMap; import java.util.Scanner; -import static java.lang.Math.abs; public class AccountList { @@ -127,17 +126,16 @@ public String askUserForBalance() { balanceString = balanceString.trim(); balanceString = balanceString.replaceFirst("^0+(?!$)", ""); try { - float balance = Float.parseFloat(balanceString); - if (balance < 0) { + BigDecimal balance = new BigDecimal(balanceString); + if (balance.signum() == -1) { throw new NegativeAmountException(); } - if (balance < 1 && abs(balance) != 0) { + if (balance.compareTo(new BigDecimal("0")) == -1 ) { balanceString = "0" + balanceString; return balanceString; } - float absBalance = abs(balance); //to strip -ve sign if user enters -0. - balanceString = Float.toString(absBalance); - return balanceString; + balance = balance.abs(); + return balance.toString(); } catch (NumberFormatException e) { ui.showNumberFormatError(); return askUserForBalance(); @@ -271,14 +269,14 @@ public void showBal() { public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException, NegativeAmountException, MoreThanTwoDecimalPlace { float depositAmount = Float.parseFloat(depositAmountString);//floats are still used, but only for comparison - BigDecimal AmtToDeposit = new BigDecimal(depositAmountString); + BigDecimal amtToDeposit = new BigDecimal(depositAmountString); if (depositAmount < 0) { throw new NegativeAmountException(); } else { if (isMoreThanTwoDecimalPlaces(depositAmount)) { throw new MoreThanTwoDecimalPlace(); } - getMainAccount().addBalance(AmtToDeposit); + getMainAccount().addBalance(amtToDeposit); } } @@ -474,7 +472,7 @@ public void handleSaveGoal(String args, String untilWhenStr) { if (toSave < 0) { ui.showNegativeAmountError(); } else if (isDateFormatValid(untilWhenStr)) { - SaveGoal saveGoal = new SaveGoal(new BigDecimal(toSave), untilWhenStr); + SaveGoal saveGoal = new SaveGoal(new BigDecimal(args), untilWhenStr); getMainAccount().setSaveGoal(saveGoal, args, untilWhenStr); ui.showSaveGoalCreated(args, untilWhenStr); } @@ -537,7 +535,7 @@ public Boolean willFailsSaveGoal(BigDecimal currentBalance, BigDecimal withdrawA public String[] checkWithdrawalLimit() { String[] wlInfo = new String[2]; WithdrawalChecker withdrawalChecker = this.getMainAccount().getWithdrawalChecker(); - withdrawalChecker.updateTotalAmtWithdrawn(0); + withdrawalChecker.updateTotalAmtWithdrawn(new BigDecimal("0")); wlInfo[0] = withdrawalChecker.getWithdrawalLimit(); wlInfo[1] = withdrawalChecker.getTotalAmtWithdrawn(); return wlInfo; diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index bca921fc18..937cc15fba 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -4,6 +4,8 @@ import seedu.bankwithus.user.AccountList; import seedu.bankwithus.exceptions.NegativeAmountException; +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; @@ -56,7 +58,7 @@ void testingAddAccount_validInput_expectNewAccount() { AccountList testAccountList = new AccountList(); testAccountList.addAccount("Jane", "1000", ""); assertEquals("Jane", testAccountList.getMainAccount().getName()); - assertEquals("1000", testAccountList.getMainAccount().getAccountBalance()); + assertEquals(new BigDecimal("1000.00"), testAccountList.getMainAccount().getAccountBalance()); } //@@author tyuyang diff --git a/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java b/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java index 4d81465511..dd3fca32de 100644 --- a/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java +++ b/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java @@ -3,6 +3,7 @@ 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; @@ -13,18 +14,18 @@ public class WithdrawalCheckerTest { public void updateTotalAmtWithdrawn_validInput_noException() { WithdrawalChecker wcNoWithdrawals = new WithdrawalChecker(); //test without withdrawals - assertDoesNotThrow(() -> wcNoWithdrawals.updateTotalAmtWithdrawn((float) 10.1)); + assertDoesNotThrow(() -> wcNoWithdrawals.updateTotalAmtWithdrawn(new BigDecimal("10.1"))); assertEquals("10.1", wcNoWithdrawals.getTotalAmtWithdrawn()); //test with prior withdrawals - assertDoesNotThrow(() -> wcNoWithdrawals.updateTotalAmtWithdrawn((float) 1.1)); + assertDoesNotThrow(() -> wcNoWithdrawals.updateTotalAmtWithdrawn(new BigDecimal("1.1"))); assertEquals("11.2", wcNoWithdrawals.getTotalAmtWithdrawn()); - WithdrawalChecker wcWithWithdrawals = new WithdrawalChecker("10.01", + WithdrawalChecker wcWithWithdrawals = new WithdrawalChecker("10.01", LocalDate.parse("2023-01-10")); - + //test with prior withdrawals in a different month - assertDoesNotThrow(() -> wcWithWithdrawals.updateTotalAmtWithdrawn((float) 1.11)); + assertDoesNotThrow(() -> wcWithWithdrawals.updateTotalAmtWithdrawn(new BigDecimal("1.11"))); assertEquals("1.11", wcWithWithdrawals.getTotalAmtWithdrawn()); } From ff1a6c4936563041b9f49a80cf06e56b43e7be1b Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 4 Apr 2023 14:08:08 +0800 Subject: [PATCH 255/368] Fix bugs --- src/main/java/seedu/bankwithus/user/AccountList.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index c916ff4f35..8a5772cebd 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -343,10 +343,8 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept public Boolean foundAccountToDelete(String name, Account acc) { if (acc.getAccountName().equals(name)) { accounts.remove(acc); + doesNameExist.remove(name); ui.showAccountDeleted(name); - if (accounts.size() < 1) { - createNewAccount(); - } return true; } return false; @@ -369,6 +367,9 @@ public void deleteAccount(String name) { if (!accountDeleted) { ui.showNoAccountFound(); } + if (accounts.size() < 1) { + createNewAccount(); + } } From a280f4051a9850498c8efaf8dd336136585f291c Mon Sep 17 00:00:00 2001 From: vishnu Date: Tue, 4 Apr 2023 14:34:40 +0800 Subject: [PATCH 256/368] Changed isMoreThanTwoDecimalPlaces function to take in string not float --- .../java/seedu/bankwithus/user/AccountList.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 5d51257022..b23e2035af 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -273,7 +273,7 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio if (depositAmount < 0) { throw new NegativeAmountException(); } else { - if (isMoreThanTwoDecimalPlaces(depositAmount)) { + if (isMoreThanTwoDecimalPlaces(depositAmountString)) { throw new MoreThanTwoDecimalPlace(); } getMainAccount().addBalance(amtToDeposit); @@ -324,7 +324,7 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept } else if (willFailsSaveGoal(currentBalance, amtToDraw)) { ui.failToMeetSaveGoal(); handleProceed(amtToDraw, currentBalance); - } else if (isMoreThanTwoDecimalPlaces(withdrawAmount)) { + } else if (isMoreThanTwoDecimalPlaces(withdrawAmountString)) { throw new MoreThanTwoDecimalPlace(); } else { getMainAccount().subtractBalance(currentBalance, amtToDraw); @@ -542,14 +542,12 @@ public String[] checkWithdrawalLimit() { } //@@author Sherlock-YH - public static boolean isMoreThanTwoDecimalPlaces(float num) { - String numStr = Float.toString(num); - int decimalIndex = numStr.indexOf('.'); - if (decimalIndex == -1) { + 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; } - int numDecimals = numStr.length() - decimalIndex - 1; - return numDecimals > 2; + return (num.length() - (decPosition + 1) > 2); } } From a0f71913c6d486a685278b3317492f8fcd7f6614 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Tue, 4 Apr 2023 15:01:16 +0800 Subject: [PATCH 257/368] Add corrupted transaction file exception --- .gitignore | 2 +- .../CorruptedTransactionFileException.java | 4 +++ .../TransactionFileIsEmptyException.java | 4 +++ .../java/seedu/bankwithus/parser/Parser.java | 28 +++++++++++-------- src/main/java/seedu/bankwithus/ui/Ui.java | 3 ++ .../bankwithus/user/TransactionList.java | 10 +++---- text-ui-test/EXPECTED.TXT | 6 ++-- 7 files changed, 37 insertions(+), 20 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/CorruptedTransactionFileException.java create mode 100644 src/main/java/seedu/bankwithus/exceptions/TransactionFileIsEmptyException.java diff --git a/.gitignore b/.gitignore index 5f279f9082..bf5b078f8c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,5 @@ bin/ data data/save.txt -text-ui-test/EXPECTED.TXT +text-ui-test/ACTUAL.TXT text-ui-test/EXPECTED-UNIX.TXT 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/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/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 1b4bcb7ff9..feeeda90ff 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -1,6 +1,8 @@ package seedu.bankwithus.parser; +import seedu.bankwithus.exceptions.CorruptedTransactionFileException; import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace; +import seedu.bankwithus.exceptions.TransactionFileIsEmptyException; import seedu.bankwithus.user.AccountList; import seedu.bankwithus.BankWithUs; import seedu.bankwithus.user.Transaction; @@ -240,20 +242,24 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S * @throws CorruptedSaveFileException * @throws SaveFileIsEmptyException */ - public void parseTransactionFile(Scanner scanner) throws CorruptedSaveFileException, - SaveFileIsEmptyException { - while (scanner.hasNextLine()) { - String transactionDetails = scanner.nextLine(); - if (transactionDetails.isBlank()) { - throw new SaveFileIsEmptyException(); + public void parseTransactionFile(Scanner scanner) throws CorruptedTransactionFileException, + TransactionFileIsEmptyException { + try { + while (scanner.hasNextLine()) { + String transactionDetails = scanner.nextLine(); + if (transactionDetails.isBlank()) { + throw new SaveFileIsEmptyException(); + } + TransactionDecoder decoder = new TransactionDecoder(); + Transaction temp = decoder.decodeTransaction(transactionDetails); + transactionList.addTransaction(temp); } - TransactionDecoder decoder = new TransactionDecoder(); - Transaction temp = decoder.decodeTransaction(transactionDetails); - transactionList.addTransaction(temp); + } catch (Exception e) { + throw new CorruptedTransactionFileException(); } scanner.close(); - if (transactionList.getSize() == 0){ - throw new SaveFileIsEmptyException(); + if (transactionList.getSize() == 0) { + throw new TransactionFileIsEmptyException(); } } } diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 379b363f0d..237764a9f8 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -170,6 +170,9 @@ public void askForBalance() { 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."); diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 51a6ece28d..1042fe4321 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -1,8 +1,8 @@ package seedu.bankwithus.user; -import seedu.bankwithus.exceptions.CorruptedSaveFileException; +import seedu.bankwithus.exceptions.CorruptedTransactionFileException; import seedu.bankwithus.exceptions.NoTransactionsFoundException; -import seedu.bankwithus.exceptions.SaveFileIsEmptyException; +import seedu.bankwithus.exceptions.TransactionFileIsEmptyException; import seedu.bankwithus.parser.Parser; import seedu.bankwithus.ui.Ui; @@ -27,9 +27,9 @@ public TransactionList(Scanner scanner) { Parser parser = new Parser(this); try { parser.parseTransactionFile(scanner); - } catch (CorruptedSaveFileException e) { - ui.showCorruptedSaveFileError(); - } catch (SaveFileIsEmptyException e) { + } catch (CorruptedTransactionFileException e) { + ui.showCorruptedTransactionFileError(); + } catch (TransactionFileIsEmptyException e) { //shows "No transactions found!" as this catch block ui.showNoTransactionsFoundMessage(); } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9e873bff26..5514cfc72a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -123,9 +123,9 @@ Balance: $123678.2 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 03/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 03/04/2023 -Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 03/04/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 04/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 04/04/2023 +Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 04/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From bc8688c52119aa19ec7c117450892ce438892e69 Mon Sep 17 00:00:00 2001 From: vishnu Date: Tue, 4 Apr 2023 15:01:18 +0800 Subject: [PATCH 258/368] Modify IO redir --- text-ui-test/ACTUAL.TXT | 131 ++++++++++++++++++++++++++++++++++++++ text-ui-test/EXPECTED.TXT | 28 ++++---- 2 files changed, 145 insertions(+), 14 deletions(-) create mode 100644 text-ui-test/ACTUAL.TXT diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT new file mode 100644 index 0000000000..2aac2ad85d --- /dev/null +++ b/text-ui-test/ACTUAL.TXT @@ -0,0 +1,131 @@ +Welcome to: + + /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ +| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ +| $$ \ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$| $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$ +| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$ $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/ +| $$__ $$ /$$$$$$$| $$ \ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \ $$| $$ | $$| $$$$$$ +| $$ \ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \ $$$| $$ | $$ /$$| $$ | $$| $$ | $$ \____ $$ +| $$$$$$$/| $$$$$$$| $$ | $$| $$ \ $$| $$/ \ $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/ +|_______/ \_______/|__/ |__/|__/ \__/|__/ \__/|__/ \___/ |__/ |__/ \______/ |_______/ + +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 created! +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! +---------------------------- +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 created! +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 +---------------------------- +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 04/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 04/04/2023 +Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 04/04/2023 +---------------------------- +Not a valid command! +Goodbye! Hope to see you again! :) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9e873bff26..2aac2ad85d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -21,19 +21,19 @@ The input is not a valid number! Please try again. How much would you like to add as Balance? Account created! Name: hihi -Balance: $1000.0 +Balance: $1000.00 ---------------------------- File not found, trying to create file. Not a valid command! Current Account: Name: hihi -Balance: $1000.0 +Balance: $1000.00 ---------------------------- Negative amount entered! The input is not a valid number! Please try again. Current Account: Name: hihi -Balance: $1000.0 +Balance: $1000.00 ---------------------------- New deposit added! You have $1100.21 remaining! @@ -48,14 +48,14 @@ What's your name? How much would you like to add as Balance? Account created! Name: sherlock -Balance: $123778.1 +Balance: $123778.10 ---------------------------- Current Account: Name: hihi Balance: $1100.21 ---------------------------- Name: sherlock -Balance: $123778.1 +Balance: $123778.10 ---------------------------- You do not have sufficient Balance ---------------------------- @@ -64,22 +64,22 @@ Current Account switched Current Account is: ---------------------------- Name: sherlock -Balance: $123778.1 +Balance: $123778.10 ---------------------------- Current Account: Name: sherlock -Balance: $123778.1 +Balance: $123778.10 ---------------------------- Name: hihi Balance: $1100.21 ---------------------------- The input is not a valid number! Please try again. Withdrawal successful! -You have $123678.1 remaining! +You have $123678.10 remaining! ---------------------------- Current Account: Name: sherlock -Balance: $123678.1 +Balance: $123678.10 ---------------------------- Name: hihi Balance: $1100.21 @@ -106,7 +106,7 @@ There are more than two decimal places! Please re-enter the command ---------------------------- New deposit added! -You have $123678.2 remaining! +You have $123678.20 remaining! ---------------------------- Withdrawal limit is currently $100. You have withdrawn $100 this month. @@ -118,14 +118,14 @@ You have withdrawn $100 this month. ---------------------------- Current Account: Name: sherlock -Balance: $123678.2 +Balance: $123678.20 ---------------------------- Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 03/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 03/04/2023 -Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 03/04/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 04/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 04/04/2023 +Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 04/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 9f324a9a98b20cf389fa7126c49c4cba79b49ece Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Tue, 4 Apr 2023 15:35:22 +0800 Subject: [PATCH 259/368] Allow the corrupted entries to be deleted individually --- .../java/seedu/bankwithus/parser/Parser.java | 18 +++++++++++------- .../seedu/bankwithus/user/AccountList.java | 3 +-- .../seedu/bankwithus/user/TransactionList.java | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index feeeda90ff..72c18d0426 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -244,17 +244,21 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S */ public void parseTransactionFile(Scanner scanner) throws CorruptedTransactionFileException, TransactionFileIsEmptyException { - try { + boolean isCorrupted = false; while (scanner.hasNextLine()) { String transactionDetails = scanner.nextLine(); - if (transactionDetails.isBlank()) { - throw new SaveFileIsEmptyException(); + try { + if (transactionDetails.isBlank()) { + throw new SaveFileIsEmptyException(); + } + TransactionDecoder decoder = new TransactionDecoder(); + Transaction temp = decoder.decodeTransaction(transactionDetails); + transactionList.addTransaction(temp); + } catch (Exception e) { + isCorrupted = true; } - TransactionDecoder decoder = new TransactionDecoder(); - Transaction temp = decoder.decodeTransaction(transactionDetails); - transactionList.addTransaction(temp); } - } catch (Exception e) { + if (isCorrupted) { throw new CorruptedTransactionFileException(); } scanner.close(); diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index c916ff4f35..de1303ae15 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -256,9 +256,9 @@ public void showBal() { String balance = getMainAccount().getAccountBalance(); float bal = Float.parseFloat(balance); ui.showBal(balance); - } + //@@author xiaoge26 /** * Deposits a user specified amount to the current account's balance. * @@ -267,7 +267,6 @@ public void showBal() { * @throws NullPointerException * @throws NegativeAmountException */ - //@@author xiaoge26 public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException, NegativeAmountException, MoreThanTwoDecimalPlace { float depositAmount = Float.parseFloat(depositAmountString); diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 1042fe4321..b62663f3f9 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -20,6 +20,14 @@ public TransactionList() { this.size = 0; } + /** + * Creates a new instance of TransactionList. Initialises transactions. + * Should load data into transactions list too. + * + * @param scanner the scanner to read the transaction file + * @throws CorruptedTransactionFileException thrown when the transaction file is corrupted + * @throws TransactionFileIsEmptyException thrown when the transaction file is empty + */ public TransactionList(Scanner scanner) { this.size = 0; transactions = new ArrayList<>(); @@ -35,6 +43,15 @@ public TransactionList(Scanner scanner) { } } + + /** + * 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; From bdd79e0946e74aa2ac3a0d1c1a57b5096fb81639 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Tue, 4 Apr 2023 15:49:51 +0800 Subject: [PATCH 260/368] Fix decimal number bug in withdraw feature --- src/main/java/seedu/bankwithus/user/AccountList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 81628d5336..4744c50b13 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -311,7 +311,7 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException, WithdrawalCancelledException, MoreThanTwoDecimalPlace { float withdrawAmount = Float.parseFloat(withdrawAmountString); - BigDecimal amtToDraw = new BigDecimal(withdrawAmount); + BigDecimal amtToDraw = new BigDecimal(withdrawAmountString); if (withdrawAmount < 0) { throw new NegativeAmountException(); } From 116794189e43d5180acfa777cc9f46740f288507 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Tue, 4 Apr 2023 15:52:23 +0800 Subject: [PATCH 261/368] Fix Checkstyle errors --- .../java/seedu/bankwithus/parser/Parser.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 72c18d0426..537f75966a 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -245,19 +245,19 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S public void parseTransactionFile(Scanner scanner) throws CorruptedTransactionFileException, TransactionFileIsEmptyException { boolean isCorrupted = false; - while (scanner.hasNextLine()) { - String transactionDetails = scanner.nextLine(); - try { - if (transactionDetails.isBlank()) { - throw new SaveFileIsEmptyException(); - } - TransactionDecoder decoder = new TransactionDecoder(); - Transaction temp = decoder.decodeTransaction(transactionDetails); - transactionList.addTransaction(temp); - } catch (Exception e) { - isCorrupted = true; + while (scanner.hasNextLine()) { + String transactionDetails = scanner.nextLine(); + try { + if (transactionDetails.isBlank()) { + throw new SaveFileIsEmptyException(); } + TransactionDecoder decoder = new TransactionDecoder(); + Transaction temp = decoder.decodeTransaction(transactionDetails); + transactionList.addTransaction(temp); + } catch (Exception e) { + isCorrupted = true; } + } if (isCorrupted) { throw new CorruptedTransactionFileException(); } From f1210d28ab92b0f94152c7b3ec39c9e3c709606f Mon Sep 17 00:00:00 2001 From: tyuyang Date: Tue, 4 Apr 2023 15:53:48 +0800 Subject: [PATCH 262/368] Updated sequence diagram to (hopefully) fit with kerct's comments --- docs/diagrams/example_sequence_diagram.puml | 130 ++++++++++---------- 1 file changed, 63 insertions(+), 67 deletions(-) diff --git a/docs/diagrams/example_sequence_diagram.puml b/docs/diagrams/example_sequence_diagram.puml index 5aec8e02d6..14072b0009 100644 --- a/docs/diagrams/example_sequence_diagram.puml +++ b/docs/diagrams/example_sequence_diagram.puml @@ -1,74 +1,70 @@ @startuml deposit100SeqDiagram actor Shawn -participant Ui -participant BWU -participant Parser -participant AccountList -participant Account -participant TransactionList -participant Transaction -activate Ui -activate BWU -activate Parser -activate AccountList -activate Account -activate TransactionList +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 +":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 -TransactionList -> Transaction:new Transaction() -activate Transaction -Transaction --> TransactionList -deactivate Transaction -TransactionList -> TransactionList:add(transaction) -activate TransactionList -TransactionList --> TransactionList -deactivate TransactionList -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:getMainAccount() -Account -> Account:getAccountBalance() -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 +":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 +":Parser" --> ":BWU" +deactivate ":Parser" end @enduml \ No newline at end of file From 881918b5c7e9dbcfaceecab5c69ac0c30613ad48 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Wed, 5 Apr 2023 14:02:11 +0800 Subject: [PATCH 263/368] add NoValueInput exception update text-ui-test --- .gitignore | 2 +- .../exceptions/NoValueInputException.java | 5 + .../java/seedu/bankwithus/parser/Parser.java | 3 + src/main/java/seedu/bankwithus/ui/Ui.java | 6 + .../seedu/bankwithus/user/AccountList.java | 6 +- text-ui-test/ACTUAL.TXT | 131 ------------------ text-ui-test/EXPECTED.TXT | 8 +- text-ui-test/input.txt | 1 + 8 files changed, 26 insertions(+), 136 deletions(-) create mode 100644 src/main/java/seedu/bankwithus/exceptions/NoValueInputException.java delete mode 100644 text-ui-test/ACTUAL.TXT diff --git a/.gitignore b/.gitignore index bf5b078f8c..5f279f9082 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,5 @@ bin/ data data/save.txt -text-ui-test/ACTUAL.TXT +text-ui-test/EXPECTED.TXT text-ui-test/EXPECTED-UNIX.TXT 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/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 537f75966a..0b3788872b 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -2,6 +2,7 @@ import seedu.bankwithus.exceptions.CorruptedTransactionFileException; import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace; +import seedu.bankwithus.exceptions.NoValueInputException; import seedu.bankwithus.exceptions.TransactionFileIsEmptyException; import seedu.bankwithus.user.AccountList; import seedu.bankwithus.BankWithUs; @@ -123,6 +124,8 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.printLine(); } catch (MoreThanTwoDecimalPlace e) { ui.showDecimalPlacesError(); + } catch (NoValueInputException e) { + ui.showNoValueInput(); } break; case "add-account": diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index da32978fe8..bc86d32565 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -295,4 +295,10 @@ 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(); + } } diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 4744c50b13..c82353764a 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -10,6 +10,7 @@ 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; @@ -309,7 +310,10 @@ public LocalDate handleDate(LocalDate date) { //@@author manushridiv public void withdrawMoney(String withdrawAmountString) throws NumberFormatException, NegativeAmountException, InsufficientBalanceException, ExceedsWithdrawalLimitException, - WithdrawalCancelledException, MoreThanTwoDecimalPlace { + WithdrawalCancelledException, MoreThanTwoDecimalPlace, NoValueInputException { + if (withdrawAmountString.trim().isBlank()){ + throw new NoValueInputException(); + } float withdrawAmount = Float.parseFloat(withdrawAmountString); BigDecimal amtToDraw = new BigDecimal(withdrawAmountString); if (withdrawAmount < 0) { diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT deleted file mode 100644 index 2aac2ad85d..0000000000 --- a/text-ui-test/ACTUAL.TXT +++ /dev/null @@ -1,131 +0,0 @@ -Welcome to: - - /$$$$$$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ /$$ -| $$__ $$ | $$ | $$ /$ | $$|__/ | $$ | $$ | $$ | $$ -| $$ \ $$ /$$$$$$ /$$$$$$$ | $$ /$$| $$ /$$$| $$ /$$ /$$$$$$ | $$$$$$$ | $$ | $$ /$$$$$$$ -| $$$$$$$ |____ $$| $$__ $$| $$ /$$/| $$/$$ $$ $$| $$|_ $$_/ | $$__ $$| $$ | $$ /$$_____/ -| $$__ $$ /$$$$$$$| $$ \ $$| $$$$$$/ | $$$$_ $$$$| $$ | $$ | $$ \ $$| $$ | $$| $$$$$$ -| $$ \ $$ /$$__ $$| $$ | $$| $$_ $$ | $$$/ \ $$$| $$ | $$ /$$| $$ | $$| $$ | $$ \____ $$ -| $$$$$$$/| $$$$$$$| $$ | $$| $$ \ $$| $$/ \ $$| $$ | $$$$/| $$ | $$| $$$$$$/ /$$$$$$$/ -|_______/ \_______/|__/ |__/|__/ \__/|__/ \__/|__/ \___/ |__/ |__/ \______/ |_______/ - -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 created! -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! ----------------------------- -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 created! -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 ----------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 04/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 04/04/2023 -Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 04/04/2023 ----------------------------- -Not a valid command! -Goodbye! Hope to see you again! :) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 2aac2ad85d..29526d45c5 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -38,6 +38,8 @@ 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 @@ -123,9 +125,9 @@ Balance: $123678.20 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 04/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 04/04/2023 -Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 04/04/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 05/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 05/04/2023 +Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 05/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 2ae6391018..f8809ecf5a 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -9,6 +9,7 @@ deposit -1 deposit java view-account deposit 100.21 +withdraw view-account delete sherlock add-account From 2da28b3d631829c3a277e954dffbf3b81aa45984 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 6 Apr 2023 13:14:21 +0800 Subject: [PATCH 264/368] Fix delete account bug --- .gitignore | 2 +- src/main/java/seedu/bankwithus/user/AccountList.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 5f279f9082..bf5b078f8c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,5 @@ bin/ data data/save.txt -text-ui-test/EXPECTED.TXT +text-ui-test/ACTUAL.TXT text-ui-test/EXPECTED-UNIX.TXT diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index c82353764a..caf9c20dad 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -346,9 +346,7 @@ public Boolean foundAccountToDelete(String name, Account acc) { if (acc.getAccountName().equals(name)) { accounts.remove(acc); ui.showAccountDeleted(name); - if (accounts.size() < 1) { - createNewAccount(); - } + doesNameExist.remove(name); return true; } return false; From fcfefa81348eaa3ce788470b90fb0fdfdd0facb0 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 6 Apr 2023 13:20:08 +0800 Subject: [PATCH 265/368] Update EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 29526d45c5..985fd1d63a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -125,9 +125,9 @@ Balance: $123678.20 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 05/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 05/04/2023 -Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 05/04/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 06/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 06/04/2023 +Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 06/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From df86a8fbd0f26b47a7ae9a669516a16b38e276ae Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Thu, 6 Apr 2023 16:18:50 +0800 Subject: [PATCH 266/368] Add create account message when all accounts are deleted --- src/main/java/seedu/bankwithus/ui/Ui.java | 6 ++++++ .../java/seedu/bankwithus/user/AccountList.java | 17 +++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index bc86d32565..820af2a844 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -301,4 +301,10 @@ 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"); + } } diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index caf9c20dad..8e9f152da5 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -258,13 +258,14 @@ public void showBal() { } //@@author xiaoge26 + /** - * Deposits a user specified amount to the current account's balance. - * - * @param depositAmountString - amount to be deposited - * @throws NumberFormatException - * @throws NullPointerException - * @throws NegativeAmountException + * 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 { @@ -347,6 +348,10 @@ public Boolean foundAccountToDelete(String name, Account acc) { accounts.remove(acc); ui.showAccountDeleted(name); doesNameExist.remove(name); + if (accounts.size() < 1) { + ui.showAddAccountPrompt(); + createNewAccount(); + } return true; } return false; From ca962d5b0390b730519c41edf0e325567cad27b5 Mon Sep 17 00:00:00 2001 From: vishnu Date: Fri, 7 Apr 2023 12:58:49 +0800 Subject: [PATCH 267/368] Wrote PPP for vishnuvk47 --- docs/team/vishnu.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 docs/team/vishnu.md diff --git a/docs/team/vishnu.md b/docs/team/vishnu.md new file mode 100644 index 0000000000..0b9d6351bf --- /dev/null +++ b/docs/team/vishnu.md @@ -0,0 +1,29 @@ +# 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 + +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). + +### 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, who helped me improve the guide's consistency and format to align with recommended guidelines. + +### DG contributions + +Templated the layout and basic functionalities of the program for the DG. + +### 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 +* Handled a significant number of issues that were reported in the PE-D. +* refactored the floats into Big Decimal to resolve overflow and precision issues. From e6dee0e9a7041b703158727692c6e2a73888e22d Mon Sep 17 00:00:00 2001 From: vishnu Date: Fri, 7 Apr 2023 12:59:39 +0800 Subject: [PATCH 268/368] Rename vishnu.md to vishnuvk47.md to match github profile --- docs/team/{vishnu.md => vishnuvk47.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/team/{vishnu.md => vishnuvk47.md} (100%) diff --git a/docs/team/vishnu.md b/docs/team/vishnuvk47.md similarity index 100% rename from docs/team/vishnu.md rename to docs/team/vishnuvk47.md From c83c052bcad82985a1db1775a1b41d1db6e48f0e Mon Sep 17 00:00:00 2001 From: vishnu Date: Fri, 7 Apr 2023 13:02:19 +0800 Subject: [PATCH 269/368] Changed date in expected to tdy date to pass io redir --- text-ui-test/EXPECTED.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 985fd1d63a..aa00d12670 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -125,9 +125,9 @@ Balance: $123678.20 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 06/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 06/04/2023 -Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 06/04/2023 +Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 07/04/2023 +Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 07/04/2023 +Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 07/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 9da38cb9ed080245a3d47842dd5d12dae80ec4ca Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 14:41:26 +0800 Subject: [PATCH 270/368] Add delete transaction feature --- .../java/seedu/bankwithus/parser/Parser.java | 12 ++++++ src/main/java/seedu/bankwithus/ui/Ui.java | 10 +++++ .../seedu/bankwithus/user/Transaction.java | 3 -- .../bankwithus/user/TransactionList.java | 37 ++++++++++++++++++- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 0b3788872b..20e25ff203 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -182,6 +182,18 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.noTransactionsFoundError(); } break; + case "delete-transaction": + try { + transactionList.deleteTransaction(args); + ui.printLine(); + } catch (NoTransactionsFoundException e) { + ui.noTransactionsFoundError(); + } catch (NumberFormatException e) { + ui.showNumberFormatError(); + } catch (IndexOutOfBoundsException e) { + ui.showIndexOutOfBoundsError(); + } + break; default: throw new CommandNotFoundException(); } diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 820af2a844..b8faf6c91d 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -303,8 +303,18 @@ public void showNoValueInput() { } //@@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 showDeleteTransactionMessage() { + System.out.println("Transaction deleted successfully"); + printLine(); } } diff --git a/src/main/java/seedu/bankwithus/user/Transaction.java b/src/main/java/seedu/bankwithus/user/Transaction.java index c813e32346..baca5b3b30 100644 --- a/src/main/java/seedu/bankwithus/user/Transaction.java +++ b/src/main/java/seedu/bankwithus/user/Transaction.java @@ -34,9 +34,6 @@ public String getAmount() { return amount; } - public LocalDate getDate() { - return date; - } public String getDateStr() { return date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")); } diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index b62663f3f9..a9b450856b 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -59,6 +59,11 @@ public void createNewTransaction(String accountName, String type, String amount, size++; } + /** + * Adds a transaction to the transaction list. + * + * @param transaction the transaction to be added + */ public void addTransaction(Transaction transaction) { transactions.add(transaction); size++; @@ -75,12 +80,42 @@ 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(transactions.get(i).toString()); + System.out.println(i + 1 + ". " + transactions.get(i).toString()); + } + } + + /** + * 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 { + if (size == 0) { + throw new NoTransactionsFoundException(); + } else if (Integer.parseInt(args) > size || Integer.parseInt(args) < 1) { + throw new IndexOutOfBoundsException(); + } else { + try { + int index = Integer.parseInt(args) - 1; + transactions.remove(index); + size--; + } catch (NumberFormatException e) { + throw new NumberFormatException(); + } catch (IndexOutOfBoundsException e) { + throw new IndexOutOfBoundsException(); + } catch (Exception e) { + e.printStackTrace(); + } } } } From 8978ad87ff807660a82dc2689be49a4c948ff431 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 14:42:26 +0800 Subject: [PATCH 271/368] Update delete transaction feature in UserGuide --- docs/UserGuide.md | 27 +++++++++++++++++-- .../storage/TransactionEncoder.java | 1 - src/main/java/seedu/bankwithus/ui/Ui.java | 5 ++-- .../bankwithus/user/TransactionList.java | 2 ++ 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index a12b8d4ed6..e1cd4e19a8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -68,6 +68,7 @@ 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 exit: quits program and saves ``` @@ -205,8 +206,8 @@ Format: `view-transactions-all` Example: ``` >>view-transactions-all -Account Name: jenson Transaction Type: deposit Amount: 100 Date: 26/03/2023 -Account Name: jenson Transaction Type: withdraw Amount: 10 Date: 26/03/2023 +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` @@ -273,6 +274,27 @@ 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 ` + +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 +``` + ### Exiting the program : `exit` Exits the program. @@ -319,4 +341,5 @@ Please keep in mind that this will result in irreversible data loss. | **Show the save Goal** | `show-saveGoal` | | **Add a withdraw Limit** | `set-wl` | | **View all the transactions** | `view-transactions-all` | +| **Delete a Transaction** | `delete-transaction` | | **Help** | `help` | \ No newline at end of file diff --git a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java index 55f05e6f7e..032e268c89 100644 --- a/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java +++ b/src/main/java/seedu/bankwithus/storage/TransactionEncoder.java @@ -23,7 +23,6 @@ public String encodeTransaction(Transaction transaction) { return encodedTransactionBuilder.toString(); } - //@@author xiaoge26 public String encodeTransactionList(TransactionList transactionList) { logger.log(Level.FINE, "Encoding TransactionList"); if (transactionList.getSize() == 0) { diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index b8faf6c91d..de6e3f7466 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -131,6 +131,8 @@ public void showHelp() { 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("exit: quits program and saves"); printLine(); } @@ -313,8 +315,7 @@ public void showIndexOutOfBoundsError() { System.out.println("Index out of bounds, please try again"); printLine(); } - public void showDeleteTransactionMessage() { + public void showTransactionDeletedMessage() { System.out.println("Transaction deleted successfully"); - printLine(); } } diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index a9b450856b..21cfc4d1ce 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -100,6 +100,7 @@ public void printAllTransactions() throws NoTransactionsFoundException { */ public void deleteTransaction(String args) throws NoTransactionsFoundException, NumberFormatException, IndexOutOfBoundsException { + Ui ui = new Ui(); if (size == 0) { throw new NoTransactionsFoundException(); } else if (Integer.parseInt(args) > size || Integer.parseInt(args) < 1) { @@ -109,6 +110,7 @@ public void deleteTransaction(String args) throws NoTransactionsFoundException, int index = Integer.parseInt(args) - 1; transactions.remove(index); size--; + ui.showTransactionDeletedMessage(); } catch (NumberFormatException e) { throw new NumberFormatException(); } catch (IndexOutOfBoundsException e) { From 4ba0bcc5f0d94de8d68c1066aedd4738c83d84a6 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 14:49:35 +0800 Subject: [PATCH 272/368] Update EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index aa00d12670..3824925ae2 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -125,9 +125,9 @@ Balance: $123678.20 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 07/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 07/04/2023 -Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 07/04/2023 +1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 07/04/2023 +2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 07/04/2023 +3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 07/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 95c29752650b5a7bb9d8d456532c8f99a6b65884 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 15:35:43 +0800 Subject: [PATCH 273/368] Update DeveloperGuide.md and fix typos --- docs/DeveloperGuide.md | 101 ++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 37d4b424f9..6e8e077bcc 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -15,14 +15,14 @@ * [Transaction Component](#transaction-Component) * [TransactionList Component](#transactionlist-component) * [Implementation](#implementation) - * [Account related Feature](#Account-feature) - * [saveGoal related Feature](#SaveGoal-feature) - * [transaction Related Feature](#transaction-feature) + * [Account Related Feature](#Account-feature) + * [SaveGoal Related Feature](#SaveGoal-feature) + * [Transaction Related Feature](#transaction-feature) * [Appendix: Requirements](#appendix-requirements) - * [Product scope](#product-scope) - * [Target user profile](#target-user-profile) - * [Value proposition](#value-proposition) + * [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) @@ -32,21 +32,39 @@ ## 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. -{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source 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. **Configuring the JDK** to to ensure Intellij is configured to use JDK 11 +2. **Import the project as a Gradle project**
+**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 & implementation -{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} ### Design ### 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. **Interactions** @@ -70,8 +88,8 @@ Class: `Account.java` The `Account` component: -* contains `name`, `balance`, `SaveGoal`, `withdrawChecker` attribute -* stores and manages all the account details that pertains to one account. +* contains `name`, `balance`, `saveGoal`, `withdrawChecker` attribute +* stores and manages all the account details that pertains to one account ### AccountList-Component @@ -79,22 +97,22 @@ Class: `AccountList.java` The `AccountList` component: -* Is an ArrayList 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 teh AccountList array +* contains an `ArrayList` named `accountList` that contains the various different accounts that the user has. +* `accountList` is used to navigate between accounts for the switch-to feature +* when a new account is created it is appended to the `accountList` array ### BankWithUs-Component -Class: `bankWithUS.java` +Class: `BankWithUs.java` The `BankWithUs` component: * The Main Class -* the whole program executes through the bankWithUs class +* the whole program executes through the `BankWithUs` class ### SaveGoal-Component Class: `SaveGoal.java` -The `saveGoal` component: +The `SaveGoal` component: * Allows users to add a savings goal * allows users to add a deadline to the savings goal @@ -104,10 +122,13 @@ Class: `Storage.java` The `Storage` component: -* Handles storing data in the save files and also loading data, if any, when program opens. +* 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` @@ -120,25 +141,28 @@ The `Transaction` component: Class: `TransactionList.java` The `TransactionList` component: -* Contains an ArrayList that contains the various different transactions that the user has. -* Has methods to add and view transactions +* Contains an ArrayList +that contains the various different transactions that the user has +* Contains methods to add, delete and view transactions --- ## Implementation * [Account related Feature](#account-feature) -* [saveGoal related Feature](#savegoal-feature) -* [transaction Related Feature](#transaction-feature) +* [SaveGoal related Feature](#savegoal-feature) +* [Transaction Related Feature](#transaction-feature) --- ## 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 ## Appendix: Requirements @@ -169,25 +193,20 @@ minimalism of a CLI interface, as it provides only the essential information and ### 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 spendings 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 finacnials | -| v2.0 | user | list all the command that can be used | so that i can have a basic overview of the apps functionalities | - - -### Non-Functional Requirements +| 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 | -{Give non-functional requirements} -### Glossary -* *glossary item* - Definition ## Instructions for manual testing From 40db42bcf489e78453c3064fe81968183170e26b Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 15:44:17 +0800 Subject: [PATCH 274/368] Combine Design & Inplementation sections --- docs/DeveloperGuide.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 6e8e077bcc..459e48e6a5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -57,9 +57,6 @@ You may want to refer to our User Guide for the list of commands
## Design & implementation - -### Design - ### Architecture
The Architecture Diagram given above explains the high-level design of the App. @@ -145,12 +142,6 @@ The `TransactionList` component: that contains the various different transactions that the user has * Contains methods to add, delete and view transactions ---- - -## Implementation -* [Account related Feature](#account-feature) -* [SaveGoal related Feature](#savegoal-feature) -* [Transaction Related Feature](#transaction-feature) --- From 27b4a6ff848586105ccd86b7a7025f898cae3636 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 16:30:21 +0800 Subject: [PATCH 275/368] Add instructions for manual testing --- docs/DeveloperGuide.md | 77 ++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 459e48e6a5..700f45ea94 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,8 +1,8 @@ # Developer Guide * [Acknowledgements](#acknowledgements) -* [Setting up, getting started](#setting-up-getting-started) -* [Design](#design) +* [Setting Up, Getting Started](#setting-up-getting-started) +* [Design & Implementation](#design) * [Architecture](#architecture) * [UI Component](#UI-Component) * [Parser Component](#parser-component) @@ -14,10 +14,6 @@ * [Withdrawal Limit Component](#withdraw limit checker-Component) * [Transaction Component](#transaction-Component) * [TransactionList Component](#transactionlist-component) -* [Implementation](#implementation) - * [Account Related Feature](#Account-feature) - * [SaveGoal Related Feature](#SaveGoal-feature) - * [Transaction Related Feature](#transaction-feature) * [Appendix: Requirements](#appendix-requirements) * [Product Scope](#product-scope) @@ -26,6 +22,7 @@ * [User Stories](#user-stories) * [Non-Functional Requirements](#non-functional-requirements) * [Glossary](#glossary) + * [Instructions for Manual Testing](#instructions-for-manual-testing) --- @@ -34,9 +31,9 @@ ## 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/). +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 +the "Setting Up, Getting Started" and "Non-Functional Requirements" sections in this document as well. @@ -45,11 +42,14 @@ First, **fork** this repo, and **clone** the fork into your computer. If you plan to use Intellij IDEA (highly recommended): -1. **Configuring the JDK** to to ensure Intellij is configured to use JDK 11 -2. **Import the project as a Gradle project**
-**Note**: Importing a Gradle project is slightly different from importing +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**:
+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 @@ -73,20 +73,20 @@ The sequence diagram below shows how components interact with each other when th ### UI-Component Class: `Ui.java` -* contains all code that interfaces directly with the CLI +* 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 +* 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 +* Contains `name`, `balance`, `saveGoal`, `withdrawChecker` attribute +* Stores and manages all the account details that pertains to one account ### AccountList-Component @@ -94,9 +94,10 @@ Class: `AccountList.java` The `AccountList` component: -* contains an `ArrayList` named `accountList` that contains the various different accounts that the user has. -* `accountList` is used to navigate between accounts for the switch-to feature -* when a new account is created it is appended to the `accountList` array +* 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` @@ -104,7 +105,7 @@ Class: `BankWithUs.java` The `BankWithUs` component: * The Main Class -* the whole program executes through the `BankWithUs` class +* The whole program executes through the `BankWithUs` class ### SaveGoal-Component Class: `SaveGoal.java` @@ -112,7 +113,7 @@ Class: `SaveGoal.java` The `SaveGoal` component: * Allows users to add a savings goal -* allows users to add a deadline to the savings goal +* Allows users to add a deadline to the savings goal ### Storage-Component Class: `Storage.java` @@ -145,15 +146,6 @@ that contains the various different transactions that the user has --- -## 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 - -* *Mainstream OS*: Windows, Linux, Unix, OS-X ## Appendix: Requirements @@ -197,8 +189,29 @@ minimalism of a CLI interface, as it provides only the essential information and | v2.1 | user | delete transaction records | so that i can get rid of trivial transaction records | +## 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. -## Instructions for manual testing +## Glossary + +* *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
-{Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing} +## Instructions for manual testing +### Launch +1. Ensure you have Java 11 installed in your Computer +2. Download the latest release `tp.jar` from here +3. Copy the file to the folder you want to use as the home folder for BankWithUs +4. Open a command terminal, cd into the folder you put the `tp.jar` file in, and use `java -jar tp.jar` +command to run the application. A CLI should appear in a few seconds + +### Sample Test Cases +Please refer to the Features section in our [UserGuide](UserGuide.md) for more details on the test cases +that you can try out. \ No newline at end of file From 7294aa114c5fa14fb028ce6ea6212c3cf9014aea Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 16:32:16 +0800 Subject: [PATCH 276/368] Update EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index aa00d12670..3824925ae2 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -125,9 +125,9 @@ Balance: $123678.20 Name: hihi Balance: $1100.21 ---------------------------- -Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 07/04/2023 -Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 07/04/2023 -Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 07/04/2023 +1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 07/04/2023 +2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 07/04/2023 +3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 07/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 48904d31b2a03127f8da88cac5d0ea03ea87c0fc Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 17:05:50 +0800 Subject: [PATCH 277/368] Add PPP for myself --- docs/README.md | 2 +- docs/team/xiaoge26.md | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 docs/team/xiaoge26.md diff --git a/docs/README.md b/docs/README.md index bbcc99c1e7..cc4c86a239 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -# Duke +# BankWithUs {Give product intro here} diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md new file mode 100644 index 0000000000..1964eb7ea7 --- /dev/null +++ b/docs/team/xiaoge26.md @@ -0,0 +1,38 @@ +# 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 + +[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 have developed the add deposit 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 all the features related to the `Transaction` and `TransactionList` classes, including adding, +deleting, listing, parsing, saving, and loading the transactions. + + + +### UG contributions + +Documented the `Transaction` and `TransactionList` feature in the User Guide. + +### DG contributions + +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.) + + +### 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 From a67dd448615dd9f6ec2522a0f282461789ccb875 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 18:58:37 +0800 Subject: [PATCH 278/368] Fix errors in UserGuide.md --- docs/DeveloperGuide.md | 14 +++--- docs/UserGuide.md | 111 ++++++++++++++++++++++------------------- docs/team/xiaoge26.md | 2 +- 3 files changed, 67 insertions(+), 60 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 700f45ea94..c507ed2c4d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,7 +2,7 @@ * [Acknowledgements](#acknowledgements) * [Setting Up, Getting Started](#setting-up-getting-started) -* [Design & Implementation](#design) +* [Design & Implementation](#design-and-implementation) * [Architecture](#architecture) * [UI Component](#UI-Component) * [Parser Component](#parser-component) @@ -11,11 +11,11 @@ * [AccountList Component](#accountlist-component) * [SaveGoal Component](#saveGoal-component) * [Storage Component](#storage-component) - * [Withdrawal Limit Component](#withdraw limit checker-Component) - * [Transaction Component](#transaction-Component) + * [Withdrawal Limit Component](#withdraw-limit-checker-Component) + * [Transaction Component](#transaction-component) * [TransactionList Component](#transactionlist-component) -* [Appendix: Requirements](#appendix-requirements) +* [Appendix](#appendix) * [Product Scope](#product-scope) * [Target User Profile](#target-user-profile) * [Value Proposition](#value-proposition) @@ -55,7 +55,7 @@ You may want to refer to our User Guide for the list of commands
* Run the tests to ensure they all pass --- -## Design & implementation +## Design and Implementation ### Architecture
@@ -147,7 +147,7 @@ that contains the various different transactions that the user has --- -## Appendix: Requirements +## Appendix ### Product scope @@ -166,7 +166,7 @@ freelancers, and small business owners who are looking for a fast and straightfo ### Value proposition -Fast typers may benefit more from the CLI +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), diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e1cd4e19a8..e5182e5942 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -6,7 +6,7 @@ 1. Ensure you have Java `11` or above installed in your Computer. -2. Download the latest `BankWithUs.jar` from [here](https://github.com/AY2223S2-CS2113-T13-3/tp/releases). +2. Download the latest `tp.jar` 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 your BankWithUs app. @@ -15,15 +15,15 @@ 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: - * `view-transactions-all` : Lists all recorded transactions. + * `view-transactions-all` : Lists all recorded transactions - * `withdraw 300` : Withdraws $300 from the current balance. (Subsitute 300 for other numbers) + * `withdraw 300` : Withdraws $300 from the current balance (Subsitute 300 for other numbers) - * `delete` : Deletes the current account which the user has initially created. + * `delete ACCOUNT_NAME` : Deletes the account with the given account name * `deposit 100` : Deposits $100 into the users account. (Subsitute 100 for other numbers) - * `exit` : Exits the application. + * `exit` : Exits the application 1. Refer to the [Features](#features) below for details of each command. @@ -43,6 +43,8 @@ * 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.
@@ -86,17 +88,18 @@ your input: `BALANCE` Note: Balance has to be a valid number.
-Examples: +Example: ``` -add-account ->>What is your name? -Steve ->>How much would you like to add as Balance? -1000 +>>add-account +What is your name? +>>Steve +How much would you like to add as Balance? +>>1000 Account created! Name: Steve Balance: $1000 +---------------------------- ``` ### Switch current account: `switch-to` @@ -111,34 +114,34 @@ Format: `switch-to NAME` -Examples: +Example: ``` -switch-to jenson +>>switch-to jenson Current Account switched ---------------------------- Current Account is: ---------------------------- Name: jenson Balance: $90 +---------------------------- ``` ### Deleting an account : `delete` -Format: `delete` +Format: `delete ACCOUNT_NAME` -* Deletes the current account. -* If you want to delete a different account, switch to that account and run delete. +* 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: ``` -Current Account is: +>>delete jameson +Account: jameson deleted ---------------------------- -Name: jameson -Balance: $1000 ----------------------------- ->>delete ``` Deletes the jameson account. @@ -150,13 +153,14 @@ Format: `view-account` Example: ``` -view-account +>>view-account Current Account: Name: james Balance: $1000 ---------------------------- Name: john Balance: $300 +---------------------------- ``` ### Depositing amount : `deposit` @@ -167,15 +171,15 @@ Format: `deposit AMOUNT` Example: ``` -deposit 100 +>>deposit 100 New deposit added! -You have $190 remaining! +You have $190.00 remaining! ``` -* Cannot deposit negative numbers. -* Cannot deposit arguments that are not numbers. +* Cannot deposit negative numbers +* Cannot deposit arguments that are not numbers -Attempting to do so will show error messages. +Attempting to do the above cause the program to show error messages. ### Withdraw : `withdraw` @@ -186,7 +190,10 @@ Format: `withdraw AMOUNT` Example: ``` -withdraw 500 +>>withdraw 50 +Withdrawal successful! +You have $140.00 remaining! +---------------------------- ``` * Cannot withdraw more than balance. @@ -195,7 +202,6 @@ withdraw 500 Attempting to do so will show error messages. -See [saving goals](#add-a-savings-goal-to-the-current-account-save) and [withdrawal limit]() for more information. ### List all transactions: `view-transactions-all` @@ -210,24 +216,24 @@ Example: 2. Account Name: jenson Transaction Type: withdraw Amount: 10 Date: 26/03/2023 ``` -### Add a savings Goal to the current account: `set-save-goal` +### Add a savings goal to the current account: `set-save-goal` Adds a savings goal to the *current account*.
-Will raise an alert when attempting to withdraw more than the savings goal, if attempt is before deadline +Will raise an alert when user attempting to `withdraw` more than the savings goal, if attempt is before deadline -Format: `set-save-goal AMOUNT` >> will then prompt the user for the 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. +* Any error will only be displayed after the deadline is received and processed Examples: ``` -save 300 ->>What would be the end date for the duration of your Saving goal? -11-11-2011 ->>Try saving a minimum of $300 until 11-11-2011 ->>Save Goal has been created, Have fun staying frugal! +>>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! ``` ### Set a withdrawal limit: `set-wl` @@ -237,7 +243,7 @@ Will prevent the user from making the withdrawal if it will result in them excee 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. +* `AMOUNT` must be a valid number. If `AMOUNT` is not valid, an error message will be shown. ``` set-wl 100 @@ -248,6 +254,7 @@ 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` @@ -280,7 +287,7 @@ 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 ` +Format: `delete-transaction INDEX` Example: ``` @@ -331,15 +338,15 @@ Please keep in mind that this will result in irreversible data loss. ## Command summary -| Action | Format, Examples | -|-------------------------------|-------------------------| -| **Add an Account** | `add-account` | -| **switch to a new account** | `switch-to ACC_NAME` | -| **Delete an account** | `delete` | -| **withdraw some amount** | `withdraw AMOUNT` | -| **Add a savings goal** | `set-save-goal` | -| **Show the save Goal** | `show-saveGoal` | -| **Add a withdraw Limit** | `set-wl` | -| **View all the transactions** | `view-transactions-all` | -| **Delete a Transaction** | `delete-transaction` | -| **Help** | `help` | \ No newline at end of file +| Action | Format, Examples | +|-------------------------------|----------------------------| +| **Add an Account** | `add-account` | +| **switch to a new account** | `switch-to ACC_NAME` | +| **Delete an account** | `delete ACC-NAME` | +| **withdraw some amount** | `withdraw AMOUNT` | +| **Add a savings goal** | `set-save-goal AMOUNT` | +| **Show the save Goal** | `show-save-goal` | +| **Add a withdraw Limit** | `set-wl AMOUNT` | +| **View all the transactions** | `view-transactions-all` | +| **Delete a Transaction** | `delete-transaction INDEX` | +| **Help** | `help` | \ No newline at end of file diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index 1964eb7ea7..272429ba87 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -17,7 +17,6 @@ I have also developed all the features related to the `Transaction` and `Transac deleting, listing, parsing, saving, and loading the transactions. - ### UG contributions Documented the `Transaction` and `TransactionList` feature in the User Guide. @@ -36,3 +35,4 @@ Further modified the DG template and fixed the typos and standardized the format * 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 From 2477793e5f31ab15b1238ff8add20f72aa59c190 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 19:07:15 +0800 Subject: [PATCH 279/368] Updated command summary --- docs/UserGuide.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e5182e5942..374ecd2244 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -15,15 +15,15 @@ 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: - * `view-transactions-all` : Lists all recorded transactions + * `view-transactions-all` : Lists all recorded transactions. - * `withdraw 300` : Withdraws $300 from the current balance (Subsitute 300 for other numbers) + * `withdraw 300` : Withdraws $300 from the current balance. (Subsitute 300 for other numbers) - * `delete ACCOUNT_NAME` : Deletes the account with the given account name + * `delete ACCOUNT_NAME` : Deletes the account with the given account name. * `deposit 100` : Deposits $100 into the users account. (Subsitute 100 for other numbers) - * `exit` : Exits the application + * `exit` : Exits the application. 1. Refer to the [Features](#features) below for details of each command. @@ -341,12 +341,16 @@ Please keep in mind that this will result in irreversible data loss. | Action | Format, Examples | |-------------------------------|----------------------------| | **Add an Account** | `add-account` | -| **switch to a new account** | `switch-to ACC_NAME` | +| **View all Accounts Details** | `view-account` | +| **Switch to a new account** | `switch-to ACC_NAME` | | **Delete an account** | `delete ACC-NAME` | -| **withdraw some amount** | `withdraw AMOUNT` | +| **Withdraw some amount** | `withdraw AMOUNT` | +| **Deposit some amount** | `deposit AMOUNT` | | **Add a savings goal** | `set-save-goal AMOUNT` | | **Show the save 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` | -| **Help** | `help` | \ No newline at end of file +| **View help menu** | `help` | +| **Exit** | `exit` | \ No newline at end of file From 6ef4f3a938ce0c88835380301188747e4c0ab6cf Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Fri, 7 Apr 2023 20:43:48 +0800 Subject: [PATCH 280/368] Change the names of .jar release in both guides --- docs/DeveloperGuide.md | 4 ++-- docs/UserGuide.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index c507ed2c4d..82d46f5aca 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -207,9 +207,9 @@ Windows: Command Prompt
## Instructions for manual testing ### Launch 1. Ensure you have Java 11 installed in your Computer -2. Download the latest release `tp.jar` from here +2. Download the latest release `BankWithUs.jar` from here 3. Copy the file to the folder you want to use as the home folder for BankWithUs -4. Open a command terminal, cd into the folder you put the `tp.jar` file in, and use `java -jar tp.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 diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 374ecd2244..c9522eac06 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -6,7 +6,7 @@ 1. Ensure you have Java `11` or above installed in your Computer. -2. Download the latest `tp.jar` from [here](https://github.com/AY2223S2-CS2113-T13-3/tp/releases). +2. Download the latest `BankWithUs.jar` 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 your BankWithUs app. From 1b47352ef5694a7396d86330381692cdbbe3b67f Mon Sep 17 00:00:00 2001 From: vishnu Date: Fri, 7 Apr 2023 22:27:39 +0800 Subject: [PATCH 281/368] Add new method to avoid - signs in any transaction commands --- src/main/java/seedu/bankwithus/BankWithUs.java | 3 +++ src/main/java/seedu/bankwithus/parser/Parser.java | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/BankWithUs.java b/src/main/java/seedu/bankwithus/BankWithUs.java index 5e9087e566..7c100a6e4f 100644 --- a/src/main/java/seedu/bankwithus/BankWithUs.java +++ b/src/main/java/seedu/bankwithus/BankWithUs.java @@ -3,6 +3,7 @@ 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; @@ -116,6 +117,8 @@ public void run() throws IOException { parser.parseUserInput(line); } catch (CommandNotFoundException e) { ui.showCommandNotFoundError(); + } catch (NegativeAmountException e) { + ui.showNegativeAmountError(); } } } diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 20e25ff203..8a5a8b067b 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -60,7 +60,7 @@ public Parser(TransactionList transactionList) { * * @throws IOException */ - public void parseUserInput(String input) throws CommandNotFoundException, 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]; @@ -75,6 +75,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce break; case "deposit": try { + checkNegative(args); accountList.depositMoney(args); transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(), "deposit", args, LocalDate.now()); @@ -102,6 +103,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce break; case "withdraw": try { + checkNegative(args); accountList.withdrawMoney(args); transactionList.createNewTransaction(accountList.getMainAccount().getAccountName(), "withdraw", args, LocalDate.now()); @@ -281,4 +283,10 @@ public void parseTransactionFile(Scanner scanner) throws CorruptedTransactionFil throw new TransactionFileIsEmptyException(); } } + + public void checkNegative(String args) throws NegativeAmountException { + if (args.length() > 1 && args.charAt(0) == '-') { + throw new NegativeAmountException(); + } + } } From d1cd747be8017bfefc8feb19558a5924fcc8450e Mon Sep 17 00:00:00 2001 From: vishnu Date: Fri, 7 Apr 2023 22:30:17 +0800 Subject: [PATCH 282/368] Add a method to check for -ve in both wl and save goal --- src/main/java/seedu/bankwithus/parser/Parser.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 8a5a8b067b..b58a207ba1 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -141,6 +141,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce } break; case "set-wl": + checkNegative(args); try { accountList.setWithdrawalLimit(args); String withdrawalLimit = accountList.getMainAccount() @@ -163,6 +164,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showHelp(); break; case "set-save-goal": + checkNegative(args); if(args.length() > 0) { String untilWhenStr = ui.getDeadline(); accountList.handleSaveGoal(args, untilWhenStr); From 70e9d956210d3aa97c53f6384eda889eb85a3ccf Mon Sep 17 00:00:00 2001 From: vishnu Date: Fri, 7 Apr 2023 22:35:14 +0800 Subject: [PATCH 283/368] Add JavaDoc for checkNegative method --- src/main/java/seedu/bankwithus/parser/Parser.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index b58a207ba1..96de2524f1 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -176,6 +176,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce accountList.showGoal(); break; case "delete": + checkNegative(args); accountList.deleteAccount(args); break; case "view-transactions-all": @@ -187,6 +188,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce } break; case "delete-transaction": + checkNegative(args); try { transactionList.deleteTransaction(args); ui.printLine(); @@ -286,8 +288,14 @@ public void parseTransactionFile(Scanner scanner) throws CorruptedTransactionFil } } + /** + * 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() > 1 && args.charAt(0) == '-') { + if (args.length() > 0 && args.charAt(0) == '-') { throw new NegativeAmountException(); } } From bea8d494633ef28f06cc6067815c440d5aead04d Mon Sep 17 00:00:00 2001 From: vishnu Date: Fri, 7 Apr 2023 22:48:13 +0800 Subject: [PATCH 284/368] Add case in parser to only show curr account --- src/main/java/seedu/bankwithus/parser/Parser.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 96de2524f1..8c571ce6b1 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -4,6 +4,7 @@ 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; @@ -200,6 +201,9 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce ui.showIndexOutOfBoundsError(); } break; + case "view-current": + Account mainAcc = accountList.getMainAccount(); + ui.showCurrentAccount(mainAcc); default: throw new CommandNotFoundException(); } From 056aaf4da935621a5f7928bed9f280876ea38b77 Mon Sep 17 00:00:00 2001 From: vishnu Date: Fri, 7 Apr 2023 23:25:04 +0800 Subject: [PATCH 285/368] Add some asserts and test code --- .../java/seedu/bankwithus/user/AccountList.java | 15 +++++++++++++-- .../java/seedu/bankwithus/AccountListTest.java | 12 ++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 8e9f152da5..49f176cb7f 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -332,7 +332,11 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept throw new MoreThanTwoDecimalPlace(); } else { getMainAccount().subtractBalance(currentBalance, amtToDraw); - ui.showWithdrawMessage(); + if(amtToDraw.compareTo(BigDecimal.ZERO) == 0) { + ui.showWithdrawMessage(); + } else { + System.out.println("Withdrawing $0 has no effect!"); + } } } @@ -478,7 +482,9 @@ public void handleSaveGoal(String args, String untilWhenStr) { if (toSave < 0) { ui.showNegativeAmountError(); } else if (isDateFormatValid(untilWhenStr)) { + assert toSave >= 0 : "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); } @@ -496,7 +502,7 @@ public void handleSaveGoal(String args, String untilWhenStr) { * @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); @@ -529,6 +535,11 @@ public void showGoal() { * @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); diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 28dfe8bafb..083ed778e8 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -6,6 +6,7 @@ import seedu.bankwithus.exceptions.NegativeAmountException; import java.math.BigDecimal; +import java.time.LocalDate; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -141,4 +142,15 @@ void setWithdrawalLimit_nonNumberInput_numberFormatExceptionThrown() { assertEquals("11000", testAccountList.getMainAccount() .getWithdrawalChecker().getWithdrawalLimit()); } + + @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)); + } + } From 966aa3e76a97b5f0e56cece1e211dff044e524a7 Mon Sep 17 00:00:00 2001 From: vishnu Date: Fri, 7 Apr 2023 23:49:39 +0800 Subject: [PATCH 286/368] Refactor some code --- .../java/seedu/bankwithus/parser/Parser.java | 2 +- .../java/seedu/bankwithus/user/Account.java | 3 +-- .../seedu/bankwithus/user/AccountList.java | 7 ++--- .../bankwithus/user/TransactionList.java | 27 ++++++++++--------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 8c571ce6b1..d1b490024e 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -86,7 +86,6 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce } catch (NumberFormatException e) { ui.showNumberFormatError(); } catch (NullPointerException e) { - // Will almost never happen, but who knows ui.showNullInputError(); } catch (NegativeAmountException e) { ui.showNegativeAmountError(); @@ -204,6 +203,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce case "view-current": Account mainAcc = accountList.getMainAccount(); ui.showCurrentAccount(mainAcc); + break; default: throw new CommandNotFoundException(); } diff --git a/src/main/java/seedu/bankwithus/user/Account.java b/src/main/java/seedu/bankwithus/user/Account.java index 9eeb8355d6..87c6b43101 100644 --- a/src/main/java/seedu/bankwithus/user/Account.java +++ b/src/main/java/seedu/bankwithus/user/Account.java @@ -56,12 +56,11 @@ public void addBalance(BigDecimal balanceToBeAdded) { //@@author manushridiv public void subtractBalance(BigDecimal currentBalance, BigDecimal withdrawal) { this.balance = currentBalance.subtract(withdrawal); - withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); //check later + withdrawalChecker.updateTotalAmtWithdrawn(withdrawal); } //@@author vishnuvk47 public void setSaveGoal(SaveGoal saveGoal, String args, String untilWhenStr) { - this.saveGoal = saveGoal; } diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 49f176cb7f..0c46bb9164 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -332,14 +332,15 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept throw new MoreThanTwoDecimalPlace(); } else { getMainAccount().subtractBalance(currentBalance, amtToDraw); - if(amtToDraw.compareTo(BigDecimal.ZERO) == 0) { - ui.showWithdrawMessage(); - } else { + 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. diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 21cfc4d1ce..39300b7169 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -94,6 +94,7 @@ public void printAllTransactions() throws NoTransactionsFoundException { } } + //@xiaoge26 /** * Deletes a transaction from the transaction list. * @param args the index of the transaction to be deleted @@ -103,21 +104,21 @@ public void deleteTransaction(String args) throws NoTransactionsFoundException, Ui ui = new Ui(); if (size == 0) { throw new NoTransactionsFoundException(); - } else if (Integer.parseInt(args) > size || Integer.parseInt(args) < 1) { - throw new IndexOutOfBoundsException(); - } else { - try { - int index = Integer.parseInt(args) - 1; - transactions.remove(index); - size--; - ui.showTransactionDeletedMessage(); - } catch (NumberFormatException e) { - throw new NumberFormatException(); - } catch (IndexOutOfBoundsException e) { + } + try { + int index = Integer.parseInt(args) - 1; + if (index > size || index < 1) { throw new IndexOutOfBoundsException(); - } catch (Exception e) { - e.printStackTrace(); } + transactions.remove(index); + size--; + ui.showTransactionDeletedMessage(); + } catch (NumberFormatException e) { + throw new NumberFormatException(); + } catch (IndexOutOfBoundsException e) { + throw new IndexOutOfBoundsException(); + } catch (Exception e) { + e.printStackTrace(); } } } From e7c26f1af4871e572f0d6dc269af1c6d50cdea27 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sat, 8 Apr 2023 12:59:17 +0800 Subject: [PATCH 287/368] Fix undeleted transctions for deleted account issue --- .../java/seedu/bankwithus/parser/Parser.java | 9 ++++---- src/main/java/seedu/bankwithus/ui/Ui.java | 4 +--- .../bankwithus/user/TransactionList.java | 22 +++++++++++++------ text-ui-test/EXPECTED.TXT | 6 ++--- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 20e25ff203..51216014fe 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -173,6 +173,7 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce break; case "delete": accountList.deleteAccount(args); + transactionList.deleteTransactionsForAccount(args); break; case "view-transactions-all": try { @@ -253,9 +254,9 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S /** * Reads the transaction data from the transaction save file. - * @param scanner - * @throws CorruptedSaveFileException - * @throws SaveFileIsEmptyException + * @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 { @@ -264,7 +265,7 @@ public void parseTransactionFile(Scanner scanner) throws CorruptedTransactionFil String transactionDetails = scanner.nextLine(); try { if (transactionDetails.isBlank()) { - throw new SaveFileIsEmptyException(); + throw new TransactionFileIsEmptyException(); } TransactionDecoder decoder = new TransactionDecoder(); Transaction temp = decoder.decodeTransaction(transactionDetails); diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index de6e3f7466..043d23b344 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -62,8 +62,6 @@ public void showWithdrawMessage() { /** * Creates a scanner in the Ui class. - * - * @return */ public void createScanner() { this.scanner = new Scanner(System.in); @@ -131,7 +129,7 @@ public void showHelp() { 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 : " + + System.out.println("delete-transaction : " + "deletes the transaction with the given transaction index"); System.out.println("exit: quits program and saves"); printLine(); diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 21cfc4d1ce..4de589da37 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -23,10 +23,7 @@ public TransactionList() { /** * Creates a new instance of TransactionList. Initialises transactions. * Should load data into transactions list too. - * - * @param scanner the scanner to read the transaction file - * @throws CorruptedTransactionFileException thrown when the transaction file is corrupted - * @throws TransactionFileIsEmptyException thrown when the transaction file is empty + * @param scanner the scanner to be used to read the transaction file */ public TransactionList(Scanner scanner) { this.size = 0; @@ -72,9 +69,6 @@ public void addTransaction(Transaction transaction) { public ArrayList getTransactions() { return transactions; } - public Transaction getTransaction(int index) { - return transactions.get(index); - } public int getSize() { return size; @@ -120,4 +114,18 @@ public void deleteTransaction(String args) throws NoTransactionsFoundException, } } } + + /** + * 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/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 3824925ae2..6aea817bf8 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -125,9 +125,9 @@ Balance: $123678.20 Name: hihi Balance: $1100.21 ---------------------------- -1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 07/04/2023 -2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 07/04/2023 -3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 07/04/2023 +1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 08/04/2023 +2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 08/04/2023 +3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 08/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From eca1f42b63662d79f2eb65daa54f07eb764efe5f Mon Sep 17 00:00:00 2001 From: vishnu Date: Sat, 8 Apr 2023 13:20:17 +0800 Subject: [PATCH 288/368] Change expected date and rmv unused import --- src/test/java/seedu/bankwithus/AccountListTest.java | 1 - text-ui-test/EXPECTED.TXT | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 083ed778e8..e8ab639520 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -6,7 +6,6 @@ import seedu.bankwithus.exceptions.NegativeAmountException; import java.math.BigDecimal; -import java.time.LocalDate; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 3824925ae2..6aea817bf8 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -125,9 +125,9 @@ Balance: $123678.20 Name: hihi Balance: $1100.21 ---------------------------- -1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 07/04/2023 -2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 07/04/2023 -3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 07/04/2023 +1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 08/04/2023 +2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 08/04/2023 +3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 08/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From a3fb0f17d64e452b1af6ffb3ada2aaea246a892b Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sat, 8 Apr 2023 13:36:17 +0800 Subject: [PATCH 289/368] Update PPP --- docs/team/xiaoge26.md | 50 ++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index 272429ba87..09fbbb78db 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -6,29 +6,38 @@ Helped create a CLI-based application that acts like a banking app. Users can cr ## 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 have developed the add deposit 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 developed the add account and add deposit feature, which allows users to add a new deposit to the current account. +My teammates have also modified and improved these feature to suit the evolved needs of the application.
-I have also developed all the features related to the `Transaction` and `TransactionList` classes, including adding, -deleting, listing, parsing, saving, and loading the transactions. +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 + * 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 the features related `Transaction` and `TransactionList` components in the User Guide
+* Fixed typos and bugs in the other sections in UG as well
-### UG contributions +### Contributions to the DG -Documented the `Transaction` and `TransactionList` feature in the User Guide. +* 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.) -### DG contributions -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.) - - -### Team-based tasks +### 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) @@ -36,3 +45,18 @@ Further modified the DG template and fixed the typos and standardized the format * 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 +* [add NoValueInput exception #156](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/156) +* [Update show help #98](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/98) +* [Add main architecture and example seq diagram to dev guide #100](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/100) +* [Branch withdrawal limit #71](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/71) +* [Create withdrawal checker class #67](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/67) +* [Change the attribute balance to String type #58](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/58) +* [add Account class #24](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/24) +* [Wrote PPP for myself #158](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/158) + + +### Contributions beyond the project team + From 9972953d91ae2aa2aeefa913bbe71d1d5b3d4abb Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sat, 8 Apr 2023 14:15:38 +0800 Subject: [PATCH 290/368] Complete PPP --- docs/team/xiaoge26.md | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index 09fbbb78db..d4b3c6be6a 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -11,18 +11,23 @@ Helped create a CLI-based application that acts like a banking app. Users can cr ### Enhancements implemented -I have developed the add account and add deposit feature, which allows users to add a new deposit to the current account. -My teammates have also modified and improved these feature to suit the evolved needs of the application.
+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): +* 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 +* 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 @@ -59,4 +64,17 @@ deleting, listing, parsing, saving, and loading the transactions.
### Contributions beyond the project team - +* Reported bugs and suggestions to other teams: +[#142](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/142) +[#139](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/139) +[#133](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/133) +[#129](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/129) +[#126](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/126) +[#117](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/117) +[#116](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/116) +[#101](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/101) +[#104](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/104) +[#107](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/107) +[#142](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/142) +[#95](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/95) +* Developer Guide reviewed: [[CS2113-T14-2] BagPacker #61](https://github.com/nus-cs2113-AY2223S2/tp/pull/61/files/bf0684974cef3c42639ecce53b4a5ff60dec3a7a) From 19e56645c0af572ce67815ca8e19aa0844a56f9e Mon Sep 17 00:00:00 2001 From: vishnu Date: Sat, 8 Apr 2023 18:35:38 +0800 Subject: [PATCH 291/368] Add implementation section to the DG --- docs/DeveloperGuide.md | 76 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 82d46f5aca..22869728b5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -143,6 +143,82 @@ The `TransactionList` component: 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 + +--> Identifies 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 deposit) 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 + +**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 + +## 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 --- From 47c19ff642165eee65966d930c71bc67ff110112 Mon Sep 17 00:00:00 2001 From: vishnu Date: Sat, 8 Apr 2023 19:07:24 +0800 Subject: [PATCH 292/368] Made updates to my PPP --- docs/team/vishnuvk47.md | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/docs/team/vishnuvk47.md b/docs/team/vishnuvk47.md index 0b9d6351bf..98a97f5159 100644 --- a/docs/team/vishnuvk47.md +++ b/docs/team/vishnuvk47.md @@ -10,20 +10,43 @@ Helped create a CLI-based application that acts like a banking app. Users can cr ### Enhancements implemented -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). +* 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) ### 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, who helped me improve the guide's consistency and format to align with recommended guidelines. +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 and basic functionalities of the program for the DG. +Templated the layout, wrote documentation for functionalities of the program for the DG.[#73](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/73) ### 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 -* Handled a significant number of issues that were reported in the PE-D. -* refactored the floats into Big Decimal to resolve overflow and precision issues. +* 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 + From 99351907dd69b28ed20cb327e12d246404ca5d60 Mon Sep 17 00:00:00 2001 From: vishnu Date: Sat, 8 Apr 2023 19:45:50 +0800 Subject: [PATCH 293/368] Continue DG implementation --- docs/DeveloperGuide.md | 36 ++++++++++++++++++- .../seedu/bankwithus/user/AccountList.java | 10 +++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 22869728b5..7b2ec4a6dc 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -174,7 +174,7 @@ that contains the various different transactions that the user has **Step 1**: ---> Checks the args(AMOUNT to deposit) for a negative sign in the `checkNegative()` method +--> Checks the args(AMOUNT to withdraw) for a negative sign in the `checkNegative()` method **Step 2**: @@ -220,6 +220,40 @@ that contains the various different transactions that the user has --> 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 + --- diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 0c46bb9164..ff9f708623 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -273,12 +273,12 @@ public void depositMoney(String depositAmountString) throws NumberFormatExceptio BigDecimal amtToDeposit = new BigDecimal(depositAmountString); if (depositAmount < 0) { throw new NegativeAmountException(); - } else { - if (isMoreThanTwoDecimalPlaces(depositAmountString)) { - throw new MoreThanTwoDecimalPlace(); - } - getMainAccount().addBalance(amtToDeposit); } + if (isMoreThanTwoDecimalPlaces(depositAmountString)) { + throw new MoreThanTwoDecimalPlace(); + } + getMainAccount().addBalance(amtToDeposit); + } //@@author vishnuvk47 From 3e11b40aec5017f0c38380d3030ac82911ec3ba5 Mon Sep 17 00:00:00 2001 From: vishnu Date: Sun, 9 Apr 2023 12:52:07 +0800 Subject: [PATCH 294/368] Add some commands implementation to Dev Guide --- docs/DeveloperGuide.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 7b2ec4a6dc..a92759adbe 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -196,6 +196,8 @@ that contains the various different transactions that the user has --> 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 @@ -254,6 +256,28 @@ that contains the various different transactions that the user has --> 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 + --- From 089fa386c1c2cb48fa878da0eb6807854e67cd40 Mon Sep 17 00:00:00 2001 From: vishnu Date: Sun, 9 Apr 2023 13:33:14 +0800 Subject: [PATCH 295/368] Made some changes from float to BigDecimal --- .../bankwithus/common/WithdrawalChecker.java | 8 ++++---- .../seedu/bankwithus/user/AccountList.java | 20 +++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java index dfe236e6d8..8996952d10 100644 --- a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java @@ -89,13 +89,13 @@ public void setWithdrawalLimit(float withdrawalLimit) { * @param withdrawAmount the amount withdrawn * @return true if will exceed, false otherwise */ - public boolean willExceedWithdrawalLimit(float withdrawAmount) { + public boolean willExceedWithdrawalLimit(BigDecimal withdrawAmount) { if (totalAmtWithdrawn.isBlank() || withdrawalLimit == null) { return false; } - float totalAmtWithdrawnFloat = Float.parseFloat(totalAmtWithdrawn); - float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); - return ((totalAmtWithdrawnFloat + withdrawAmount) > withdrawalLimitFloat); + BigDecimal totalAmtWithdrawnBigDecimal = new BigDecimal(totalAmtWithdrawn); + BigDecimal withdrawalLimitBigDecimal = new BigDecimal(withdrawalLimit); + return ((totalAmtWithdrawnBigDecimal.add(withdrawAmount)).compareTo(withdrawalLimitBigDecimal) == 1 ); } @Override diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index ff9f708623..bf5bae30ca 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -115,11 +115,11 @@ public String askUserForName() { } /** - * Asks the user for their initial balance and returns it as a float. + * 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 float + * @return balance in the form of a String */ public String askUserForBalance() { ui.askForBalance(); @@ -269,16 +269,14 @@ public void showBal() { */ public void depositMoney(String depositAmountString) throws NumberFormatException, NullPointerException, NegativeAmountException, MoreThanTwoDecimalPlace { - float depositAmount = Float.parseFloat(depositAmountString);//floats are still used, but only for comparison BigDecimal amtToDeposit = new BigDecimal(depositAmountString); - if (depositAmount < 0) { + if (amtToDeposit.compareTo(BigDecimal.ZERO) == -1) { throw new NegativeAmountException(); } if (isMoreThanTwoDecimalPlaces(depositAmountString)) { throw new MoreThanTwoDecimalPlace(); } getMainAccount().addBalance(amtToDeposit); - } //@@author vishnuvk47 @@ -315,15 +313,15 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept if (withdrawAmountString.trim().isBlank()){ throw new NoValueInputException(); } - float withdrawAmount = Float.parseFloat(withdrawAmountString); + BigDecimal amtToDraw = new BigDecimal(withdrawAmountString); - if (withdrawAmount < 0) { + if (amtToDraw.compareTo(BigDecimal.ZERO) == -1) { throw new NegativeAmountException(); } BigDecimal currentBalance = getMainAccount().getAccountBalance(); if (currentBalance.compareTo(amtToDraw) < 0) { throw new InsufficientBalanceException(); - } else if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(withdrawAmount)) { + } else if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(amtToDraw)) { throw new ExceedsWithdrawalLimitException(); } else if (willFailsSaveGoal(currentBalance, amtToDraw)) { ui.failToMeetSaveGoal(); @@ -479,11 +477,11 @@ public void handleProceed(BigDecimal withdrawAmount, BigDecimal currentBalance) */ public void handleSaveGoal(String args, String untilWhenStr) { try { - float toSave = Float.parseFloat(args); - if (toSave < 0) { + BigDecimal toSave = new BigDecimal(args); + if (toSave.compareTo(BigDecimal.ZERO) == -1) { ui.showNegativeAmountError(); } else if (isDateFormatValid(untilWhenStr)) { - assert toSave >= 0 : "Invalid amount entered."; + 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); From 9c61fae95ab1f5420f87afdc97998f926d518afc Mon Sep 17 00:00:00 2001 From: vishnu Date: Sun, 9 Apr 2023 16:39:15 +0800 Subject: [PATCH 296/368] Change date to pass io redir and added a line in PPP --- docs/team/vishnuvk47.md | 2 ++ text-ui-test/EXPECTED.TXT | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/team/vishnuvk47.md b/docs/team/vishnuvk47.md index 98a97f5159..4aaf453739 100644 --- a/docs/team/vishnuvk47.md +++ b/docs/team/vishnuvk47.md @@ -19,6 +19,8 @@ Helped create a CLI-based application that acts like a banking app. Users can cr * 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) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 6aea817bf8..0e53aad42b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -125,9 +125,9 @@ Balance: $123678.20 Name: hihi Balance: $1100.21 ---------------------------- -1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 08/04/2023 -2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 08/04/2023 -3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 08/04/2023 +1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 09/04/2023 +2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 09/04/2023 +3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 09/04/2023 ---------------------------- Not a valid command! Goodbye! Hope to see you again! :) From 39965f0e748a9cf35e0de46f75609bbd43749909 Mon Sep 17 00:00:00 2001 From: manushridiv Date: Sun, 9 Apr 2023 16:47:09 +0800 Subject: [PATCH 297/368] ppp --- docs/team/manushridiv.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/team/manushridiv.md diff --git a/docs/team/manushridiv.md b/docs/team/manushridiv.md new file mode 100644 index 0000000000..98789b9013 --- /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 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 PRs not authored by myself +* 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 From cb413a2220a7faad90eac4f9731004bc4869bbfe Mon Sep 17 00:00:00 2001 From: manushridiv Date: Sun, 9 Apr 2023 16:52:06 +0800 Subject: [PATCH 298/368] changes to ppp --- docs/team/manushridiv.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/team/manushridiv.md b/docs/team/manushridiv.md index 98789b9013..f754f21ca4 100644 --- a/docs/team/manushridiv.md +++ b/docs/team/manushridiv.md @@ -32,9 +32,9 @@ Modified the DG template and fixed the typos and standardized the format. * 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 that are not specific to a feature e.g. Non-Functional Requirements and Instructions for Manual Testing) +* 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 not authored by myself +* 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 From f22b10e354d1db77f2deebb03dffa7dd10b45545 Mon Sep 17 00:00:00 2001 From: vishnu Date: Sun, 9 Apr 2023 19:28:13 +0800 Subject: [PATCH 299/368] Wrote a lot of JUNIT to validate MAIN AccountList methods and functionalities --- .../seedu/bankwithus/AccountListTest.java | 151 +++++++++++++++++- 1 file changed, 149 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index e8ab639520..b7617ca12b 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,9 +1,8 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; -import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace; +import seedu.bankwithus.exceptions.*; import seedu.bankwithus.user.AccountList; -import seedu.bankwithus.exceptions.NegativeAmountException; import java.math.BigDecimal; @@ -152,4 +151,152 @@ public void testIsDateFormatValid() { 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_largestPossibleNumber_onAccountWithLargeBalance_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()); + } + + + + } From 1f88ae08ba2e026a263a60a49fe57c5acb397a2a Mon Sep 17 00:00:00 2001 From: vishnu Date: Sun, 9 Apr 2023 19:30:47 +0800 Subject: [PATCH 300/368] Delete extra lines at end --- src/test/java/seedu/bankwithus/AccountListTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index b7617ca12b..e338ddf36b 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -295,8 +295,4 @@ void deleteAccount_createNewAccountWithNameOfDeletedAccount_accountExpectSuccess accountList.switchMainAccount("Account 2"); assertEquals("Account 2", accountList.getMainAccount().getAccountName()); } - - - - } From ff5412400c4d30bc12ff52df44c44707906804aa Mon Sep 17 00:00:00 2001 From: vishnu Date: Sun, 9 Apr 2023 20:55:59 +0800 Subject: [PATCH 301/368] Enable assertions in build.gradle --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index fb5d6dd6d5..521b899823 100644 --- a/build.gradle +++ b/build.gradle @@ -43,4 +43,5 @@ checkstyle { run{ standardInput = System.in + enableAssertions = true } From 6734aceef395d2aabfd44f0635e88b0ac4c53421 Mon Sep 17 00:00:00 2001 From: vishnu Date: Sun, 9 Apr 2023 21:05:03 +0800 Subject: [PATCH 302/368] Resolve checkstyle errors in accountlist tests --- src/test/java/seedu/bankwithus/AccountListTest.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index e338ddf36b..2039be3452 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -1,8 +1,14 @@ package seedu.bankwithus; import org.junit.jupiter.api.Test; -import seedu.bankwithus.exceptions.*; +import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace; import seedu.bankwithus.user.AccountList; +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; @@ -186,7 +192,9 @@ void depositMoney_validAmount_expectDeposit() throws NegativeAmountException, Mo } @Test - void withdrawMoney_validAmount_expectWithdrawal() throws NegativeAmountException, NoValueInputException, WithdrawalCancelledException, InsufficientBalanceException, ExceedsWithdrawalLimitException, MoreThanTwoDecimalPlace { + void withdrawMoney_validAmount_expectWithdrawal() throws NegativeAmountException, NoValueInputException, + WithdrawalCancelledException, InsufficientBalanceException, ExceedsWithdrawalLimitException, + MoreThanTwoDecimalPlace { String amountString = "500.00"; String name = "Test Account"; String balance = "1000.00"; From fa6b66a23984a012c07613485d57009d1dbb43d5 Mon Sep 17 00:00:00 2001 From: vishnu Date: Sun, 9 Apr 2023 21:09:23 +0800 Subject: [PATCH 303/368] Change name format of test method in accountlist --- src/test/java/seedu/bankwithus/AccountListTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/seedu/bankwithus/AccountListTest.java b/src/test/java/seedu/bankwithus/AccountListTest.java index 2039be3452..85312730f6 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/AccountListTest.java @@ -262,7 +262,7 @@ void depositMoney_largestPossibleNumber_expectNoException() { ////As per [PE-D][Tester A] [Bug] #144 --> extension from this bug @Test - void depositMoney_largestPossibleNumber_onAccountWithLargeBalance_expectNoException() { + void depositMoney_onAccountLargeBalance_expectNoException() { String amountString = new BigDecimal(Double.MAX_VALUE).toString(); String name = "Test Account"; String balance = amountString; From 5451ca785c8c644c0dd0f4763fcf7f53e93dad00 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sun, 9 Apr 2023 21:53:04 +0800 Subject: [PATCH 304/368] Move test files into packages --- .../java/seedu/bankwithus/StorageTest.java | 22 ------------------- .../{ => common}/WithdrawalCheckerTest.java | 3 ++- .../seedu/bankwithus/storage/StorageTest.java | 14 ++++++++++++ .../{ => user}/AccountListTest.java | 3 ++- 4 files changed, 18 insertions(+), 24 deletions(-) delete mode 100644 src/test/java/seedu/bankwithus/StorageTest.java rename src/test/java/seedu/bankwithus/{ => common}/WithdrawalCheckerTest.java (97%) create mode 100644 src/test/java/seedu/bankwithus/storage/StorageTest.java rename src/test/java/seedu/bankwithus/{ => user}/AccountListTest.java (99%) diff --git a/src/test/java/seedu/bankwithus/StorageTest.java b/src/test/java/seedu/bankwithus/StorageTest.java deleted file mode 100644 index 613e8cd14e..0000000000 --- a/src/test/java/seedu/bankwithus/StorageTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package seedu.bankwithus; - -import org.junit.jupiter.api.Test; -import seedu.bankwithus.storage.Storage; - -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")); - // Storage storage = new Storage("data/save.txt"); - // assertDoesNotThrow(() -> storage.load()); - } - - // @Test - // public void save_accountList_noMessage() { - // AccountList accountList = new AccountList(); - // Storage storage = new Storage("data/save.txt"); - // assertDoesNotThrow(() -> storage.saveToFile(accountList)); - // } -} diff --git a/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java b/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java similarity index 97% rename from src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java rename to src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java index dd3fca32de..8af4a19cff 100644 --- a/src/test/java/seedu/bankwithus/WithdrawalCheckerTest.java +++ b/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java @@ -1,4 +1,5 @@ -package seedu.bankwithus; +//@@author tyuyang +package seedu.bankwithus.common; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; 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..dbf659c149 --- /dev/null +++ b/src/test/java/seedu/bankwithus/storage/StorageTest.java @@ -0,0 +1,14 @@ +//@@author tyuyang +package seedu.bankwithus.storage; + +import org.junit.jupiter.api.Test; +import seedu.bankwithus.storage.Storage; + +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/AccountListTest.java b/src/test/java/seedu/bankwithus/user/AccountListTest.java similarity index 99% rename from src/test/java/seedu/bankwithus/AccountListTest.java rename to src/test/java/seedu/bankwithus/user/AccountListTest.java index e8ab639520..de1f20bfa8 100644 --- a/src/test/java/seedu/bankwithus/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/user/AccountListTest.java @@ -1,4 +1,4 @@ -package seedu.bankwithus; +package seedu.bankwithus.user; import org.junit.jupiter.api.Test; import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace; @@ -12,6 +12,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; class AccountListTest { + //@@author xiaoge26 @Test void depositMoney_notANumber_expectException() { String amountString = "abc"; From f1cb8a36ac40e89e22ac5122a24fad3899648456 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sun, 9 Apr 2023 21:53:28 +0800 Subject: [PATCH 305/368] Add tests for TransactionDecoder --- .../seedu/bankwithus/user/Transaction.java | 4 ++ .../storage/TransactionDecoderTest.java | 52 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/test/java/seedu/bankwithus/storage/TransactionDecoderTest.java diff --git a/src/main/java/seedu/bankwithus/user/Transaction.java b/src/main/java/seedu/bankwithus/user/Transaction.java index baca5b3b30..067cedd593 100644 --- a/src/main/java/seedu/bankwithus/user/Transaction.java +++ b/src/main/java/seedu/bankwithus/user/Transaction.java @@ -41,4 +41,8 @@ public String getDateStr() { public String getType() { return type; } + + public LocalDate getDate() { + return date; + } } 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..6c1549837e --- /dev/null +++ b/src/test/java/seedu/bankwithus/storage/TransactionDecoderTest.java @@ -0,0 +1,52 @@ +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)); + } + +} \ No newline at end of file From 099fb1f67ab7cb33401b826b36f9929988f69830 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Sun, 9 Apr 2023 22:02:46 +0800 Subject: [PATCH 306/368] Remove redundant imports --- .../java/seedu/bankwithus/common/WithdrawalCheckerTest.java | 1 - src/test/java/seedu/bankwithus/storage/StorageTest.java | 1 - .../seedu/bankwithus/storage/TransactionDecoderTest.java | 5 +++-- src/test/java/seedu/bankwithus/user/AccountListTest.java | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java b/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java index 8af4a19cff..e9f8e345a5 100644 --- a/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java +++ b/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java @@ -8,7 +8,6 @@ import java.time.LocalDate; import org.junit.jupiter.api.Test; -import seedu.bankwithus.common.WithdrawalChecker; public class WithdrawalCheckerTest { @Test diff --git a/src/test/java/seedu/bankwithus/storage/StorageTest.java b/src/test/java/seedu/bankwithus/storage/StorageTest.java index dbf659c149..9aab00d6ce 100644 --- a/src/test/java/seedu/bankwithus/storage/StorageTest.java +++ b/src/test/java/seedu/bankwithus/storage/StorageTest.java @@ -2,7 +2,6 @@ package seedu.bankwithus.storage; import org.junit.jupiter.api.Test; -import seedu.bankwithus.storage.Storage; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; diff --git a/src/test/java/seedu/bankwithus/storage/TransactionDecoderTest.java b/src/test/java/seedu/bankwithus/storage/TransactionDecoderTest.java index 6c1549837e..4bd37ceabb 100644 --- a/src/test/java/seedu/bankwithus/storage/TransactionDecoderTest.java +++ b/src/test/java/seedu/bankwithus/storage/TransactionDecoderTest.java @@ -15,7 +15,8 @@ class TransactionDecoderTest { 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 expectedTransaction = new Transaction("MyAccount", "withdraw", "1000.00", + LocalDate.parse("23/08/2021", DateTimeFormatter.ofPattern("dd/MM/yyyy"))); Transaction result = transactionDecoder.decodeTransaction(encodedTransaction); @@ -49,4 +50,4 @@ void testDecodeTransaction_invalidInput_extraField() { assertThrows(IllegalArgumentException.class, () -> transactionDecoder.decodeTransaction(encodedTransaction)); } -} \ No newline at end of file +} diff --git a/src/test/java/seedu/bankwithus/user/AccountListTest.java b/src/test/java/seedu/bankwithus/user/AccountListTest.java index 4763bb5e33..834d7d3d4b 100644 --- a/src/test/java/seedu/bankwithus/user/AccountListTest.java +++ b/src/test/java/seedu/bankwithus/user/AccountListTest.java @@ -2,7 +2,6 @@ import org.junit.jupiter.api.Test; import seedu.bankwithus.exceptions.MoreThanTwoDecimalPlace; -import seedu.bankwithus.user.AccountList; import seedu.bankwithus.exceptions.NegativeAmountException; import seedu.bankwithus.exceptions.NoAccountException; import seedu.bankwithus.exceptions.ExceedsWithdrawalLimitException; @@ -148,6 +147,7 @@ void setWithdrawalLimit_nonNumberInput_numberFormatExceptionThrown() { .getWithdrawalChecker().getWithdrawalLimit()); } + //@@author vishnuvk47 @Test public void testIsDateFormatValid() { AccountList acc = new AccountList(); From c50b98bc0434787f7449f232858a78bee90cf159 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 10 Apr 2023 00:04:42 +0800 Subject: [PATCH 307/368] Create PPP for Sherlock-YH --- docs/team/Sherlock-YH.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docs/team/Sherlock-YH.md diff --git a/docs/team/Sherlock-YH.md b/docs/team/Sherlock-YH.md new file mode 100644 index 0000000000..6df2c96b7b --- /dev/null +++ b/docs/team/Sherlock-YH.md @@ -0,0 +1,35 @@ +# 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. + +#### 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 From 410caeb6bc5b0009fc64f8312db37005192f348e Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 09:11:31 +0800 Subject: [PATCH 308/368] Changed gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bf5b078f8c..5f279f9082 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,5 @@ bin/ data data/save.txt -text-ui-test/ACTUAL.TXT +text-ui-test/EXPECTED.TXT text-ui-test/EXPECTED-UNIX.TXT From 9a046420acecf5a01adf8ec504411994366134f4 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 09:12:27 +0800 Subject: [PATCH 309/368] Changed back cos i am an idiot --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5f279f9082..bf5b078f8c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,5 @@ bin/ data data/save.txt -text-ui-test/EXPECTED.TXT +text-ui-test/ACTUAL.TXT text-ui-test/EXPECTED-UNIX.TXT From 65743094644e311f5497179aeaa251bc6e71da7d Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 09:12:55 +0800 Subject: [PATCH 310/368] Update EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 0e53aad42b..fb61dc3fa3 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -125,9 +125,9 @@ Balance: $123678.20 Name: hihi Balance: $1100.21 ---------------------------- -1. Account Name: hihi Transaction Type: deposit Amount: 100.21 Date: 09/04/2023 -2. Account Name: sherlock Transaction Type: withdraw Amount: 100 Date: 09/04/2023 -3. Account Name: sherlock Transaction Type: deposit Amount: 0.1 Date: 09/04/2023 +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! :) From c8b21dca858566f575d13100ca49b0fc16ed6d3a Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 09:19:37 +0800 Subject: [PATCH 311/368] Fix minor bug where delete transaction 1 will throw an index out of bounds error --- src/main/java/seedu/bankwithus/user/TransactionList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/user/TransactionList.java b/src/main/java/seedu/bankwithus/user/TransactionList.java index 19689e3a04..b8fd48a576 100644 --- a/src/main/java/seedu/bankwithus/user/TransactionList.java +++ b/src/main/java/seedu/bankwithus/user/TransactionList.java @@ -101,7 +101,7 @@ public void deleteTransaction(String args) throws NoTransactionsFoundException, } try { int index = Integer.parseInt(args) - 1; - if (index > size || index < 1) { + if (index > size || index < 0) { throw new IndexOutOfBoundsException(); } transactions.remove(index); From 1a1fa80667345de7f4a539298739b33dc05afa1e Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 09:29:56 +0800 Subject: [PATCH 312/368] Changed startup message --- src/main/java/seedu/bankwithus/ui/Ui.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 043d23b344..38ac2abd6c 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -206,7 +206,7 @@ public void showNumberOfAccount(int accSize) { } //@@author Sherlock-YH public void showNewAccountAdded(Account acc) { - System.out.println("Account created!"); + System.out.println("Account added!"); System.out.println("Name: " + acc.getAccountName()); System.out.println("Balance: $" + acc.getAccountBalance()); printLine(); From 98ff82ad2506e21fba0d7261fcc4ca5120dcb7f2 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 09:38:47 +0800 Subject: [PATCH 313/368] Fix set-save-goal command where normal inputs cause an assertion trigger --- src/main/java/seedu/bankwithus/user/AccountList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 5f236fefbb..393ae3861e 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -485,7 +485,7 @@ public void handleSaveGoal(String args, String untilWhenStr) { if (toSave.compareTo(BigDecimal.ZERO) == -1) { ui.showNegativeAmountError(); } else if (isDateFormatValid(untilWhenStr)) { - assert toSave.compareTo(BigDecimal.ZERO) == -1 : "Invalid amount entered."; + 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); From 0c037b717fcc3ee3d9e3d8a79718b8d5c6aab753 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 09:47:30 +0800 Subject: [PATCH 314/368] Change withdrawal limit feature to use BigDecimal instead of float --- .../seedu/bankwithus/common/WithdrawalChecker.java | 2 +- src/main/java/seedu/bankwithus/user/AccountList.java | 12 ++++++------ .../bankwithus/common/WithdrawalCheckerTest.java | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java index 8996952d10..a5c3918494 100644 --- a/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java +++ b/src/main/java/seedu/bankwithus/common/WithdrawalChecker.java @@ -77,7 +77,7 @@ public String getWithdrawalLimit() { return this.withdrawalLimit; } - public void setWithdrawalLimit(float withdrawalLimit) { + public void setWithdrawalLimit(BigDecimal withdrawalLimit) { DecimalFormat df = new DecimalFormat("#.##"); String formatted = df.format(withdrawalLimit); this.withdrawalLimit = String.valueOf(formatted); diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 393ae3861e..6f1b4f800f 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -158,7 +158,7 @@ public String askUserForBalance() { public void addAccount(String name, String balance, String withdrawalLimit) { Account newAccount = new Account(name, balance, "0", LocalDate.parse("2001-01-01")); if (!withdrawalLimit.isBlank()) { - Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); + BigDecimal withdrawalLimitFloat = new BigDecimal(withdrawalLimit); newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat); } accounts.add(newAccount); @@ -177,7 +177,7 @@ public void addAccount(String name, String balance, String withdrawalLimit) { public void addAccount(String name, String balance, String withdrawalLimit, String amtToSave, LocalDate untilWhen) { Account newAccount = new Account(name, balance, amtToSave, untilWhen); if (!withdrawalLimit.isBlank()) { - Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); + BigDecimal withdrawalLimitFloat = new BigDecimal(withdrawalLimit); newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat); } accounts.add(newAccount); @@ -199,7 +199,7 @@ 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()) { - Float withdrawalLimitFloat = Float.parseFloat(withdrawalLimit); + BigDecimal withdrawalLimitFloat = new BigDecimal(withdrawalLimit); newAccount.getWithdrawalChecker().setWithdrawalLimit(withdrawalLimitFloat); } accounts.add(newAccount); @@ -425,13 +425,13 @@ public void switchMainAccount(String accName) throws NoAccountException { * @throws NegativeAmountException if input is negative */ public void setWithdrawalLimit(String args) throws NegativeAmountException { - float withdrawalLimit; + BigDecimal withdrawalLimit; try { - withdrawalLimit = Float.parseFloat(args); + withdrawalLimit = new BigDecimal(args); } catch (Exception e) { throw new NumberFormatException(); } - if (withdrawalLimit < 0) { + if (withdrawalLimit.compareTo(BigDecimal.ZERO) == -1) { throw new NegativeAmountException(); } getMainAccount().getWithdrawalChecker().setWithdrawalLimit(withdrawalLimit); diff --git a/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java b/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java index e9f8e345a5..742b1a71df 100644 --- a/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java +++ b/src/test/java/seedu/bankwithus/common/WithdrawalCheckerTest.java @@ -36,7 +36,7 @@ public void toStringTest() { assertEquals("0; ; ", wc.toString()); //test without withdrawal and with withdrawal limit - assertDoesNotThrow(() -> wc.setWithdrawalLimit((float) 10.10)); + assertDoesNotThrow(() -> wc.setWithdrawalLimit(new BigDecimal("10.1"))); assertEquals("0; ;10.1", wc.toString()); //test with withdrawal and without withdrawal limit @@ -44,7 +44,7 @@ public void toStringTest() { assertEquals("1000;2023-01-10; ", wc2.toString()); //test with withdrawal and with withdrawal limit - assertDoesNotThrow(() -> wc2.setWithdrawalLimit((float) 100.10)); + assertDoesNotThrow(() -> wc2.setWithdrawalLimit((new BigDecimal( 100.10)))); assertEquals("1000;2023-01-10;100.1", wc2.toString()); } } From 36a1b09b9426e2f41e0f08786f47a91801535205 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 10:02:09 +0800 Subject: [PATCH 315/368] Update expected.txt --- text-ui-test/EXPECTED.TXT | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index fb61dc3fa3..175b069434 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -19,7 +19,7 @@ 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 created! +Account added! Name: hihi Balance: $1000.00 ---------------------------- @@ -48,7 +48,7 @@ Account is not found, please rectify the name ---------------------------- What's your name? How much would you like to add as Balance? -Account created! +Account added! Name: sherlock Balance: $123778.10 ---------------------------- From 1b5b626bf7eadc07191798c834c2c2d0d0c4ecdc Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 10:08:28 +0800 Subject: [PATCH 316/368] Update seq diagram --- docs/DeveloperGuide.md | 2 +- docs/images/deposit100SeqDiagram.png | Bin 73306 -> 67686 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a92759adbe..1da2bb0da0 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -67,7 +67,7 @@ Given below is a quick overview of main components and how they interact with ea The sequence diagram below shows how components interact with each other when the user issues the command `deposit 100`. - + ### UI-Component diff --git a/docs/images/deposit100SeqDiagram.png b/docs/images/deposit100SeqDiagram.png index 4815797d2668d67f01eb7b2c0566edf3cde5626c..12ef89bc01a11d03edca859332b6a8d708443c3a 100644 GIT binary patch literal 67686 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 Date: Mon, 10 Apr 2023 10:12:29 +0800 Subject: [PATCH 317/368] Add note for seq diagram --- docs/DeveloperGuide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 1da2bb0da0..b909e226b7 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -69,6 +69,8 @@ The sequence diagram below shows how components interact with each other when th +Note: The lifeline of the Transaction class does not end after the cross due to a limitation with PlantUML. + ### UI-Component Class: `Ui.java` From 981143a3aab200cde921560e0d425b33dfb74dcc Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 10:19:15 +0800 Subject: [PATCH 318/368] Modify UG --- docs/UserGuide.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index c9522eac06..3d13265620 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -70,7 +70,7 @@ 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 +delete-transaction : deletes the transaction with the given transaction index exit: quits program and saves ``` @@ -246,10 +246,10 @@ 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 +>>set-wl 100 Withdrawal limit set to $100! ---------------------------- -withdraw 1000 +>>withdraw 1000 Apologies! Your transaction did not go through as it will result in you exceeding your withdrawal limit! Withdrawal limit is currently $100. @@ -265,18 +265,18 @@ Format: `check-wl` Example: ``` -set-wl 100 +>>set-wl 100 Withdrawal limit set to $100! ---------------------------- -check-wl +>>check-wl Withdrawal limit is currently $100 You have withdrawn $0 this month. ---------------------------- -withdraw 50 +>>withdraw 50 Withdrawal successful! You have $9950 remaining! ---------------------------- -check-wl +>>check-wl Withdrawal limit is currently $100. You have withdrawn $50 this month. ``` From bc95782d644bff43c0c603b952ef00d20d70e4fe Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 10:21:50 +0800 Subject: [PATCH 319/368] Fix broken link in aboutUs.md --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 2742158a78..b4ee7e05e0 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,7 @@ Display | Name | Github Profile | Portfolio --------|:-----------:|:---------------------------------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](docs/team/johndoe.md) - | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](docs/team/tyuyang.md) + | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](team/tyuyang.md) ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | N.A. ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | No portfolio>>>>>>> master From 31c9fc3f8bcaf7289ba3fc23ac26d4b20a8f1924 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 11:05:47 +0800 Subject: [PATCH 320/368] Modify PPP --- docs/team/tyuyang.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/team/tyuyang.md b/docs/team/tyuyang.md index 08066ce804..65f89e447d 100644 --- a/docs/team/tyuyang.md +++ b/docs/team/tyuyang.md @@ -10,7 +10,9 @@ Helped create a CLI-based application that acts like a banking app. Users can cr ### Enhancements implemented -Created the withdrawal limit feature. 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 (aside from limit overflow) and works as expected in all tested situations. +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 @@ -25,9 +27,17 @@ Created the puml diagrams for the main architecture and the example sequence dia 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 in the PED were already pointed out 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). +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. +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). From 8c637979194c2decada480e0dd8f254a96ae2b6b Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 11:44:25 +0800 Subject: [PATCH 321/368] Removed image --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index b4ee7e05e0..76f224b1b8 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,7 @@ Display | Name | Github Profile | Portfolio --------|:-----------:|:---------------------------------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](docs/team/johndoe.md) - | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](team/tyuyang.md) +![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](team/tyuyang.md) ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | N.A. ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | No portfolio>>>>>>> master From 672694adc396465f302e2825bb5a897027f22efa Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 12:15:27 +0800 Subject: [PATCH 322/368] Fix bug where add a blank line to the savefile causes undesirable bahaviour --- src/main/java/seedu/bankwithus/parser/Parser.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 273de348d8..299e86f47e 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -220,10 +220,15 @@ public void parseUserInput(String input) throws CommandNotFoundException, IOExce * @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()) { - throw new SaveFileIsEmptyException(); + if (!hasAccounts) { + throw new SaveFileIsEmptyException(); + } else { + throw new CorruptedSaveFileException(); + } } String[] splitDetails = accountDetails.split(";"); try { @@ -252,6 +257,7 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S accountList.addAccount(name, balanceString, totalAmtWithdrawn, LocalDate.parse(lastWithdrawnDate), withdrawalLimit, amtToSave, untilWhen); } + hasAccounts = true; } catch (Exception e) { throw new CorruptedSaveFileException(); } From 18fe653aa91350724e08c9946df00d23d001f97c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 12:33:26 +0800 Subject: [PATCH 323/368] Modify behaviour of adding empty lines to save file --- src/main/java/seedu/bankwithus/parser/Parser.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/bankwithus/parser/Parser.java b/src/main/java/seedu/bankwithus/parser/Parser.java index 299e86f47e..bdb4e7b607 100644 --- a/src/main/java/seedu/bankwithus/parser/Parser.java +++ b/src/main/java/seedu/bankwithus/parser/Parser.java @@ -224,11 +224,7 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S while (scanner.hasNextLine()) { String accountDetails = scanner.nextLine(); if (accountDetails.isBlank()) { - if (!hasAccounts) { - throw new SaveFileIsEmptyException(); - } else { - throw new CorruptedSaveFileException(); - } + continue; } String[] splitDetails = accountDetails.split(";"); try { @@ -261,6 +257,9 @@ public void parseSavedFile(Scanner scanner) throws CorruptedSaveFileException, S } catch (Exception e) { throw new CorruptedSaveFileException(); } + if (!hasAccounts) { + throw new SaveFileIsEmptyException(); + } } scanner.close(); if (accountList.getSize() == 0){ From cca576181f4e7e565d786d952104b3f0af915c58 Mon Sep 17 00:00:00 2001 From: vishnu Date: Mon, 10 Apr 2023 13:19:31 +0800 Subject: [PATCH 324/368] Added overall architecture portion to DG --- docs/DeveloperGuide.md | 54 +++++++++++++++++++++-- docs/UserGuide.md | 1 + src/main/java/seedu/bankwithus/ui/Ui.java | 1 + 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b909e226b7..35fdb80847 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -260,13 +260,13 @@ Note: Withdrawal will be cancelled if it fails to meet withdrawal limit or if us ## Command: `show-save-goal`: -**step 1**: +**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**: +**Step 1**: --> Calls the `switchMainAccount` method from teh AccountList class with the NAME of the account to switch into. @@ -274,12 +274,60 @@ Note: Withdrawal will be cancelled if it fails to meet withdrawal limit or if us ## Command: `delete` -**step 1**: +**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. + +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. + --- diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3d13265620..c101f84abc 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -71,6 +71,7 @@ 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 ``` diff --git a/src/main/java/seedu/bankwithus/ui/Ui.java b/src/main/java/seedu/bankwithus/ui/Ui.java index 38ac2abd6c..2744a3860a 100644 --- a/src/main/java/seedu/bankwithus/ui/Ui.java +++ b/src/main/java/seedu/bankwithus/ui/Ui.java @@ -131,6 +131,7 @@ public void showHelp() { 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(); } From 4e30f83a8f9327c9d5a3682bf89bfbf9084f4a72 Mon Sep 17 00:00:00 2001 From: vishnu Date: Mon, 10 Apr 2023 13:25:15 +0800 Subject: [PATCH 325/368] Modify DG --- docs/DeveloperGuide.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 35fdb80847..987e448ee9 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -9,7 +9,7 @@ * [BankWithUs Component](#bankwithus-component) * [Account Component](#account-component) * [AccountList Component](#accountlist-component) - * [SaveGoal Component](#saveGoal-component) + * [SaveGoal Component](#saveGoal-Component) * [Storage Component](#storage-component) * [Withdrawal Limit Component](#withdraw-limit-checker-Component) * [Transaction Component](#transaction-component) @@ -63,6 +63,8 @@ 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`. @@ -73,6 +75,7 @@ Note: The lifeline of the Transaction class does not end after the cross due to ### UI-Component + Class: `Ui.java` * Contains all code that interfaces directly with the CLI From f63cd6ef97dfc5b2940da210f385d4051124556e Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 13:44:19 +0800 Subject: [PATCH 326/368] Add show-save-goal in UG --- docs/UserGuide.md | 10 +++++++++- docs/team/xiaoge26.md | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3d13265620..81c20f7cd2 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -96,7 +96,7 @@ What is your name? >>Steve How much would you like to add as Balance? >>1000 -Account created! +Account added! Name: Steve Balance: $1000 ---------------------------- @@ -236,6 +236,14 @@ 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*.
diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index d4b3c6be6a..2b33ed9aab 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -32,7 +32,7 @@ deleting, listing, parsing, saving, and loading the transactions.
* Automatically delete all the transactions of a particular account when the user deletes the account ### Contributions to the UG -* Documented the features related `Transaction` and `TransactionList` components in the User Guide
+* Documented the features related `Transaction` and `TransactionList` components, and `show-save-goal` feature in the User Guide
* Fixed typos and bugs in the other sections in UG as well
### Contributions to the DG From e5297326384da95d256031bef5011745828ecc44 Mon Sep 17 00:00:00 2001 From: vishnu Date: Mon, 10 Apr 2023 14:02:11 +0800 Subject: [PATCH 327/368] Change typos in DG and refactored some else after throw --- docs/DeveloperGuide.md | 12 ++++++------ src/main/java/seedu/bankwithus/user/AccountList.java | 12 +++++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 987e448ee9..ec4a1a15a9 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -305,11 +305,11 @@ Note: Withdrawal will be cancelled if it fails to meet withdrawal limit or if us ## 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 +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. +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 @@ -321,14 +321,14 @@ the corresponding method in the AccountList class, which in turn calls the corre 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 +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 +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. --- diff --git a/src/main/java/seedu/bankwithus/user/AccountList.java b/src/main/java/seedu/bankwithus/user/AccountList.java index 6f1b4f800f..099fbccc03 100644 --- a/src/main/java/seedu/bankwithus/user/AccountList.java +++ b/src/main/java/seedu/bankwithus/user/AccountList.java @@ -313,7 +313,6 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept if (withdrawAmountString.trim().isBlank()){ throw new NoValueInputException(); } - BigDecimal amtToDraw = new BigDecimal(withdrawAmountString); if (amtToDraw.compareTo(BigDecimal.ZERO) == -1) { throw new NegativeAmountException(); @@ -321,13 +320,16 @@ public void withdrawMoney(String withdrawAmountString) throws NumberFormatExcept BigDecimal currentBalance = getMainAccount().getAccountBalance(); if (currentBalance.compareTo(amtToDraw) < 0) { throw new InsufficientBalanceException(); - } else if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(amtToDraw)) { + } + if (getMainAccount().getWithdrawalChecker().willExceedWithdrawalLimit(amtToDraw)) { throw new ExceedsWithdrawalLimitException(); - } else if (willFailsSaveGoal(currentBalance, amtToDraw)) { + } + if (isMoreThanTwoDecimalPlaces(withdrawAmountString)) { + throw new MoreThanTwoDecimalPlace(); + } + if (willFailsSaveGoal(currentBalance, amtToDraw)) { ui.failToMeetSaveGoal(); handleProceed(amtToDraw, currentBalance); - } else if (isMoreThanTwoDecimalPlaces(withdrawAmountString)) { - throw new MoreThanTwoDecimalPlace(); } else { getMainAccount().subtractBalance(currentBalance, amtToDraw); if (amtToDraw.compareTo(new BigDecimal("0")) == 0) { From 8f3279d34bc085c779256646cdd36d38307c24d3 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 14:31:42 +0800 Subject: [PATCH 328/368] Add view-current in UG --- docs/UserGuide.md | 52 +++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d948781ca6..33f951cc8e 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -123,7 +123,7 @@ Current Account switched Current Account is: ---------------------------- Name: jenson -Balance: $90 +Balance: $90.00 ---------------------------- ``` @@ -146,7 +146,7 @@ Account: jameson deleted ``` Deletes the jameson account. -### View Accounts : `view-account` +### View all the accounts details: `view-account` Shows a list of all the available accounts with their account name and balance. @@ -157,10 +157,21 @@ Example: >>view-account Current Account: Name: james -Balance: $1000 +Balance: $1000.00 +---------------------------- +Name: john +Balance: $300.00 ---------------------------- +``` + +### View current account details: `view-current` +Shows the details of the current account. +Format: `view-current` +Example: +``` +>>view-current Name: john -Balance: $300 +Balance: $300.00 ---------------------------- ``` @@ -347,19 +358,20 @@ Please keep in mind that this will result in irreversible data loss. ## Command summary -| Action | Format, Examples | -|-------------------------------|----------------------------| -| **Add an Account** | `add-account` | -| **View all Accounts Details** | `view-account` | -| **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 save 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 +| 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 From 003ca3056d468005286c527667347c0662e0917f Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 14:38:37 +0800 Subject: [PATCH 329/368] Fix minor inconsistencies --- docs/UserGuide.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 33f951cc8e..dca66282a7 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -75,7 +75,7 @@ view-current: shows the relevant details of the current account exit: quits program and saves ``` -### Adding an account: `add-account` +### Add 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. @@ -103,7 +103,7 @@ Balance: $1000 ---------------------------- ``` -### Switch current account: `switch-to` +### Switch to another account: `switch-to` Switches from the *current account* to the new requested account, if it exists. @@ -128,7 +128,7 @@ Balance: $90.00 ``` -### Deleting an account : `delete` +### Delete an account: `delete` Format: `delete ACCOUNT_NAME` @@ -146,7 +146,7 @@ Account: jameson deleted ``` Deletes the jameson account. -### View all the accounts details: `view-account` +### View the details of all the accounts: `view-account` Shows a list of all the available accounts with their account name and balance. @@ -164,7 +164,7 @@ Balance: $300.00 ---------------------------- ``` -### View current account details: `view-current` +### View the details of the current account: `view-current` Shows the details of the current account. Format: `view-current` Example: @@ -175,7 +175,7 @@ Balance: $300.00 ---------------------------- ``` -### Depositing amount : `deposit` +### Deposit: `deposit` Deposits AMOUNT into the *current account*. @@ -194,7 +194,7 @@ You have $190.00 remaining! Attempting to do the above cause the program to show error messages. -### Withdraw : `withdraw` +### Withdraw: `withdraw` Withdraws AMOUNT from the users balance. @@ -322,7 +322,7 @@ view-transactions-all 1. Account Name: xixi Transaction Type: withdraw Amount: 234 Date: 04/04/2023 ``` -### Exiting the program : `exit` +### Exit the program : `exit` Exits the program. From 14ddef935baa23d2d8e3d59e7f9ee4b694e6689f Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 10 Apr 2023 16:08:35 +0800 Subject: [PATCH 330/368] Add table of contents for UG Update PPP for Sherlock-YH --- docs/UserGuide.md | 53 ++++++++++++++++++++++++++++++++++------ docs/team/Sherlock-YH.md | 4 +++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3d13265620..21716c74cb 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,17 +1,40 @@ # BankWithUs User Guide -------------------------------------------------------------------------------------------------------------------- - -## Quick start guide +## Table of contents: +* [Quick-start guide](#quick-start) +* [Features](#features) + * [Help message](#help-message) + * [Add new account](#add-account) + * [Switch Account](#switch-current-account--switch-to) + * [Delete Account](#deleting-an-account--delete) + * [View Account](#view-accounts--view-account) + * [Deposit](#depositing-amount--deposit) + * [Withdraw](#withdraw--withdraw) + * [Transaction History](#list-all-transactions--view-transactions-all) + * [Save Goal](#add-a-savings-goal-to-the-current-account--set-save-goal) + * [Withdraw Limit](#set-a-withdrawal-limit--set-wl) + * [Check Withdraw Limit](#check-the-current-withdrawal-limit--check-wl) + * [Delete Transaction History](#delete-a-transaction-record--delete-transaction) + * [Exiting the program](#exiting-the-program--exit) +* [Frequently Asked Questions (FAQ)](#FAQ) +* [Command Summary](#command-summary) +--- + +## Quick-start guide 1. Ensure you have Java `11` or above installed in your Computer. + 2. Download the latest `BankWithUs.jar` 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 your BankWithUs app. + 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.
+ 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: @@ -25,11 +48,16 @@ * `exit` : Exits the application. -1. Refer to the [Features](#features) below for details of each command. +6. For first-time user the program will ask you to create one account when launched. + + +7. Refer to the [Features](#features) below for details of each command. + -------------------------------------------------------------------------------------------------------------------- -## Features + +## Features
@@ -38,17 +66,25 @@ * 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` +### Viewing help : `help` + Shows a list of all the commands available and what they do. @@ -74,7 +110,7 @@ delete-transaction : deletes the transaction with the given t exit: quits program and saves ``` -### Adding an account: `add-account` +### 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. @@ -329,11 +365,14 @@ Please keep in mind that this will result in irreversible data loss. -------------------------------------------------------------------------------------------------------------------- -## FAQ +## 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 diff --git a/docs/team/Sherlock-YH.md b/docs/team/Sherlock-YH.md index 6df2c96b7b..76c1db6b3a 100644 --- a/docs/team/Sherlock-YH.md +++ b/docs/team/Sherlock-YH.md @@ -30,6 +30,10 @@ Users can create accounts, deposit money, withdraw money, set save goal, set wit * 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 From 591e6214014c55e59d4f1f9c40d0ef5a746e6397 Mon Sep 17 00:00:00 2001 From: vishnu Date: Mon, 10 Apr 2023 16:59:48 +0800 Subject: [PATCH 331/368] Add Table of contents for implementation section of the DG --- docs/DeveloperGuide.md | 102 ++++++++++++++++++++++------------------ docs/team/vishnuvk47.md | 6 +-- 2 files changed, 60 insertions(+), 48 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ec4a1a15a9..822fcb8f68 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,19 +2,31 @@ * [Acknowledgements](#acknowledgements) * [Setting Up, Getting Started](#setting-up-getting-started) -* [Design & Implementation](#design-and-implementation) +* [Design](#design-and-implementation) * [Architecture](#architecture) - * [UI Component](#UI-Component) + * [UI Component](#ui-component) * [Parser Component](#parser-component) * [BankWithUs Component](#bankwithus-component) * [Account Component](#account-component) * [AccountList Component](#accountlist-component) - * [SaveGoal Component](#saveGoal-Component) + * [SaveGoal Component](#savegoal-component) * [Storage Component](#storage-component) - * [Withdrawal Limit Component](#withdraw-limit-checker-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) @@ -154,154 +166,154 @@ that contains the various different transactions that the user has ## 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 +* 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. +* Calls `getAllAccountDetails()` method from the AccountList class. ---> The `getAllAccountDetails()` method parses the `ArrayList` from the AccountLits 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 `;` +* 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 +* This string is then passed to the `viewAccount()` class in UI, where the string is decoded and print to screen ---> Identifies attributes that belong to a particular user by splitting the string based on a new line +* 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 +* 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 +* Checks the args(AMOUNT to withdraw) for a negative sign in the `checkNegative()` method **Step 2**: ---> Calls the `withdrawMoney` method in the AccountList class +* 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 +* 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 +* 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 +* 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 +* 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 +* 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 +* 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 ## Command: `add-account`: **Step 1**: ---> Calls the `createNewAccount` method in AccountList class +* 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 `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 +* 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 +* 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 +* 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 +* Checks the args(AMOUNT to deposit) for a negative sign in the `checkNegative()` method **Step 2**: ---> Calls the `depositMoney` method in the AccountList class +* Calls the `depositMoney` method in the AccountList class ---> Checks if the AMOUNT entered is empty, number of decimal places(accepts only 2 d.p) +* 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 +* 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 +* 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 +* 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 +* 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 +* 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 +* 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 +* 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. +* 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 +* 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 +* 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 +* 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 +* 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 +* 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 `checkWithdrawalLimit` method in AccountList class ---> Calls the getter method which then returns the Withdrawal limit +* 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 +* 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 diff --git a/docs/team/vishnuvk47.md b/docs/team/vishnuvk47.md index 4aaf453739..e6bccf6f5f 100644 --- a/docs/team/vishnuvk47.md +++ b/docs/team/vishnuvk47.md @@ -27,12 +27,12 @@ Created a User Guide for the BankWithUs software/application, which included a r ### DG contributions -Templated the layout, wrote documentation for functionalities of the program for the DG.[#73](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/73) +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) ### 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 +* 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) @@ -49,6 +49,6 @@ Templated the layout, wrote documentation for functionalities of the program for #### Contributions beyond the project team -* [reported 14 bugs during the PE-D](https://github.com/vishnuvk47/ped/issues) +* [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 From 0f20d83ff13dd313a783a7c118630dc56bd7cfc9 Mon Sep 17 00:00:00 2001 From: vishnu Date: Mon, 10 Apr 2023 17:12:49 +0800 Subject: [PATCH 332/368] Add portfolio links in AboutMe.md --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 76f224b1b8..93e6a519e0 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:-----------:|:---------------------------------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](team/tyuyang.md) -![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | N.A. -![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | No portfolio>>>>>>> master +| Display | Name | Github Profile | Portfolio | +|------------------------------------------------------|:-----------:|:----------------------------------------:|:-------------------------------------:| +| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](docs/team/manushridiv.md) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](team/tyuyang.md) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](docs/team/xiaoge26.md) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/vishnuvk47.md) | +| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](docs/team/Sherlock-YH.md) | \ No newline at end of file From c0962cab8bb1be0505c0037881d1893518a662c1 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 18:17:49 +0800 Subject: [PATCH 333/368] Add new seq diagram for withdraw command --- docs/DeveloperGuide.md | 6 +++ docs/diagrams/withdraw_seq_diagram.puml | 49 ++++++++++++++++++++++++ docs/images/WithdrawFunction.png | Bin 0 -> 38408 bytes 3 files changed, 55 insertions(+) create mode 100644 docs/diagrams/withdraw_seq_diagram.puml create mode 100644 docs/images/WithdrawFunction.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 822fcb8f68..df8d1f0d63 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -219,6 +219,12 @@ Note: Withdrawal will be cancelled if it fails to meet withdrawal limit or if us * 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 +**Sequence Diagram** + + + +Note: Many details especially from the SaveGoal and WithdrawalChecker classes have been omitted for brevity. + ## Command: `add-account`: **Step 1**: 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/WithdrawFunction.png b/docs/images/WithdrawFunction.png new file mode 100644 index 0000000000000000000000000000000000000000..e599f966c30f4ad409beed09474eb8022f1b23cb GIT binary patch literal 38408 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°Q?pSEau?(Y%lZe0@v01rq=!VdjI^b5WBU5_6$QCW%bww2RF{=G$)n)yi?=a zZ4jXYkLo z+9L2oYO3MQ8}p8agfmBtGlQ>jith4w=B(=u0c)0?FJR+sYc(pTo~WjR$1_9sH8y$* zst3AxRjMn=C(AFcsS4kJw9j>uN*rBj%0r85P#Ik*TU)LW>G`j9XwJBab+EnY@kr98 z+opJ6d)ea!KA{!?@_}>PkU1qdRI9vL9pS2KTg3+JOVQx)Y-~#-R)?FiI|8%Hgxu7iP{#%8K4S_3XGV?gTST#g43(LsX$}PQK zW6GtHsJaR+=?J%OWHIfzmb1~=KaroBJ44fM4N7$=&^|I{)E4!RbRY9Gs)JQnL;W4SY3S1^8 z;rqtQ6)`gg_bW_l1_ggO2LSVf7LTsTX=64P0ekeNYh7lKgMk)d!ov1R-{(+QYc8|(U`YVCiem*Zzc_RJoe=>I=`*>>A{nGm);(| zqu)3)Y?e6ragp${3a`UlDjnhn2=`p-p|*99rdm|Z=y(w~@t(55W}ywd7Z_cG8barD z8qOY)7Q%^8UNijL@AGXOi4u>?)I>)WQ%}9!HvlQr-(8XHiJy6Q{IgIL_tDNnu_rAYgFYDcoMtDx;uUO8h`bHIL$AZ&o_ zm;6aKr0|&nOZ0*RF^(gkM3L z{KDsiS3$L_RO4Rq!D6;UFGyyLtE-N^FWJu4K_@#hkb+pil4V2Kal^$Hx(6PYgtN3C z4zse1MC@ZsXY%=ufm&f%`2Heq@6aNN1d+1y6)U_XGJg@LKP$Df;Qtvi>=0D^AL1n> zt*foBp4GZfc&31*J0)cV#MQ1Y;j-+x^h0-*D^7U{14lpO*6!vH|Nq2PHj+iw(_<}7 znLED5>puvH+44WcabJnB6Wx0>!qul3_41u2b6(8GuAf**WtC20Yh6eT;sq*Emul_X zpYwE^U#l~ZZN7H|tKzGH2u)10Cv4U3AtC~vnrN(!Z#p%k_k|x6{{3t1I{P4{@!3O% z_ieD#h!w+5;emJyqbB0^YEcEImcM^l;c0wXXOvaRqSM7i<#|F6fPaI&bN537B|+m& z==WFyusBA;m_2Nn>F(1WXB`d6i%EY~Ex+)eOS;)~AJhKwMRZxkh;UaQ;ci@d!# Date: Mon, 10 Apr 2023 18:19:54 +0800 Subject: [PATCH 334/368] Adjusted size of second diagram --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index df8d1f0d63..c3102a9a9f 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -81,7 +81,7 @@ For a quick link to a summary refer to: [Summary of overall architecture](#summa 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. From f7ee9718592da10f8651c1d37b789939bb94f53c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 18:44:06 +0800 Subject: [PATCH 335/368] Add fail wl case for withdraw --- docs/DeveloperGuide.md | 8 +++++++- docs/diagrams/exceed_wl_seq_diagram.puml | 21 +++++++++++++++++++++ docs/images/ExceedWLCase.png | Bin 0 -> 18058 bytes 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 docs/diagrams/exceed_wl_seq_diagram.puml create mode 100644 docs/images/ExceedWLCase.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index c3102a9a9f..e6b001044b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -221,9 +221,15 @@ Note: Withdrawal will be cancelled if it fails to meet withdrawal limit or if us **Sequence Diagram** +General sequence diagram + -Note: Many details especially from the SaveGoal and WithdrawalChecker classes have been omitted for brevity. +*Note: Many details especially from the SaveGoal and WithdrawalChecker classes have been omitted for brevity.* + +Exceed withdrawal limit case + + ## Command: `add-account`: 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/images/ExceedWLCase.png b/docs/images/ExceedWLCase.png new file mode 100644 index 0000000000000000000000000000000000000000..693bb5e72d5b17bc2dbc39d297f489c997318504 GIT binary patch literal 18058 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 Date: Mon, 10 Apr 2023 19:18:28 +0800 Subject: [PATCH 336/368] Correct a grammar mistake in PPP --- docs/team/xiaoge26.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index 2b33ed9aab..e8a8f70b04 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -32,7 +32,7 @@ deleting, listing, parsing, saving, and loading the transactions.
* Automatically delete all the transactions of a particular account when the user deletes the account ### Contributions to the UG -* Documented the features related `Transaction` and `TransactionList` components, and `show-save-goal` feature in the User Guide
+* 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 From a5d771ff1bed33c483cfa1a8c00fbbbdb24e4a9d Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 19:23:51 +0800 Subject: [PATCH 337/368] Add seq diagram for fail save goal case --- docs/DeveloperGuide.md | 4 ++ .../fail_save_goal_case_seq_diagram.puml | 46 ++++++++++++++++++ docs/images/FailSaveGoalCase.png | Bin 0 -> 38046 bytes 3 files changed, 50 insertions(+) create mode 100644 docs/diagrams/fail_save_goal_case_seq_diagram.puml create mode 100644 docs/images/FailSaveGoalCase.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index e6b001044b..5141eaa64a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -231,6 +231,10 @@ Exceed withdrawal limit case +Fail save goal case + + + ## Command: `add-account`: **Step 1**: 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/images/FailSaveGoalCase.png b/docs/images/FailSaveGoalCase.png new file mode 100644 index 0000000000000000000000000000000000000000..f2726d8901e26bc1b6b5402f1bd74a616bfc9b02 GIT binary patch literal 38046 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 ao|EZ#Bz literal 0 HcmV?d00001 From a3519701c9efd26817a405cac173eaa93b778123 Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 19:31:40 +0800 Subject: [PATCH 338/368] Edited PPP --- docs/team/tyuyang.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/team/tyuyang.md b/docs/team/tyuyang.md index 65f89e447d..0c104cd7ed 100644 --- a/docs/team/tyuyang.md +++ b/docs/team/tyuyang.md @@ -20,7 +20,7 @@ Authored the withdrawal limit section. Worked with [vishnuvk47](https://github.c ### DG contributions -Created the puml diagrams for the main architecture and the example sequence diagram. +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 From 2dc485841adb0a29bf477288bd5e7fc4a3ae7770 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:34:02 +0800 Subject: [PATCH 339/368] Change all local links in docs to weblinks --- docs/AboutUs.md | 14 +++++++------- docs/DeveloperGuide.md | 4 ++-- docs/README.md | 14 +++++++++++++- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 93e6a519e0..08f00fd3ff 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -| Display | Name | Github Profile | Portfolio | -|------------------------------------------------------|:-----------:|:----------------------------------------:|:-------------------------------------:| -| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](docs/team/manushridiv.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](team/tyuyang.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](docs/team/xiaoge26.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/vishnuvk47.md) | -| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](docs/team/Sherlock-YH.md) | \ No newline at end of file +| Display | Name | Github Profile | Portfolio | +|------------------------------------------------------|:-----------:|:----------------------------------------:|:---------------------------------------------------------------------------:| +| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/manushridiv.md) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/tyuyang.md) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/xiaoge26.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/vishnuvk47.md) | +| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/Sherlock-YH.md) | \ No newline at end of file diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index e6b001044b..a9c91fe686 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -418,11 +418,11 @@ Windows: Command Prompt
## Instructions for manual testing ### Launch 1. Ensure you have Java 11 installed in your Computer -2. Download the latest release `BankWithUs.jar` from here +2. Download the latest release `BankWithUs.jar` 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 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 -Please refer to the Features section in our [UserGuide](UserGuide.md) for more details on the test cases +Please refer to the Features section in our [UserGuide](https://ay2223s2-cs2113-t13-3.github.io/tp/UserGuide.html) for more details on the test cases that you can try out. \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index cc4c86a239..04b6c7fbd0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,18 @@ # 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) From 0164b00e289d59e741419a98c9f0c14f8fa8f2da Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:35:41 +0800 Subject: [PATCH 340/368] Fix typos --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 08f00fd3ff..966adde0f0 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -| Display | Name | Github Profile | Portfolio | -|------------------------------------------------------|:-----------:|:----------------------------------------:|:---------------------------------------------------------------------------:| -| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/manushridiv.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/tyuyang.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/xiaoge26.html) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/vishnuvk47.md) | -| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/Sherlock-YH.md) | \ No newline at end of file +| Display | Name | Github Profile | Portfolio | +|------------------------------------------------------|:-----------:|:----------------------------------------:|:-----------------------------------------------------------------------------:| +| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/manushridiv.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/tyuyang.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Liu Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/xiaoge26.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/vishnuvk47.html) | +| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/Sherlock-YH.html) | \ No newline at end of file From b3a1116a6f076191deafe47e8337d21dc85326f8 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:46:53 +0800 Subject: [PATCH 341/368] Undo an unnecessary change --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a9c91fe686..f2f4d2d92a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -424,5 +424,5 @@ Windows: Command Prompt
command to run the application. A CLI should appear in a few seconds ### Sample Test Cases -Please refer to the Features section in our [UserGuide](https://ay2223s2-cs2113-t13-3.github.io/tp/UserGuide.html) for more details on the test cases +Please refer to the Features section in our [UserGuide](UserGuide.md) for more details on the test cases that you can try out. \ No newline at end of file From 6efc33e112a9e6adeef2a39c6f2759f59b14efb5 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:50:53 +0800 Subject: [PATCH 342/368] Delete redundant lines --- docs/team/xiaoge26.md | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index e8a8f70b04..c5471c7add 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -64,17 +64,5 @@ deleting, listing, parsing, saving, and loading the transactions.
### Contributions beyond the project team -* Reported bugs and suggestions to other teams: -[#142](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/142) -[#139](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/139) -[#133](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/133) -[#129](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/129) -[#126](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/126) -[#117](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/117) -[#116](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/116) -[#101](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/101) -[#104](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/104) -[#107](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/107) -[#142](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/142) -[#95](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/95) +* [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) From 4d0dabe8e96e721ac4a9b4669c8aad3f57267214 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:58:44 +0800 Subject: [PATCH 343/368] Delete extra lines --- docs/team/xiaoge26.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index c5471c7add..25d8d354ac 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -53,14 +53,16 @@ deleting, listing, parsing, saving, and loading the transactions.
### Review/mentoring contributions #### Links to PRs reviewed -* [add NoValueInput exception #156](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/156) -* [Update show help #98](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/98) -* [Add main architecture and example seq diagram to dev guide #100](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/100) -* [Branch withdrawal limit #71](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/71) -* [Create withdrawal checker class #67](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/67) -* [Change the attribute balance to String type #58](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/58) -* [add Account class #24](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/24) -* [Wrote PPP for myself #158](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/158) +[#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 From d0053ae9fb781b39548d9fe5a1f0577d0c30afdb Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 20:01:25 +0800 Subject: [PATCH 344/368] Fix format error for PPP --- docs/team/xiaoge26.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index 25d8d354ac..30a4979912 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -29,7 +29,8 @@ deleting, listing, parsing, saving, and loading the transactions.
* 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 + * 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
From 73448480e1930e9c0f0a167109dab3f3acd00850 Mon Sep 17 00:00:00 2001 From: vishnu Date: Mon, 10 Apr 2023 20:03:22 +0800 Subject: [PATCH 345/368] Make and add UML diagrams --- docs/DeveloperGuide.md | 6 +++++ docs/diagrams/BWU_class.puml | 21 ++++++++++++++++++ docs/diagrams/Parser_classdiag.puml | 14 ++++++++++++ docs/diagrams/account_class.puml | 20 +++++++++++++++++ docs/images/UML_CLASS_DIAGS/ACCOUNT_CLASS.png | Bin 0 -> 185184 bytes docs/images/UML_CLASS_DIAGS/BWU_CLASS.png | Bin 0 -> 105919 bytes docs/images/UML_CLASS_DIAGS/PARSER_CLASS.png | Bin 0 -> 76949 bytes 7 files changed, 61 insertions(+) create mode 100644 docs/diagrams/BWU_class.puml create mode 100644 docs/diagrams/Parser_classdiag.puml create mode 100644 docs/diagrams/account_class.puml create mode 100644 docs/images/UML_CLASS_DIAGS/ACCOUNT_CLASS.png create mode 100644 docs/images/UML_CLASS_DIAGS/BWU_CLASS.png create mode 100644 docs/images/UML_CLASS_DIAGS/PARSER_CLASS.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index e6b001044b..ada6f59bb6 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -95,11 +95,15 @@ Class: `Ui.java` ### 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 @@ -119,6 +123,8 @@ different accounts that the user has ### BankWithUs-Component Class: `BankWithUs.java` + + The `BankWithUs` component: * The Main Class 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/images/UML_CLASS_DIAGS/ACCOUNT_CLASS.png b/docs/images/UML_CLASS_DIAGS/ACCOUNT_CLASS.png new file mode 100644 index 0000000000000000000000000000000000000000..9a63630d73f3b2f993eb6da6a6373cee05070282 GIT binary patch literal 185184 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
pZMIw}aa0C$5E3#Yh zz`0uCnbt4ACd6Sdqp>Za4+X=N^&?Lu?ic^g%#|f6PwG{ENUTju5wmCSs_jDX!rlb5 z0={8OF(onQchY+g3A1Epj)kY6H#!r4GW49oKVCjJTdS4u@Yfy0a?~JXO??W%LRI3& znfsKSJ7;35+>>3xN$d|x=FOY5<0+9H670!_a9^oT(=!e{M%B5qEaVU78HY9%3%?W_ z?6p9jY3sS;Iix6=f*eMb{+rw=pe4|B5k`Nb;WJAV;`mlYlih-?qWgsOKMrGULHztDKUTJUK)^W&HAq3lqjciTRxFJ-qWO| zg=J5>5Qnpmk8z(j#p+9Ay_KTS19=flTd6jljJ@`_InBp*;A{Pe|O#}71Lg}Dm)$lEeLqot@fPuaN-y5;pP@PJL$wXHkH~t+ZLn)FLEm{RKEnCmujhXcN>n20Kp+e(%ZL8|kDnpB zr|<~iEt4H#=R(>in|-`M!+)=-uuDD+{-`TU~T3H@_4{d8rs z#*&uoHwks?iClO9+PMn1@rHjXi)gM#{@-l+nzz7U-2*dAijq;-{;YnhX z0nW~EBnq&m!EV5{7Dm<>~23uAbDVL1*gTOIk70OKEU95aT>im zY0U*uJmznXR$E#Cn3Y*t$+R;=8a9$<^3zlCtdgW`otmj%pg)~Aor`!El(;5K6&3&z zj0RdO_btZ(CURnNQ9%(zCQX77!;-PNoAe$qWkt7S#QnUbFZX_9+3H@%&QtS{ov)d3 zzrShxB{<;rT>!XV8yfwy*ZyZm8HZSwb{_792ISeJyc4;Ur`A@7o=1aVsXjtZbH4A` zhY+BxR2UR0kpj@#CMmgsXLd(zXxsZ`cAtLZL1$)IY$O67&gseC^du0hIH0l0C)>9y zFAul)Js1H(H@zD#IKbZ_o+&{<*1n&Gl>f5tI0392Bg$K@Hlfwaq_c@B!&0nudRJd z0dmh@2eEx2MKtPNgr4ZVdou$pVS}azd!eKe3K9 z@6`g~5*C2!Am#7$PJj$E)I3AvfFJKxEEO$|_z38=lXLIm-l|8DFHuPd|9{e=|K~3| zBw!$Uj;uP(J%h1sYhiG&Gy&>m%`W#4hnQo1zAKtyQN8i}2z*S|cZ;`yKC-|wEUIKD zb6W2KEWG=U#*fMtq61M{LWSv*!^XUmk~@lD$R8XUMMyDT&HM>4HNQmpUjkf{AD^bd z3l16pFY$5;l5#`}#W4>(*$KI^SXBhask1TF>N1KCb>lktzRE8}s}q3(?@Z|*);HEH zOYek3WPJK4soB!~*^Jt@rX;&Agb%M(!{BDrfm7FUd9r;^YuL}SJ6thh0UoSbg%6Cd ze3adH_dcy;{KmUBN$myw;p?TpzQj8Q5+0_d<}UC^X`rK}>i&vgzUL=ZoWSn>%)HT~ zNMX6E%ji}YGneVopvt7q>x39FH)+YPD}Ml0wr}>_6>+!$;2>JRBRlL{@RsPOAJ@*+ zDeoUml$&SS13_zzV569V>0h=UR{R;*Fcs)>FH>g4~9qaJbQvW6gtTw(#=Mkq$I9=`F>Ot>9cgprjJ3lPCEJM->I$lHhAOKR~snl<)? zJcBz7&uX##LMekyZ)ylzcSl&Yx$cK|-rv?udLk({4D4FFN|EdT18fo|H&UO|MNJ29 z>D^08uj|I0{LoreOGxj*iEHv`Ile5!N!5LO0G5qgj6Z1!R!BC0s~Ehbi>e1y zUGXDX_y8cQ?_ve9OxDm8Ym_Cx!>W0A7t91fomNuBm(mEo7@4;^n&x7up_2 zAlFqmeR+9GfIh2e{`Jb@P0Dvt6w{H5)8}Vl2HN@GH%2;vpc~96H$(&@(i(GM<>2sg zHysDG;{?g6SF+cy$b0wbJiBZ1P7QEqZa?vN6rBD7->5C%9?RxKlTwfFDWn_>YYh5K zTD=+OndidtpIkodm-Ne0$F0~YW@{;$Yx^X!%epTY^5SzB$7>$ftrY%5v6WGP>KMu7Ae%kLiKD()?+CEZq+>&&Ac7p{G zwKZ^Y`c7+{KmU8p6&Hf=mIyK581pom`_oP+c%8TL$*i%~82oVAt*{Z=7pbxdpxmPQ z5h5S3`6IZ+3)p_vr~PnO9j5U3y$fDX`YHM)=OKe89D-b2cb0cZ5?Z@fK;dQ^;D!sh zj$9W$@uDT~T?sw*oYrVSAGMWUlmEe_)J>qBSKqHb-1?9`~1 z(;L_C1R3F-4@sM-NLntX37BhE3SUmp^~GmTT1UHfrBrj|8${o3r~ZKzvW=nK3cy{W zslK4zJ#RuabVW7eNEJdnE`p({IOT^|K;1WMuY8B(z8EgK$rcU2c+w>-qZ8220)q^L zOg~we1m`;%=y^{`sqRVOxfxBt`gc*wQu*0s)LtOmda1jy)a=x{^fEUP%9D%Gc=<)> zQZ;u13n{BHgKowcR8*o;fL0a#N98A@SQBY#03Lm#xp+w6gqH~aSq@`N9k0uo!C+VI z?_^+djj~OxK2wBQNRvykMJ9W!0Fd4~X3|#lzGZajZrAz#cR;^9&;vG+_CjKr0m%4z zK=fbjp{kDdN)faII9EeJ>7bZ=wx_|34`6&F!G02p*0S#s}g<@fq&o00~H>+RbFos;X4Yw_wd za@~_atSuedwKzBJ84q*X=vt$l-v>HOzS*70ib7&`SN{Q^w?D`@C^hXN%~e1i%bH&s zrDw(5AF1F!JTc!CFM;lElgMnTpidrbuz5Yrw$*0kh|0b7HJDnhxdYo+|DPD-o4>Z` z@hVS&q<-W@-W#FR-ngp&KIVEk!t1r0| z_TB20x_(<_m#9W$;2iHn2y}BX%+jUOU4%mDruR{pTJ&Hrxf6jk?G@6S0}v?qA?&*> z1_&SUh(#scls%ifVP{Df;uv-R2{IN*rNfZw7Ai1NCG4hTsvLSWJ{|1rqfo%Lr?-uJ z;Jj|_AvOdzcbfrIGdOFwvT+XjcIf?Wenwnn zmzO=dHncnt6xZQ;sT<4Oxa`KxEPBI%EVwt+E%D})E|epf^GA4oBwtUQF^OozVQedY zlRU%vG{d5NYJ?hb59NLb4yw)o+Y!2pgnrX`fuU6US;_dv?~ll5CA7~p*es_lx=yiU zG?C}Jjg3{=!jhXXDN*djg`eqWJzqVRQ@h&9E)#ONO+QF&E!`t&ub3GeWh?}!JY{0M zP)ext>Hl9NXy#7Nb zA5Mt}XNsNf7TCvwl%BM!%bRycN!fOPIPc?+!W{hywg4>^P>eVdsd2fVsJPy7?vZq2 zGGEKZ0S=_q`ZB}QB=tM4!3JI{@wCL=`mIp5JPC~VyqTu3=fgNo-9>(8oYm#_TfFF= z?)v|nmGVz6>0u^?PBxkfB?hWFs-gI9e26IHISYN44!Mh6LO<=J{mB;(Q`uC%u6#-# zf~RdbKEq|!CfITS9V3L`t;ykM$)vGT(6`JXy#aHM&N@vA`_T{`cxu15^9x?#IvxGAZx!a@o&9+UJrBrfnKC{Z- z2nLOViI5eF2ENQacS`b=EfXguBsn_0-$E!bkbcql-{{!pPkiWHmadIqCVuP2G7u59 zMGp&i>1lcl90aI^9Fw@u{nrr_5qJ}^P`b7II^8cc9>V?CC*T6bF?L954xeGe?1Ql0 z$Wez750UQ65p46mjsP2%sekFhdiUyuuffNCts|K9RgfJr%^A0(I0y+XH-9q#%uuw2z$H{)O*C~- z^gm4#icjVnCnw_w=U6)?(PN9|6$yUlGx)+cm&Ge4l!>vDK$|SlIJHePtIptLp*+v-oq6{ znRAO3+S}^oF{YxsaJSp9(yq8ekT;mt>*DG3XV9({hJb8m4q+D2_=Trl+#Oqg&X7Cn z%&xKv9dvR0^dGZ6o+hJ=7CX%Ke4Yfx9tSeJAi8mW@`Im9$}aBEo@O+t3n=N7*&)DS zCO+bC&#KT?D?T-CyT{!J0YH4q+rHo@yrF8UV^en&`4z{Jb|$x5>PP+>4R8Y}W@e!+`h;oC?9@II3{7BKLBR(;>R4IezK6_`g&XIhfxf;WM$bF=Wg z(9w#35uOrRFOkb(CprV4F`M2*xRuDG2g-X^>Q-;&wu0PnY{4IF_aOk~P6MXY$>W*$LB0RqCxKDDH6 zSZdYo)Q3sI#qpb6UP$;%XAw}z_d;i(eHNrI58&8eI5^2NWE}DDS*Eme4~R8h+D#5xv7dXV=8MgwPM+;Qf5q6L6jqJNiLj zX=04;Kf_cvrAZ`J4%+-tFWy9xTU!DfsoSUr#)K#Rw1X&rdex`f#A*$uEp;X3#b{#; zH|MDdr>29c*+1~enAA(5NSe@P*&=yiwtB!brUawNqB~!UbH~P`6(hJ%O`qxZp;_Ya zuQ3ri5{>4uE1-ZtslhMmxImmBACVC5`3Oy0LFL0V%cp3wTv{X#cLmHkWs`B^j1B9? zSbX!F374$I@4I$KJRiSyKa(=%lOL(P*N*z-a9CgBn!$Q44)5@`j`{CCKGEgG zRNzycQ_U5Wgx~vucA4gK{2iwRAx`AVeN^d7yI>6Bx85_}OXPn%sE{DcH<;S3g_+}F z;~frmf7*qI5miM02I0=!roLm0Fk^nefVu;p*X>yr39YOzCKFn)-@fe}Pr9PM4$vIk zx8z>8#w-T6M@88%4c=;?g7^Et6SH-U`SXp+N;_@qI66c7x4PWGCRYq;8 z%Z1-D!@=jw@+?!$a)$lh&-H#>R|EwbHfi55-_dkHb=xHsO7T$+Q-W*%42&FI0wzb| zdA(APx;2Mky!?GtYU?vv4^YyNSn!w}-a~1SosAzR!$q&p&L6;E2CYA z>BX(!Zy?ZV1DU_yVP2{WTzj3(%^4f-Sy*HP8Nypcvv%TQc92iF)!yTeWuu`C$Z|cF z@+_WbCM|V?z}>L%ST4RQ`k7YxgFFe@<>=jvHcl;iuQJGZGT#*WzWdqUiIWm=ULV%A$Mi=Kv>w^R+!vJo2x= z1luPPqV}NE%GC@sFPKkvDnnm9Djp4(13$1n!x|_Q6@OdMYW`ZqEnHJ_sPJLHWj~2` zGqM#OaNzqj=2x}jBDfv1ykM%Q<1=WnpdhMWq|c}@w9K+xPX1)4@ORqYEfaON>K0NI zZ(JGX2Za0i}+n4;i>u>xEVbvYd%D!o1?jX`Gk#!_f57k%k}1iWRLQqwqu7Wr)S z0?s>^;|{34x$rUPb!uG0y-AtqH|`~>qx55|?C(_r=9d#AuOXmr0fd4zWIpi7o#oa} zrukhF<pGZsp2t`uThlVQ`37ElF z7V$%#UsAb-m*s@9%1cO;$f|7J&E&*eywNKrFTV*TDxgy6^>X?!r>Mu>sf5S{d8O%- zjI;0ZJWF&wwQANOtn>X8m@odwkeFJ%P()pv!Be|-9^XTF61_rqwcJ=-%`b0rax7}i zxW-OQGz}zNat_EkU)|DuL1LS+n^rwXv1`IXTy#tcUl^G$5nOA zfVZOsB*)8cuW`bypw?Xkx@}grxobA+^hz8v^2Vulrxbbf1MduKB3mOknp^uYm*C^#l3ymx`_LepGcyZqC>xFn^%qL{$yHt z{)$d4mWINqfTE4~SHD1Vg31d9T&V_TCd2l)S1(ovo6xykYGvLX39`zfawP;~55hQ8 zBGNOofk!}dk=F>K?rI5S=CtNsS7Nk#cQPkaq+QIW^%#BwzIh*W z3GyZ5WloS9cWgPhZ3pty>2J6{CGBIV``J-f=Fbyb!RYCrSFf81^%QJ|FNcLS^B`Z` z8K9q%PWf(|zA_)n-FJl+Ii0|BU{z3Iz#b*tk3c@YMFGW|fV5GgK_eo&`h@Ba!Pig! zN#?_5jP2drIEyEvCq+t zR$PD->h?FnNb>70UOI}+{G=Mb(*HHsMYXsdiB!L@#z8Nwy8nnec{$vy5m; zDY|(acWmIXe~4TE@Tul3I(l6dGrZnrX)X#(V!bACBTwu*I)#IQ=Zfc8CH5;iLG9Gy zULdN|k|0T;&$KHtbD|d7%B~kI;~>!H7a+4wLzUpizXru8^@31$cj6cwZYAUvo2q=U z?2Mw#5MlP<(p?dt)L#8_jt1FL$h>;oXK#CFHmD;${g`AtdtL37Q2$|<75G~mw{)#q zFGJs?!Q0B)LCn|}!^3l3PES%9zQ>O(?uOW`{I?wJA37w<&v%i$+k+4>zF&4O?5nkb zF|J2|xVRPi7!;C!Kn@8jESf81g>rXYu_@yc6ONSjFADiAn&JUDkE6UI<7yI02KJua8I1Y6d!xqeH6AS|`5peAFjwXc38cUE?LM74dL|z~@n zbJ6J4jNtQ;FU^L!dce8O^3guz=0xJ!WO>NNdDBtfcP@iI&2E-+%Jev|TSxj<;OX=Lu^dp($U zO;3yrMh4B0x$?*%Lm3RZ_}UP8h#OH(*=hP#aGotnt!Rstw8LHpc59xL9F{e%dF9Ta zXd2ENIEr~zRh&i%>ORkVS;IvOt{$9*%pE>ec_HzR{WtED@=S&S7YWEF6Zs&N#=L!2 z_;vG-?jq|T&tRAMP9nr}5`#xN>*dRTZC@C5pi$$`_f8E}9y_7`Ft7z>BlaF$7|Ibx zW%0dz6Z6eZ?>lE~dq4G5Z4-xa=WiV|@Dy-rvO4G-6?nThL=siJuiF@6BEzMoGt+si z%Pu3s))N;_l5J7dY31ZPUUX=AkqPjF{nh6c7W}XM?rbt+Hp@~{jI*8u_OQ%Y$j24h zq*m))j7#Htn2r9SR(4Z$%&7Ds4S|jUdV_~;haa4ilP)I>ZAA^xTVXm>4vn3|=)>$% zzGUM=g>M7o51bvh++Fj6NyI>vZQ(q*13A;9ZV)Pw`v8>V8r zhUWI+?U%+C7sxQeo+xE9DZ@4sqis9D>62f;md8BqM(eeZd`CYCr(k5kskssRmY;9?kK{gGP2-+y5B;P2 zYR$rFvJU{On=EZeru7d;622n6yl4c?R@vrV)cNxq<}+NycJrK3l4n!i4%bhC@RX2l zX*K>q2giQlAQ@5sXbB~!8MvC&TtA#fL=TPWY}4kyOPV>8gaCwcdAYUrToNZ_o9hK| zJnQ94=Huqy0e&@)cNeG~&bEzIyH1}RD~GwrY6(ugjm#lmQi~~l`=2LCDo^QfU59nd z8%(szd?9h|8Rnc8xZ$Z7Sro~ z;Qr{Ei^vMqaO1rH=1cezoS~r1G+GsgrE<2Z=rO4P$JRjtf}Jo);fedgX1ufs{89W}-$u zdZJ_zb#?d zF^{Xb3=Bk&ih8Pj;IieiUko^~TJnk279`Cw+OGLc2}3>}mVkEULiC-W@el{}y3kXD7={aa_a(;44EN2WGUk-gr44OYeyPNKtu%2iq zWLymqTMCrOHcdX|W(Lz6H-4)1qnO|WLhtPxh~=8q^)P3z<@$@ZOaj7bcTV47TOM@272!{HiCNaHVuZ+Wxft+n>G6+w~q`FH5`OTkLgD!8-6ze`_ z-Fq+jsknajs6!&bL_tYA#o&h&UecldDM?z|rxDkp$!kNeTwyo-N(!~kg>JY2ssnpr zdN!V4pNqv>UjJ-U&AFRexoh3Q*D zp9T-7%{VAtb~oNW5g-Ly{W*mNPIELanS(@Dm z9MZKhUhvsyDhj<9zwJa}$SobvTNfhe0K-WRJSdBqL@r}VFU`?)o$tE(KCf==48?(DqJyL90|UMW&JjFD zDefUYf5W=+TXL&|3&&Qr=R)!`&R!U

A%BS>oH^7l_jcf+D3+oFB!}nfFCKQ7L_n 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..4a2a9f30a4c919134a47deab25ebd1f67ee0eb04 GIT binary patch literal 105919 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 ?lVyKzTa0Dt{^YGKxUb-RPuEh zqh-jeFOUjz@-DzX`w^~mhTT>rcWn94d&_Djyqt z=H=5KkdT!qeU>+{DtRAo(#dIRe4nF%abX5X5D&XGG1PB>3HKbR@LsolDm#F<>;ee} z7Th^NKxW-e(SzMgj0Uh03o7lUAbyb?t{6CWa(p_}d8!2!k$<-R&pkc+3c@dvt1?Z; ztC?_w5y=HMzNi=qp`pCU1{V-%J;Hmt6zU{xqvA9i`js9N;Qo1nysN~4-6EgP-vG_x z+7@;4W7yzhjPszXF%~UHUSkHp@jHR2%P&_h-Zpoll!+woktt&+Nv%EbKZ^$&#-TD76Ye8LZu8Gk zKi34#JVFkDs$`0wz1*~CT_8X)J_Drf3V4g(aK{%Tic=QS0St42wP>-kc2Pd1kw?~+=YM95 zDvn^MlM`;TgIgH_%0t~?){(U+lkb>BA{fK25pvwD#jpv7la+G+OTnab?rqV_viZEH zQe}cY^GLp7H~-vik?EeYpr$dZheGIasoAS=+4Mc=p6Q^v08bvPC&A?xU1Ukl3t1o^ zum$PMh-kOYkits>7PX`5*UpECzLP$=CG0)A>18hmtqcT8j+n?PYYws5Gi+$O@}6xB3V%OJ(#zmJE%Q+b)}2XwT#v#{No63u_U@xPw%EdsP5q!;)fK+eDUR7gNU zFaR;0)&Hp1`sY^q7p}wl7J+vnD)=rzuTyWAVzo?BA~bpI|8@t~^Z>zj8Eb5+xA|{Z zA_92F|J|_v`WCBkK=ui3{rD0|fb!1;iojeo@Nm^RiFm62P=kN{%fB%$`Dk$SdCg7r z!v9~sl4W)t(LCZ25RCc`gZL7N(H$CswWbACQ+d09Kzh6hB-03U30H7j)a4BW-OnH* zJ9DU8OFFzosEmlUjRJBro55L$Foke+Y&uRt6u8g!(D?lVc5sQ43lF~(El+@SS_nV` zB)|3m5OHiu!DABq2IS~-0H|47&-5^?{U(E1S3RNIkC^Ekz%B&s(r5!<8tVw@CCGrI zh1?@KYP8!-i>_7p23HZ0Il28y;8k%7lxycZ>2?(nwg9|{7Cg8s#@zf8;a+nIWacaD zOvN6*rbamGf987iAcU(i%?kjt@q0p|V}|EXM{qznhK~*FM)l_^#y`x+jDf-I0^yYHTA%V;anAwnyrvmU<@yo8Fy3&dLXj! zkqusDOCX7NZNw}e0GX#ljL5nZ0^!jEn9TAV+GHC^MjT?=+XFBK?S~%%E&}_`!>NL) zp}O_7{*bjTAi2JO3Z$K$QLUd-8o~D90DLo=$%bcvQHtKLSkax0AD-X{Y5)l-+;8~i z=F(9Jq|#>_(R)Mk6!y;#c!Ejx0k%<(u%L5XzPd{IAIm(O63jK0Y){bV`YVvg&hDiG z;Asw!uC}-zf;)Z-N{2rIO};z;3i7q(=7P=fJ5%S2+fjWph9>g4VFwEc>{hiS_wYGqX7G-e%qQ<{wQ~y(l$AI71w6|K-|Y z6ol<^sSSC5ipUg>0b$|jmy-xu{f_@EeflO#DQmDEZk}wgPHIahy;KQy_XY&`H~EBX zJjurhRSPmK0skapx<(~>^i38Boo|+!bD@0FIwxR;pY06-s~~&VtvxvsgH_O!SEc3s zyK@lwXU^1=hs110B4_F@W`q^3{G~$pCDv#*S~$lfpc)b?|nDczu^ad zRa7X9U{_3Q0IZTnwHtu7azR)c6qD$+j(!KNiYd{%UPo!Z28npT&R7|$EN>Q&Ed$_n z;hb|UoEM7lK|3L^A~%_v1+l^$01I|$f8#o{*HaGXUjnG>kl>0jH>!H;Qyz%Z?_%w5 zte$}`x#QA`<+tWWu#P3HdUY(aK2>fuutr?FV?k;r9_V-{v=R@e+=9DX9r3uS9c^BQF`?$#kppFBQvnNVW> z;H+E4Z%N%obQhXvu;__qQ-wL-yT`yDY#lET8=I-5T05?_4=Q)tG0ya%xT&}(kz)G z`Jd-Df@o2+5w8_=n%#3_B`}pffRZYJUN*}HhIF2wR-mD@`2ubLkX#Wqr|3{7huCem z2>-&mzvKH@vH*E$*x*}?r69#|xw6@L(BrlQ7|YFLm`yw=Qcz0hIMWyVRTjhov+LRF z4}Qe_?10C5JJ!CWPw^Ct!VVBbWKJ~xba!eGnOer6d!=19it6GEQu%fL_vQ4)bI~70 zp{a+6j_(e@GVq|#b^BNv28wOWJb>ZJh3j&t?qhaGhwN&7T=k)QCAjJ}Nw^h={>`P! z4);d@e$^xXLt9zBS6dOu`KNZ8a$+|WrhXI4g7k#QBz7<_mr%u_@t`|HS<-pYvt03i z9O2($@vI1;WbMC!g3)twh5vMsT`1t}83etg9(NvC#0v|$Hc^@qGy;m#1A2d5R`E)uyq;k8 zl!-?@y#zGKyriWkRuKU6c7Y}Qsj96llcNeW^(o3_3BH=tl~19@{oJVU@AvRdKXWc< zQix4hW#Kg!2A2~m`&#uJ^qnFE}>^Jo-IP0W&3I=+oU5X>1t8K6n(z&%Mv|R-yzmfAzR@z4IqT7K)B*ca6IWu201&H5)JF9y zI!fej+Ad0IqhO$kyYCnD&fI%jXENP@{>A?)EjxvQ;1YwaXpzV@*n4raLkP2Ovmo7N zcTOkX3(rJ`8glqhst_)OjdMr2N-^~HkhGODojGGCxi}d?mPjvHb-zmS_CkOy-M|Yb zqlUFCBc1<1o6l*$hSBz@(o907h_x;dEwQLh>*nsVZ9a!Ed#zQHy&x8i#B4GIzQgVu z5J68MAM7I3DKR+_k}lCc(A_ngVomdyG#%5c$AuaQOL-Gqiq2tq(&33!SU;9XL7L4+ z-2ZdXEDfunGjftSRDkkLk~!X*H>?8Jd|ogMmS5A7v?(nK_jbt{8Vy#b-(i}HZKTBF}Ui+C9GWk2nZOoL( zyV^4*w2xY7Sm#E?`$Lt@lH|)y9BZa6++W}70Vsli%B7dCIi@I+Qpg~lP~GoqJUy5X z4#c^3=%0k+8Qnc)I|DD--9CENc*T_S)0_3pgOmEo#r`ohm<=jJXkTy!g=p1Ce{xmy z((vkeWMpMvC7YtMJv1cJHpZ-DHw|I#Bhh*jNy0)r`&e{@-V zGQCdGi8-9@X7N09pa)wzuvY#ciSJA{U9e}embC0@Y|oebRwKYI;W2^vP)FxDj6~ZZ zW!A)6sE`W?+^J6CpdPbBZHMK1EH5E$2(RnL{ZCzic;*lcxA-yCZ3=kQ(=E1b0b}&o zIL5Y%aDh^Njc`_ihXH!x_PE`0eU*&KKCa5$Z&k1=%_Vw@lX&v>WuB(!G*&J=U3~(k zi_VUEJ0XG0L(to3HT{4`Xic|##io+R`;2(HHdcam4#vQC^5_AR{B$_)^&!UxekzA4 zB@GPqbx-{wb>i3{de}FUtko>)(C?i(6U8*)JUp|w_E6|_>`3XK`LqRKe5!Du|9lzi~a??iW+#ImzLXC8mnt;x@>X?D4F zVGFI(mYmH4M$oGQU$}BJJVvd$mSyt>s|^8xG$F6ZuJrNKY2+~>7b>a=be4zdhe?}8 zpX;ErHd`1LS^Olb$?!FFl(%_<3b$xHk@cQ|xnU8%x&^Hf+Pr6DaQihAV|$}byAS(h zC@aCdR5ddDv^79=)EMf#ZO_-~J81|$I<(*7D05W9xSGODkS4dLmhJ4-pR2P`;;9Qh zKl&4kWQ*c`BF|Ov{>1boBBwj#{;7mM)*wD*ZJPjbauZ`j!g;4sWy&j8@r|%xBOXX` z>XA||ZF&?5ye$3IO};%H-V{i8=7?VC$BnZe)^HDvaEnVOHoE%IH)OW(h{8;5-bq)>dPAweI zhFIOtOSy8f>J}v!(UaVZ?APM=uNAimBDrb4#vTRR_sur~hpS6fB{;*Z{pOugeD1X- zmb(IxV5pvni7WF;HA0K@pZVaLH=F?SwEazEa7nlJuQt3A zrT#tV_s>bP;Yhy+jw-y8P-EO+uAuT+AX1KqnI2BfeEkOs_{NG0hAIj(i%Go@`?odc z*ij;EfJH)KV&FyrOh~rK z!|3cf!;|Tc833%@7ip~~M&N*z)999F>=Q5JHYo{R<;fV}usq4p#84AICh z=9CpN9Hw=Q8F?v-)+W=F+X<|Eob9+}-%Q+U9r;cJPz{ZVZD%GzS@kAtW1b{vguBp{ zhRQ(6))MACn%#(dviJ-3z2f9V(CO^|U;|GdL7ro)GaKS4o5U|VJl3aA=+E!t>@nKR z=5%4#j$lv4QPM@^qfex#3?{K*0Do=4I{X>1$U5airI`1<1?)rTB65qVL?NFh;3i;06vMr8z?fJg9diO!igaQvE+jFWW|fQ0kjUN!GJ2m5R@3;h}eScR>r1zNUVqCARM>u#UIL zm^d-axe(jQ9kCu)1nfubo3!=$q_Pff|NDBiQa*5Rem8@|8{SZU0`RklQp zi4f;pswP_g;Otl<3fiI9?9Xa zKV4t!+W%7agZKi#TVZ|PPW^1F8a>4!+$O2=@kJHJziAZt8QD2DBlq%qX>3l?=MR&H)p%bqvYjHf`ICs!r? zn~a*IJ_W%{m4pa0&@h@`v;c62ij)>MM91JH0)>jubk*aUH%e&fS~I<$^sg{=Z}~mE z-y%RL3;JOmQQQ~bZ`B|Dcw7CcZhSnP7ZQwqyDx*@&H5aT;n*z{Qa@28N8fp&J~}ySA>!b;dS}wS}znis#OY~ z_<-YM!YVC<)l`+)i~Pf9+#>C->$j88R1yp>wEU9O1&`l*G(d?SeWiV@VNmKNq4YI$ z@u6cD@ww&Mg6_`(RSVb0EnR!9x4O5t8qXNvjc>H$)$hma^9<&yxI2q;jdsFi1z@D+ zglvs|z(nEjlxkUp-J9K5N%ACuwFhGThf$WEP>TkPYb(uES{80nNtzw3Vxz<3N7&${W)UexT>?VOnS++J0mC)0js2+Y)~M+<`Ku+Gb$ba1H5e zd>7c&%iD+Dm!e9>Yckgt`lS0!c=dm1$WMl-Y3%Cvi=kc1L+wA5qt~(?y}3};=3jZ8 zt4%{YY&=S%@7*VkrG%Xj&7;K9oTRjhP!a)I(dryY$DyCO+K(whflcI6k`B31EEVI$=cCbKNt zvGWKlXD{&Ep;4E4O(+h{ZqE>E{Fzz20h7*p1-`jj=nwYYA!bBP97n4gLiod~(yn2K zkloN=mQO;^d!E|Bl(!;T69${KqeLd{*V;TCI2!oPzYL^hxzCv?Z%}{Nv{430=HhXi z52MyRuRI9_&fXn|NyVIBeG^Y)>EW=!yc&L)`^fW68mj;Ta$_X|*uWM*_epN4FcUF5 zR}+Y4Y+kGsnjXO2shi~(&7g{E!gf<-fO)o zdY|2YszCOHp=j%W)I`3~3QDiLX`1;+Moxp_IH|N{kWLxIR9BwaO zHq`QVZ5x@0ZGs;X6)Lh;bWAxF{ZQEOqqz(n*Fe7(f+hK+$;2>Z)kug z3X>@?@y!xB9pPe^OB%PjS;YY3H0tRq6KT9z&GIT*Gm?804BEb?`yUB&2ZZUYqR0yQ z)q$VdbBBD~`|&+F`PnMb#-Wx-7=&=*M8sHHk~xC3*M;+nPJPIQ9Zoe`pEH(H0O5}q#(T-q*~j`FR;p{cfux=LGe25Z{;QEhJ^$-dz(8gBk)q{V;gP;gPO zDG*Rb`4LY;U>7X-N^d1Z8 z%A;6KCo#c(9_I_~(FzQuxFVSLglYVYGZpc&6#Lgi4P_hKAD$9)Ti$G*Pe7jnvj*O4 znTqJumG2{f_#9t>tZ|>(H9rv-(?NaVGw-(5osf{7ve;)#O$0zD*RP2^E=wUK>+x~s z*Ycr0pci7)@t=(ky~0X+J?gUr!m2x#%dwHvhYS z!3`hO1fcJ%AHFo!9Nmjpp1}j_BH03Y*jC@1jg?H1-r_jFJl~jVg{C|LpYEGBo`1@6 zlkxOn`NKoQ^p7e@+ue^+Pw(MSz>Ekx3Lqw|HAoe?A^8^#DNd$$?2T7y-Jp{(3?VV;?X$ z8*-Fw3VVdcPriO%=6v~iQ9!-7x_10#+zBj1{3D*h1X!&zk zLoUp|AZj~{7)%NpQjCy7@tbG(z)cxkrFJi;*D z^gq<>$KWRQuTP)8_&1G3B=6rDY}P;x#IeI$Pei_^TBP+&W`{u&Mw(`)ciFs^whaF! z^jQ4?+lA~@rTq7A{zK@cQKPIe!f)>(A>H1};Ft6MX`uEi6Rq))-1+T2XLffhhaJXaMAix6Ry82|tEgL@xxwQzg= zlGL`Syd8M%&$^q-yXMXchGqr)uTTE<@2yA-i%>6riq=RER7zxpRy?PF{2f*&lZE6z(TH>!w2^yPimRrY$AaW zym|uJTcwv8;INFl$t4 z%O4B(0VnxJ+o=t$1Atl73D@8jae!w*TE)*v=Pa-Fi1YZfh1(mCZ0~kpokd{*bgrI; z$9pulX9{*J_ozK-#R2bx+~TAi&Umn&r9~aBNN&YZs zF}1o3=rzh+AlhawzwvkjT2ElHl{UICaM~-Si z9o_b=q-l(7OmJ)WXgH<m3}!cbtNq7J_qQ8hE*PCn5BqAR2?WQ!qMtCwqmu?k z;Lo)|?%tn^+WQMY!n0p*CtGd=*nxyUdZCU$@hyb&+72+%y9C%KUx82^6_wl^IUaj+ z^LeYXM9Ks@M8fWpu2IK0gvewRC}z13{e_zVa7 z9cBrt#0P$xAClXFz?H%QC=5QC-^Ed#@&L1-HD8z{3sh%F>7t}b{~khfl6ofpNf}0W zd?Z_ShWcCKi@ex~ALtEp{;4f*5Ml)bH1Ix>bZ-cZHSau^<6Bx%hy|1k0W@H-193~DW+sc0Ss1oZX1BRhZd<=kG9IY}u)XE`)Mu#>ld{prLL-`@!pKSpN!ecJ>v zRyB!%HP$cr_mo9YK$yS0U&XOUXezjxQO~O1#m<0qYgL@DOZ z7WHv|33`=dAFT2nJ&85XD^7>Ynukt~fjyeYpBO_V7s;k>#kDoZ>& z!ALYfy&D(2sz|b4f=ieccbU>?%A6hwV|ArLx&5(lBN#n%HW$Sj#4+QLM5^y|{C#Ag zKJKiaAROg-Bu(<8v+lLM037UfDpRkTcJSGwy}M-5ndn2ul-#Sl0QJ|`0d*%OEz{lBMlqHmL3b1RxVZ&OXe#LZ&Y^t zG8M%;dkiQMZj%N=O++CsKoaFaXyTMVD2g|GR8PSAn)=UKDfI|76qr-c59=!Pvu37L zxu>y?5n6e3>p_(j{jZ*2eO0^kG<%D2ZJf zj8zsxJ4i(;D6;QW12Vxb->^8J1dXlggCPGpuI<~;C^Kx_po_^pQ~rU_&2J(VI*Cud zH#y*%S5@MY@mHWKE&+vuj%KtIfHUNy1<2W}W+3=xgW16%xmd(1>-}X#^l;G1!h*lQ zK&5KU?_%uz^XHTA)L?I9_2pnh1UYdNriWR1=c}1;w0W+1<94hN`K+&~^9sR&*XSJ) ztSgqtV@EeB>p@g24M{v1PVMN%LD+&naq_de|4cV0)VsI=#?r768yP8{;_t8f-MM$} zsuxH|UT;3hlVu$0uOgg%)*67*Nf}=_oL6AhM63Qd)&^%xEkh zN+$ELy}FM%9jcL5;J7AaYv|nDahQXi1^O7Zm-=0Ar=aPQTfc(;u1ZiZlm4Q!7WIk! z{pamDS~%n`EhFl{5TeXSchyh^ZB)G!2w>ig$(KRN?3X}^IN{!b+F~#p3-mKRJY`fl zTjS#+a-z-F2!geF+6g*%{x|JjkuKr z1DTqv{B(LA{0_EW0_%T_rBF2iY_!uVl;|p-c#Lb9*L`?xK?f|qE7K_eHkz^zKo9Q6 zFyB+<8Sd#Uvf&NeM;aszuv|(NrK*>Pz0kG(-~{&I?$23>J}w3>nXmPv(FnXC(ciQ5 za-&QOo;`U~z4Qr#ZczFj)%eGhhq(icRE|4VuuV%uS7rs~Up^1x>K37OLac5PyjpDR z*R)dmN6j;{+O}BgCeeJRqrf+m(y6(}1zm>CXLMamJDgXUU{$I#Mpo<+OSH$BSog$& znCxvS!-_4R^80aJ`Sp#c4^>p_d%|Y~Jk`W3dY^h zJGE(WtypH#Z>Dw-quLJkMe?Vp6qMGEH3}4&S3()#yn#Z&s;Eh#wERUY@3ReZqk?(?Q1s}66Zh8+uKC32%5b*brI@!Rq8s4D z&y#pd?9Isgc~Y&sX#JT$0QPV|aSmE4Nf@gi8TlgEWlCaTXld zrq(K7s}}4F&OFiWV{76}OxT_oocK);b6OGaH|r9+AuhBi-LdA7= zK1a+hU)97(*?&@hYX@~@a_@mns4u81`q_3-P0^`lyA_l z39BC*&cY$i9niQ7p$|AHf#0buZg~`Tlw+Rk%HK^qL76~f*prSX7V}}xI!%k*d?2+v zyA4X7gEn+P`UCfM?@>KbG%xdysIfC2qe3hh&0bEF8W7E~&olUC;bB)|Lv()99APF^ z(khN5*>;-hcauZD5TmicW!m5U`@rZxLuP@eCjDYmw=fA3M8T%fg)%2t1*cmlm=|D^ z8T01aM|`_4d)4iYils-mO5WNCv6mP&nG3s`- zkbuxIp7{kPxs0_BcN z)6r|yCO9g;`{h@69veVzS!lmh^p|VN_4|O#k<-XuS#@Ut34`4AEP5Z)aj-bpJ%aZ~ zsx-zIl$GS}P=~#|sOo##n{zpa?9z)=P^Z**Wxc%{T=UV&d^G#!V1L0ULwa=ZPD}5u zN!cwX8mv5WGHXbf&Fzpv74GY(t76G+pigKK=IKyyMJ%VyWZ2A~$ju}Q7oiu*Gxk zi_!Xb6UYg26W@~1suEyfWG+MLysOth7#GvmUnA6xS*1vR|06fsuKZ7a^_rN*srM<> zTg9mSx)l(qJlU5|d-2S7%ZZ34(5(nYm>Imkb$-3C&Wux~VO2NE5mts_v?FGbl8KeX z`eF@}dNlXp{3k~ELq3n-S$7N)Wf&f%wWKM(-;qy)0cAl|%J_QV#Bp9z@S^q?B-<{T zCLRU{d3}4b9enfj7nz3+1m;`*ivb4^Ka56649Es9{~{kf$%QhEj0PB%5$iI+qq-`j zD!gvig<7o7*rhxJpGl)-d4;wUh{~Whha3g*8sjdoj1pw9VoFPj{tI}(B0&wsQt!4c zrHsp81cAc3dVi~#JhP28CI6F@)bHp!_-p!P=D}PflW9*2VqS*db`m`4EH2Rg7+FY7 zFrT5Y@^CaVft&d?Dzg$UtqSLt(azpJ$toJFtdue~sd#{o&uXX&sTFX~F>&Xp)b^QR z&w^_0NhkV{v5KQ}+Bc)|{Cv_cnl4;_@vF;6GQ@Y>OpR`h7gL}@OdczutCOiSml(LB zkH~yOLjSA`>kE?dn*|zQa^^z)AlmXOBn6F3j3m~|6YsYV3VJP~(H~G}*pntg$pR7u z%xjNZ-%HIn?p$jPaj0`DD~K7{ykE{a`;|J7=FYA+<-QBxh{@t^bzj1-tzveA_7riC z)n=IBo{f%z@_BP>d2*ygP@Q*gABdV3c*{9uy7y?XhI#mfS7dk<4$PJl<*MlQTN|a3 zpr-Kz_!o-ql(g0oOFu+zd;DF{Ukw(LMnm;4EGCozMK+Yxwjt(55Ji{7-ffKi9atFz zPgRblevt9KU_4SmO062#IlbrH`GXY|nd6CC+VF)y@q(%<>#?_HK8Zaist#(hD4$o! z<2>&%hO~QC8NwtT>Wi*63!1eu5#J!6blcnbg)WhWk6zl_qkP=^IlM1JnI)VNH8wpK?xqN;F4n?&tPbq z6m0EyWJabia zdvWG@x2EG7Wth(G7yE>7!d9w3WiUAi1!^_dqi_{f>z#6Qs~b*qg#7>mediLFfL01o zA1PjYn-*tC>6LRV!>6i)i$(dydhh$IH>~L%yOg7m?r6W|q{g@iY`S{Lrtp>7@%$!y zB&w*a9@#CP^Wfy~;@VezE85$B1$KaL=a>NjI#H`|U38Z#*|e7H9Y^dQqpK2n_^iUy zJLe-OdRL)~Hha$e-;3^*P*^D|woF7-#H8NLM<5RRw_pJ8A?>Xcqs~zFW1^aB$8dMA zp~&F&N(KmgwQ}mOI=8-vlY)6!><7@&4=~bxlESp@cnTc0-W1P{-o4CFgK?1i?*1#J zl2?V?RN&nqjC*N#=D#fr z_>>7D5N#)6xvXHV2wv-=P@G(7rYK$p>#2OX0VpRvIvuLJm@M@@{?c8e{+;L6G7x8^ z`)%;W1iIEfA0a>dHFIMq-;JVYzi^M|M{ZceZv=>r7H!YEx7#T_;CROlxpE7UU3`7E+0p79RjC_xEg2v`;MH2piRvAN6$My-Pk zO8fZ`ndphT!jPCMtPsZZWso`dgzn~da!W9PQzFk zAc3^sY9Rdk!7<$xbBIY02=?>FaZroU<@|CDh*7^(M3;q+WWhE28D391nc*jF>uK$911D5>#3D#8DKO099Y1pok*jCo7W_RtGhAnH&jAd{(6NGdJ8hK84&3@ihuQ~3%qO|p& z)pfX}EaF+$nU+jLn%1%YkZ1=hD42X}H>p(V6IEq$%>*CMyg2TG>AOAtD?l3sgU+9I z+}oH?w}#uKeDVJKouMPM;y72fn(=<}A<`V?E@jvvHM07{18#t(lR`C=DT89b3(;bDTSe5G^0N<}_JAvvCd!J;L32_1+>F2SNvl_0GT(;A@k|d>bJ=)Vfb@NCeWW z2RLC;jozpe6G0SeX)egpNIQ9tlG_;V*+##Qu(J8_k6C@PSB&62m(G6{5ThDI{L;|x zvT`nQus=&oy~Zk-m2s3F-Fs8xQt3=0jx^DRz8ED1kmwZDs<-1=gZ>lT-?3-9|&J1}^vE-=qT;%U?^Uk^-6v(2bx_!owFRj2es`Heu5>rofs$!a41_ zQuil7og@~^pXU(eVm)YQ`%38?r|=j?=Zed|g+<2Hd|VN^ZVk5DcW)H(&doJSu3tN2 z1fPo_$Mhu1uXEp2InnOsgnozVL4D8`)hbrB}Hfr>B3VqEi#oDpAy-#m5o zFuA!Rw=K~D?*I*fMR+9&b;Bmk5!seEDE9eIZ~XYB8znehcsu9UHIV~iE;tWpi>y4+ zL7VlI&d5H=S%^{wKOJ~zc*T#veK7@C@e4EYDA4jEDy}NW9Cs6L?OyH3Hym~% z=a!%G*=W-K(Az54nua3012nQ}Q@JyR{|zZeNh_OL1toR%MF_wt;bsP0ZyqxEKW)XV zRuKj+_H~B3FV`C$pVez-Om_Lm3Ywp%6_h|*N08kr?7O6Ta#cG-Qpc>p$;GP*s(op3JIF zR&`VKNuCTNDyLSy^J6C*1D_co(K0VkDw6=a{qc4K6*Z53TYnpf#4oJ5zJ<`wxAu_){5HQJ+$6 zWZq(*QRZtjnHTWRo64+7ZSm4HtI5RJq+X$G?`SKS333hTaLUri_eZtfGvShM2NqG3 z&L;XC6fL7ySG9kLQ10irq{L9KPyUZGw$LNmy>$v^_y)LTGg7LRA)*0z1O`>VLA}i@ z#!VHq5q3Ti4g#ZBxwGzvQf0{2u^*i#ZgadIj?vcY8M1BC*Dl74~UfY~MI z?}6V>0C|`rxyOk5EM|n1<%_pCmH;JPZ;Jj#QWsXW<-x_jb0}ey2LO6{2K~=%Ekd5t z`*$Hv5TO>Oxq~)5@H5}Bzt_GEf{?Z0SU+|{y(@xJR9w1o zhgUWERC0a7cC#MG!pb{4RHvcv0^yCKm=E`2%_bI1Cx#ucf8XP&P(S?mZ_bxg4RKMm z;?3b@2o?&e28*%Vm+`F{1-C=0pPoe{d++)r?{8F98E3z5>!;Cylr^U@(SS>d4+CQ< z=P;xz+Oi@v{OAo|lpEYCzP4VOzV{RVx?iKO2zL2vZJFeI2JW|bt*J>TH4Y!FC@};M zi)J7D1~GBYPj~<`i=;0dGq3Mjfsy+p?=LVdY}ujgp_5|sxv(9PU`&AG=nB^VK~an% zZg+HWBk^y}TJ#-~TJQeJP*M=Cr8`Hf7meW{o=thJu*D?xA67eH=`9F#mS!q$^#AMv z|KQHAWdMTJVsr@ouYc`8ga{qg=GS$9uJ;eJ{2~Ng+qZ2!;=leilnuP$Fx&nMSCRiq z*e^nkFu}F20|yEI>tC^6AUO8Pq~i^j|3<<8Btf|&1FM~}`QocN@!zi?j4}sZ1hst_ z;De6!n*|OM$s0R=faQNm2#zoVn3DBfjKW=7Y_|XV!%zmO`?vaA!4%qDz3~3)Sj9-S z;5y~ba!rZH{aI;$M-AZX!0Kp?`0Zq`;Smc@U?)|>3+id ztNcI2dTSYU5zwBPAiOg4u0iM%uC6vDX_AJgf8_vqLuwhgp)M{8yD?r9V z*h;>d6pbR5HE_S{(fy7Po^=2dT-+7k4Y37u*8v^{>v}zhIwo;YzkP6n}j!O`Q_6;KXDn5}=5ytbb5z1$H?Dz)V2$Mpn^ z*&RPOls($L+;&hGM_tl?!G`u{bRoew@aM7Q0mHW>@9o=88!Z|@(uzm1WLI6?Bt-{@gY7C?+ z*sg;DFSPB-yK)!pp8G_eG5@w_8~_}!F~DOviW?RHQ$~(FpNue_(^^SixUxXVQSQ}0 zHh6Fg0txH^ye-sq)&WgIM9HcX2w}V4FI?|>AmlH(dIx6{dX6Co@k&FQF^V$C2H1z3w40y zLbjq0j3S}~s(95Sg*L;0&76$C(-qL~loIM!rBo}>&_kqVNT;?@d*?xOl-cmtJyah2 z%<{k!(eJE_%Xj2!k5VlVSZ6n32uhyC9;z>Z;@UKfk17>0Su?Ni-_5;h$K(nI^Ot)T z3{m3nIq*IT1}foZUbT-75&$DJ2B>J{G+mV#u*niltln6GyrM)_%nqlSpx4gC?m@B! z9KP?1?Gf5H;N2n0MazIoQ1^Sp@OOZhR;+h0We>{JtV#n1aZm$5ZO`*5VBLq(J|6(7 z$qEW!l?2M7gUjr54>D#T+Gs)OlMLM(@+J`kIcp=+7%0|$bOqMKFRPnOIF?HDY13W^ z0y5Ja06A!`^&aPy8U^iJ#VLhE=t9!muSNj&c*n6zfF*c< zCaZyV-`WT%6UdR;fs+EBqw(i6FcX=hiT#4`MtgxZB%cXur4qFBfi`1Nx0X*4AL26L>_{k5i;V_>G%kjVgQ% zEeJFlnMcTt)FZJ3wIQ@sP>N0kYBtIu)OlcEw+Pi~>UkF<<%lXzuP)!m1Dai*+-<)y zxeCE$!(z@ApEgU7vsK;dzKY)qs{RFi(4}9I`r&<6aY9cUsL)MoeblLd`zpI^=@Ndr z1f*bCpy)(%kzyMvvVd7;B8406wtqbNlBS!=W7fO#?H4sz3uvif#LR$!;KGH0!ZNSm z0C?TJOMU|EvdVy=A}c&wq(&AtBAP?T96JnJ=FM-^#da0}KZEFP#S1_|7j!$m37i&U z&MXS(RDtHCZVFiB6`>jXa9ZSO;(uQHq<-_g)RzdfdiqobfA}RBOn2F`b7x#SsrNui z(y^jIB^{R}_NoE^fVHCYSXG>;moe4It zy=IMg=Y(sv0Nn4agNFQuNt>@36l0%w{T`OMWKUD!tokP7Gk^~k?TG(G&<8pz-|Cb4 zC(Im%q=f~OQEe(kXZOpSRRiaVmkxhY$@q(qq6ma@YiT`G6EPRuh%L^ zJ8NH8fM8P%D&Yd|$M?Rk^FkjzdgMGX51KUPE{9Se^lOX((Tet2`-2vom!OPXE>PrT z%GA=e>X_0hnl}kgI}8t=q-oOB*AS3s@fZd4rMwYN?zTafl*jE>3(hflU2NH9a|Aei zTm3hNlO|8BMebwfMm^w)C&}knc_-QI(_FB@+oTpzfe)%BOO^n|5G6_Hq7{@Ue8bT`a z)Aa_I0x{IVn~_3+euQ+2us&9(eY~RFof~g0QA_s$f`4@`85A$qjMU=)l=hL*xf3to zz@G7Lndy8$7yH71*2YvvAZujC(oZCUB`v^<4g|Vc$Blf>MP|iR{QND0ekn&*h%b}9 zKWy8omW=jo$>MU3E*0{S(njTo#!{?@Z&Bq+Emgvazj%zP-i; zK2bHHn;)W|xzD5LUIAhsdf16jt@=K7#!@G)uahU+xxXE4Ep~x?29MAvktjNldUFQ0 zV@XlF-mdaVZOJp>u7Jj`s))OJE0PnUnvi9>9Q{02w88;)S}??js!E{o_yZ6xHWOc3 zRvurD|39|gI;yJgjrOLbyQDh~(ka~%azH}58>B&$ZUm%5I^<9yAPs_acM3>Ihms%F@$9wtUhzD0ekRGZhPcBiB1-({OXdB=iWU5)Hv)%YMe;K}U!~;9 z*U)H9s*16x^v(H<-_6128hgE`(SrgPHsw~z&-ANM>S7?tq>5trR!C#kdJl=H96p~(xoiDg*c6FVL6J$O1e_-qxH zRAEqRvNVhsmqTGDi!qr1h@%&-2=Aywd+WR7BySo^4*&4C;YV`hx$p_pAD+l(A*Sil zh8JUL-AOpX2ZI_^SxPFI`6bilc&!Zwj>MC*cjP=E+h}`OC3%KG`1`}H_|^DLA-8dh z%?%!3T$s&G%ndw^@7MR+2s-xK5xO*c(<|Vz(r@8zy&>7~_UTNU=doG>~h7Bl}`9 zio%;%Ga*-1Xuhz-OQ!ak7?+a54XZ*nPxu+@5gTeTS&3JtFXnWOiQCHvSob9{QL)L@ zdpx%ny!J8n_Hq&+z4LH}on~C_*1esq>Sn3d9t$hTch7w@{w`=YkmdrI3@kP^PM4MhmTvLNtc|1L!UP&JQ$z9(ePT z^_{-Q@Uzdhxc4nk3m4JN^9nEi;@1A-fnj;Pp5(s7)!;j;|Jp!B;_~cD?&FX&lU=X) z_glyWT9hw#dZmA|x8*kRv^u3|qra$eBYrADnmMQdR5`tW@=v3;aEiPi6J6)#-5=OW z^!7Iq_m+jG7&lc)%IxKqn^#1bZmg)gp4&h%I(EkN=ah;-f*?6+O!sQ zgyQ6bEwA@TpRPf!oSVpk59uu1iHUjAoECJ#XRG^6r!_hJLXlDO=mTfLZ|`cBrbIML ztDmnQ>Dw1hdldI~&B;{WVQSJ$6U)|nwd&n2VeNNeej=dF{y=N#@Wmutovn`zrTF9l zY;S&Q39H!`GD=wbR=1R#QnMa)LEB5x@voi_zm2HQ<(0p}=|fjdRUyB$-*Hw}HAild$QF@B zNE&h6+kFqdOYi2HEnacW!n-i>*)8%d(lWMtK{=QEIF&*ooUT>T>5Bjr`Jy+P)7_G{ zOp4EY3$kSkvSSOr?p7av zT2V68JGf9D_AR!BC_T%&9g07)H@}!Gt4xk-QZ`>U%8Yv}eLcPM!PJKXc{%=vT6ef@Nke&3Nm0aP{#CzDyV6xF}#MmMp0 z(?f~X+TO$_0}eYH5Ppi?6iErvu{XY3x_W|r0xf9Y6Gd$4gX}gf+h2sIesjxl0vagnC0f&?RPCaPrG60po!#XAeKz23C?_bg8Uj!cdxk%EB7n zQ=F)_>&bD8Aiy{TeLaBOmE&8T!SOjp7HOs|w}oSAWB!*B!*Td!t*&_PGuqWyp@mQ5 ztVZn;xVonJhO{M0?z6)m75TdMFj1VOsF}vLK;v znkns$oM(VilZzg8?mDt?_dH8k!hd94OYcdKA05jpT~z9#$!fiT33lq_qAqv3R8yt# z4GGEY_m!6UZ2N2tS$2iiHHxiRJH)M$HNDLTxw6lHuu5DD* zNn>l{fVyKV}5yF8#3uw-D8v;M*88P+rZ@bOFyf6D^LrogB#w(B;a zf#XA|GP3>M;ES`;d#GWYMyHpWw$r{dl zYR~Of>w5!Ew0-`$&-@Knu&3y(@L6^z3AZfn{Y$Ho{odC{&imoZ+qc*d8hQ!FUm&>L zAUP$ZmaS0qM|D4qy-7AnHXo|k`!=HSQpioYe<{MR&}ubD*BdA?@jJo!qkR(hT(>?n zr;?xqYG)2oE7Z*?76;;YY68z^_@+jwl-+iBK1cM4q6~C((V%5QLZjOT>&)|?#d&gb z^iYf^Yr&4OQ-e|otdFM}GkBY-)a+Nyb`sEU!!ti7Uj&>1wPqz1mFUn6)^UVB~aT{0fxy4*MSwYTN{evD!` zv#NL{!_e{5tz@lFgDP zG@~-P=4;7!-w{jO>ms3r?#Nyw8VX${qA56LfQhcds3w{}8IiB|mpbo7C=)Gt8HQER zbo7T;e7{`ZB&Y}ig@C~)pKYbI!#bS;qXTY=X&EN(CUU*WQ!L%n5ge-=mZ9Fh^J*Hq zO1ja8HoH?hMPJn&LQNixYOlSvI6pma{lx5j3dJz?8+9K1t-2xTk8&&gPFeHkE9|rj z@o$u;&l1(Y9al?lWD=5~T9=U*nuymf1mT%{mMO}qN>X2*I+(ZJFuJeM0w4^u**c;m z^)MnoJ$jDJa;>8}n!5*3-1+gzrCLFRGQtb0M9%Lebo1oB`n%nKkTLP?&DfbZgg!eL=2>14Hk| zC-+}}{T%SUNEToB)?n6No6J6~uuH+JomUDeoV2==n|>$#JVabc)7dZ7%z+Ry*vj30 z-)~H0=bYGA`Dt#op}fBJE2#E+>I#J>9@?0TP=VtS^uUhsS8uK_Vfrt^^H;yP zCGia}7|WAauoKDibQ5Bpc7BWMB|3agQ|F*|45?8Q3;vcH&Ui$oLvooZ!9CmA&zpU- zu)kR#q;UM|Xg3?4-v+JUGwjuF+Ah=Eij5@$ z67~MoCxHY9%F-X&U8Lq#lxxgzqE`KDMmvS@UZmFX;P@RRAMx)mj68G-`lIH<(;fB zH(gL+TWuoR<}lKkam%xvoaz#O3ac#iKF)e;yn?pKMV7Yfz9N}%Z5m6AM;w=yDkGA5jMjkV=^?>ZtdniOTPSvHAKlK5{}{G>p0%{PVh@ArE72Y*nt0AeAa!NmCd@Jq%{~vp zNI9+asFS~rkh(Lsgiie^v{XCpD%8IJC{;XX20Mq#MDl#5Y0vY6CyK`{G3?X|{I)Y} zg;>r~kk#yItlKMe@|2yqOadeME>;lxvk^20KHf>VCjsDE-^A)^Fy$Ppge`{KBi z5)|7!y-`TF_d&$#aIQk-b??Dp5gqdQZ7 zE`ei*BX9DGPGWoc@QrGvhVZ9lkxsfUTnq=yKmz~VMZ$?}g{B|=Mfr~T+1Vl87Utvh zFF#Z2%bJ3E5<`q7r+b0Lw9H^1?)c zOuWnyW~N?tadn|Ri_uW|kMxvHci*0+U{zMnpLzwDr}97B7tkOLSpDz{$KC4}1(DR= z{9bg~In^ZQuD%C~`u=g0RuM+MxBFP3DzE}6g%jBO-5MH@qMm23%Dd^?7V+^UPI*#; zM>6rvW89mY6glrVFn!_0U7`{$jam0cxn-^hKM0+nUSWzeyp5>~Y7;kdDb|uhVU4bR z-*>J%m69#K<*GYb12+MMtkeTtgOAiX)Zn(LZZvLoz3_M>uOcgFb9M&8zkD(|{=sF? zA+Q~>$CU`I&S+)5N{kWJa;wl)Z;`{a}Q8fH0)T#Y?6 zBR9tsNfjeceyCE5QI^a2HYI^PduX=D5atIe_}0}mD~Jv_Fus{Qg04c9a^eyxMU}8= zx8$alcjn9V$@DM}D};VTJJ;cR4-nA`)Cg!mIjf9@E}M{^Pe z_jI*=P3@@pP478tDZ?S=5)NU^c`_W~V~;V`qP^ohAPu;<-nv!Id?!_}Kd;zBMZET0{dX|G<)u=~@w^n{rwv`EEc?!3QFTap>?o#uA zsQ^6vVr#<}WzF*BG4%oO-0cnfK0cv(Jr2}-7J4C@5BTSh*f^jYOC%^qcYU99J8czu zsd}5lJk%v7!N*nP(4qbJa{={RQRNg53fh_OS8{?6yC#is>7|&K(Z=()bMV2f)V~LV zr>!F}n=L3fXDgDNn;2lK&3Z8kge$|d2f7mRt+r8GKx2)%isWI3A-C_FtpKssR+vI{gx0#KP=xxvjzCEi1AKsXM_jJqDN-BggTjl6% zF|JG`nzyL>qNlXzONnBJZ#*Wfyym)Z;fU}L{U;70j`Ik}9DU-OfS)57y03~p+pgK& zdVDsM{Za5R>8PK0V*@TAL)@Fewd%s|4R{pXpC}UqdB$6ZW=8U9)(~@;=!xX6Sr1fH zXj8Btz9tjkN*9`R)xlhX7R21Qo<5HUS{qc1y1>=0W?PnY`+%mE*|ORJE(7*cq}=-UqmB@%k2%_yrF z$-X?vgH7Px*;fy#4-;y)*?A+~m-JEJ@24V?it(RrKfSr(IG;w3Bk7VT_Yd>NGhy+~ zbHMlzPBu&-r$^_<82>pclX=KGfMCeAE_v#~E~SF4V$aAE$~vD4nJzw8RU-BWyxnrv zr26Oc{H{4$$aejDco7LnegfO-d1{1PHT5UoyD$H0JWC13>Uti#@d}wUP=hKCv>y0L z=SAnwp1>R*fhLXSmY`82-w}j@o5gWN;@2YKtLZT?3%8hHJ@$1}NFjfFK;bwf=k>l4 zor-&*#eE08FP%un#BE#Y=XLFd!V@#5wi|AWL!&nBIZ#rojtPaT$BV8=vneYjzl!11 zP@9|H7Xj+f^?AXqu88`vQI0l_YO)U|mAhh)44?9k=&1V3$+Vp6 z(mh8`2P58eBvM#1UH>?eV+G^0H7$*Ay@v5P(fzqoBBdBAvc@~2(&gRB%bgU6A*+JbpK6|80qW~%wt5~(i6Ir5G4mJ%^!7rvN2e3HQ!CP*jlqa5 zqT*Ry&3BX)`4L%TT>Elcb*T;F)%FPMVJM7CTr7!OWKPph5>psfb-hcq%W>lRqxkQh$qW;_E=!Vhk#(ytm)h@44g#fNpT9;_zN+$hp1hZ$ zJ92=K_7*ijnJ1i4apYh)j1^fqMUcQke5-rvMqTMjl(z;MeR80=LAW;vFCoHBT(>wTv$6*hjjyJ&L`^Az~ z+GXlQ>nm&*g_Ic=J-(v5ms~3kPbzS>*HUAuoQYtv_gi5pEt)XL3e<^TrMRB)Ilz54 zeUV-6?Wogm5tDyw!HTy@>loJ{vC?~!&dOaI=Dk(4^PR%wuZ&H8aw@Te9#9DkMhw` z!QmU~xd?2HFFxpps_7o6FF(Zjjz;piSiIAv=D@%J z)z5gG`uY=1RdMM&H=wrRMHk(Ak&U(vKX{*S-CoU@rweMs@IFg| z)tZqbxzy%_`Qw@~bOYBKR&Hx9+jC>;9bVF!VKnuESg}8tX~<`VVBnKv1r<1~+c|GS zW82~cqkBsXi|0bM3pkcC{^(VXmxku&LsJgjKP+WFH}7zR5Lt6@%ky2+FcMc~*6Khj z#bi=Clf5xj=mgsK#Ck=&qs4Zk+x&ps9RoZ_=EwgSY z>@_VewM;!nriA9hV!{nVxdW?Og_U+J>Ui1fG}2l zVb#CBmXU_*d_~h#(+$v}&r+0Tcp4jn=^uA1iKpD-HSDg4zcPEb9zlNN6XJ+Z=p%9C zaZVjt2n^aw6Tm^FYY(Es;y{o!d6zHo8Fymjo<_5!Ys+sirKF&q@v@7B8^5RnZ{z zel(S34=>$!(N}vXr8NElbnQ$s#(q1cWhvR4l^GQHeb-PF+{-Xrv6_SEVm$lI;wSFH zUOXq_N0*ct7VPlbpIiyX5&JlE>wCHAmH2M`o5-48AzOd*mAOQi25B1w<1c=A>&>V2 zgqSJ zBb8GDwt)_L?o^En`=etykU6>`gXoUvSIjF5TDW`}$UbyYd>4~#QQxz0UvBxQ|0yr~ zZpOq$Vz7NapYV=xhVhH!6DSf5Xe3IyeP|%pun83XU@U0QAoVTY{S`&gX=a563k|LF zP~m;1$nuog%l^sWy^jR~)@CUIg%yw8lnSPP6wEfKR-6EP?WU#bC+{_I6g=5!8yT8>vpuA8^$Q4eMQo`P%1nJmGrRbAm5=b4 zG#a|AVH2lLS~)K{G|MR2RaE0wz8dANKv9_mPFx3s z+}H1`J;{_{BflT*VZG@mGHm~R2A&*oXa0yG`vpVhpIhs|JMX+x0Kw7)9-UD!?6W%t5a$&6d|Y*^Ojq^Enwp#hjgl z;Px-QK^RK23g z_xlWuhb%Dc${bP-g+H7jnz1HiIXBxk;4KKMqBA)L*6lRpf+DHMZSG>TEX`K+V^y^$ z6C1`lD=sX|bKeAjr+D0cky_>>v%xtsigOIk>21e?UUd8zy;+OcU6H}t-cpYq+2>xV zBE?L3;C6@k$83n0*9*#wXGm)03a}ieo9M=>oFaA@^^XyhBV;`!TMT5&7$OBz=EhG8 zA2hK;!BHvp%%0*tRVeq|um81#1TaO;x+u)|Z^XoEyRoWkQQIR$jY}NT&NV|D?Rj;-&RK9ZHS2;ppXfR%L&3#fR&90TQ#bbA2 zPDg3Os=VbplUWj!CT0!0-30jdU#4pSnHi;}0Yw&H~^UeQ|rc}d<^W7g#(Y@4B< z8n^$Cgu#z4q3^ig2a3wZB$&!nV)#eTmPvq&n}-lrvMS**%hipvw6Hr<0eDbRizWTY zUgEJ-8L{sZ@AhpsIoT- zXZgLEHO-C&4g7wdj)5PvVYCgr~H$0;kS!x+3p<@0)H+&jZPEOT*dtvdA5WM|~ zu&D4$A{(Q@!*O)A&2iIOPmu=bnEm6T!}vLe(<)zEMt!)-#n<2O8s8M)SSHV2-)J+@w3l%R=*h}~^I2L$K~5);(f8DreS?~grwkG7mL=;O zbZn1H#sv5MFoT_LB-ClZL86SH1n19hX&(I-b~*JLfdOUMz6U58HV655`sPyB$0I)N znuLSGUusHeH+Yc*AF4hle$@K0)5mekNk_9lk5W3d$9rwPsB+1vmgeVb?0r@-{dCx( z+nXN-r7FALHne5^3C-3|EvRu{usZz(`rLn!gwHB!SVj)mzcitC(f5^}i=ZVzw9@|G zw*Pf7>+v1F>Iy&;w&e=$V5{&Ilb^>-?uZmYSV6ntJAAdXi(dT8!~U9MSK}78S+in8 zIX7EN4TDPFNN$GFG>p`EgcbN9fAakdF~gR z{$Uw1%G{CvfnI#G?S?}*EI3v+OEdhr&@qMtx9OkCV2!BZd}34@wH{(}d`sbd)9V(i zH^;qM49L+=k-*_Pv~Hcq#&J=oCNiaFRA=Nviker`8Kyc$5^t%NY@b()tI=Sfbh?Q= zij|P5{Q5maOG@%`>W3x^5o-4HNgZr59|d%BTH#yh<&twEVsOFo={A%G3dsc=DMz0H zgf2vuW}O1qT_WEiUhrN|qPu?8PBW`P5^J5EHTEABe|$8Ul@-< zJNZ-kv?p1NEZz(+dn`kwbF>^D8;*nJUzTBpRnfxf=g=4@Jrj3o%kh|<>X*|9`OPro zO$XM*o}K%Um_mxL;22*jCCe|S_A6ueEuWP3w^R{AF#Y!p^w#1(`hE&Cy9!u<$W8GEUG#9T1;X=t8~itBBvVp2TKNKy`ku( z0lS+K!b&r*+Z_+l7f3`C*FR)<&9_Y5Cu`Hjy%yi&43#9t9l zT3qV72G^%DR-T8J`*}6Jq{%Uw^H3boO8=zCP*5Ynr#vL$Pz!cV*$)i6Ia8K=k&H;} zA`QE*xlZxyzYF@x^90WtTx;UmMDqo9mCIYp-A&g&*?dO3y+L1Ef4Z(jDXWm~`orCG z%)m_C!yp)8_mAq|agkyM&ifFI>0h*^UNd z^sk%ay`6nb+j-BlT3$kmh3$@i1$JdN^O*6I>rl17 z#O#YW*1}iA{nf**)f{AK^k{yFPbt?|*v_E5i%QF7WgXZJQy`Zjyv#Uv6kW&W&N(jn zabm)6US$;%<@njS&pmvn)S$np<=T07etz0u?l93WQp*NI&Zv!lDB`NC_{I1&*D42* zIYAeN1FXyivN9|{-A>>&up_UZZPdIZSVy)nD07&Qd4AHi-{d|^Y2T)oWzXhC!`-9SCD^ARM)TRPPit-9Fu}{PB6RP=tBjqOZBzt2`}4!8O$6~* z>9&a?;#+07W-*Uce;e!S+o5XXhCK&YVym8=O&52O6BFN~aV^S+*JIJYZ9A@E1#yXu zz6_WV*{}Q{bk#~q&Wsz@@`U?_z3W>Yw@l{lPLq(dSLJC|2I9_;%~AsrGmqtc`?1Au ziyiVNTeG&FKXff3#Rf`-g{?;9IN$A}w>!4g87tn1@O|6-)+--0eV8k)KZYE<_z=p**2ET$YFm zGuB3BOZ^I{bDt7#)8{8l%{^CHVT-hc6fWoU3}S^Jvu1sv^XGLr<&@NHT_+~mR>z-K zN2kcN=;J4BBomk8?ZghRtI##EmV(Q9)uAXB)R<0sj(Ig-cRi;x6o=L&l=t)cUIc2{ zx~^XLtsopj%yHk~Y8Jh1|k_tI!zGf{D$-8_yniH|XTVr9F zSG)JH_(@i8MP<{g9GZh4JY0{7zI2?CbVaM{Ia-w&{lP~M|HwN`+lVoFLdUJ_D4$P6E#03YZ}E^e-l(1Zo^1Cj!PNX-_C98`H%url zV)TY)g?C+3a>IN6k3E(d2Q#(zH0=UT_($$zUG%>U+kTabo*%*YNEbcxM~KfSKJW`_ zehV|sl#sfA*Cd@E_KW}N#{f|dy{$^@p;x1KaHv#nMkt>p|fqt}~+k$ub zK_I8?$!$mCksSTR^8)O_l^8LzPO+B|URjx9UkOF}3Ec20?zW9^vl`}+6piXlx;TyS z@L;ZsTVWV*>}Z^Y#dV~i6B7=oE7>z*aMUe*KyD4)hWlGOl%zjSq=$7aFiO5!`@~Lc z^KQPMOQ1M^LOo2jdoeOE_SfToa~2*Ug_FF3-0Ah$vSo|DlPz2F;!=8DP0Wk=40FF% zT~A8rcfI?%d=p8X_!q_rYn1mFMES0w_?SC7`FhFoTT|k`|Cm)!aS`h%!vmw$(}^Q2 z29@&O(}{CH`;aL}%9X1A4C=!YUYP4pVG=E=r>o&&aBAd5TwwjnL4$)L3CbAi!k5^+ z?w{4uqo01+FVsV$c~qje@zIz&)$hDUO=iGAm<}7B34YfHF)jm*tqO+i6Y5|t#*X2* zD8seUreS99%YQx(n+hq$1AtlH3VaCrRrCE3ztIR5R)l`Op5kNGy>uqt`RWBE!+i@0 z3&`w~cNT}%5OK^!!~c*0PzWHiMG;*DZf4}9DnwX;G;XCRESJ5ayMP)IyhRkAm#bcG zesqx%o)`CZr0Cdwdf%r^DjU-HKE3}xhAgV!27(~$0?r_^wD2x_JxI%f48B_P5PMTMhK**#9+DeUw6n=Rf5C zc*Ra^@}(e@E&F8E5q0M|Gyv13=YDW@`d?NiY&R6w?a0gYBjm9o{P*huxQdRwYLfZK z2Fn+$z`y4i*^2Q0bQa}@0S{OHcLNjM|L2dt04rP5KE5yFzwX%o{f8U|@NmhM*0+55 zzyJMTe=}AD=CV2ZOQio^&i|lR-x0$7VVVx!#?-+wAqbQ$rf+|GuEBfBZ~^DK*{`Gp0k`juKUDfLw*bhcKVwW6JMclg(R1r1=>{rrnla!-tm?vK4@)!gVN24y z{Q3>}q0nMF;NAypIQ>)J5}-TrS||aI^EX7kKl;@>1Sh_~cW3=}aN1=zn5XABls6
## Design and Implementation @@ -77,6 +78,8 @@ Given below is a quick overview of main components and how they interact with ea 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`. @@ -92,6 +95,8 @@ Class: `Ui.java` * Contains all code that interfaces directly with the CLI +
+ ### Parser-Component Class: `Parser.java` @@ -227,6 +232,8 @@ General sequence diagram *Note: Many details especially from the SaveGoal and WithdrawalChecker classes have been omitted for brevity.* +
+ Exceed withdrawal limit case From 60fac5413a39412ca656fb2eae6ea8161a28d5c5 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 21:42:46 +0800 Subject: [PATCH 358/368] Add more page breaks --- docs/DeveloperGuide.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 34c0eec828..d57ef83b44 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -244,10 +244,15 @@ Exceed withdrawal limit case +
+ Fail save goal case +
+ + ## Command: `add-account`: **Step 1**: @@ -374,6 +379,7 @@ list of accounts, and the Account class represents the individual accounts and t --- +
## Appendix From 95e0b04ae19482bd9e2cecac2ed5ac4b8a9e97a8 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 22:06:29 +0800 Subject: [PATCH 359/368] Add one line to DG --- docs/DeveloperGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d57ef83b44..1f00909b93 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -441,8 +441,8 @@ Windows: Command Prompt
## Instructions for manual testing ### Launch 1. Ensure you have Java 11 installed in your Computer -2. Download the latest release `BankWithUs.jar` 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 +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 it 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 From d86e2574c13b342241b616f4b7e64e24ff1bd2f7 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 22:07:33 +0800 Subject: [PATCH 360/368] Fix typo --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 1f00909b93..22128e6bc4 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -442,7 +442,7 @@ Windows: Command Prompt
### 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 it to `BankWithUs.jar` +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 From 3992e9d055ba4b8eaa039d065d2ce0a84e8588e2 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 10 Apr 2023 22:15:59 +0800 Subject: [PATCH 361/368] update UserGuide with table of contents --- docs/UserGuide.md | 76 ++++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 36ba01f9ee..0a7dba8e48 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -6,22 +6,22 @@ * [Features](#features) * [Help message](#help-message) * [Add new account](#add-account) - * [Switch Account](#switch-current-account--switch-to) - * [Delete Account](#deleting-an-account--delete) - * [View Account](#view-accounts--view-account) - * [Deposit](#depositing-amount--deposit) - * [Withdraw](#withdraw--withdraw) - * [Transaction History](#list-all-transactions--view-transactions-all) - * [Save Goal](#add-a-savings-goal-to-the-current-account--set-save-goal) - * [Withdraw Limit](#set-a-withdrawal-limit--set-wl) - * [Check Withdraw Limit](#check-the-current-withdrawal-limit--check-wl) - * [Delete Transaction History](#delete-a-transaction-record--delete-transaction) - * [Exiting the program](#exiting-the-program--exit) + * [Switch Account](#switch-account) + * [Delete Account](#delete-account) + * [View Account](#view-account) + * [Deposit](#deposit) + * [Withdraw](#withdraw) + * [Transaction History](#view-transaction-all) + * [Save Goal](#add-save-goal) + * [Withdraw Limit](#set-wl) + * [Check Withdraw Limit](#check-wl) + * [Delete Transaction History](#delete-transaction) + * [Exiting the program](#exit) * [Frequently Asked Questions (FAQ)](#FAQ) * [Command Summary](#command-summary) ---
-## Quick-start guide +## Quick-start guide 1. Ensure you have Java `11` or above installed in your Computer. @@ -68,7 +68,7 @@ * 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 + 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.
@@ -126,7 +126,6 @@ your input: `BALANCE` Note: Balance has to be a valid number.
- Example: ``` @@ -141,7 +140,9 @@ Balance: $1000 ---------------------------- ``` -### Switch to another account: `switch-to` + +### Switch to another account: `switch-to` + Switches from the *current account* to the new requested account, if it exists. @@ -166,7 +167,8 @@ Balance: $90.00 ``` -### Delete an account: `delete` + +### Delete an account: `delete` Format: `delete ACCOUNT_NAME` @@ -184,7 +186,9 @@ Account: jameson deleted ``` Deletes the jameson account. -### View the details of all the accounts: `view-account` + +### View the details of all the accounts: `view-account` + Shows a list of all the available accounts with their account name and balance. @@ -202,7 +206,10 @@ Balance: $300.00 ---------------------------- ``` -### View the details of the current account: `view-current` + +### View the details of the current account: `view-current` + + Shows the details of the current account. Format: `view-current` Example: @@ -213,7 +220,9 @@ Balance: $300.00 ---------------------------- ``` -### Deposit: `deposit` + +### Deposit: `deposit` + Deposits AMOUNT into the *current account*. @@ -232,7 +241,9 @@ You have $190.00 remaining! Attempting to do the above cause the program to show error messages. -### Withdraw: `withdraw` + +### Withdraw: `withdraw` + Withdraws AMOUNT from the users balance. @@ -253,7 +264,7 @@ You have $140.00 remaining! Attempting to do so will show error messages. -### List all transactions: `view-transactions-all` +### List all transactions: `view-transactions-all` Shows a list of all the transactions processed by all the accounts of the user. @@ -266,7 +277,7 @@ Example: 2. Account Name: jenson Transaction Type: withdraw Amount: 10 Date: 26/03/2023 ``` -### Add a savings goal to the current account: `set-save-goal` +### 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 @@ -286,7 +297,11 @@ 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` + + +### Check the current savings goal: `show-save-goal` + + Shows the current savings goal and the deadline of the current account. ``` >>show-save-goal @@ -294,7 +309,10 @@ Min amount to save: $300 Deadline: 11-11-2023 ---------------------------- ``` -### Set a withdrawal limit: `set-wl` + + +### 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. @@ -315,7 +333,7 @@ You have withdrawn $0 this month. ---------------------------- ``` -### Check the current withdrawal limit: `check-wl` +### Check the current withdrawal limit: `check-wl` Shows the current withdrawal limit and the total amount of money withdrawn in the current month. @@ -339,7 +357,7 @@ Withdrawal limit is currently $100. You have withdrawn $50 this month. ``` -### Delete a transaction record: `delete-transaction` +### 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.
@@ -360,13 +378,15 @@ view-transactions-all 1. Account Name: xixi Transaction Type: withdraw Amount: 234 Date: 04/04/2023 ``` -### Exit the program : `exit` + +### Exit the program : `exit` + Exits the program. Format: `exit` -### Saving the data +### Saving the data BankWithUs data is automatically stored when user exits the program. No manual inteference is required. From 27a9f1f0b78a0a2f1362d3531b675990cefea218 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 10 Apr 2023 22:18:28 +0800 Subject: [PATCH 362/368] update UserGuide --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 0a7dba8e48..b1150fbc0c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -11,7 +11,7 @@ * [View Account](#view-account) * [Deposit](#deposit) * [Withdraw](#withdraw) - * [Transaction History](#view-transaction-all) + * [Transaction History](#view-transaction) * [Save Goal](#add-save-goal) * [Withdraw Limit](#set-wl) * [Check Withdraw Limit](#check-wl) From 9dab15bedc70edcaa66c02b11cb816578978a8a3 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 10 Apr 2023 22:27:23 +0800 Subject: [PATCH 363/368] update UserGuide with Command Summary link --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b1150fbc0c..b9d368f4ed 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -417,7 +417,7 @@ Please keep in mind that this will result in irreversible data loss. **A**: The text file is updated every time when user exit the program. -------------------------------------------------------------------------------------------------------------------- -## Command summary +## Command summary | Action | Format, Examples | |----------------------------------|----------------------------| From fbd3caaae791ec862ba7f98e5caa63b400ddac27 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 10 Apr 2023 22:29:43 +0800 Subject: [PATCH 364/368] no message --- docs/UserGuide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b9d368f4ed..441653c187 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -19,6 +19,7 @@ * [Exiting the program](#exit) * [Frequently Asked Questions (FAQ)](#FAQ) * [Command Summary](#command-summary) + --- ## Quick-start guide From 6758594b78428c8d29bb617b6f970fe930c1748a Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 10 Apr 2023 22:33:27 +0800 Subject: [PATCH 365/368] no message --- docs/UserGuide.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 441653c187..c778505396 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -20,7 +20,8 @@ * [Frequently Asked Questions (FAQ)](#FAQ) * [Command Summary](#command-summary) ---- +-------------------------------------------------------------------------------------------------------------------- + ## Quick-start guide From c906d2a58f4b189435989cdc8af545574e94af5c Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 10 Apr 2023 22:39:33 +0800 Subject: [PATCH 366/368] refine UserGuide --- docs/UserGuide.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index c778505396..911b5c3dab 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -4,19 +4,20 @@ ## Table of contents: * [Quick-start guide](#quick-start) * [Features](#features) - * [Help message](#help-message) - * [Add new account](#add-account) + * [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) - * [Save Goal](#add-save-goal) + * [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 the program](#exit) + * [Exiting Program](#exit) * [Frequently Asked Questions (FAQ)](#FAQ) * [Command Summary](#command-summary) From d82481a40b5dc7e36159214e38c100f553c123b7 Mon Sep 17 00:00:00 2001 From: Sherlock Date: Mon, 10 Apr 2023 22:44:14 +0800 Subject: [PATCH 367/368] Update AboutUs.md --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 76f224b1b8..ef65bb21d8 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -6,4 +6,4 @@ Display | Name | Github Profile | Portfolio ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](team/tyuyang.md) ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | N.A. ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | No portfolio>>>>>>> master +![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](team/Sherlock-YH.md) From 9a0c7d414db2b99af90fefd4c6847df6ecdf7ff9 Mon Sep 17 00:00:00 2001 From: Sherlock-YH Date: Mon, 10 Apr 2023 22:57:02 +0800 Subject: [PATCH 368/368] Change AboutUS --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index ef65bb21d8..17af0c37dc 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:-----------:|:---------------------------------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](team/tyuyang.md) -![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | N.A. -![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](team/Sherlock-YH.md) +| Display | Name | Github Profile | Portfolio | +|------------------------------------------------------|:-----------:|:----------------------------------------:|:-----------------------------------------------------------------------------:| +| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/manushridiv.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/tyuyang.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Liu Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/xiaoge26.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/vishnuvk47.html) | +| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/Sherlock-YH.html) |

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 Bq%8md literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5a81099d8bea3e27a47f5d3cbef7a27bfbf54f49 GIT binary patch literal 76949 zcmd@4gyb^SUC`R26VApJE~*A>k+~%DzTILRLjWdf<(Y3S8ls zKqo>%!WMleBcrAyBSWL+>}dJU&H@QZF(O$9O*c`AXt9ieHV8t9F85+n1%FHK1v-0R zpldln0#Z&FDLSkBZ?%r9Pjs04zcpn$s*s$uWh*E@v``akCY_YO)wxr7AhyprBH?9u z{(W~>r0Qf(hZyN})u2L z8!j4#wW^g0_SN4B-5JXza`tUJ2<(!C4v%cCN%kn*S!bV!dN8ye2k8kPhfV?p(jH+oFP2wYT<{cHMPfMT;|HIHAv2tu zj+oRd&%^CM#gdwmwOL)^iKYdtDpRlga^?*yH)VHL#~@sfbZOwd8*#pI>>o_V?J0j> zl){J+nf#4xYR_^w37t$kxLzlT>IqH-aThhjw?U$dnepY*luw5WI9``_y1eayGZ7;= z9|C9aSMb#xG(V4JWzk~8C9yrwg$;GvBf@m?R=VHcEDPq3SoSCBTCi1f%fKvI_N?j& zy$tk9uE(G#DGB#(DS>&vdadR3j+F2iIf38X>n?#Mppy(i-39MIC9pi45{68W6}a>B#5{j z=j(DWZ`UL4qYt7-xpoeoQFPS4kHS&x@KI7FG5IK!AIwV5jLuD9-LuF`BatXdGT|ek zNJYH+5k5Gjt4$JcjGV;7IB@h2xq3c5T{g0mHQgVNE@hHx6z?mD>!18`?L>Am z?!!%ULUll*0PB#3g|@sZNFiBECZ1@i;6iR1 zKY7)A#q6v?T_oURZSLuNhBvvGHZi5TWaoY1*mq z^}vyjOx{RD_JZ7p3wT;sBoBEMxokUK<&r+bSNqu=o545>^!tQCfeLDW2c|N3INeTJ@6*_U^#g4&XaxOz96qbG!fyhi zF2V{0D8Z{PJPdidcwL4^N-{hI1axwiv{-RGpDFZW?WAntjpJqdFn+O(Ma)Z6(TMfg z{v!I2V^hd)19_8^r}io-ME=v!rtEW~%n!slSfdu!jBkSX<;h2hHobm7{Tb3KdCeX8 z)f9W^u}ixsH$QQ7zA0HMN=9(9=@VTX?bw?39p6VgFz#Kt&7aeNpSr`*S&OrM0$iav*dhEcHGGNIzBz(7bQ zYnzMKOrjA!+m+Up--XkKy5eLCIwGjZmZjTD+*NA*Y)$x4Q<9bT8~q*=CA}e&TcUVj zVNq(KU@@fdb5XeF2Q5}j_pcOM4JF5#YrJ~Fc1mYV3W=A$$bPN;vj0VVEaxn6$t#y= zs&bUyrBTUp!jhciJ-{+xI6$tYrNyhoIq6g+J?T}HT;!uQQYfx=Tlgj4vYL;4+ij9bAHKe)+E49pN_!}xS)*m13Ov8!+e**l%i}wF{?TTCOtkn?Ir6hb z{*#jK={JQnT05Vo=!NA43aYk5uO43UU$J=C@vG0h$;iw6X85H=p-HCcmBPzjEs(lZ zqiXUnK_&-kPq`_Wv>|FO$}egs>Q$qBBb#B+KH-A*!eHaUsr=@nO^n|!PM`iR-SQi= z+D6;i*esiH9BZ=*B%dLR;!U+IA6-t8IzZne5U2N~f1$8T?lgzbSIry62YpvRdHCL> zExtm%Fn-25b5tqM$Sl+;(5d#wW;L%zjLDTqf+(loCee&(Bu!YEnD?Vzzn$4x+SByV zv==IMsqU%%{8jufxt{Ucay410a-TmR;WD;gv{|$=G3A~zO_9s&wtrcfUtp24_GZw1 z@LYRJTS+^zB)ud{Z%5CiB(h|u`Uh8 z>a^?1_Nn#>&%Mv7@UUW^$J)e_XZ_6L&Uz^};z`i_uw~tw^6YAJZ{KjaW#pQZ8ZDb5 z+faO@M>m!rYLHsvC54lw~qh4_leXT#47l@@Hm{Jy(I6&`tPd9vy%qcrJ6Ev#2Y zQEo#MsY^Wsz1>m8PtO_LU3W`n&IG;Zf7Kg09jqX)e(YURDp!hQs%9zzsVbJJ_+~#& z(#)Dj7G?EvKfZh%{Mh7$3o8pBx0{d6{l)T;ZI8z*aE2NW{7QBwVjPr}Y0kysF&5vy zo!F3gUO+IGFy@}`2bXuTt-sxZ{@(sAPL)xYa{ivW-T3#;=$&mSLx7S_u7A}fv2GILnY@+ zua_gYqE{OO*=Q*iY&*L9t-h<6E107ncAnkp?6Xa?ak2(f+w2zgOb$)v7cZ5jHLu%+ z*mi%ZNvavEF-(q6{=UOD^-cHO!f)!zRx3ygXEJp1Wzmx3vSWQS_gk}DraTpk3~_s6 zht>v0*Oz9|S}NVzD^sv@Xe(|UG^e-MJA9EPVfQ6+??R%H#}pnzO*S>(LkjjSk0-;!VjuJCl2` zx$J|XrkC~l-mg}Ty8Sw@`2uF{Mt`g=y8V*+5sZbmO10?K<@0;R>28&C0V`WATT_(J z>&^AhTILC0sWeD;eQ58(qoYe~+mv zb=1E$yE`a>k7uy;r(e?J4j zl0ScOf1m&Li<}UOga%w81iqf19{%fTWYtf||2lr)jc6yOA)}-O{A!pvTUa=_SUb9M zk7MWq7cjtzdM-#v#EgjV1Etpthrpbs-f8N(>Z&LUn>pHZn3y}7T5x#UgAx58iFyhH zhxQh(CN!S*b`CDWo?>)=o)89(5tljXX#PCnYAZ&ktD;6DTGT){90E2@8-an7@f7ND_EG5)5F7q!-JQ@(bpMpW8brS)rjBl|Vsvzff&TsX*E}se-~DGK2baHJ3wS|J z#2rp<4ld4r_YE`^MO+nDd*^9krziW)9#}JA3~^ooLD4_Y|DQYm8S%eb>i(yt;B)@} zZuwt#{@GH?#ll&}(H^d{zWH}UQBK60|JO?VwakC60_!Y}Da!fpJrl>& z!l7gXwvpnU>?=*+7Z9>Pe=Wd&X5fqX1->SBof?}7NJx@MO0rU#o)302F`Bi;ukUq| zlo=TZ;4(g?RD9|6fK)>*?_i88~N;=FIr`v>Wx%o8SX75ubb1+Jp9K;2}3gx{9-`LJ_-EUH^dN~ch93uhfvi|8_s=^prRhNQ@c;dM zrlo-=p~h)P{_o}RKuBWg0|Na2{V2-N*utxQFP#M}1|AET^sJ(u$4S{2QLXNdEAT(Ivm2 ztdC?Ld{N0*Phr1abNN~R~GnQZ_oq77una=+3I*Pqe;@4l$fJq$0Hb8K5s zfeMall^M0jx^>wn#e>tIze{L39(cBp%5Ao?{e$P9%hE^okW$3m_4ex2#pj^KBdvyo z9{${JhD*R@U3t1K;GSo$f|c-}Gd!mGQRiqp{aJ~~V?E6(Meh`tp;R#HWrX%driW45 zp6-)~e=dp_{zcpUwM6!hQk^m*3+)z&Mp}-h+&^TZK~fUNLNfgR=RbrfZXAUH>U{OP z(CPmz4dQ%IQrPrXh}m@U=gMs+iyBn;XBpfxiT@TRNpV1z1~#e+Y7w$6$%yZ{9E3K1 zxsjdiI#OKL+Bo;FAalN=mug29|oxj8oGSv!#E(K^{uk}?i?$ARY)%G zTYtTg9pJljb$)Qb(R>JdVg1#e_Uu-PJ8(LI@Qz`on&RhUXz*L%ucbH}2fz z8oJMRx7=Orz-?Mc{*s`eW_mzlJqna@h=B`11B`JI;H&iv#~V@5n>Pijl;?YOOJD4M z<4N2scV2E!eaomcXiSbI;dFobk;84Ltj&Kcx8#1SAbUQP++njwr!1@5pz?{t{Y_PN zUCprY4#TsA(POzt;)b=sk4>jj`kZ;ktPFqVs@4Dq5bMXbGY-V5mjVqD91>Wu>up=s zQk%hRrMe<`e|v5$;B{<%KB4idL14*u-0y0uAfjBnOY!<_&v2>L&#*HThiDGsSXiuI z=iom&szAM`Dt4-Q4#VQCe}IfyzcpTPy_RIsW*MHZ@7OXKO(8VqcY8WrI}@2=Upw0) zcGN}W5Y0EG$QIjrd3Sw4X;f{M<<)b0Hs|Qi2aEhgve4x5N;quiWJKb8XZDlJ#&D@d zf$Bc+vS*9+uf#9Arh@|${?e*n;=snuODNdnAU5vT;~-_ocoZ40!C(rzUsK&rn`h^X zJ_n33CfgHV9e~$*<-7j9ai?^Ln8P4dw|3Stqd{QNGcWw2A~`&M{d>lBYUkH-G9kzG|I;&XfTt1*i{ZWHPXPv%sy z{_=&+vB2ByXA;#Y{&~A}K>L2ryNon&7&Z!uiVe{s?C~5h6k+dgK(D+q>YN6Qw{D3hgzO?~Tz zP3~@a3bF2|+mk1>VWU>sA+QJ>uhu79vwUS=(dGRR4lt;h2GBT?0;On#n+cky#m6i# zYVr1puYTL{@VuME_~KH;tT#sG`Pp`HnLCLASZc+E$x(4PP@w?m-pE|G4kLuK2`Go<1+1^nUWk2K3QCBvkcst(?$A7>&M14|BjTrn27D*fazoqg{cU%`Fnx z6?B)AZRTpfoioS{hQL_TK4H`~05WYDOC@$gM<{F%aC_=MtWje#2{Y|pjD5;CKyVjE zkP?Q*W<%|Nkz*D^#BcqBhWb5e3P#8{@QS-K*RWG>&Oe4AP699l#~TJ;^AVmTjtC_I z1B8Ni;;tAf8BU(#^fhYNd&px2&+$o)AKekXB)5jo{OwK6 z3(+Y447CUbdY$v zN~Sp)w(>%dF)x4Z&oBXqVGf{QyZ;RH73Bpz6raO9h5m`)h;}Xq)2%Z;jhU+FfE7%faGqLRhIJZc}%0u1#XF<6d~5j-VcUo z2ur{DBSx1pz+eHx$!}QyOj`;u7}{i(^8m}8U^>73HnsB0_o&UnoUIqRO}mwYzM*26 zT_GbCqWW;zu}~l=Y?Q$ht5!s9;cUAZqXb;L!`;ng44Y3l)cV75S?krn9$;M@j#j$; z^`*}|9W+SC6y}z^HYnTdrVTyvBQSvQ`_m8dKl5v1Q-Ro-Lx#PEjV#>J z_wkrew6Wm~ff06t`X6lyh06;a`23LZkO=b1C#vQfK7enyZFOJtvf@lo#6AM_zcK&i z$Hu38Hua-<3Qd0J3)2U@SB_(!mBd?wS1^EZw>6K-2xB8d+^*8QtT=o-f(i(R;tD$#pT8UHvKo%eu(h!8>^_k#I~QtOt@<_JQEx zY>wy!5PP=Big|*Kyw;v@=IUCFc;+IFn52t%lyd4fx!da$sAhJ#e_f2@11td9Y2UB9 zPFxW|*rO`$pWVnl7zdq-=2Bvw*(*_DS1T%=)}X!QzdbSt@W?l!jyC@Q6OxYz9brPg8U7=F{`LRG0s1iD&pi*9Z$20NpJnoTDCYee zEJO{Za>UFYSs#j&{FsY^UJ-Vmp$$wS>Fz5)Q3{nk#s;-X0 zqzc^}7Cliu@5GZ}Sg-&zZNA*3Gof@E^S>Zz5DWkanw}fYZ(}dM3oN-Jps6Pmi1hby z#V_900nu_(+x^{~-*G?40S3X?uUqnW>7{UqYP#NU!b(ZRH9!Pie}6s+0=l%KT>be2 z;S2zqTO{9@Mf1%AFxViHnEeCA*74fl0uVPY#7f+4stRv?rrY@|KK)noa=@-UIlJUc z&AZ>N8kq-Tw)NOL+v(E%FBuN3sba0^|FWUcugaz_KYBA4|c zr~8|e*g5k=6`n=^#b&SlvbH;Cx9th18r$h%&!+nKyKR8CaR7iqtbXPw&#GFTgJCus zZC>=>6Quo#9PKb3SA)GzCv{pj5Ktl}Mk3S`2&uo#%aIuViV@kb z|17#yz6h-BA6z;9Mdc*7AJefO9*O`R9(9Y}#q7sr3=Ez(N4*P!oNc?}7t6>?v(*oQ z==Yn*`Mk>l07va2KeV_5SmOX~q+d(NaE+M#&9Bm?ec|&y`dC5XGSW0SF!2p$ax3$M zrmOAZ+oJu2rfYZq-=hlq>9(a#hcpH_sP=QUr*^e7rjhkFgoCL9uE1J0^(TTrq+_92 zoXtO|U-GE`X!3AGP(C`v+Ux>06U+iWXLi#-WPg5hGIGriHUK<~yQzeZfl~;=Df*#` zrdrt^v|g72yPdgY7e?uRc#`%aT`1Ol$$ic~i-c~(4po)TiWmi2yS|B=1bw7VNJjqclurL)wTMgJexKd$r8JDi?g==g+mv)a~*_6 z1zrlcZ!v!9E-gabD&uqpumd8cA|(KFjFF|N4l%nt9^|}rF17s^-bY}?r$O(ZsGctc zv^6ci$0FRw14x_J&Q<^lwCw^KgjDnEk z?0|r&mpY(1AOLt3AKLelIh5+QGvzr4snf+eoQ(qk>njaFkaXjdz)nNDF`SuE7`f{v zFb|g5twp1BjUyr0DQzmv)`9%MmQ&OegtNnJAv%v<8Px9Y!Y>Z#;ZfqZkEkZ^ zJu6O>Mex(%Rw&&p1<(X*Q&OfrX|s@zaVHV9?)Xwpxf_6Ny)cM;C2?CVvq{H5psbF7 zV)KAa+sAiOw_R#&ApwVLp$kn2)EB7V&sx+Cc0R8d9Lm8OlZ@Rg0bwk^4HO-(% z*+-%x=m_lVr*I8KufJ(+jD3&f?D`ThK(&n3hX5&boQ2b@=~}O32VRX9xDwuyTwMr% z!wfwvL{Ja@#=xx8=RB7D{Lno6;%HkrYE_7*LP@#^nQ7uS`#Q0|xP~i4k-|Nq!*J9e z^AV{+>freu^bkR5>`H9)e(ux?yk>p$_a2L0y~I|hA5yVfbUo!z@u+s+)H!6Ti{%7% z=!fV;U%p0{$L2l;(6m=s_V)r)A=nn6$gYNsu1?_}nN-rtXM8ApPPf;n{C=z7lf~jU z=MnFJv_;3GFKKeySuazUC0_~N!Ii=9@#2tyLpfHD6`l{%51~y5_UL29^urGMR88n8MjN2_H>{8cl(U6tU{fJVk7gk& zsFQrWsb?O(|ID;;z+Q;1E`a3NdW#|TwCr_cRFu+aN7gjx**^P1`fJ8Vi@OL`pb4`1 z37P6?=8o9eOeYqqEE8TvbUFqoWn5`PlqP*(?hw_`Yb{w$R5pytyAV%n-uL8t;(pep z0OW$!p`uWSWh?ZVPCM2JrcqiU?PLBqJ6`H_MP?HNQd4H=43#6(Mu~c!e8e_BJ4DB{ zKTE~}*3T~t?DDM>WCfKU-D(#eM(tjXffFD0wi6$$Ubg;{vnA<5Ts`H40+0yZ;r2(p zup0LNvh@Z`YH_fLIOd&0?rgK=_8_uM`ev3P853uT9+v>X-KUJ!Zefn<<&S?Dy_EHo zWq+*NFMXAo(cSzcYWVp{v@})-5f$e;A8kTzD7dp&&XZi4_xWotedecGjLj_SRk(r= zW8W?}x&>b6uzq8WPk3@am(JcP;=s zxWHaFzp_MhC$DH~4a~Ut8Fb@GiVXfr#Rn19uI`re#hpkZs?c5r8_zg&na&lIFBl-{ z;Z`7ONs2(vb^F-8!T2)e!pjuUuYz-Qy-d#;D(_8N3CG@)qo>2K27BfnPsQ(wMG-i8 za`nbi8<*%ZLlZEx_@xEm3v|y3IaMc=1!+w&&}!61%PFR*sGhMsJ?=dZjq+f4ZL<6z zRs*_MImjVCicFi&*?cG+PnXjhfkMl#P^w7#ha~#T=Lbb#!AE*Y5$O<+Bt{f+BaSga-s$ewA2u4nbYw_M_&j_GJj;9N z>^hLd8jLdB2r{-o%8hInJ4?8$FH^=m5EI%I^LSfOkuFLSdcO_l!K&+=gOGrxLx^%? z0rn+YNY@+*`#;RhAGy1frQrI!VG~yPH66N`4Bcjrz1Ruf*Vj2`i(GJ!l!E{2HS^TKvufJDCuD%^)fJQ-#{teiU zqXEM7R}}YjcV(9x_42?k&&ut1?x?UV!qT1%<)O-n?)-DhYhOZD6K%1q2ap0L{Xsc+ z7jHdVw}2^=@?8f>Hz8Tvfd53HIvFL8%a*4+F)>MH-?1-&YV~C0w$m;B`xU}qHI6hT zK}Pz#KXlfgwQo=bpow#6YB0=zC@RXuJPRvY*$HA~(l3f`;^pH=biO*~qY-*L?>es1 zDmWsxa;czRRpOmYS){OSo1hT)HW1t1b7k|!%Ipa{G=;-(n>s6_C>qi+8*JvqDD7!BqN%Yw)8_qI%zrH6etnmY=%N7 zQ=U^A&l$Za(Da$$<_y38a7&22igQH4d@aabumy0b$C79 z07~)tk_CwSP9w>J6b>Q%5BpN(dw-5aYQ+6sA-;O@<$+ZU{v2<>hZ0*-Dhg2{^}#1_ z*(P*-vlwDM3?=9G5Ly1ZANY?v57A#fe--m>L|YIZ4{$Rn*(6=pb~vq&7w%hQ-9Sbl zX9iiP0LW^_h@I))@3O8_#S3xzGIL$8Uh0a1uw=M+sJ9_Rs)|ELbQH1RS6#_o>>vR1 zo%ix{NnR}HL&)v=*m|8zL@CJNRDSDP92lUVDl@tHof6xHc{isvE~hs^B{vFRWJN1W z@cxgYAWZW}c16@XbSn8PuP->J+W?b)z7ZS4IWiQ%D;(g8engn6jt2|1BAj)8tukjV zy4Bg_zGu@-iFf}wPuXi=Ik_I;*=qsZbp|(tU^)OmCBoiWNpO_;f`$PfN_z6XPu!}P z4@i678{}+c`3y&@7;m-(%wiVM#|XkkaAY)RD5}d_T@O0Ds32)h!Q9_yFd}?o<`HrKKQo9)LC3UYu`w0X}cPZy?Nrwi*E=P7jur zM&c{iJev=>YV7BxaLDa-7VZ#5=^c1yuL4W^~oDKtO5WL zj7sET;TiMDC^~T&FF!ro?3l&W}65_*AMly~dJ3YIb6 z$f{|U&L(ZtR5x$*MX^Rf%$!-Q*p2@;Y?Ek68!Ze7mOZA+O=R?w$ICpo#BUB|4r*3O z-}cvJycwq&?1O!JiG^PY`s7r z?f?D+JqMVhF{Ck@|GoTx04S~C`(wENZM}hm|KF5W1ih!{^1tyE@cwNbFb`--sqN3| zcOBe69stCz;B=k>UY*@6PaVMbB65nD5r0#kpBaEe6k)8kw%kLH1-Fk)7b}ssIbxT; z5`kQnyBzKbfJ!|865&}T+hiCbXa?#o=(PyG4XQsxAY)*=oe@dtlZ_FNmnm#c8FrNs z#fD9_bAWv|1a8iAH0`cPY;4jN>gCgvkIIt^wH^TcuQP(^uSgdM5|{|)iddhj?rkTI zfUCY;h1@*r-w|*j9kAv_eGwBT<^cQxd!H|OL`HnotO>Zg+(0lhue4-$oTJ(i90r1o z5C>pz)SIcl6NBcO+9AhbK$g#S#w4r(gNVu8RT7{RY7r@L9@b*%zqae&M4=((!&&qK zzG;JTz?gfpoXc+-w|JkvP8l7Tr#U=myKfxiXc}4oEJg$>oMi^c$xxORf2&Q`uLtL3 z2)TUm0Yck_mF`GCA!%VWT#D2gdB-BuAUg=rv;vR?Or*L{0%bBdWhTXFBXmo05=j1O z@(t(3&|x8l&5IEpSOBU#^d^kF;gh}?1miIHaq)~d^}P=PKPd!HksZvvL%fGvhh>T?otAL3m_s~0YI%ic36f; zc4Yfs^@A9!XUa{^L@pg80WK4$-n<&LZ$9dANY>Jh_-3^~-{5e0yyk$&gY(%=MX?jr z#VMU(5wjf@KYeb!EK=mO#-nHHi;+g}%0X^6af%?}T;qm{)#70ot>7M@h+$_6$i>;E z9}NEF>j?Y9!!bH(KZTobM7j($a71&@Qo-df=%$@YN#UMA%K!AcNh{$=%D~v&-L>Pv zUY;tUvSzXNH_b^G>gD;cX@_d*YutiHj@&s}31C06#ko;2xDyuIE^v<7PJs)M+W*5(QeRKids}2xIrlN0(@Gh|o9|5>O#_s1{kF7=*YYZad=TAHskDI{&#rP3H*ZPJNWg_zm7a*vwCP4KKfLyP= z(@HY#;3uizc_3@GgKuDYgU_2&4`fRTg zI~5D=bKe)72iYTBXLrMRMnq4d4%E~`YYlT)1k%)fS32ZzEuqix7y81K&Vcgu-&7o z?>`0OI_nsD<9*|Mt!9*A#Rd{C?qKfnsbvVZWC3#UKK z@?60HsKzKdi%kX>HmD4?JWvnu>ELDz<4dP%?*g`osKdPAb*iTv+k)3drUMYR#-NZ` zmgoDI!VxqZF^P}ZN;v&I;CJCbChk`jz$%;rMIem;f}e28gin$QyB4;U0(oweHumX; zXb4HM-P*&S;9v0yS6V|LmB)r6m^!nG+p{c%fG@mHjAivQF4y;uQr#-p>QqPXf znOdN#javXSr9UdJ2+*eXGNxkkjSoBS04)S8PV31a!E>MxAgF0GHI7#5paOe7 zO8uY+xH;PYXJ|e8T^=DislO0!25_*^j2gl88c?^e&Wm|`3D8l_K%GPb zg0Ld$tp&1Z^&P=z*VjZAxjh~+uJ;pz9<1NQoO7ev)B`@aa>vi=}WTV zzrLI?i)GwixohW3_`rVZf7pQ*<3oc%wL1?smH^m;d4M_I^(q)BB4G;ahY2rg3Ml$$_gQfke0w5?qny4HJ<@)urb%Fe_zE+!`n|qDjEF#Ttld~^>r?{sZM2r zKyG@^Y$X}rSX#HY3|iJN))f_%0N$Q&a2dNa^gX{nZ@a%#sb@N$bCd|Ux1gdm%~)b4 z%zPGs3o#)NWn}KULI|=cD%eMNkLmQE0~1c@&*KF~9Kp>R?=YiE8y#v=nN- zGq=s0FyeO^$@z)$R>`<36P~IO-$!$hRX3iM5`A}vxY1_sLQZl3Ij)4Os?u z+C9Qdwq)L^m-2BWpK$T#1>9&{?%X&X>=f6Z-FPP?-o^{qt z)!6C?xbM!$5;P;Z;&%F=Q<@9sJ4HOgA7u(`*e5l3dq_LH33bMXdkDYT2js@BGYl`5 z!yUnm&jEh)_Lz4>bUXmfT4zS7HX47yH$V{0_v5a()sEMik1Uz2%S7SFow=y18N5tu z-mX*}qZuBf%NVW;h!Y#S{C+g;t2XB~iBdgXMsmoqNQ@+JN0(Td{ScA=5O?nduGrF~ z`BvXcdT4#NlQHjVYuL01h4stR%(q-c9tVpN4;YKXf{0=|P|Zm%mYdM>>ZQczVs!km zE*8UjBvFFREpOIo)?wFp=dAuj(vF$Q8v?(hc!v+E51J0d@BPZJpJBZtn&w{;fsplx zWoh0!^*EwVvm(F650zMZwozQhH+4~b}==#EWu z6DL)&e4a6CAsiERcZ4i&wF}g$olm|Fjj@@4sS-;VFyJgJ#MOHUFQJpkpIeLMJh#ep zOCjO9DIBes1q_P71h+rvmK7P?(sc6EQy}0Tux^TYE&t1_X9BQ1TV=?#aL*asPy-Mk zG{d5>R=~GEK9%2aJ!m;Un{)bR=r*Z!*PNyXPwz&?u-*0svQ%bb=}gc~((%!iD|5*p zRf=iCK{9R!fRH>-uP6gb@EEwQ-|oSagRtdu36v0YI<;KgsewoSso>ESln~OBf%xAymK{rG)3@$ zI_urfftq%jFfYwRC^%NqfWG-{*QZwi_h_@wSkpFrXeilU&W@~VFz5M;Ya3)kV}nh2 zB$j&;?SUB^?Nxc0z(XU+^Mr_cjS;%sFP34|tw+kR5xLXd+>D6bq$fgqrCft>UU$UV zK01i?n)@1dAaZVv$}FhOBXvy4t3GfmsEjKm1o=qTMwVikz4S;_o~gWH12&uR6)axQ zRPO*V!s7tFxr26eal72O)&WDG=6@z;63)^(M|y5qnlIRiHQ1bUG0Cq3MTVbU4$LNtLh+yo<-bkCYEvq)s#{ zahSmEt*h*TzEHXqoS#i*_Xl@=l~h3@_4h)c8qN*Uf0+09?t=RbsrRCwyzr%K{dX9( zlfURCEp{}u{dTpNEL>RlMYw{$t335Yc)@HbcGr~hF zpTq7Dx$h{XoJ4RG6UcTr;I!?%%2%gQ$wk zoh>0hB#9W<=w(N;XuEDhuT=q2Fcr$8Ydx747}^Afo%5EeZ)1L>9mc0a#~pTK{_!nK zb6R5h!89_lN0tm+mJEe7(+3M~PG)HewI#%p(+uRcmfGYx_h=?}UCs+#Hf@i%e$51n zxK^t4lKY;{_l!S)`w5yf*^#zsIQ_m-4mW=HIo7a&2=tls0uOi0v_Gg`f$1e~5L(QIcf?6%S6!!9%+Y73t3za?^chi zF3JoDVV7N(bNs0t4jP~X5)>?tF60S3bBFO5C|%@v?SJt(=nHe8Gk2lnW%CoN z%&G~}hKJuPAEsxJdSn`D1rFyV`6Xa>0gdCxGJ0&AjM|(6vqQ=n-raWlZmb zd&1>|DqK$b8vc8R640cNEDe2cxXk(;BFo{rjxP2bFFe_zRSUqTw+iw#_6!qKybojQ zyHlBc{p69*~?6{1ub z^7=h-wm!*;aB2t4e2qOh1SB*jIpWRSqS2O}i)zDuB8G3Ny|C}l*H4}LQ}XpRu&0qk zceDF=L1xHE2F3hV+;8x9HWf`h9q{FHLZaYSloRFHl(wiGT%|&1nbY;d_RLUx z*`brj4;ZMXL*!Cu>DL)v!kuS7`q!`ESr$1u@GH#&89cPyXROtEun1hiMIgZ>j89EU z#b7ItoyPfMBjeh&aaiD7(PmX=&XjvM>U8sc9D z4U0@aeaEsXDJ3R;=3YGU93gaG`NLddz-070(SIR++EMG|(x^*C<)Z{4qK}Tk2JMiB z!7v>0Gmi^L^{VhCrL|MLsGhnJ!Q`1ERZ8%t=dJ|zEsX(Gm8!yHmj6Em6e>Q7~j0xRLNhVq0ZU(IaY|q@4DfE8C%c$h^8L={`vce&!1G( zIZG$=bP)VgA=^VQ7AUFVXPJbr1h7zDnDi*DP$KVLPT>nJkTkj!gu4MMgwf9ywee-V zQ!zttCbS4}puR_)D!PO@)=_t+QRU9VJOrwC)Hv^QV>DqHUxp&2)p&o}ndsS()Rdp3 zaA?Ms%e^cm_y$_AN)Y9`8VDE6w2h&58gzOKBy`Zt#7TQlt~D{JeRKNSfYcAAj?e=)+S(%&W z$V53FLab2fFHTDbafbXbmbnt|TI%&pZuE|M*?nY)3DLuse!5VwsS&$HxjC|tzr|3S zatIN!bNQ-AoDX4Hf0S1Zu}Mb@G>EH8O^_h1-Ge=uHpQglfa6@|gcug;BarpY6*=+i z_Ovi!v6){zd<25Rh6RX{I)|jTBzfT}ssbqvkGY_+M3mpkieMNOilBD+oW&u|r8!*57b*cQEtiO@iM_*IDpHVis^=kPpoQ~zS?B0Vs_${_-`#Eu^pfiH!EGL1?lB^->7A&b5dtxA_84Z%(h z3!%b1MIs;g}%Q0Q7?A z?uSFJS@hR^nu2N5N!QhKZ_E9lAugPG>KL;?QT2zkFdXq4anokdRnP&N=^TodfzRK8 zL!_h;X2Dpy>BN#l-_WYbd%L3eTCnj=`z%F{E8GTxOppa3D0BE4cWLk>goq_~FDTcw zQpiX+nb;;?rO-%8RMo_ap97bA-x8SLp({LpMVS6`gl#An`Od{>%*oCj=>n?Aj82Qa zS7+%FU^>655E$(~+n}*QrYCmVcvw73EDCy#1wC|zL;3AnS~2*1gXYN?>^9|>-;AEw zA}&>6!c!^~7*T~e@&l6vNHuNh7Cs$Ry4VI5v1(hz$zx}XD#|XwU z^r;UC6PcyIq!~gKEGx?ZRyh#~KBSRN@G91AR1+)ZEak<8TWX( z$-lB5#V_$-)i9<9mTOem0b(eBL&X)?)sDT#_&Vqk>S;b6fgIkm5w;|*DEv;R{24F!6SO*i^q92P9yA? zBkD6=kyvXiTQ1NUfgF2R*YHsVS#C6@YE2jmw$)3%GWHTq-|Pr5CMbWLco0lHWp?nc zjq!od?eB4-k=e>qU^|;tJTpm^3S6QUU@&(c0-D;Tgk~PjU_X}_uJu?8UJ&Cv$Sp28 zCWalJlR_uKW_AG7ve$vE3HmUxJ{!J{@QM>opY|!#qz^Axm#kSqL5w`#;qIom5!!BAYNMRZeUteb*MO zz=?RRC>ZRtM1LF%mQ)4|3+gRU8_}o!@DU62LTWV(=cT|1y{IF+Yf954aVGS6o%vvA zE;k&QNXS<=0u@hCuJ$4<;ucQX@$$Vj{bM#L7ga4txz{iShS32*YEK=PFA%i(3Z%zH z%qL|~oUs{r!(S5Pe;XIi0GsN|$98xvxIrg)8!b11A#(1bW_jkJhV&9!7`KquQ; z5U}ap*N}jGOfN<|@)3+&{=^dR*&(NuH}Xhvs+5kNzlE{NBCQLlrqxLo@IRu1_TN-l z00AQ|eVdb0k4rb3l44PV62tCtD+=fYKjbu7R*)NP!g7K!+D-p5muX+gye+E9BjkF* z=Wjm&tW+Pa>{A2zm^7=7KI<>ev`-?K{lb!^NW6Zi$KT=gQmhC)?3yR_M9RI=n zCn;-CxR_ZMQQn~P3NG(E^;!lP#$w8Cv{0z)0Qwfpmgt*=-7CH3g4MxGS~hf0mr`U>GpCb8VCI#dQC+LqZ<{18?(afOp$|T8(i6iIUvbza_^Kk=DlXzc&}h`W_th*HrT@Ik%nLf`#opS5HF9j`vVSKJV@P=w z!Z8OKFe0jT5<5P74$gEzL1R;6Uu)u}0CeMuUWQSn%l*2illQWM_IH@FS=4gIXa^nr z)0K$E!p_(1`e}fNhQ<9q+`Uy;lx^GoO)~=`UD6HGh;*ljv~);=QbP$y>(B@ypmZZB zNQ;2vkkTbx0}|4bQu3YS^W5>i@A9|u-?n?@-h|tEp*Cq8SAuYEXJTdVHwDp~cIUxc)(75oW8cdq=u=3b+D4`*|f|X+=HL zd{5p$xf)pXmT9WO!a(DLPcLpRAx0&kMh&9bFSPdZS4+}QuMl2-s-*h|=eA9KOlYsvS z>vd<$7FNP7a&5Ca{ZJbjmMo!NV*6Z3mp=}Re-4*j9geX*%efT8fI?#FO^cE=*zz;B zadH-UtUNRsxQeIrvR%Q8*iJu_UIj57(MA6b-f*!csr~3;1gVngJ%hH4TX1(FWNT9p zFcLRsIZJ8Y7+f-MFMhFZ=)PwYMEF9oCgRE(-fkj<-?G#aoZDjy3w0s#e`AJapmbNe z+|O+)>Dk#lLa{^8Blu=;J|Ykn=Sb6a97B1VwjU{@SVe$?UXM#W)BRh4I|^p)->l_( zJ&;6(xVNDXG7E2^z>boK+1=xl68O^jQS6Na7OUwKs)X93fv3!h<=9;M)KTmPSvm@c zryCDP+}9)8R3=?aQQt9-MF|5-3T6-Clz{eQS`89g>Ao>~p(z2ybMDA;L48%Nl+?H( zoqWu`cI_VmmUdhj#r$O71MF|!n8Zw6`&mJRaG;)t?B%hLX$;HZ?f`$@QIvWy=E`}V zP3Texcjm|jrWX|Y{9~aYyVPqxsYtQ1mEnyC#G3cl@$+fvSR`JXwR<%PWQCIA;k4|x z1cM9ceCz4NuMF2_;%+rnqLnXH(iAPsF~R*?%=tOejwu>HQkYMOrvqeD53Oj88M@op zt5~K48+l>hf1@iZ351JvZIK;IRFr*ya^OT$i3!=nF`VjS;V)21eULhY{2W|Tdz-9= zyFZn>-dqYNJ!V;UMnlZllxH}=$xqo%j3*FLq0BgPL|0T7Hm{!VaZb`%M-7|da4ac6 z_)nD-?hR07u$0nT*qarxMq9#g-cg+n0uQk%@%1ek$2WnWjl~6818@CCD!#0rs3*LW z14pJRS~6!*5_D9fx$q4g2+Dpn&qVIOMAiC zPP@z}tb~QpO&>y2R(;AwuIbgY{Y9Q*K+4p>?dVf!80j%-@4Yv&Qh6EGwkoQ`p=w1U zw{|;4ZroU+rV_MP%1ds+`ritwA>sc6_T-?@2hdPv(#*vRkUHlU5r_Y z$v@Q@C5NM0S0uQ$s|gkrMRu}e%(Hs%gidN(X2Y-kV%RDtZY&&kGpsqwy1 zy;r3j`D$x>r~h_$d_9!As>|5q*MX(7LyBiKXD&fMVGfI_PB_eJkQDg{LMh>xJMtdk z4;Nd1rfv_v7UUpg>g>6)=a%O8QXsbZ+Al>9S9;C(;;P76Lz0NZOSt~&V=WOiuGgPf zraj`i5s$c;xsha64J}Y7lKjn$5KNl;y?lF`tII8QABo82ywn5fgKf zyCGPVxJRcD=fsgJINY&E@L)&uwq}3CtX|d*Re;qsZE)Rn1rJ7yQ;G|bo^NWM&wd~$ zzl~*hC=FW}CqLqYA(-ry0tZ6!U7c?riTCO?ngvxAzmR|qu^N-Ehzd8bXWb4%d*ST+ zk=WTC8J;}Kx$_X^cK8>cp*IfAQ)<6MfFzrbOKEyX|1Ow(e7}X>w;Kh#mp-@4eak+X z?+}B=#tdZC!u)r=zoQb0h1pGB!QpWZa=^^gK0;2a$VTjP-bX}|dY;TIwU*aQG(;S@|B&({v^nAIQVQcoY0)vw(OoM zQak#9eR<$~T|XNFBm)mzh5(o~of~UL^wKcyU)Le@_I(h+iq0~ko4Dox8D>D}D2e2Z zwgF*5)<3De4<9%)L_lc35ZEa?1XUJk!MWLu<}SO(^XBigB+6+MiUF?u!&Z)#D#9xe zz;IzRfc3kL9~tML+>oRf9#E6lUKEC0jR^iT)fPWne3YwcD*G3^s9f^3cCM^Nh6 z&F_xl6?yG&VIh;^LjQ@CqP!y7iYxwD9%*eIBEV*0;k4zXci;gd#uP_>-*ChWpFvqqj9bX1%wiN_Vi?@RN!Fg9>|iO-Lpy55OD`- zAoYfp*LX!BBs4aVExS0Gz8kQb20I4{_$zOWw_Z%1YHi7u%3|GIrtx|W^PuP-NWIhj z(WnwZEK|SmY^!iK>`%B8OgK?P&O%Z!4P2?8BbFqTsi~@0sJ~&+5Ck{RJ~$SoI@GYiO>yPL1f{CKIP7!SUUw9 zP(x+*TQP%L;M%DlYiFLg4oRPS0n14)Dvra;ck&D{M;cIwhL6qXn{hY2GBmQJrZWRi zrh~qLTWc2;O|tF;R<)h#8sOOI7sRy(17cU;YTrfK;%%$iHz&*Y_?nJ%eE{Nta+*Hj zUKMs+*ux2wH5!xQS#=QWa3~ zGJlX%n!DvximdL`k$DpNl_g$klpoBw(_^3v2F@V+7gtO2#0R*gE*wq+fKO`V!=(e( z^82E!G$Yk#Zc6&MV|INmfBoD=p$*=*O%FESh49B+1CP$>b0HIl$H4i_8X=eCsp-f8 z?!Cp_&qQq@Vo`@w%|E+nc3&yp{23AEC!XmOs(Uxvd}0nG9J}ilh+_ic z_jNsZ51Yh}h86Ef(3Ahes0oc`2j}TMFnzcJ@5liLdU;e>k~H|Ds5n>ioj;M@Mt+@( zm3Y}k!*zg|_*s(T7z~^sb>J52jv<%QD$P&4XPzq!GHSaWq*@Pr>o&CSv~(+6Y-k^D zGiI?V1=^2)?FdjJc)DA^-VnpzJcV>=yO%$(4!k0r!Cf}(>&2jedook=o-)LD7!VR< zRc|{1>#_s379IwPpqi1zFW3|?qYi$iZhL`D-dt$%&#NDK)d_Nz&l2wcS_BbAk|An^ z*Z>f7v*_3Xfybzw9SuADA`o}-58E9rtKkc}RhP z4&7RRxo(AYmjF-DRjyDE3`8Zr04L*QL{Bq#I-{HU_MaXMC4P5P;*?Xii7aTk^%?{a8O5YG;L?V!k2eFz(c9|<+9dzTZ zr9LJ#34bN$OB`1Re0Str4&4R@^c=U>bIVaE7?v9X!dS~FXAmV58Y1FDmB5&|Cj2*X zb0kw4#IFwwWRxO}Gg1opusE3oo}gx_H@Idhz)j{aPusKx5$u?S*Rg*8*hrs4^DF~^ z5Z)|NOE1v*%#B27g!id)XP`!95?&iiC5@|ZOi6MhY6%)}exL-nT-+^y>CD{INJN*q;;n9)GCDVi~*$(k5RG|D@ots=QVasOe zMhc9^z9w~vu$yDx+9BJ;+K=syWymyvOVX*-*Xj{GLq*!HkX%!Q;iel!l=O0JJshH{ zVDPi?>wl{sRHZ)&`CbTPu0*qD*2_O^+^L=IqUh#sZDhhC$%C*w#$tMA^iV9!N;UTN zYzFfqu>n~U$*C7gsf&n=!Us3py8^glWBtGs-?n!EGSsf#UNX>LMbK*^mO%TwKg8YO z4G?5eb|BIplhX{BUzr`PEZtqeMN^{>F};N(!&|MZReqbyex_Jcwy~})W|tn<2v`+2 zs$*-pc0E53jn*BQu>a%zC07Q?4$_5C0Ty!!BUIe*bR52la-mLEJ7~#X!&m#InP_8) z_rOeqa1dprD(O|~fL}O+BoXs87V;jeUQdT(N#PR}Rw=N)afv$3)m5UZluI-6M$g>U z64)|T&rC#->t*i^|6Jr(kS_dkDU}Bk-{aO3OK4@8ug9C61%$3_7eO-vgFS9_F~RKk zn#)v^ss~A_uH_#8F{S<~H!M)&xMT{P)WLm=S9J093am7YtJQ3w_sBn}zLCZvdeb{g zGO2>~Hf*r)zBm0mMVs83Y^*J2Jjejl+)EgO$f=yKAhHgO#ir$7`|SYd$&u&l2Xdt0 z5u&du`iF1pi3zsE?n}lJ-BtK@yYIHT*iTExJ}R|hW~P{bp~!kvQBo_<7&TLH|4W$FLQZLYc;91#J7j8uZP6kocT zFVE^#a}}JlyR)&1A^38{;U??RT~`@1KZcgg|01hUCF3Xwrx=oKu>Rhg3CUy_hFGqZ z7g{CYim*#*2gyeVOZieDpC@Fcku7dFF5DJ3mR(8!*%3s^ zW29Y58gp;O?_Pm$cdwpU+c1fWfZ_Y#>)%1y)0gQWg`M5fb(qm(scKM%I&oo-Ygb6T z;X6Egr^#Fy_w-~za5*>{V&4whrkWnmlV(;4pb%WD!yL>j!dW8!jh4;1jzX6A2d??@gA;Zu^uOKxLzMThd zsg*6HxK_GLZEEn4tP<%EIby}uAPe#MWP2L;?WJfZgs5kl@A$2ve}S96zQMv*=xc|^ zF~flO#u;(vj`)dlFMOxC=Q~kN!mv>X$s~uGW>3XE63D+($fTjq!PKq>dIx1|CalCn zBYe{7TSk&PfOy~se8d%$EJ(G^FQFSK;@+bNzvcj-Ch6W%s{+Xbfo#lNYeF|W@gGHM z`*M;3h(02#HF=X-=hWrB6@n3b>Vjo1tvT%`6&E+Z}H^-wYS|`JfoAp!1(x z=Oq$;XU6>sLC2hXDY~!`pBk~B1>DcSo32Wnkw@PQANh?`IF2wIR@-X~rK~%L5hCo$ z=HXCMGvIE#Y7}>pET{F~TWGpsMvx5HP`~;5JrH%ux<7qw6pr23EL$utzFv;ur?r>{ z71)`_`5!dSf1XhgBnG3JePVo2Ti7j2E%8d;*GB}XHZt<*}rhW+8% zz+vW;!2Id6t&i&yW}X_KeSa=1&1~0=1a?p@uwYSjHLKCZq3ZdV+e*4e@;UuQ%YLF> zU4mIVa7Y2Y5(DW^LB#o#>Rho*u8VII5x4sU0O0Jg<>tRkE`sF+WzoQYwGojHq>G-G zN2-8b4s`9_?VvqzK~WhlY*-$L7rt6g@fF}(X07R^(5wmb^J2x3FSRjKWsP2Hyu(32 z$cpeC&XErqe8YdV*s?FKRj6iYF^z~i^UD|;ZdX6)CJ>owW#GcZHcJP~nd@>!IPHEvGO32LQ1sY zYaDxa&W(lJua&11&0QodpwjK!fNT>Fs|?m!ProVbS+f5Su5u!TWjtACPHK?~@-q%) zWXCKW{TmgpD=^{-@_$Dvmo|b-sHoEByw9RJYp0Zz{{#*R{?X>Qz6d3Rl(3j556b3B z`4K6xu>KsDM+awPCdvlJ^*uVcY2uTMDvR!) zE5-^pg!ZEMRkMDOegYk$UpZ~A8(dDvfqk%=VxG@XhEx~o6Gur%vz}4v`36tcaK?CH zXQ^RjW?g;^64d-?1dr zhA1ief6;Bo_)s#A^r?i$U+w;XJ}LADP^j!6_dEY70{&F3cyB>u5SisqSO3qs`_qwz zgCK_xR-yGj``e$tAEpkp1K3bg+`sW4sER@n^yk#ibp`*|pGB|%iJ)%XLiGf3Y{D%}SFZ&C+14qb1hK?Ob!I?k+- zr~jo8qT2fuaEN$^jqArcTA32xK-cuB%;2L5iYd^$WurFn3*><7fMc9-degek2bheR zmvMD!yng7S8p;MhR4g<)L#;`uekSM)_>=?dt;0Ml+c>fVmV?e#-^QAZ=E!5B!Z&Qa z;78(j!Mb*uoi6-%dGlMzTchsu)H@ChfU@z+4#W|?P>V{!@xMdRsBZ{>PV3mAC^tHI z+K2F;gV4J)|4fDpi|qLZ3o4Oe*EkJw6x$-xwuwr9SgWYo6bL1fr>G72&1^b|UIHts z2Z#n#qhy}dBt2B3B#rZMSdp+E@Ioeo>BT(?0Bs@g|H?f7jX!P9v1mIY9s^z?3^dnT ze#{mCcJLV)PQ%{&5TrkU0>G)Xd+dm)DxG)Im(33)Br$9mB%DVoe=Qd|H&AuHwM92b zyR3urKzRB+QR@x*eSMu<7^LhEU|wFSKBMK2WG5T_4hz0XACK$pf~1g__tu0r5Z|;% zJSLegOL^Z`VB&pcPC)&ujkTx2RL`8pPvFK zp?iYHs{8HdiVT0>vZE*~xYE=h$nu#3fngrxoU(Be4c>}|q7WZ3d<{K&YoM}w3TP5s zd**9iSD+03akGpF$U-xcdoKoEd^Bwis0W3idynwXAdq@l zc!B7VjkW-6-p^Bxp@ov~ zuc08ZX2}QAP==uM9~{90FzJFBkx5WXNjVJCeg<;Tg;V5YbOkI+OwTmEtTrw6q`}NEb#$sN_b36(<4xK_yg|A<>Jwgv6#~JIuPk{It9E-v9;Z$ zV@Z$-X%eg6e(ZI>{b&k67QI1DWt^9V0;}OSfXa5kQ>`?zF?Sc0i$U=T;zUwifV_gz z9F8uDJl#cHW`rl}Jsn!24+s5LOe}8_ScQ4z2`Y4>5Pv6AHiXyWy9`XZa0bL&ZT_5z z)5ldJ95Zzt?vF5u@2?aaE!q2Mb6@K8jjv$g#--K*M9pIJtr>!r=D>?{^iaq7fVDeBEQQWzv>d^*Vue@VX<&I9_1@=4Zv*zychjSt8U$Z$pJBYcv)*8YTD zMoa!$dgaL3wPA=KfTVLucW%30gFN`>LxAa7=tZ0~n+p`ljtaP3Rol2G}JpP;*tsD_gvOJIF`p zdZz?;kKBUiMx3v?Mc}c%56H=wj7%BoIz?DCJ$S7+oLiV_|Hg>Xxg9KETOhj=#f+Hl zy(1d#aA6rq-xyZW)lPM{W3oUkF}eUzD+IjJ;gTSpLxOnuZ2#6W`bt2nB-v)I`G2&m z9CMIlJYLRrqSm6bxHA)%u!eeaPBErtT*^UeB@WP;uP#;LhJbb9tZz^bQ~-A$rn1v*?F7j8~t}RJ9sVE2IXkH1;Lksc=h}kkNA=11ad>H z@Y`gX1rc2_@*MP`HHU+e7Y_Y!mcjn9T*Uwcl%oz*EYe8h^P@2>^X@phzzzCbRDv>k zAjuvPr76vFDHVZ(439w5B3QWDDC4z6tQ48=xIsft5UU!QC$ar3BHL$*AW<21`fG_vfyeSu&{-knyKZ{_ z($m|yv+RM&rbvCq&Q*A2C2b%tOw(o0J$;nKq7 z>Y{=lO(UT3#CbPIVk=gS#OXN%*++7VClwcL?bp6T1XeFn0n`ORS}3-R3;0HpfD-h(^8@e4 z?kH{9M!WtZn-HcOnYIoPj%M6QoU+P|b8CXz$mhc=N>g+g!h^r~l*>PX{9hKBw&I3! z*1j^Il{LQDZ$RqAeF-nk_(wbYfCEYc;jc_UuuCD&h6-{=jr{ELgd@qL@O1$Gg~@tN z9C`|(ev|b8syxAuN(@F1lvnC_NU?ea{j^99Ll#<<;Zkr+?UPJ5a`N${vm||O?z=CB z3ZzC=RDi_Tj6crGN&GrAo+>ZGPtG?CMU`PreWf4;&`jSxB->a}Wj@7!StA7ZU}7ZJ z?vKcgv-O;Hrtv2TOXQ954?6?2FKuW2$8b^wh#OZpQ8Vb~V!p+n_7CzC7Q0MW*;NYJ zRRVI)`%QnK+eS+Z)PbPW%8FQOcTYQf1xI}eiyv-k)?@cU#3}Rd#Vv@qM;)p3rVjQx zP~!WDHh=HijukkJ^M@J1iCT9wk$mh;86-^S4iY}qW=i4!*D&@aBa~sI0?(mT_@35eq?g2$z!-4rwlOzEc%uO=V1!-JER3YFiST|el6p|Aq8lp2xbk=kH9d) zu7l6BBf(YmBAH?T9y0YlMe{A*@}a*=-ZOQSj)hd~Z|WH*V$>;D2li?N5+JYp9Y3S^ zxQgTbDS|8`x%Rr!Os+-}0F(=nB6A0xX5w2a5s6pnBWLVf*i4TbwH#{Fuf{^xb8D!6 zOcE;rp-!-<6HDG~Ds7Rov!#keQ=}-;-2G-s`s;p#61~olIpEv){Vo>Ggdz0WXx|Bh zLacGE`lQM?E`^<(I5X}apv{d!IF!UEjozvFtw{izDlmJyi4eB(zJyh24?T#7x;;#h zV;kFf_;*I1F&L5*0Xq){uTi+ZMoRC~|Md=q?M&P{Vdctj8hIg3c@H917I8dI9l6(x z#W}V_=wDxZlE@302{BVAFsi+}!Tg$aJtHahJMG%U?CFHjY>|V{$#zyv@bO{Bo$5Q8 z?;464nm=r&jo_)}DocPkayzJANWciIghKpcAq$M-+Cesa;#8$G84SLJ`^8pb34A~i zzPb;BhSCqjkZ>g66+72C1kVA`oE6xLW8a>Da<2j`do#0vgNwc^FDpPD6Ryrz&ng#Q z93G7| z4{+&j9{q57bYbEPB9H1OsFb=D*pvBVUI!N@8$`FHA2;#5%E$l|+yqxM`^GmWPu{b3 z2L}T%dnq#6&;r{30u;zUTSUJ*=Y~<>X-WN5YQ$-3IsaBJGWS{b>9pNj*m4v{mpY}n zmyVHZ{c7*5)FK{tDN*nq7%^LY*{S8;nHwcf$SOXUDQ8=@Z`QgGiop)o8XT2kc+$qz2%A>+7D2S)7qz4;S5m3D?&5S zh(JU3aJw6vFB%F9Uu1YQ!CHJSh9)PCFYZ0SPY9?3*g>4b$|l}Fr(=l>h9`y{&V)@X z<~_1p14d%uV8$pED>CDV{6mfBtu<y%_*TwUutD-mDRheWR~`BR{^(7!eyAn5Ts}-pF`S#pLZ-}8<0W0wHghmY&2jG)U=_m{lD(-aQc zScwzNt?yu1GBW(R?NabzYm~#oKK2QvBs`;JDe-@2{}vc~a3>5kN72dzXRYSWR%x{+miJ{4=p~q^keA?0-2ih*KQv3!_!NWwAj@Oyp~9Q-ZoTkQ{?SLE{4mX{vKfNKu~iO9*+)URV=en52)yfTi}-I zNP`I2QgC?eMF?1dGFAGl4i*IPj8?#7678B_dzFi&Sywg)iZXZ2?~cwF;=}8xD;R5p ztJe6%$VU2qe;I5|*|V=&7`w(s5m}()6Zp!SXzL&^+4>l?EchV1|KQj8WDEW2mss(& z6asJ5EocQI!ZDMmar{QtSYmIt4D7eu66kR#^>KN*{tDWd@vEIm_e}_Qq8V?-c!S#9S(@D zWHDt$TnT)h^H8U9lAZizUUe>|H+kX)P3E>H0^AFF7cO6|1a*Zd$U=JblksSqW z6UxVOXxQG+4r!ttX;+Wx0TI*wZrLxY(HdtpcSn>+lTUZl?kp+E@Ms)mD@h(DHz}nJ z0(VF2Z}t;vq(!m3!jVk3D;md11F;txQI8C@2gIB#I#oU8WA?>O%=Lnt_o zfoGKjg;5H^Zm2x|RS(v;|2)tc813m8`8+UYSSxc34~aaMqSCl@DGTjRP~y{&F+i;t z+9-QRd_A@GqE*vNlq6xAsAAX_lXU`gu$-|N*23PHV#EdV=0j-Ii@&-=t!s1%hnu%BVNhSnE9oyX98lAKRigSl^cO&QDzcRy)2mO~up;%FWLF>)7* z_7?1^$=L~UAvkD^A<==d!)boGBU{!gXQ~DAFLiqsWSNhTISB5;&cRxqhataCG8Cc^ zB71TukBLzs(4zCo*8?nv|J^Kde7FR9F*w4Lh-Mr|pw%Ct1L8RfdXlYCLUm?V@0mKP z-?;@}%%bB@0(3pyeBhKr2R)5$17Q(OE7b5aXa@Q5yk~Hw`KtScke^$wTwZ)q-E(I> zryn^&Q%&Pkye7V!R)l|Hnqbqt^)k*WgpS8~JS@b8)T$hseN*gH8&!{@MHh>=sXtg$ znSYHvGePGVz$K_S*I8f>VR<8%rD#sR6FB$`hnn89-(@n82%lX|Gm zEiu7T$Now*rti$-m>%1rF6VcSj53NzHIqcy|t;+!urt6Uj{OQ@l7 zFi%@CwZ6t4_%US3{z*t)ueq>rqNr_Kk;COjM%OuHrvgpr%?pig&8%D+yGjEg(OleC z;#)+yqyOW0wL*31#g2ayU64xrb>aSb3Nm$DL-mTtjt>62`~UTHfd7>n(gXiCL|7@C z^RKV}SCznp+7R!{^Y8uHAOEf%P``g91^(^$lIQ~S|KUFvjt!duDw%)Q@b8fSd+u6$ z3R>lH>BzuOH2_|F*yb7239i>a59MFiR-!Njvq+O`V>R=y%I@!L8=6%F{w<5aI#}*syU1S; zwI1q2lb&1rzwif_k*6VGo7O~i1MT1yH`139>(aL>$xz-t1d!8cF2GK77y)A- zU{6;OTT8KNnAijYCIhH7!v&CV(x)Fa%X_$T$Y4taNx!aFz#c${;&Of8yuQkC%!@)i zxHCWo09K{jfh|*M7=Ox>k@z4oa9Cd|fUa1}w5G^4DfVfPd;K#402#sxn5g0>LDBva2I|W0L*&UG81vi!1~IK2S6)!mT7f!| z?-0DBBNGXxGX$g$1mshIa@o7}>>x4wk`-lzu>x)`La_G*A5}4AVwmTm;YEYWh-Kn# zCz)Qy-AZn9!s`3lyG@`Z|MV=mIR+HNuBexOSsP>h0+zalTmb3;q$BF`t6$x+H;b~K zJ!!u}9;^VB3<4^4x1C)yjE?~wQdZ4qmLAcg05EpP42Ut6{XmQ{_>yTr9ejPUs9HFZ zeSNuJXHe6-cbbW@qYc&|g^$=2MvPKm0`m3S^=~CAW9Q1wJo}4_#p~a}ZoiDx@hTu6 z>z1RDpwN%)KbT$o{j^UgEB7-e47>^{3~*cuCKS=rTtN*e#2>Q{#^(%w+BM>Ux1y`I z1!x?l@<8ya+j%y22)avw2jE_?%L0wdT@*41y<`SV(~T@9NpUsrLuGGbVH2U`-Zi7U zz2%@Re8!kYeIP+7wiE&bdd0U*To2&Uo6}yq>X!XY9JK#}p<{6z6hyO0r()Dxtx)A} zr_HBL;mx8KKS6U4{{CIshyLezXQ1yT1i}!k?qtTPZ|j+mb}Mwa*F^9~L1K8z@8j~o zB++QeOmBaE?4cig${bq$2@vT4D+g9P(7 z0`8ABx?XV)FQ<1V16*@TpP&CDQnFzWI473U*yNVo4amF zWN$5=J+2{Q^fE!8I)R^VgL4@7mMFH8{m8nCg2Su@RpHIVf6c&AdIhTJW&tos5KW?s zq9_7`8r}?WLJ5XOHgON(XU}5`7BFi2<%~0G2v);T&CL|x4gGm==yY;8LdU>RfqW_e z3c;AGN&FC!I3eHk>*w#Rx>(O; zTaVoJRshz=D26EQJvoed5!Iaxzezj+AidV-iR$2eKTmwY0|0Tt{%%?NOOoOXV z-Y*H#PzuSPri!KW`$0a^dQ5uF%PiQW{(4Gc0aUXPtSIMpl?nS@y;`$pn$kz4l&T^G zPBXx8kFo3Ln88=KgwbT?#|mi$QWKeIt)5{+Wo=bXeW>?ySqjb?^P{3TOVm39x@)Hu zpQ~hRd;}Kp)c5u0NtO2f-9V@*{z!L|IB=@q5=>6JC z3BefXEjaa+rMB^{03nC%%5EVb+qYNL$(C= zxhguYCUkxijYH%egL?;YWdXJ(&v%rrG@e)WI9+*&UF1u(AU(l7zD&Qh)RD}W{$Ofv zf>M$YfSX2dK5G;(tsS(QY$!t3>4j>wBf!m8im+RccL>+$b<5R`8xpkm zv7d?3EQRYP^m*@r*>W&6#8)$K4UPT!;B5 zxh@-fGE-O#w>6A20HvPwUe=Rhr2`3&t3ifIdm5h8xq79hY$I zQm`MJY(Du^_g=ywY6nY9@DX@#)%+Bh*F0EtT&h34Pz3NHN_TZ7&Tk!5a@F>`FMtB& zSqJ9$*2FxsSLoE47~tjh#_V`VEW@w$O%vFfsP=vexR^21j5HvuG`-=$8^e#VqbKye zSyRwlpM98OWQbW!oYsrW6ZAN2oa!UX2XDiuuEKp9?Q))E4*dhBrV0X#uLaz%KNr^ z?WC!)_3%EP6+Hg?i@b6}^#0pAUsXTJ_+kX0hM$C>InJ<%Q$=IgqP>v0*RV?zs^gc9 zZCLm5aQE?ZRi01dx<5H~orc-pE=g`*Af^4m{XtXJsy@Zg|11Q-_f}gId|>5IiX+Qr zJqG`nooA|#9NTv>A8gr3+YQ*ePQishh$5b6{cY1E6vq67eTxw)*DGnKXC6c9#J$qf zVDI-0O!^qs4ep$_(LJ5Yz0o5Ve7=G=%LOy>_{x@#@o$3_a!Hj#0Lo2IdFpwOj%#N4sX!w6Aec+Uk4QFA+*+-?x*ig}kMF}qj>fCB|^4N?1nBTI_Je<7a z=zqdV5fvWPZgV7asF}pM>ej^9`ksdc!_P0o0uL#{UL8Dy@33en*DK^YI)~z{ zt~QarWUZc)56?V;vpuB^c_VRA*AjYVif~whn zc+PsOZhh|d;w57=9W_LgH;$j^PViA&XYz)MMX&6CbPFso^QmhFIy8kfasLEUZ(bE$ zB^6nX-G$wdGMB-WxaEcQI(}ocdq@`sqfKBBvq(#pDg9*ZLfRs|a=q@!-EJ*k`<>u# zX7KP~)x%ZaWFzgWz#@LxOC(`mmG%4g{SFtISuwhwN)>rDT_&0E>Ws2{xIU&YR>g}f zIL!CVuiqN#X~3p4np~R98|S?^p5F`l%vDaZZ@5N|ZD}W|zjJZC+qc1z`OcE^mx`#K z7AD8fR9;F33bLRrRy47;BoON=e%`5E9>ZQ<@xVx?-*{n6igpKs-QfMNsu=HFqK{Ts zp?Th1eNhyZwwD47?xvi3Q7RR3!{l4{{RV1TZVix_wcSw0H(bNqDBh20b?f_4kFB|Q zHt55w_u?$Zt^lnSHRQ4T^X6X}+$H6{^*BhiwKAvC(N17xMX~}f;zd)@I*$ULoMjp0 zCy&{)Y?d62n%7~DuW8C+*1p(&5O9D?IF{HMH!9tkEs~*N#xk6-p^sdX!NWJvEX7;R zlgrA;(X!a_`5Z!u!C!-O86{GN<}AQYVOtbKg@Jn%Nvnidm#;f1<5%`~iL;e`Sq&h4=_|hY{Y47Fj>!_%qk>?_5+_+5 zhrwp}sYy*=n2|QVFK(muMZ14a4%|n?MfH#imIkH{c|vFsOz`Mc&J&%|6v51{d*y5v#%LN5!`vn92k z+{MMg5POM(M;bmQj9h+kF>PS#@=f?ruq&P~^($#jgjc>(XhZFieMnzCyBR55ZEGl; zWmo>!_o{XHe#)=8chE#Bdk2k_nUXn1*M=YO7-RhUqrcGq?)E0#HLD9u;8k(qd3D zcspE-W&a)@Cm*RDs^`S*-4jDLSM@N*6c{hNHS4fGcWQ6aY)?>ha76P*%tJp*ru&LM zCVi{Cp?&JFR~sj>KA}%YNm1x$LgDju?(?z)RCTag(Njd@Q2xG|rEi4G`Sef_#k|UN zyy7G5;;C74$?oL$nlQ**~p%QK6RVlb?;a_k72lc*&&IbuNH=Ka+{;Mvyci* zcdr_^%Eij58k_CHnyMdzvM$cGZM$vc7_s2?bfNTmd5378iuw+EW8jG~vGk44cS#xv zCfAc%3_qFs#FI9@SZDruvuM$M8FN6w4S5}_&xfRsrD1`J+IfpkGzKU_eZ)1ajU&sR z)#W;o4C|@9>2Qhp)XKhTCzIGQNxsFyl|*j_vS%yZ+7ecL3#dil|+_t(8i4FU83 z=MoA%{EReSv6^lRItm9}*S1Jeq3iurRm>rp`Ptgip$qwtkd@U9NKE zq;l15w{PAj+h{dvkfHZ-1BV;GnNQ{&7fUwBwziFlKAK%ZU#Ozp54$&zPH+4jUBNmt zGPVh?82yR9_$y5N-r+CU85^?Cqw)A^7q@qY0kseFgn9ZQr5O6T_YidPtD{5vM{Ld7 zouiBZJc?tBqSmi?$>M05lAE53&VD6xffse}H3zOw-3)M5&INvo24Zivi4 zQS^;pxc6DKG($Bx1*}6!)1`=idq!=zDCt@wB#A}S_FJ!KYp^QLb) z=G}B}i{$6+?{M`PKj(#6hq|3~x(aKAhzhoKFAM0D>T?wjHyk^L+0;A~S0``7BMYeT zEqEmTxfS|ufoGI7jgu#ayR6Q7uDJBdaov$p0M1UKqoHIly69+tj^&+iZYB8q=j#d? z%dq0a;S;7DB5h0!su)9kjA8Wcd-cW7=W#S4&XDGMtRDG3&AdlHE*oZGPtB}F&- z5CT0+LxZ3$bY-Q*r!k|Kl|e;nbDsByd(G~5GYu>*E?%K)4wUYDpIh+~>9;*06T4ge z+LT+=fX?@e#zYm{Za~6kv{5wOOjdZX$d^P2n&NyK1YS9QjqB2yjU_C?kp!ui9X|oE>*r>Igs!S=R++hBxN6`b7BK}22V?g$+~lP#lw9WOJggu(mVtP zM%@9%psU$ydQep=rSA79rU_ZaU$oj$A-6Am~f09}%UM@N_l9f^G|5cJ)R~k-dmCbpUSWg?|kJG8t9n@OIUrDJQ{L}N8bl{X=9lD9nW7d zYu;Vsf+3_e&H3F6zXcZ0xR%(6f^YPE`z6aa9b0ruUkj3)VT@i^bdF6NxR4L5ycTLl zy<&5!@#6~Up&?ou+N(PGSJmAHcn{J)XC8v%<3!iN8Q0L?4M;Nltg_K7b@-iZ1CGH$ zA$Hf_@xdYH8T#CZTHbxDd{(sH=haWmjyEwlcJSX&G#|@}Q}IU)w4vc|z3zGb(f{=f zI{wVf?x!J%7?@~WChcYla@a;pW|rh~bzPsdu(`g36t+Th3e$DBc*bi3qb?u1lDTv* zcPy8r^%`JAe``H?-T8Ht_@l%Gi^%+@^^kA=&gWaUy*Jokh$a#{2p_CJKleVcR=}Ke z3qdp0J9J5tM%fI3ti}w7kQD4ShtpNeivV)0V@y}fevlkqotuz^)wF(!z3Yy zpHcS`<^GfA*}`4d0kh-nY69FCQp->JmN!0$$tRLY`H+fn4H&;jGW>BjsbahHesby4 zd1~jFM3Zj!P`%Zx6CVMTGpE!$;|eB%ru#*>6%*I(js5QDorxc3s^(xGb-$~*g@S`Z z)y%QtIaALHdxDBD^}VHn_|Ovud3o7qJ=O$r!yUf~=9GcRPtnywNuLXpC8CiDSJizt%5mIM8#*g44JxLTkc*dy60uqi!J;r1i7;e4 z#|&W;@HePxRz&) zLP_vkZ_NOzArTPBXN+g>M?oc(ZI*-hM^cY&xGmu8)kdzxQ(%???pPBalcX-Hug z{8Y~wYA6jYl;-a=``DfQa#lz)`C0i3$@tcB0*J^LCrk?*xt8kMR?KEBZ5wGxRDvmE zrGh+@)bocq)G3f;R>VS9k3_HU~ ztPCsN{&rTvUoj7i(NW}TFAF2T>Hp4_TC{Y1Csfl#i@=52$Q6^ zZS$!9f;Hc{X{I>R&ja^d%DGw2B6g)#-Ro&AiWV#9IaK8w43d3TRz-(;l#GS+(0;UU zVGY<#MCtomhF00G+jZ;quGlq&&@@fHceVx3mNmVVvynI`{II^$ey+0zlPiFh+ad9lhmr=;=Ty^w?N^uvC%U$l_T8`bv>LMY1+7|a z=)~-vKU!EcW=AfRL!_#Y5{{nlWJrCVV5@#p*Xics$Q(p;-x%zpJiWTRh~XXbI24t0 zI$^3}xbTvlRx(JP#9-pIP7_>W5QbJfN-8i`BoRE{jAV>s7Lzr;{ib%I>UO~|5L&?r zm38VpjqQoP5WlsmnBG^Lb)2{MD&O6YnF{3FpACNCs|nCx-`b&vSx*3vBgez!W^+NV@P@LpfEs5ywF){6g6 zK241f@#(MZ@V%K_Bc5#?b9I~S+od=fnS?m|Hw$xihJ^2iABOXc+Ci9xJDaOL+%gwR z_~B-To}w_^cS4sZ%K~~XMVcjvWJKRNg}Z4jC9be2I{qB;<|}%uT;#GO8`CE5E)jh@ z!GQxCQ%-RLSxFA<%_u{CvXMv88pCn&B@ezVa)rfmUJxg<>}}o?)%^X#6h(Q=|Vsf8$JGnhO?YCBcf_jMNKmn~7?$qCyhdeJw$bUZpC&ofkmt5bkQ zSbbYhpBp$Lis7{DYIK_>9Nn#*LLyP5qBDT1d&WeuFM3&$ST$x#;~dW>ZM>JLf}~5I zQ?<@|u|$iBtUvV7c*W%N@+N84cPx%UJH;=d*c;4)$p>j0@?0<0KDKzd8ZrLoh91^P zFyc7M=ui>1pZ@};&c`VNp6 zt<7#|FWMB0R#AZ+G^@(B57yWLSlz+O>>W2vs?Qr>P8t4|AuK3-2Nd7lPXX@{PjsiI;mZL{@wDR z&~~0a%Wb!hQBmv|V|IGvX4&d9=j^ykFD5%dDA|``$ra)ek#_Z+_N2fUVZMnKLqCLO z80VI?vl{CS#XdYYi{Cv*X$v%I{p!7i(!6hB%~Ysn?4&S#B%9NpB=c>>D6kAA&B%7$ z3S3RRH(TM8yArF5O2X~4isaE}r!e5TYw5fEGSOpIFT_S;#T+HX82iG1CfTLMPxSy0 zQ79Emx2cgfVeYcL9dAn9=>F`<0Kx{IOkFOJTz&f=&eY?Ehi$y!#>qiP7&cZ<}#d4d^kSIE&T@Y%U< zU${5~&IB!Ie{3!EgAFwaO$fY9DF~_;P!se2C(X#ntsDy5_QH@Vs}$C>jSs`|&Kvvv z^+K?;v#Hm2=Ex7HvHyi=(w$j0<~_kTGEQzzXT44STWRT`*!d?uc|uDCbC612SI#<% zsk7Whfk|3IViZDpXMDz!%Hs#K%w?VaYcp7R2KE?m_ZvJkP`LyP>iNtrCf!6`J4Y`DE6~ zEnC|@45#1zCi{?EFEAsRyawh_J(b!j%Nl9KJg~H}n)~1IJSK%+&TmLlTYZ|?)vI{E^cb_wVCeZw zvEV!07#vA@Nk6G&EA{4|MyxT3(vz$c@L^Ncl*!tSHQEXYyv1dkp?T$KzHMINLU;1*rEY^QqTsHZ6Z%-iFLLAk*+8gbwyX>zYMdQ zE$C03qzM~a|N39LM#6(&OjsMqL=jeSwK#`Xb(eW^@^sNu^uK{5pSM(9?@~>kmu+h9 zu+TN;Dxd!C&?IGABK|VnqkHv&l_M>T8P&8SwgW5^xnq%ATUAk#GF=hO(Hu0<)If$G zrX?9%`Rc8$!`zqQ_%VE>@7U`A8ufct0j9>X`ul;Cju5%dca*MtmuI z=c!IG8$vx&p;UgMJ>x?9Eb6CroLSr#>-({||2+D=?09JCBV)TfT%6=sW2|ZruuRaY z?h2)kE|pV*@%Q-(D!Lh=68P4VZ6R9}>>Nv;Ww_F1W1<9XbXI5TA3wBF7m0Qr1U>&0 zs!4d@B^)JGjamYKGJ>hARWABVexIK}g7@%NA|#ZQPsu835k2%nvL#H%uBTRt_^GI3 zIW1G;P>nxy28kbxtHZY5l{BITa2wImXgAkEq2t0=OF*>#$t`~-Lq=-Z7m&Z>Sw}3!JxoVjM;aPuE_n{1- z0k8IshP+=MRe;}vC`f`h)5&r~=&)tg7l8Kgzkqd@q|cnU+NcF8O*ZF6X8Tp#W&HqT zBDp9rot@Yk6JtVKr_bf64Q-BzcW?~dAVS@r9<#CT9wqQ#{WYyo^zo+ zm6L#>)V0W2LGKnGto|2k#K6n&ef+cySb_Y!vW;#kF1> zgN5}7L|NEe3*g1jA9M>r+u9^kBx01y}VD2Onr5u}+$zc^2!^@)Taz&~w}aQsaKf>{nGfNrqA zaU1=b{cv6sbiJX?IN#46q$s&)Y!=+0u;0L1{#mO~Be zYu5q%V=stR(I9Slk$T~Ohyx++fzu%KNdcUly;c==uNx5cUx=*ISgqRyP0uqwJ>wv> z9svAJ%(h0jT43BG5YcJgK#vR$zv?O4e^-OYAPw-64?PEAHbpPnX08^REF_WFWQKB%=D^UF^J;OKjnz7|Vb z1QKADp`tY&K6K0zSOWC>2Vj`i>;NQ>Zy%(Y{92I%T0w5DN1nBU*omwTlZ<0He@F); z`bO^G@u>uiBj_dB?r^;Y5a*j%vw5x9lE=(29ss%_^C?%smLLP9?Kjc;01(da0fUEZ zkg+3*;Q%moSh3i9QcWw@Szz@4<&*Pi#su&jFbwqWUV_7vYJLI{%%eeXbp?Hu5(^+M zWA@7EdRU7gu*XJw6On#93PV7iK{YFY#Cp`~WB88%alUfRyL{@@^XCrKNJ{f#k`1J( z1S%gLg4bFHFjv&k!w{sNSa+>pNOm;aI(KZh$H%h z{u7@90IFvF-13)yfEkn~7=GYF`U{+d0>=1vAox3&TKw1*P->0`Cs-+cCZ+ZNwOWuLf#gkr0tewBY^M)##1znqlCj$H?0 z$KUS<8J{*^O){;Zd8R}$Wi{vGAKZy+4_crH*~JNN4b92W41BFgGYNlkL%oi1^E*qj z>uWrQhqX5_qnhbiT`#n+;tg4fN>FYQ{+_`!a8ow9HaT)@WOgGlf&WYDExN${ zj!FPl*Hu4f4?qlQc4q9dtOK0zuR&anI_wXqmE`yRO}SQF0exTjGXC$Yv&av^Z$=4G zscu)S{bK)tqlN?{`15pU(Y0$AVU`v4N6|AY5DnW)R6098{H>d)t9e7rMMf@+Tg-Jf z`pQF^tQ$LEBBgcdO)P5)@)iNlvj&JVs$bwhJAcxkOmpT8F060M%M+_o<2Xh+@s#-r zU!;`!8F6LIM1tU;FQp<3`DoA}9TbxZhapl>_HW&=GCZ5Sv|we-7Nu;@58M<7zj#ES zSXsuI{4f{sw0si(;U=Vi8$2P#CvXv4MAaG*=EMjpI07U#B0;@xqmF2C{ew9X+<>;a zjE6h@vwKjdiX8un-qtdWhaAI})8(zOTa$ak#>uhy>3PH;BW<_G`Y-K5o!(moGEcO7 zV_b{4(-n6jKTBNMIPppggJ*(HHp<_Fkd)a@*%MJ8Gy8+1m-uB+>jM*~6@9z`hLcU3 zgYz{ruzI#$foV1RPwUYLk8;ABCwm2kU(Nej%F5qHrc~7WFYX)K0Vpi2oxnnH_>?KO ze!-#b0LuiDyeTt6d<)R)JG!kF5WK}Ed_CN1-fJtRBv)pJqD}t|P8QubEtnm#IF=IM&-7Rjs!5W(QTNuU0EkL5)7xR7ZIv zCPy_=#n-}Xc(*-eY?nJ5^)zz69xrZ&QFK4~VuEw4Hwc|Zd+4Dd+@EV6WCun!fLDaA zO5t6Hok6{n4}fEx;hlc|Q9m^zRW;>`S8ELqUe&`4z_~NSdAmhMZL%nX?J?S!H0imW z&Mu5vJ#FXq1L#R5VOZgxX#!RPvi5+bN(>Rdzr*b$3Z7qO&vw<|A$>0ye8Hs3DHf*p z#IfjEIS9Qu>I?!-R9}v`GW@!`J^Y(SyA0{@27bVm6unOnmRd272s#f*nX@xEk$$na z`giULP{m}Pb-@;8e?n7=-C(UKE&~LW)y5`Xk_*@}KLRvmFN3_@ixLI6YRYAa?4F(b z9|KGM0|7~FYTLMDDZTh+mE=nqCstH8l8pzg$R1`m@~SPuGjYe=6}sWrT9G|`!2*nS|hsIKm#2%tdi{6{^FO5xAi4- zj`MF@bI~ANTd!Wx`wujq>Zpzxz4rR4q;Wa=^;34EZT@!gZudo%8-pVKOp##wFYW*1 z0x0K(^kJ!yr(B$gj7|a{U5;_4oo2kW_Q&x?01FTL*7CO|sA%xag!v+6*3+mh^j}QI zJ+T!P(K{;`1fe^i`NOn(d={m;(oI>cvSNRGeDzK=XmEt4dbm+Ldwss0wlO~Al^Bd$ zqn7kud61F@HK4k-1S#7TaQS8XA);dUN$jM~{?xh3=63rxud7hLdr9Xm9Gj<3cXLw@(WD2&zWzyB>ei zyi7-C*$$SWPh`l$SP^;mZ07lH#By#XWUTKR*+Vf@|cfes?HF_DI3ALUS`TW$b>d-;+UX9cc4vPbw@f|}|=*IOFtM?){~ zhSA* z?KnXW2YKA1x|I3fz{f_j=H>jV%nrLy>F}$kW<>;Jd$3o*UAXN8mV|&7&AQ|Wiu_kC zp%ia}c#JoXxt{CcyQ6sWa{eB^I;P?7YH`?BbBL|jcqEE!HGU!35#C*Vph;b_oIo))w#=fa#rzL=VYr&P{T3R2#IgV@w0a)FWLEX!L9W zapZJMu~);-2Nrhrg+i5M&Wg4~#@axGGBwp4=DL??w#oa6rFJS_ShoDe*5`5g`+c4gi9Cqw*nMHB5L4qtL-yC7=#Z^ThL(=Jak9n^^fn zCulCfOXjKhjhiszRbao&DB0ns?89MlMEN(03VVFw#_N$eN5wce#{QwG;AMn5FZ}?k zNs4iA#&``yLXlFR&(USR(@?~&h?d5Q;jFKqEvSlNfygKGsi8fouhEv6kj}FYm&j>p z)Jy>Br{?`}aDB3HEP~N(wMg*PUhG_dq(>hQdOq>ltCk>-etKJEJHz!RsR{d8no>nw zm+aCETE>HMP>o`wrJ>nJ-eFM_>d^*^Afgnyte`Ne@Sx|0dBVwQd`pDchpFhVA64`n z6v;`vavN^|i@>@$ZzOL~&Uz_+Y*>atkRD-U*uNC3E|{RLU)Imh#*k?FfTWCZjd4sm zlT$L#lk*!@eLNYEGuW8dgnxAYeoZ_NYbn3TLHjvt7W94GA6^%JJ4G9B|zwG}KmRzZn2nl+Lp+?#?sF<6YpC>o=5+FbmpvfBRd zy2W#h9~QUQsbGDkW6gTHF5^En{(ec>Y(i7UI2YlBeA>s4cKr+PCOH12>u;Vt>}qul z&oO=iQ{CEeNYhI+q)36$)VEY13ZirDP9+GD%V_~1e&`p*1Z$lwjQMkX8siaNSSWAM zcKB$O!8n1Q(_IHM!$|&c zw}h;GEWS#e#JVA*4M$N(nj%QswqjTlWyz*BdDqFVx%Jzi@3RSs!B`;Cg_%i?lBZN9 z^h&@?^CE5&v|pAB-zZ{SzzqY&b;K?@Hm~1uV*J5qD3y$18A+^+h~>N{++F7$LW=FG zTs+V2tV^L+sex~BfA=xo3@r7s4@#8&8+(q#)2&c~;{U!QJZUh$xqRaUsha9u6`sdt z>c4b*rwQdXV%wnw$3P5?C`$_}@X}GPY?VBOnXxEC*U|K;ScBegZ;ZL=WDp#rH z%ijSt!6-~7svjh^VSO=~uZ$QyPx5yAhJzl3QtMSg2cMQ%Y%-cH`eJ1a4Ju5HqK;y} z5jA96RxWc5eY5iDg#xv;zoE$Ndxn*T+m-1rNvG}&F^zHOD;!SESp}EZxCXOhF)~8i zn(v=H_e1Ia_S-~)-pk2D4o!*YcI7wzx1_yz2-B(fzYM-9h+?3IvZv;H8XDuaXbOA{ zj`qG78&}ucM`fJdDX&UUA!b$_5?xG*-Fyz6H>P7x}$u{DjIb|jOG2e!sfmcR+#USVpmU#Xi&(Y zDgQAuEW#pKnhG=6gYiKp- zWYiB0x%@jkD@zY1t;hWEw$lXpxmPt_-IfhC)iW2%YsDc_@F2fl?5sN!u{)9+vs|vUA#yHYUGM==*Jw%2HtNS)l)rp_xs_Z>vLN6p60nl5Zb8Bh)ezD z)Q8;%OawKL&1iy#fVF3zV`RX}7 zoy^{wOJ%EcjPSHUUDQ}tY5H>BDtQG8!NHO7_^9^L^s05_v#LI1-pvG(~2r{m&VZ8RYdTQU5 zi&k)gd}nb`7i{6Ms!l7evE1|6V!7BgZZ`Q8gSF)j&~IwRQ{;Q1(-~;9kT;~K`oj7l zDK~5yU_dfc z_f|%i6^2@@y0qyTKR3UYPm))5^+wp;tV5Lo_OMpY*8aI&JIW=R2u*qaz6A1^g;7m* zb`>fvd{7!UbpGOP4w6exh+ghu?j?GC3h#~97&3>)FiLz#$+!_JDtw&RK?)kf!-TD`>O|gO6Xjhn23p5JQZbF zcuv*h6`EyB-JUQU3Ti zH&bNM0q^ZcV;qzM4mRAe)4a*~M&}~MGq4XDv`_}}-QQUoItfpRR0I;GUDngy=o!GO z=l(XFTm4FZYp%5|6x0)X_n`&Arf?)U%Mp=`Ed3L+T`d@MkNd z(r(AYC(Yl!KT1_;37bekcsMYs=LMU(qt4DnyVPu~#LD@GHZ_1@B~VH@UsX3cI*q7paU~#$l;PKHGZI*P43JC983^} zTVIzV{`yH(jl<_Q#N-i3G>J7=CR&WbJ?xdgYhmRSG-ZaLNr&TK7Si+@DNEO&rz?rvYes5w|ea!L@Ib z!iNj#C75sZt{0(GT~PY05gYAOzz3;{}EItytbt>Jp0(%F#pZzvhetA7}^45Ew)2Xz!*1Cgg z8CiL!ecF59Cket-zj|X=F&CMOqjO{&hQtC6G&1TVKD8c%AAICKQ&v98q*-C|1To^`K<-t@=N2((x6) z%0erBCL;rwG!LWS2_b4jI}I`fqb3dg3uJVlo%zGjYe35$Y{<*J6R}TZ3|38kgrkLg znv-0Sm)Mb&me3&LUQH{J-61B6^bOt?ho*u?qFgz~Zf?P(SAp(W5UMhTRY+sHj^hn>2Dw&wqe$XUv@6qH3$D)qu;w{mblHpd<3u1~ zVt@3cHy`9~G9ePDAI)Lrj1EhYO*eONZ88C!FTYDWavE1Zj7Le9xE6Pr{IyRnU)IgO zP_FShr}8i#!;YNV^WK+%^@+NRn4h<-H|z(6s_Z-n9^w*%uCLj~155U#E%@K=64{_c z>ObfDXzlM0rLCXb8;}VQhU+t#*eDNte2t7FTc7!1(qT}e3fv6bR><=Fm~oWAy&q+N zS9)Fbd#d1KIlsY$cY0>=rN(wjmOGpB7;3vAs`7-^Hl>>izdsA~5sCn>E0dY89x@Y2 zLiJ~jmZ`V$WA`wV(`^yCNG#`=Kq}gb3T20j+!WnD9#w%i zWio$S!SCS)`_o;rgZhR^35=w39t)uzbOCqdz$cpwdSJ&-ZGV>x(v)QXaYEcRj)ccnWX)SSJ zB3m=Cv{qn2MB~$!^Tp}>*Qh;9OQVGeF1vi`u9W+{F+@F$t@E{4TX`b5kDO|KHcLZM z2fnGpq^bE_Oj}j#!N$l^st9kk(4&v_fvboKB9E7!I#pkz?^0#u`U;c1P@Y#hjpc!v z=i4@7)#o@ARIqKdiWMcx)FhtNV$EfEhzq+fgU>ls)5sypp6g0amRdR=n0UxEsK-b) zYR(my`0?!$i)RE%(Q6u;ZH{e5fFR${!7q)qGs-nkx&oF(eOQgLH0JUEaJfWlOCsMe za%IYTW&`IotYC%KYVR?KLz_tpyq2z&m@Rja_X{0>j~aWyB_@eF-4FxMB!5xkK!pMa zX3iTuCd!9s=1MtZX(A^&kli-W$ieE)En11UX~jti)|xr^nrH5j*F4ci&>t1#U%RVm+fkc~CvuQ0DbQoGz2aCQh%fAt_nbtzEuMf;kBV@5CxcUW;xZ~{l*lh&`= zvL3yn^SyD$wnn7xbU%23#=Yj(*g^5SJFJD{57wj_oEKX)?xp+OkAtO(H`|7FdB_ov z>NcfGN(!9nS>vJQmS4l=-Q7Q=WN=fl@Zse`7-^RsxP-4+`TJ$@dO~~nsRmJMn=JJQ zM(bpxB?l*r13hnPx`}=k_oKWutka2~W-sJMnr=Q)=FN@Q%zl%qz*o?3gcwTVE?Xl3LbH7Sj-C!BI-n^L3ReRs81H zlO>c`Tce?L6y-nDm+0(;2Sw1qWX0v*!e-~=t5rgS-ldx^CbJD0xX9TkP92Xj_B{e% z67uL!hHhrD;^>*Vk1zsKfmir0DK?#sMTGcIMyQ-jS8dl^Wl@nxDq)T#3h@4s3M|A>L>p`q{;^S#6; z@&$DO2kKcj;BNOy@=VP@U&YQy+xMNVM&U2hlUZYm=H-)2`Zn5_n~Bj{jG}IZ<(~aA zPFC5K?JH3YUHnRl3G5*9fz;NYbdh_Vtm1_BOF)797vZC`(9_V}Fho)I?bqLlp)1CI zp%|CYrI|nKxy=CXc?4>PN-3%CP1N!^t@KRb+V;(rw84Mcu>^L=d9j<~6+(U*?LtO% z=CwLK!Zzs1Zr5MKLQyq0$=dy+ zGOFEnxGM6{Zu8CGajG{v!;XFdLdeP=vWZ-i52*ILHZo;iiyxZXJH@DHjqfx!_rK7= z*q1CIqA(5;B%c@Nc|DA(qnMlk$1qmo%JaJ5hagK^(&ArU;ik%yrGtDzFz&8d)uT^6 z`+eJCwv7>(tU)%?#UZYWEnFWcpVyV*@i23#<3?4CD?+WR2^x8^vQ~emVlPLNF2FOt zP|}6lMocBtA{DcA`I8L)n8&X4#<=(p>&2mf&E^EZg$9~Sjx7l;;=-i;*fLsG!u<;Z zMxT^nRzZ|88g=op(3Z7)lnqElCTTYJ+ecgOtGRU09=Q@CXAY%&sFa#7J$ipZ;S^k% z(p7kdVPA~&wMi1=D`e2LG_jlLAfuQWFP zQq}qFz>G$Xko0cso7S;1s!s`cq|uZ>+>=uK07&F9QvQhfev#C~q``_EmjyO!&n@C9SrNGDFZtG7nq*0vS z$$a^{7MrakY))dvX7()Sb;W1j+umOoKYEs(ndIvs8zz0I_c}?}h#=fVbBsKqFV4NmZ-MPi%Y5_X zt;E*qRAUK+9c3?Zl0$Ie9Rx=)!B{%6WG4n;@pLU-mDWp%v+oPMDnDi7e60e8LLM26 z6w3aU&w4Mx*$CV}wG}gkkv9Z~6%DxH7GULS0+qo{8yAZ79UcN@2RFn>L6(&d zeJt7}K~iU1Yu@EX-xrbUt~o;ZY&7BYn>vkE?yK0{M0dEkZwJw`!bmU;r2@{qTxpa0 z#s;y>bR%d8r3p4%D!Ci0_FLqyX>QN$Xs$lN3w4Z%*?VtgA2LQ*y~t52##`O2z2e}| z4Z;16b1ItgLBSF-59_V6)}M<<7cgi-$|ipg@%@gYwvFerJJ~P^Y82?p%2@Z^tV}rC zfyc03wfUm2c3#ql7B7=Cm$(Lnv+b1}r|X$pgri7GuaN_OU?sYTX>#U-Cs(Aj3vueT zv=c{i&os{}vbeq%`*$XG;wMf&V|SRhQXp2&+2Xy_F(6`I$!s-UqY!@{id&IMIKa*Vf)3a{XMyzy|_X^@Vtt)GtIR57^jog6T zo|@3rNtbc7#|@aUXKnrZI{)R9$Zv1zjn@%MHbgh@v~P%?`sk`es-d0c%4x6_3=+?X z?M0xZN?>$KcSz9CDkDgE(*sBZGHGEV^G}Yt4I3xt0wgypp%1KS{uhygE=NDMQlo`TPmTyp?!5X zv@5zfnZS-lQbQCjm*xJ*L-uKUW zi0OIbp0vLax9(+(p(6nL>kvB0w*;z_PF2fdsHrj!Hvr)1^Xgl1V2T=f|0n-g{qw0P z@@&vaWg;vS@}~!^h)|ekYY|Ln6fHy!F;O!7md_)s#}%_mf!dhrZ(hNcI3w!b#;cZrI<7kiWrVzV)RB!PvwK;IJY91arP@J zv(NmaA2Y`}3%l6Q3%`W05^ugHuy7`@ct7vG=Gt9in{*P5VE!IqRTp!#?bjl7L^vBq z)ZdMz9{pQKXeQGkNRmm+f%48$IFH5i*4(|m|9nB`peg~W>x+K6piHpmpz|V_t*ien zl`5Mfa1U%k#higBF&zItIjB!{0?%~riV&Ei3|8c=sy5)iLYga47u%Qm(>hp+#2wYe z;aq6WHJBT37q=w{`}*BEhaRFmRrD2to8vBiY?HN0A(z|7M(l6@&}8<}3~rWwjVrdw zr0rhu47Z<9)5AGruk^X_@{=xv*AaYJyo|?Ff===n8)BJ|5OHKSm0A^sA;WYDtFd(O z_#-s)BkOvGH#tFcx2E~&^eW-l&HKM%4;}6X?iCowUN`Cb`|OIMIc*OJ405XVB z67e$PZ-^V4Ym!GE-?KX)Db!x6{4Y_7BZ%fSm>B6Tk=KY8)&8V{(hX}K8q8vRZLHo^ z^gTCFIym;XgfUtamoA^YIK_3wn*=#mdo)=V)?*^@8paC%d77?%f^`)6-zX-RK7cf> zo8w|HNB*1AB9hU0=^fSaCs9QXe{ z3-M!bGT2?=dqbXG84xLPWCn>2uyW4LFi*g9r1T%DX%MJG5xrsdS4~OSLu_Z{qHZUI zo^So-W9SUN=$}hK&-5_?yL@5KJ9VX5DV6!Q_#UmJ>#L1PSz2mM1NYfgzX>(ik4_-* zyZWv!$}-x9L7oM0$R3_)MIwOuRbENVfb)kKLNp#C`7vJXK|tU4q`!t;@)akrPlQYz zI$8e#otoI7WlzTw7$19CtJ)ubOErz=0+m-`z=9>r2E5`Y@s1q0nm0gTK`b^PF9uv) zU%%TlR(x0m?ozH^oL8X;x3US)s#%xWHNEC-()>r>em5|*_5kN6!)cY8qb~__{Bb-v z4bHty*0%`1C91m8EBBq}cgEkozK?FO2PSv~&9?J)thbE9jCa1acVHZVjn=Iq&Q8kFK3@Bsm#qRhd77Emx@JV>2L^255O8nN1O z#8yEVsV=jw8)zK63*_BI;JHBXY%k&gOJceLC=MZzvDX{}iZTrBq?c1%*{-lk(}sIs z{?O#>9t;D|I^hDgn56l;J}|_|-2q5vJ@aHw!fOhluUY{{GF*E^Owk0CjafBsi9L#g zARK`RXJQYKXOdR7?v`=^T941(ZiKxF2P`HlBS^zuKoYF-RIO1_V6`JE2mtsNZ+4SU zd(Vs@rxxR2?^^(WIOqeUUa|{-n7#dj!eam$+9s)AkvwF9d4_5bH|YORouvItE<1Xu znTw@$H#bxpRAVtFgEpF9-KOcSuMw3;>tMWMf{kND`(+ChAqWFMC+Va&qV@oNpia;F zY4h$*-Ak?9HJ}(IN8rNNTAHeA{BH>g@ zylL&kjHsh{)XlO37Tz%so_dk-``*kLD4zCH8sFpZDRit_5k{1rSR$YRL+wmi0U(>| z3xMma`&d~&CBF`K6|Od~C++et{$9g4+B+C}%^?cDNcH0!3(CtFTw>KQR5Dty*&4&3 z-KW4MOS4Bcn@pjttTPW7?SDuCl;xqztUeHD%6i)+1gTps?L|R_)qRFk_S7@?h?|nC z)rZv!>-?!x8mQ<*nfy+GHTl+^as6fYMnt16(BNScDGQh!*ev42KL2ulQ568?2uIjP z4^GnvD-IA&bH8aa1GmX$TA8CALJuna-*U~w)r39(;F?`linq%18bI{(VJ(BERM+Xd zoiU))+}8w zoUdJ-&2Q-4T`qo9%cwu!KvQO@_|O7uxG$CK8^Ss}!jh_xRCktpnBfhyyo?F7z@NJz ze1fo$TKJ%3BF8|EURfhbFaXYMXpsn(s&36;yc0z8BSJ^f_Vqwk&n*ed0Effxg{7NY z*El`O@%UpQgg;bOyNO1>U6n>0U0g2HOS9=v^BUBQj=4Az9VxPoIO-aKG{1Ydlv-B( z$oTZbG3CQhMi_q`UgMb}qNkh+J1H#|t-ai#74$Kf1!83V1`Iw0PuVmm*QWBnU0xfw zb_J(CSyuKv#ld59KK4xZ$0s^R!)Q&1qKR<5I?BszzG=xR4ad`Jz6t=`0f}! zoi^a}Lul*p#1r9Ym|0aIH*pNbT(hjT`f+4$M+ina>HIgk17_uIemA@L2K8) z`=i0yypoR=2$`Z}y}=2E`{^Lm8On-k{%$S+==_Nhbqw^eow;nAVT&Y?mnXe3`YR8d)=I7zK0ZRLICK-h~VktC(OkPX6`-FVo` z+9Z)-gw8Pe|LX@Vv}zUwaATXrX|fg7){CVdi=4Htq#;`YS#~_WmO%`y-!09{Xi6{Ef?A^>OLX6ssmI#{Yu|p9g2hDF0tdH zxBH3gtdeFmpqqqrV{WoYiEt$vR9$oud>7J75sfV5Ny-0MuX3Zu(4Xv1>-Fc;qHp`r z`GxS>wQ@UWu;ocF?L&0|^wN{h`4g*jvvsjl5{Je8pOO1FIbpT2`{*yuB4=ybEAK0W zu(&u!HkV)&u9GQRoyBMJYzARSO|@Aa@TIa*PUFgUj>CXWcfD++id0!*l#|Z=X_h`E zmQ%e0BKwm#OwXTlxfhs7Y<-_~BgJ(a6?Arqg4jFvbS>pwcZW`lE7}g#;QdMVh*6+) zn?CpT)byZ?X8J;k?X890u>f*ff9(i|o+03jFDRDCEOgt8+J)@1_v)V+i>46K>DvM2 zF|I9Y{pORe`PN>ydV$J+awm*#RTcq=)!7V+>`XhnGcV>+W?fe;{Qe>A%a&)6B+PT1 zISf8Vd!;_+aV2cuePjgHc#_8_V&{wOhiDoliKB4Or!C(r5g8{O)CCqwcI(jxX$*e= zv8*|s6XKziO=<#cw>SLkvObS_8wi>P?F4TOJs#BK=hA(c`t94>0|3+C4{v@>*V(S@ zl@;$UR!BKsd7(u;{qmvh_GQC#{U;#10~TiWaU>>GQ`Fv4GC0C?tsm-|7~O9)g3N5Z z`}k{7`v4TPZYe@dRcpB3+)+wOa2S}|)aSxTbM@=zYoHc4_33+z^V;Ufax*V<>m~IM zut+iW*1lS1>F5~lHQ>Ar^ItSlhwHJ4vWHRcO43#L;3*pNq<^Z}HRV+Mcyo?!B3D0Y z;Uj_{+-X&dwY0?_AjsthjLLi%mKaX4Ur0`KBlanGr#bv+m|>_B6aGcA;%-0!ZGebwaZJ z&q`I6Ck8r0Hd;017PcjO#K<%QQHU8c{)#jX0#q8~6^5{U#Q6~Ul4w14hVfrrrXz(+ zk1uc`upUhYDQg_7A%ca9+pme~ac++hb0e}OBP|k!yE@>45xXX??;$FzE{JS<%V0R< zAaw@%#V_O;)N>F~5E5QvuNnXI;JoF+;}tCQZU3prup1-;A&9hS@g+S7p+U~q7>A@b z+7@ezP$^T@IHO$+?+`glcC5@L$iebt7Ie3y`_39h#^VVp~(3EXz zPruJ}pTnR*`ldhrf=HE*4JgPheEx)Zbo0C0Z|mYAA#<>2oBfoc73Ta4Hs&zA>+sHz zOd$9Colt@76?)*>)XyOG{B8&9-`i5M>0m452lf0Zv`SkDjr-vbm>iq5DlvX%i`}ZS zRiJDpVWh6%5A=5OS+=VigHYBwD|F+&Mh*VUA-;wYPM5YI`m0YVWKo^{2w4?k51-=j!tjFjNTOU!xuesaozWA}*wbbjR?mywLS9cOrhXWeeELH1 z^r=o{u+@{_UWeJOW=<;I>MJAkx*dVXAW-}e;4abM| z=aSlbowOmgfzJm*ip^#u1a+J?MADBJcx5S=!ZH1Uk zBsEw49&f6gpLT~?wfugzg(86sBir@HN;eUOiS{))@o=X!M?G$cbus;fwa-5(i21Sa zG0B3H;s(v3fc3_&aDPx<)d-S~=zek#>5-EWDmQN;&Gel- z=V9Ejyit~Yn{k5Q4!Yy*oG?~>+|SI|`h>^~%o^~Mh+eO8eehO^KZdOArJ_?1Y|M8( zxGy;M;_@mGUXhR+%r-S zBZwx~>L~KzD?Yvx9Mi>^%ElF85T~N(d^6xl$b~{-`xr)iTiPWUebM@VsQT)tIG&(e zEJ$!jU?DgJ2);nV;tnCW26uwXq5*~qc*u1YTFWmMQ~IsSl4_*k=|Z71jLRX!e^&9DhSn?c z!>aj!{KtmkEY`9lqAa)wX~oL;TS`c(b`Y(BZT*b#g``EOCtX`ydvp`xl$$Obgt^VR zF)|ky(2*{cNOe>+OMVK93Z8Lpe z!KkD$F>Xj5Lp*uh-6vY-Ap4tO`dy}F>;O&-PpVwfS*2Z)58 z+mYt{Gw+KQk^kuXFji4)B})lOs$QQp;RN{NQ~#|-uWR*@zD`gg#(D|2i8IsIMMJ2< zD{?SBcN`UByX!$>C*8hq-Lg+kc!@HNTU#I2FD9&}_4ZXPW%T!P~y7<26}FWwP5=N?lq>`ULgYE1X`8SZCG9|>^A#X#am zBE;}J0E$vd(g*HfWT(UCVChwQWktQW;TgDl-(U$t!f=8vmc-Z_9NIRmAmrN??0<4F zLGq*1wuFX~1F;>uAZv<1W|R*qFO%O#QT&by>%yU$3Pc!b6S;XMU#oxY6iDF`AkOIU zgTNQdX@-f}X6p!n;b%25_7>VoZcW&!8U-p(Ku9H^AgM3ev4Aii9=Sf zOnG|xLXrCwf9|N}r7wLp303^r6K7m{c9{`7Ua`6ZI%Ybaeu@brUx|v|YTj1A3La4R zM*K(;#VCw1D?-2?Krlamc{a9;My0h{=&nSBP^X+84XAk`6f)({@0cctXd5&}9&T;^ zk!LjWz8yA56oB33u%1wby{~__wCoB3hsTBdM^FHM9_)X;+QYyO`oKy5Cy?0fn|%bX0+WaU!P3TzNLSd->J7 zB!fz7$d3sXSyIw!?&8Y|l3md^basq@xb!A1^96OEQ4S)gd+@g=3!AegR}7RkFm60n z)N@AeYA9W|%L;XuI)@}+Voqi~Qb~JV+fU(`_ClPNh@8ba^}mG@P9ee}KOz$-SjMB- zHK~RM$-yqP>taLVNL>U-;mJxJBJ zf?N?pCL*;)yVS1$I4K=xafNe>45LhU*->5aYRJHU5MW;rt@% zscNC$`uSszmc0knP9gc+3B&D07dZ@j?Y%tuvc3YHVbUMKq(m-DB znF?_6>r$x&U>HjBuVhWzh>BZ?eWh7T_4kzD|EWAv@WM2`v`RO@ppq*qWo{&-gtyck z-xseA-^Lxy!KuFZ4}jRGf^5dljBY4=(X$?0VRM-LfR{J!_{Wt5`4yIx?Q9#_J#xDC z>8E{LGzelml;`K$(j!GbLPM?c?WP7qjgm=2fHMv`5v}axC*~!ep-7N(JG{EH>s?`2 z)up38F~q32FFzctKq%ID*8K{y#*2_egOB*(5hu31l+B@rg5WC~0vjp~_2<78H8>kq z-hevpr6nqJe9IkYft6nk2^1d{6j!q7XX`CE@DjxyH96+%b;4)s%o5s{9KKw|2??1U z6VfUz%bFy4I$iHFXsg$rpF^;^1vWxmSml4srf^q2yS~KYejx==uuhl4@`WYDKGxjR z)J3**g|#CzeTu=Wa=cGB?9#-x!1T)u!sEf0n?kS1(*R(KQ{P_?3hzs_25!p|t|E4$ zqh=w8HmPf|rY4s18NWrM${VtpsS>D)Vvt9-y|Iof38Z=GIz?lk{!4W;Epx?NmA&er z!Gp-*j`*>>jG84DINvZ1sB9?!-aXzqV%vYJcf9BpR7Qy11d}X?(MP)Q@A0Es&VJHP zq3UrccnEmY@=d9FK)pSfzX##FFW(T`%^|K#&~zP+2+=*}IH;CqtiTSyS#cC4^fvU~ ziU6e%Xu!ebONu-UGnxI-8Oqf_e#YVd7kRj@ zR)i6EiO{ih+;v|uxhdXfX5aLs#(UUQMSZ+Z)zC_HdTczNFIy^ux)3HxsjoL6B@syE z*Ae_^>LZkj+sgfAig!@5WEG`a>$2n*r?MPH>-Ue4Fb6}dHC>j&qwWI>g?a(>gNqdc zs*beYD#}M?x1{tm;tCUsr`snSjB8$OCSQljaAhEua=C%zABV5#RR>j7?sAt-uqSqe?cZDhl9rw+6#3AEIdQR(zNjl zrd8XmyPOriA9gI?2#(5azR)2tEaU11f!=ggwERiHHB-R5s6yJ$#6u{#`}LU5lsWJ?sV^g<+4`C*(sVU2Ek!%fVNI>^%9-p2 z0QVuHOnVXLWEs9jjya^*EO{T{YU}%b`fkXp^nn*3Uy$X1w|^PZ-nSH1-{oeuX1yFK zcV22V(`r-~P0(LZ1-H zGV?ZPHy!tTr<|$^Rg@owQJPDptkK2RrnP){Uy|eU_y8Ro!>Xrklz0GdGmdgVYWLG3 zM5c*4CvcKG)-P@*yV3EQ+-eo2eJzbKdipGW^gISDy-ZrF^fI5#!T+;$HubFL6^RRf z^_QA2f4ux$7O1*j=p%ht`%>u%(>_A1+bZJ`;R?@U&D|-JN131kxQeteZAl+`fyFo- zrQp{Aoan@l=K;3K4tY=NOP#97^M|E=${h62pn}9SyX+|rf|giDgxGdJmef|t9_;WU46uC2)2+e= zvPI>8a6OY9J%s>3lc;!2ft@puX*48t9S;2>vw(fG+o^e2LY)w>G=U zUsI#cQ3Sqz^E2Zf*cW3cpubFEASWUd?gJNsS)8S4{nsSypK(2x(Hj7{8mhM+rlF}> zPsPS>cceZ84ny>KHobZbgZmihMEA`?p`Yu_lq+OGFvJqF1&pAQ*q%9Ysw95^Dqll- zFS05Ra|NzcO@;biW;}59@JSQ_r!AN1(caS>$$CY7<{3E@?=_xek%+$?~shpKjCA)lt6tU9xbEe7l^gkS3LM9sYXla08S7&QLfF4@(+3k95L_sKEf^c+XArl4Kqo_ z@;)pg)E;=$AorOnx4wgiRefpu3J0Ni8Ah5E4invg6pIW;&01_&9TU_AM|}Pe=$3oS zki^70EhFl3yi(P%*nko94+(v4l!u2QKX>eyMb6Z{gKZq!m4A2xt#s2k;Fjk;`d&gI zM&hb$6q>@n%f%`V#tWNZxiI2X(3CS_>zm;}N~gW3cK0!{7X5CkI7J046YHZ zxbl-ri(;~ogsW(@xY_u+R|UaK8HviMbXrARF{oCWMMonU^B9w)-jRLheLjLs;B4%Y1MrkWbhD;#2wyw(WN9Y zZio2CIdgX^1!@i35z{{~Rqh1ge!KxEk8*zKI`tM&wV1*72yCpW{+RMRe=T11rfM2X zlqP&<(Anq|Z#cwBw+%U{HLH!8bVJ4UPH4Za4$Y){V|HyffQV&$fa>QFXs0M$O6KkZ z34=~L>%^r=;+JO;r^~wzp=7;E;N@m#q`ISLbA7W)Trvd|n`45Fgo&kg{Urs2JIDxk-C`hwmqD zYaAq6*w1OV#QtyVwdbbNINM|9r6!vU;!Z#TJJ^}K`kGTpsmG%F;H?WuM>E@K7I$6iw5;QNxYC~F_@%LF@Wm}#`%(T) zY!Q}`>BN`4*7I%#TbZ|>M-&&F@f?A#!Q%(M7txVe>R2nr-|!Q~LHKIz=tn^gEjl^V z$}L-%CoaeNeN#DiD#6Ly^R@J|`ureqZ|x$Y$>|?c;in`WvKa-$Mtp%2TE6<2ww7^x zxW&J*PxBOJt=A6f!&TP(+tIHG6y-*uDJ*vv<=G30`(}C;twW5~_-*NFO1}~3{0^_y zxjA{O2uJCpr5a&Dl@4yCAjCsYdARVpV}t zVhdQ}x|6GlfxmslM~251-Z8Jy`5AnYmG~*(7a-8R1=}3O1&;2Q$7E zoXc{TMrxtPdX(eOZijJUouq%(P0OEM7Uyc#T~KGWPAcQNs*!5N`wTbm*hW7ym6M5X z`l~0Wq7`*B>hWfHqwQ2M62!Ccn$?>0AlEh918mj~!@R6XUcy zOZ(N$oRCKi1IPm>d>vqY7?``}Lgy*eyrJ(8SR^(Wl!1_cGTQQKMIX5I#n6rKC> zp7rcF+{EB-G^!CNu1`|vTcFdvPkaI>YS=IXrhc>={@DNasMB&SeoHpcL01xlU?#e= z)Ih=@V;>?J^|0%Ncf`TRR_V2`0J_5l-L*d!dsHVAu7D0I3dFEJ)pSPVgtzBC%icgT zq5e?Ujw|ZXeFqnx=nLpOiog~U^~u6VJS-8cJ}_4ILJ7~Ute%-4)S354{BYdh(K8K3 zxMfu1s(-@)f*s8l3bK($Lb1Rykh_c(>$#GU8_v;*kT6$BRcv(xg?|B2$sx^#gdiZU zy`mSgJIp9yv>-^7a$vml*fvUb2&u>2cy%5en$HRffp+-0gJ@CkvHG|*19s>5vYM5S z0n6GI;2}vZSr+cf=b;sSkiRT29RvQnF=(Hxw{At;beq9pC=1%o*C16rF*IGGpUl)` z?ikg_-kM_@QPB-79f_zuhD|{<_K;m}L0Jnk`k~UKm){s)pXWDmkSgy6R+Z~deUxtX zm4)izXld*H{Npm-d_;k$X!FOGQ^C*=q3g*kC&K6XQdspN(0ZbmLnztJ-|L>Uz)*s3du zDm6a*JNAiEXO};L$5jzkRsN`+bkXBl6XV1V|NQdK;%KsXCFSKSHB_bBP@E0ST?Rsf zK$C~Mi;-D=TmOChKi96SBF)^QL|lt)(l2_gRFiQUUvmwloGB-P?c#A|tvB(>w>7&l zE(0yJGaNR9Jd#h&Lr-^IivqHdjJf_kMe>Cb%}&~}x(JL$8%86LnPloNep>3T(%5ob zxKiey@FhLo{h`PECg_-dUp0ABl3W7Crnz|O^e`7^t(G`l*pc$D+kMfy>;R95QQxw{uVQbdGEr)hj$DbsOqc8`%F|X!) ziXIZwQ3(Er)B*<4QRSTPD6YvLD>LXuwvJiuENtF@l_cNBfyIO?$xC8j1~{2q1wX`( zf|}7>YTq$Xi-Jl0KV^|KiECcduobj-lMJLAo*&?ZNAVFcNof+*RVUs6l9}CqOwZ?& zf0RSUe?hh$QuMh0irj;fIG*dtm|At?d{ciV=aMUjAhm|Nm0!uU7YlC?Ak(Nub_DF> z<1Fqf){B!TdNXgkR#j<*AijYU;%u-LiAV9O+23yb724h=;VGiqC>ssj*DO6e80j{- zyt$pIhdrYIZPH$|ux)vf#pJmU}zk9a@HeYC8HU0jxgU zB@E0cD$;C|bO9|Q{xq(V`50y25uGG7qP^eZ54nR~MhK)Zmfh=>cd$zQw~D z!-Dkwm&S2lg?6e+Y*;w@a*vF-4ciJsQ~3k~5jhy}(svW>f9M?u%-&*CBN2ubyMm;W zBNmkPLqDMtk2-a4&Ww7cREzMr7<^F^Kkuz$d=74gZopQH@^ zQ=$mlFh9%Fqb@0;{93jFDtxF`;;O)z>KBsI(!K#Via^#jx=4}A-*SUWF-`nBjB+s# zj6WnEv$Yjw`C~sW@60!-vu(3GHj9jSsjztlEu}pJABd^+2cFP^;GphnDznj!CR0iz9?F zPYSpi&ufXaq_N>ci10(D5TaX5w)vLUsC*HEmdKM4k7tdE!F)Q|zba8JLr=PbLS%o;t?VsL zyJ90bic+cA+se10MhuacMB#}|+OOl6-n)iW(}cCK^1JL2_(@RVLu~#9AKFwTg)gHY z+;ypaQ@&0A{zkFYRPs&ZYLM1fo0>^3S$oF{VU#;3HPC~hph9{0yqR^BYKZA~OyxP- zXN0NiqGWJZc4p`TH0h#~0 zZBA4BRtWzi3V~mM$iE(&!FZ`MObP7uymelTWdV2lH(LCG2>h=#)lEJl2fQU49O%N7 z5RiLKL3)a~7kPGMZ|UlMVBVU#)f_P>6p;eCYf71gOFa{bo;Ff{+# z`R@Y<8;GBAuN8p7AywdsWD;|02-uwK}E;?m=mRshG@ z!qc{fZARv`&6V{osr?DK^H;YBYu(&d07tgCw6D>)?|o(NbJbOH`mdu)0J`z>Sufd* zt({XE@~|f{=Q`5nKl#@!8q<;K=W*OeCChN&@Z@gkm%aD7G3n!{&n=UFuP*@>Im2tp z=TpkJ!n0zteR|FSGI3+rV=SoubL+xPgNDTMqsP*Le&fjne&XY9)YERq)DTKTKo@{m z*>=RZih3A~axP4F{OQX1+p%N_VoS1W0={i*KeAn_e7>tZDYcU8`UiWwPLPsXra)S3 z?eXGiVh~uvAP?VBc36CK9^QEqzIB}ZxqV-KX%E2gzxtkGrt8a*46r0xHJj{HeYywaEv>1(ow$#Ay7~Zv;fnX0!h-^DQ_=e@ zt~Cje439H&zpBkz5Dn>U>@&(puW*GhlB&3bPBcE1Mv=2(iSMVX5%j(xJz zxizdy*(}}rzR{=kq7)z~U0VW>i4RLCJhJs4kfg()cMEeJ8f=Ookgn>qzvn>33i&xT zzv7A4iD#=@=lzo8ekyEgLC@$2UD4-ms&(bQeTDh7!t2P|4foqBGQVre(?RD`>HYkG z(Cp*U%9E`dps4FQ1c?y8UnlNt@&s0tmRi>D`nKtOw)YfYqYUQpAM*|F@+an>&)A<; z*lOv!fPp=j;Cy&GdGo~_~feB~a?%_||sa6!LXdHA)WTSCmAd$^dZ z;;|=d;IYQvs@{3d-#O(4oYo%Wp*+CtAK*RL?N1O2^-Dv2MZUef$R#Yg#Uje*F5HJM zf4AU;|$JAfDBgsvRu zUjwI~cjuj#I-Tmvo!jp#Q{wH|Bu9yLL|2o1Zj)Nw+7I-Wu6>@biKUE~Q^*{Cr0d-^ z`rJ4E@aR|g-7@L!ng=Ru+7Uc)U!tWr4Mnc#u8t$$SnSbKBUDz_ovUu`9(`p_e;V~U zq?+7S(dTf$yX^koY&c3CQdI-ymufPbgd!w_`eh73 z#@F?*gG=9-@sAQ-^gAANt@>^=rTQ*(n`hQd4(NPjDg-|plLE5;q3nnIy#A3O_TH5T zlmSIn&#FYW7cDWS`a67cDS8@{I|xTS9j5??cT&4e%(xz4S#>JL`_kk&6>M~Cl#~m> zBg)th|DKZ|*ckek)CJZK$+N-}_}HlYHZNnF4?VB)+ZOX%2z1ZQX#q6EwZ))F7Jgn| z;ZlAka7_uK3cJ6X>(u`d{jB)3srcco;~&#>5G9Oo@qMNHubOjJ@541pThTwNg}k=i z)DLKayQ2A(fT^Qoe{39eB?K~qcPGzJC!7`9<^=PSg@PCXy&weJYT^M(%({^n^2zW?GfWpC0wZ;=c#~fiJgstkAdcF?pQF2@Hd)VJl+{0rJti6ZDm8SR z?lii0?0wx@nQ`e&!m!OTs}9=LSw2g&-Z79i)HBsLj1)zHM=t1Yr(cWZQyz}t@?|V{I^fD* zXsI;Z)-NW<#Zvcd33X#Sr=;;``>rJWzKcS^TwcqmFurZk%PZsbS%v%0K9`?mb=Uua z^-k(FFKQ+^+cpG!+}bwCJ!SNyrsn*9>Z88$U?q@+&LDcq;CteK$UXJ>i{?|+*Sd6M z_qpez_H4M)n@NJtop{#(q~F44u64PdxRyH*s`Y-?6aNx(jrRDP=e}yz!Z5)vFxwXs6U~M)s`P*oVWJNIP_dy{d-}_y4ybeHE97!F3+1s8>fnn ze4k`^;2c2gj#A_9sNcsHu=NqfsjMrZO-4&L>W9xpM@|z2|26FTM$c^4P6Vfhoo6ey zX3dywT+15VO;SgKx?SIs@S8bm9;eInjXWziXTrnn*V7%ZY zn+Ufg>EV}$@6~2rmJPWlxp%FtTomvme9KF%nJU@&*ADV3% z=NQz&KYCR$w1XPG6SY65WbN}FUp01mvA?f>GQ#zoSIVreR|{0Z=$$W_$~xCUr4AN2 zb_n5*zco`3=-F-ig*VqEX}}+jX=V(&=eNc>XjNnN#Q(A-c;GOi!;~)m6@!$h1787d z8+`Jw=HzyiPczCM{@v9!X?>v0`M4q})sfxrB%0oAi^qxBcB{tvvo|+uade`?ND$ad zST+IrQ5wsd3)Wk4!1de=E4|B{`ZDT7mJzd0Vlr;${W&V2^I^F2u)cJ5N(0BlKx38O zayFFug51oI{5si@&sgA2_@P%gy-!Mt@J?rOok-S<3VW7*uJS5{a<|dAC}~}61w1wf z-CrT_zUGXrk-%+v7%7iL*7p|P7Ej|7=-ByEJj&J^OHNI}iJyX_~Ho`u%f!(8TS!G+ZWjCMbxUChp;{{9pvwGS-5HBUnzM&t-?6ov)aG zgh|+SzMWIS9-xX&0(~EZh-Q;uCZp2R|Fj8Cv7a0wba%Vrf`q0NKbHIS+03o!lHeMJ0& zuYU~F>0)$}L%V$Mdix~SNwy8lv4d-x_1Q%H5_sk_wpYE@mY!9%|ROHlE~U(Ze$ z;gKex+`UnHUFpO@+o}@r+>p2I$2AYp8_{?Oi%C)kW0;G(G;h8(|2Ik<>FZ$#m`9>J zw#+7SRFbXr@sUFT9hU5)=kowOVwA^pF41JTWk6is*)MPUuty}q!Fkj4Dvht19a9;{ z+pdk9gPv@Sgla6R54!*I-E1R{i{nzkgK7Ho8m$O) zAPh$q;Nj^K>*|5`b&1)G?qm+b5iZKY30M+IVWS8(G#FFG~nY2nxKC?loZ$<%z@En$pMGp}*u~IB6^G=6V zo<`|K3;|h^#26&8GOmxB2pJ57m@2fWw!iRx_8p9WFp1q8ge+Y(G_tP6WP@{}aWSKh zi9wToO>WCqMiAD7AHr1i*F4|ue$HnHLyd_EEu9xJOnXGc_B!4-O!eC7E^6gv&|J$A$t+c_@Bd%riUefaO zJ4_H~rF2g7#ypzaHb>w`?-1NytGpgIg=o}D)0sIZH4XjF$#eN<9e*QFI0!1{)NawO z;WlMt&^EE1{`$llj=V27M%&u{M;}8}a2Id{Tv$cB;~NagT~g+9)b&;tp(-W_s6J2{ zf8P+_3!Zzq56Y=ns$2F>4^6&}lML8g3fwFsQ`0}f>5?2u>91OBVH}>0~_Q z;$3t^Q25wMyfl00IETw+rZo?Ppfm=_h3ZUcqq$c`^nybHUXK|oF;E)eo*8}`yhM1m z{bgh(nU)38={AnvJKFQ0rRzMZpO7x&^@W zvBJHW58LKM_u8z1yyP@YoX$9uUO%@kbowl@tl?pQ(dV^Y9B*7e43j1l9&4Be zO=`j*uB0e(l|p;U^}dyXKw)$k6&bl54CNO!Uy=FMK&wFL=;X6@;FbQzm!o;Zf|ihcQ7!N$STDqs7Z+cBhgf|fA`YUSb) z5)q3`B;J{|A#Dt`$>G}QqkFH8b5{EaK~Bj_!=ywY%5!lecyw-Gt*?GR9!FxV#N@E* z0P7o;1qOxKkHzQ)A-@mo70Fl* zT}YLWV0z6OzYid%*9D+L#wAKsQCfp(T7m9r%s0b5PGp!Swut9z+*Gd)xR0Sxp7AHj zLD@LHC+!>x7k)(0`ADm+1n3XSnai-wIkR+4O5<94;rHzd-VkXM-Q`Cx<+rtRUY+*)bHnEb!I%_(y-|CH48?>j&R z(~Q&6Pim7){HY3?Eqyv+Q}dC}i;g{vq{A9I5?FipCSp*`7MariuCI-$u4bQY>~1xJ z#1Rh9=14i?dz}f5;M3>>XY;Q%0yPqb2i>QuAF>!m zbTJru%J2VWg7WL&`W9<@c|EE^)|~dKcCV_{%l?FYWxMu*<@euPu*#_nC;)iq%jlMV zwL0T7B1{GC`QiL}>er0 zD+t2Wat^1~04!#7M5cpV#AZFBmq zS%$Pus=r7yCp*<8v-MAOpD3WXy0Z`2Gl&kVfb>HR-z61%hwjtqYQD^sG;I2o+D142 z&Pyk}M`hkcf834+iN8!6s%7B}Wy>Wm8s@XBP!|LTn+e1X$YBQ>A!4RBOVc64UEGxOf=&o zX=gf;C)<6w9oEh_vQTTcTI3^dAc=>=wAI~@hN+iwxmk4U@Om_mK8FOv`QIzCvnOj-8f@P`yR z2yiJRpUvO|8z|m!NUt(rIDylK?8%OTd99BxwfZ44>|Ta=`y(1)1w09s_*ic&Wv#ws zL$ffe{5_RqPgGW~z>YQNJW{pfK%xy4#Da{tSjwc|sjCz(tJaNxW>qr} zbnOIU7%7pZA&Dc;{0vsul)0a*JjA0Jr)-u`pLFT8yDNpOhC{yxV!%iroyZ$8;O{t5 z7U~c2tmJtK4bi_BInn9TY|xc@kdIglyFY4~M{cZ3C%;I>B)jclOp|dGYV88*fC!7( zlDr&5Az`H?4CtU@p(Oh?Mh_52HZap9S#`wNvqwu-0i%y zC%|SRVW1GQ0&@XQa+qL?tWSAgzC|Ng`yJ|kOH+>pd5YbwB~ za3_SGw`!#|t|7CfT*=o2{yfg(4fl9~zP! zHc8)onNDu#jiK+@%&JTDnQfEa-`UiE>H%vyJ9QM@McBI6^vgh|O~)^FFL{EsSfm$e zUMo+O>0q6htHm>h|BAWy8Xn;Ab9D=@rM0R3LE25!gxZrmIjzD<(_U0E;J2(n(N_Ci zURHe!x{FryJq(?6A>Jd~^@FPdX8ZMk&{cK7F)#F;uoNC+=eZ=q@7wtStg1hWS6BDV zLSE4~_q-c@-KI%?7aCjSW2Tm8`skGEmvA`J-kX)gl1z2=y#rOV-{B?8=}rMKK{-Ru zk(Nhgaq*cMb0pAp`I)4;U>dD`P;GvGF)w05yTNUO0m&#^ONK=N*ky6{>yKy7Oh(~z zqFp`e#*VPWLz^yyvu--U*jr%Wwo#)W7{(9M`U5+SW98*s z1Nc!jQr3hyvcYFQsai z-;UkoUJDhp4(&Xa?1vRo_K$CwKADa3d@0hZg&W0Ey2x}AZ`8$W^o?&1X4qY{>&Fl| z*#oZPv;Y_=p*#{e1*`PkI5jN{7$*J+`3q9?jm&-!;4g1s@8hx?xp!$P^|t?{J|>mI zXztZe$A-LfrbqdcvQwJRd7tct{h@~)%d+pLG_x_M#El9zrPjYFieS&Ad+yUZsL)#^;8 zp7aNC{GpCsT7A_GyY8V^Ju2FQ8t9Y*gkH5cCd}Ea@S*FL=ngtx*`tFq*e#Hers7Y>f{-MjRBu;o(N?Dq2-JBiOF`bcgD#}JnR$n*7JkaMzuqlO6aY4?GZ zGHN!ivC}tW`m&!flz*tV>lvkg>mui5P`gsfAkMT!=eNAG?MJL zfNQ1Y8#sCEaHO@*cc@sGb<4{foLk;yGGJ5*{iUxf-y!qGztdM$NlS=ww%}AivR0s_ z0G3oEhPB-slLH=0`5DEl4T?%jtBTbUsT`l7AO73n0ih*#!aO(=v7P z9ateS0HS{7k86rD^(Hzuzp+rf7EZLi=?<;7qyEM)b~)-ZV=sfZ7xnSPT$*|f)Avsa zNeaR5t&=?G)Gir`uWLaj$HP#qTy~RB0U|+Ftv!(XyTBc!jVA@qDFMP7sIT@KBH_(QOGOt(|dwwb+`qdIO^UOiQF!!q@sq7KR1n8}T z2PB7pOw0zE)(Hfk{tEFfV&m5-?S|S^ugf>gX69zUxHKKCJE>m!RvW7E@Gwe9FY3P;x1WT(|F3Wu1gPvd` zzqAyyB_%5Uewj<1ckn`>fa{vqb>0>*ENx8uRxZsDC)2~|SFuT~P0OzX z@Xk=?TKvcgh6zp+NBOp{BkA|3w(KvfHQL=nBxY_E@tc9|Ia#A{szoQPZG1&)Dca#e znB2p_DhgP_n`Y``)sg`mMVw6|i|>0|tAz<=0spJ%Pyf1dVaP(-uNP6pIZ}vl{V|CA zrF33jBK>TuF;t*?dTz^Hz+LFg8-Q7ds{-b(wzKaH_jbZB-B7?E1KMMobKx^#GX7}x zs|deAqdy0BZ85KHblYUE z3wu#S9Fs)#eN7cR`aW^T(>Qc{{?+$5Jqdj5BlqVS8Rx}L#I1vn{`V9kDYtG!)f zgYbsr7Mo=L^)93}(vvQKrDpVLB7R?Xwmi73Q(N;BT zl%6~knJ6Zm$DVIYT0i79 zh6A~DHq6iBt&<&PL#GacPJn{+(v^u=x~c+i{)oM5-?vio$4FkhHF~D0OS8t+5l_t5 z$^6>q)PYIELlw;=xI0F|qercd@UR-uTuoU&4-Ul%qFEb5{qIbTsyz%^y3Cr{&4%BujmAeI`#7k7aHus?D|wmuxY$2ZvP$N+!9obZ^~$gI8vs+KE^0wC$@OI% z9kc=!mbf{#zZp*|@Y)?4DLrHYQ!3Afl3Pw6AXswP<=(x4VLtX;P+5nS%_X?E5jj&i zyZvq|w6hV28v~Zlb<=@_Pe8$@pidbt`hD5cShDR=rX(LXN#QeYrYPAt;G0YO2aLil zMgoa5P`><7M-4^gDdUgx3Uyx^;?V6I2t>`%(`h^F;f4S0`<6SyiHaMr$S<=weEuq? z=)MAV*dTD=WispGZyM0aK{vth>dw4TV>h5=)5-#`y^1N3Q2$62n)(-*{#WN;%#jvt zZNu%$1K{zU^i0NlERdLF(+PVLKVQS^3Ue4`mW~`sY(bMqRjA7Gzl3oPyL50ie9ZP& z&;OKn=KoNxeH`c5lZo^&D%&J=N;1e{EMpCkvL;L>VoYRTvW7<4nxU~XhlGq6OO&w{ zF|st6VQfjqWM7W;gwVOC(|LN%tMeZ`_b=D$zFyb;y1w`Ky6@}y<^B15TaGtU@l9{3 z2VAgBPHuP88YkeW*k2@y-R_RC$XYaT&0?7q;L`H8;v&Qop&RRc;a}>ZC=pH zpj*Re5Fqjq3`)tU2Xl0fC3|Cr6`&thN5?stAGb$PASZ{xR{j=FrF81J*0ig*WNwId zQXXYmVH4Oo%;iTQOR|(Y?VRR!hD^aT>_W2&a3Rqhr^acm_AwdSb!?K_BIL&M;jYkF za^<;)W4uaY7=u?vl4b355&%%QQ4dZQ?X2LGN^%CV`gh#J@Z5J#`}M@TOZv*RFoJLNu+W#afuag!C^~yXiX9B2D$nHY3`xoC5O{ z!xBBi0KLcgD98~AzN5=$MeOKDli-QZ45b83!q}|Zr3k+v(({J{7w$$ycBT&a=5T9; z)EM#D=Y$hPGAup!C|0#|syp{|WI&kP^PyqwH@GY(j3X5lE0Xl31U{ZUc)8}B(wMk% zicnmrsk)Y4@#Uhlf}?T!T%=4}<57sJ!596@IV$^k(3DmDfvL9SFlo*B{T&$r+8I)& zBNW7`RTOPvd1k1EE4k~Ft>;){RU}7(jLQU$Z`h?gyfZ#t6oW9up;nQfCDB*KdtO2V ze+zrRK?-_s@2=RfcL1>RvQOa};6?JW>H{tPmQ%Jb4Yc9F?qe8Xi6(;te=Fz!|H3T? zT2PHTuz_>ElnFm7D%l(ZE#_l_v9~eqZ}}E(^oh=d%HIv2l8%jrLdKXsr{%72zE(zQ zkP~xK*?5#HsJZ@qC@-RwU^)UUr>3T%rGC&%G&iOf{7C-L%QjS}3F27tq<W58{OI5m(ava{mR0$&2ptPZ$dQ<1gik8skm_4UgXyT39Tkt?JMTdX9^!VUyt zkD{<2(iKOSg%-OvorBu5POrQ0Uq?zYNrK%4YcxXO;{ZeCgm+oQrBNyGgf*y(PAr?S zwmM^D-ODZSjg(#wl=0S06DUtCiOK4{Uq+Cgy3DX(ID88D>>;5rt*SYlaEUA^3znRy zpfV<1G%W65w4f2YiEM}JRA|Np9V4wnM6oI`oc74_ys2Pm?HQ*X>z>lZUd?QO9$$76 z+q-yr3*15GDfjRFD;Kn!@;lpNAhEE$DOf;-@8f#j1vC7*uChRuFSPhD$zhqi>~jEK z%X@`Dq(gd*w@1-XMDVN&K_LAlT5++syg-})n{DzcC9Mth|DJHRsn#Lvv~F4Oe1mL^ zFW;FVcLlFgqlNzRbu;{XLPqT{O zt6yGjy`@PWzg2oy`Hp48Hgo89K3oxN^Welt)Si)8t9HuXaY$Y!D(vT3)GW?nz3W|# zqv013%Te@-{I0ph=&mf;CJbs$h$SkfA2e5QBv9kZY9fG=?Z>%<<=0)YNd=*0iVMC- zz7w6ch447&`;dWvDr(Id=vXpJsyu5-y=pjU6}^@X(=-O zivJ^r1 zm(u}Hri$E>Gp(AkVozcYPvKY$ura4#pxdWXd}}ej)8hns!7NRQKb7}r53jbZ@v1|t zr7=;RST5P)eKcguMY#wcl?nmt-2Msg#UmsyfYpt4zfz`fX)i4T;;jKmO0*o9b5=LA zuGqgpEuvjs~-#?~l9lgzdYoLB^BfyI#V+ZwVS#q0yX!M^W^cVcH_zi*|4 zLnwgAt_!8lUX%Q?-##=dYrr4AwIv(SV0Mo~q-D0-GH8iB9av|VkKZ@k@?s~M_bBcw z0UrX;>rz`vLaNccdDkMh<3O_#%`{Z9aMa@mkyQMD&KZLtyn+2^rQZ)XCb^J60TMY> zoIh+dxcYQGvoJkoV5#&Ob8mUPF;2(z=8h1*zjXGHl9)FrqomC zHdXHXeQHQ5iJM#ThV-r3-tFY_bYoR?MeCnvE~3W(|K@QPAUc*x@-N(-%3b;II(<*jkmyeiQ{gNE zIf&eas6%Nm#lDi)Y@T@URll>t(fr5a_Ah5!`%IKfz2JR~Cf&Zx5 zelfYw_=g0E>jP2(agP)^iyxM1K?Hz)7i~gspueZ{o2&uJ17Or>o+HN-QhxZ%>SF-8 oN&SGt)vWKC`=*8XzkRjkFKkR|Zv|`>Tg?Vs#s+5kBwb|mpXsM@J^%m! literal 0 HcmV?d00001 From da3f4a7b43843efb282967b0214aa794139a7d2c Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 19:23:51 +0800 Subject: [PATCH 346/368] Add seq diagram for fail save goal case --- docs/DeveloperGuide.md | 4 ++ .../fail_save_goal_case_seq_diagram.puml | 46 ++++++++++++++++++ docs/images/FailSaveGoalCase.png | Bin 0 -> 38046 bytes 3 files changed, 50 insertions(+) create mode 100644 docs/diagrams/fail_save_goal_case_seq_diagram.puml create mode 100644 docs/images/FailSaveGoalCase.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ada6f59bb6..ac0d9bfd65 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -237,6 +237,10 @@ Exceed withdrawal limit case +Fail save goal case + + + ## Command: `add-account`: **Step 1**: 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/images/FailSaveGoalCase.png b/docs/images/FailSaveGoalCase.png new file mode 100644 index 0000000000000000000000000000000000000000..f2726d8901e26bc1b6b5402f1bd74a616bfc9b02 GIT binary patch literal 38046 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 ao|EZ#Bz literal 0 HcmV?d00001 From 98590a4e8e61b1ec8c9cdfc35a93e9db538f79fb Mon Sep 17 00:00:00 2001 From: tyuyang Date: Mon, 10 Apr 2023 19:31:40 +0800 Subject: [PATCH 347/368] Edited PPP --- docs/team/tyuyang.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/team/tyuyang.md b/docs/team/tyuyang.md index 65f89e447d..0c104cd7ed 100644 --- a/docs/team/tyuyang.md +++ b/docs/team/tyuyang.md @@ -20,7 +20,7 @@ Authored the withdrawal limit section. Worked with [vishnuvk47](https://github.c ### DG contributions -Created the puml diagrams for the main architecture and the example sequence diagram. +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 From eb6969b8b253b144c17064f360aebcdf0a088891 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:18:28 +0800 Subject: [PATCH 348/368] Correct a grammar mistake in PPP --- docs/team/xiaoge26.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index 2b33ed9aab..e8a8f70b04 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -32,7 +32,7 @@ deleting, listing, parsing, saving, and loading the transactions.
* Automatically delete all the transactions of a particular account when the user deletes the account ### Contributions to the UG -* Documented the features related `Transaction` and `TransactionList` components, and `show-save-goal` feature in the User Guide
+* 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 From a5ee3fbdf4ae25e0888b3d99106ad7a8f64782f8 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:34:02 +0800 Subject: [PATCH 349/368] Change all local links in docs to weblinks --- docs/AboutUs.md | 14 +++++++------- docs/DeveloperGuide.md | 4 ++-- docs/README.md | 14 +++++++++++++- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 93e6a519e0..08f00fd3ff 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -| Display | Name | Github Profile | Portfolio | -|------------------------------------------------------|:-----------:|:----------------------------------------:|:-------------------------------------:| -| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](docs/team/manushridiv.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](team/tyuyang.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](docs/team/xiaoge26.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](docs/team/vishnuvk47.md) | -| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](docs/team/Sherlock-YH.md) | \ No newline at end of file +| Display | Name | Github Profile | Portfolio | +|------------------------------------------------------|:-----------:|:----------------------------------------:|:---------------------------------------------------------------------------:| +| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/manushridiv.md) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/tyuyang.md) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/xiaoge26.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/vishnuvk47.md) | +| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/Sherlock-YH.md) | \ No newline at end of file diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ac0d9bfd65..a5363cdcc1 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -428,11 +428,11 @@ Windows: Command Prompt
## Instructions for manual testing ### Launch 1. Ensure you have Java 11 installed in your Computer -2. Download the latest release `BankWithUs.jar` from here +2. Download the latest release `BankWithUs.jar` 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 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 -Please refer to the Features section in our [UserGuide](UserGuide.md) for more details on the test cases +Please refer to the Features section in our [UserGuide](https://ay2223s2-cs2113-t13-3.github.io/tp/UserGuide.html) for more details on the test cases that you can try out. \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index cc4c86a239..04b6c7fbd0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,18 @@ # 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) From 44a17b524d922bc3b1da2bf1bbc72eec2e999b49 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:35:41 +0800 Subject: [PATCH 350/368] Fix typos --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 08f00fd3ff..966adde0f0 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -| Display | Name | Github Profile | Portfolio | -|------------------------------------------------------|:-----------:|:----------------------------------------:|:---------------------------------------------------------------------------:| -| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/manushridiv.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/tyuyang.md) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/xiaoge26.html) | -| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/vishnuvk47.md) | -| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/Sherlock-YH.md) | \ No newline at end of file +| Display | Name | Github Profile | Portfolio | +|------------------------------------------------------|:-----------:|:----------------------------------------:|:-----------------------------------------------------------------------------:| +| ![](https://via.placeholder.com/100.png?text=Photo) | Manushri | [Github](https://github.com/manushridiv) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/manushridiv.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Tay Yu Yang | [Github](https://github.com/tyuyang) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/tyuyang.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Liu Xiaoge | [Github](https://github.com/xiaoge26) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/xiaoge26.html) | +| ![](https://via.placeholder.com/100.png?text=Photo) | Vishnu | [Github](https://github.com/vishnuvk47) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/vishnuvk47.html) | +| ![](https://via.placeholder.com/100.png?text=Photo>) | Yao He | [Github](https://github.com/Sherlock-YH) | [Portfolio](https://ay2223s2-cs2113-t13-3.github.io/tp/team/Sherlock-YH.html) | \ No newline at end of file From f3086b534e3fc0b02b6b125df1eb5e6be41109ee Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:46:53 +0800 Subject: [PATCH 351/368] Undo an unnecessary change --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a5363cdcc1..125ceefe02 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -434,5 +434,5 @@ Windows: Command Prompt
command to run the application. A CLI should appear in a few seconds ### Sample Test Cases -Please refer to the Features section in our [UserGuide](https://ay2223s2-cs2113-t13-3.github.io/tp/UserGuide.html) for more details on the test cases +Please refer to the Features section in our [UserGuide](UserGuide.md) for more details on the test cases that you can try out. \ No newline at end of file From c731f6118135131fb68e091a88a49f5a3d013a88 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:50:53 +0800 Subject: [PATCH 352/368] Delete redundant lines --- docs/team/xiaoge26.md | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index e8a8f70b04..c5471c7add 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -64,17 +64,5 @@ deleting, listing, parsing, saving, and loading the transactions.
### Contributions beyond the project team -* Reported bugs and suggestions to other teams: -[#142](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/142) -[#139](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/139) -[#133](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/133) -[#129](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/129) -[#126](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/126) -[#117](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/117) -[#116](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/116) -[#101](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/101) -[#104](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/104) -[#107](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/107) -[#142](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/142) -[#95](https://github.com/AY2223S2-CS2113-W15-4/tp/issues/95) +* [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) From e77269a5f25f4589e45ce60fbd0374ad7b8ad335 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 19:58:44 +0800 Subject: [PATCH 353/368] Delete extra lines --- docs/team/xiaoge26.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index c5471c7add..25d8d354ac 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -53,14 +53,16 @@ deleting, listing, parsing, saving, and loading the transactions.
### Review/mentoring contributions #### Links to PRs reviewed -* [add NoValueInput exception #156](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/156) -* [Update show help #98](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/98) -* [Add main architecture and example seq diagram to dev guide #100](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/100) -* [Branch withdrawal limit #71](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/71) -* [Create withdrawal checker class #67](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/67) -* [Change the attribute balance to String type #58](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/58) -* [add Account class #24](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/24) -* [Wrote PPP for myself #158](https://github.com/AY2223S2-CS2113-T13-3/tp/pull/158) +[#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 From 45b0b616b3c66f36aa08eebf65bf14204053369b Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 20:01:25 +0800 Subject: [PATCH 354/368] Fix format error for PPP --- docs/team/xiaoge26.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/team/xiaoge26.md b/docs/team/xiaoge26.md index 25d8d354ac..30a4979912 100644 --- a/docs/team/xiaoge26.md +++ b/docs/team/xiaoge26.md @@ -29,7 +29,8 @@ deleting, listing, parsing, saving, and loading the transactions.
* 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 + * 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
From 464d21f0472f238d2ba6f19102c88b83ae7e5267 Mon Sep 17 00:00:00 2001 From: vishnu Date: Mon, 10 Apr 2023 20:26:08 +0800 Subject: [PATCH 355/368] Add some links to my PPP --- docs/team/vishnuvk47.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/team/vishnuvk47.md b/docs/team/vishnuvk47.md index e6bccf6f5f..b206fabd37 100644 --- a/docs/team/vishnuvk47.md +++ b/docs/team/vishnuvk47.md @@ -27,7 +27,8 @@ Created a User Guide for the BankWithUs software/application, which included a r ### 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) +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 From 06b817ec314b3f2c282394c18bc7a34456e8ffe4 Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 20:54:48 +0800 Subject: [PATCH 356/368] Update instructions for manual testing --- docs/DeveloperGuide.md | 49 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f2f4d2d92a..dd129837f6 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -424,5 +424,52 @@ Windows: Command Prompt
command to run the application. A CLI should appear in a few seconds ### Sample Test Cases -Please refer to the Features section in our [UserGuide](UserGuide.md) for more details on the 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
+ + +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 From 88b997b11ec8ae6dad72cd325fe3fcdd0285ee5d Mon Sep 17 00:00:00 2001 From: xiaoge26 Date: Mon, 10 Apr 2023 21:40:43 +0800 Subject: [PATCH 357/368] Add page break --- docs/DeveloperGuide.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index dd129837f6..c324eb4652 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -65,7 +65,8 @@ a normal Java project
* 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 ---- + +