diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f439f93ff8..3f1368658a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,5 +1,33 @@ # Developer Guide +## Table of contents + +* [Acknowledgements](#acknowledgements) +* [Design & implementation](#design--implementation) + * [Storage Component](#storage-component) + * [Design considerations](#design-considerations) + * [Visualization Feature](#visualization-feature-) + * [Class diagram](#class-diagram) + * [Sequence diagram](#sequence-diagram-) + * [Add income/expense feature](#add-incomeexpense-feature) + * [Step 1](#step-1) + * [Step 2](#step-2) + * [Step 3](#step-3) + * [Step 4](#step-4) + * [Diagrams](#diagrams) + * [Budget Feature](#budget-feature) + * [Set and update budget](#set-and-update-budget) + * [Delete budget](#delete-budget) + * [Reset budget](#reset-budget) + * [View budget](#view-budget) + * [Product Scope](#product-scope) + * [Target user profile](#target-user-profile) + * [Value proposition](#value-proposition) + * [User Stories](#user-stories) + * [Non-Functional Requirements](#non-functional-requirements) + * [Glossary](#glossary) + * [Instructions for manual testing](#instructions-for-manual-testing) + ## Acknowledgements **Xchart (A Simple Charting Library for Java)** diff --git a/docs/diagrams/Budget.puml b/docs/diagrams/Budget.puml index 755ff562c0..11ba20e9e8 100644 --- a/docs/diagrams/Budget.puml +++ b/docs/diagrams/Budget.puml @@ -2,10 +2,9 @@ participant ":BudgetCommand" as BudgetCommand participant "<>\nBudget" as Budget -participant "<>\nUi" as Ui +participant ":Ui" as Ui -> BudgetCommand: execute() -BudgetCommand -> Ui: getInstance() alt set BudgetCommand -> Budget: setBudget(budget) diff --git a/docs/diagrams/deleteBudget.puml b/docs/diagrams/deleteBudget.puml index e689250914..4a8eb03a13 100644 --- a/docs/diagrams/deleteBudget.puml +++ b/docs/diagrams/deleteBudget.puml @@ -3,7 +3,7 @@ mainframe sd DeleteBudget participant ":BudgetCommand" as BudgetCommand participant "<>\nBudget" as Budget -participant "<>\nUi" as Ui +participant ":Ui" as Ui alt hasBudget BudgetCommand -> Budget: deleteBudget() diff --git a/docs/diagrams/resetBudget.puml b/docs/diagrams/resetBudget.puml index 8efef02d34..a21b3c7506 100644 --- a/docs/diagrams/resetBudget.puml +++ b/docs/diagrams/resetBudget.puml @@ -3,7 +3,7 @@ mainframe sd ResetBudget participant ":BudgetCommand" as BudgetCommand participant "<>\nBudget" as Budget -participant "<>\nUi" as Ui +participant ":Ui" as Ui alt spentBudget opt initialBudgetExceedBalance diff --git a/docs/diagrams/viewBudget.puml b/docs/diagrams/viewBudget.puml index 39c9ec1ccb..02c0d77042 100644 --- a/docs/diagrams/viewBudget.puml +++ b/docs/diagrams/viewBudget.puml @@ -3,7 +3,7 @@ mainframe sd ViewBudget participant ":BudgetCommand" as BudgetCommand participant "<>\nBudget" as Budget -participant "<>\nUi" as Ui +participant ":Ui" as Ui alt hasBudget BudgetCommand -> Ui: printBudget() diff --git a/docs/images/Budget.png b/docs/images/Budget.png index 7a140e5cdf..89c18a4ef7 100644 Binary files a/docs/images/Budget.png and b/docs/images/Budget.png differ diff --git a/docs/images/deleteBudget.png b/docs/images/deleteBudget.png index 761a4c3620..5857625618 100644 Binary files a/docs/images/deleteBudget.png and b/docs/images/deleteBudget.png differ diff --git a/docs/images/resetBudget.png b/docs/images/resetBudget.png index e9f8f5e578..0ea63d522b 100644 Binary files a/docs/images/resetBudget.png and b/docs/images/resetBudget.png differ diff --git a/docs/images/viewBudget.png b/docs/images/viewBudget.png index 02ff716a10..fe7179a4ec 100644 Binary files a/docs/images/viewBudget.png and b/docs/images/viewBudget.png differ diff --git a/src/main/java/seedu/financialplanner/FinancialPlanner.java b/src/main/java/seedu/financialplanner/FinancialPlanner.java index bdd75a6d00..6d6e3c33a9 100644 --- a/src/main/java/seedu/financialplanner/FinancialPlanner.java +++ b/src/main/java/seedu/financialplanner/FinancialPlanner.java @@ -1,5 +1,6 @@ package seedu.financialplanner; +import seedu.financialplanner.cashflow.CashflowList; import seedu.financialplanner.commands.Command; import seedu.financialplanner.commands.ExitCommand; import seedu.financialplanner.exceptions.FinancialPlannerException; @@ -10,21 +11,35 @@ import java.time.LocalDate; +/** + * Represents the main class for the Financial Planner. + * It manages commands and user interactions. + */ public class FinancialPlanner { private static final LocalDate date = LocalDate.now(); private static final String FILE_PATH = "data/data.txt"; private final Storage storage = Storage.getInstance(); private final Ui ui = Ui.getInstance(); private final WatchList watchList = WatchList.getInstance(); + private final CashflowList cashflowList = CashflowList.getInstance(); private FinancialPlanner() { } + /** + * The main starting point of the Financial Planner. + * + * @param args Unused. + */ public static void main(String[] args) { FinancialPlannerLogger.initialise(); new FinancialPlanner().run(); } + /** + * Loads storage from save file and starts the Financial Planner. + * Saves the storage to save file upon exit. + */ public void run() { try { storage.load(FILE_PATH, date); @@ -50,6 +65,9 @@ public void run() { ui.exitMessage(); } + /** + * Saves existing data to the save file. + */ public void save() { try { storage.save(FILE_PATH); diff --git a/src/main/java/seedu/financialplanner/FinancialPlannerLogger.java b/src/main/java/seedu/financialplanner/FinancialPlannerLogger.java index df085a588b..7751a7e0c5 100644 --- a/src/main/java/seedu/financialplanner/FinancialPlannerLogger.java +++ b/src/main/java/seedu/financialplanner/FinancialPlannerLogger.java @@ -6,9 +6,15 @@ import java.util.logging.SimpleFormatter; import java.util.logging.LogManager; +/** + * Represents the logger for the Financial Planner. + */ public class FinancialPlannerLogger { private static Logger logger = Logger.getLogger("Financial Planner Logger"); + /** + * Initialises the logger and saves logging info to a file. + */ public static void initialise() { try { FileHandler fh = new FileHandler("data/logger.log"); diff --git a/src/main/java/seedu/financialplanner/cashflow/Budget.java b/src/main/java/seedu/financialplanner/cashflow/Budget.java index 6aaae47a11..6d24cc6939 100644 --- a/src/main/java/seedu/financialplanner/cashflow/Budget.java +++ b/src/main/java/seedu/financialplanner/cashflow/Budget.java @@ -2,11 +2,19 @@ import java.text.DecimalFormat; +/** + * Represents the monthly budget. + */ public abstract class Budget { private static final int MONTH = 30; private static double initialBudget = 0; private static double currentBudget = 0; + /** + * Sets the monthly budget equal to amount. + * + * @param amount The monthly budget to be set + */ public static void setBudget(double amount) { initialBudget = amount; currentBudget = amount; @@ -14,10 +22,21 @@ public static void setBudget(double amount) { assert initialBudget != 0 && currentBudget != 0 : "Initial and current budget should not be 0"; } + /** + * Returns the initial budget set. + * + * @return The initial budget. + */ public static double getInitialBudget() { return initialBudget; } + /** + * Updates initial budget to the new budget and updates the current budget + * with the difference between the old initial budget and new initial budget. + * + * @param budget The budget to be updated to. + */ public static void updateBudget(double budget) { double diff; if (budget > initialBudget) { @@ -32,50 +51,104 @@ public static void updateBudget(double budget) { assert initialBudget == budget : "Initial budget should be equal to updated budget"; } + /** + * Returns the current budget. + * + * @return The current budget. + */ public static double getCurrentBudget() { return currentBudget; } + /** + * Returns the current budget in 2 decimal places after converting + * it into a string. + * + * @return The current budget in string format. + */ public static String getCurrentBudgetString() { DecimalFormat decimalFormat = new DecimalFormat("####0.00"); return decimalFormat.format(Cashflow.round(currentBudget, 2)); } + /** + * Returns the initial budget in 2 decimal places after converting + * it into a string. + * + * @return The initial budget in string format. + */ public static String getInitialBudgetString() { DecimalFormat decimalFormat = new DecimalFormat("####0.00"); return decimalFormat.format(Cashflow.round(initialBudget, 2)); } + /** + * Deducts the current budget by the amount given. + * + * @param amount The amount to be deducted. + */ public static void deduct(double amount) { - Budget.currentBudget -= amount; + currentBudget -= amount; } + /** + * Loads the budget from the save file. + * + * @param initial The saved initial budget. + * @param current The saved current budget. + */ public static void load(double initial, double current) { initialBudget = initial; currentBudget = current; } + /** + * Checks if there is a budget. + * + * @return True if there is a budget set, false otherwise. + */ public static boolean hasBudget() { return initialBudget != 0; } + /** + * Returns a string representation of the budget to be saved to the save file. + * + * @return A string representation of the budget. + */ public static String formatString() { return "B | " + initialBudget + " | " + currentBudget; } + /** + * Deletes an existing budget. + */ public static void deleteBudget() { initialBudget = 0; currentBudget = 0; } + /** + * Resets the current budget to initial budget. + */ public static void resetBudget() { currentBudget = initialBudget; } + /** + * Sets initial budget to the amount given. + * + * @param amount The amount to be set. + */ public static void setInitialBudget(double amount) { initialBudget = amount; } + /** + * Updates current budget by adding amount to current budget. + * + * @param amount The amount to be updated. + */ public static void updateCurrentBudget(double amount) { currentBudget += amount; } diff --git a/src/main/java/seedu/financialplanner/commands/BalanceCommand.java b/src/main/java/seedu/financialplanner/commands/BalanceCommand.java index 152b4da378..540f9df0bf 100644 --- a/src/main/java/seedu/financialplanner/commands/BalanceCommand.java +++ b/src/main/java/seedu/financialplanner/commands/BalanceCommand.java @@ -6,9 +6,12 @@ import java.text.DecimalFormat; import java.util.ArrayList; +/** + * Represents a command for displaying balance. + */ public class BalanceCommand extends Command { private final Ui ui = Ui.getInstance(); - + public BalanceCommand(RawCommand rawCommand) { if (!rawCommand.extraArgs.isEmpty()) { String unknownExtraArgument = new ArrayList<>(rawCommand.extraArgs.keySet()).get(0); @@ -16,8 +19,11 @@ public BalanceCommand(RawCommand rawCommand) { } } + /** + * Executes the command to display balance. + */ @Override - public void execute() throws Exception { + public void execute() { ui.showMessage("Balance: " + getBalanceString()); } diff --git a/src/main/java/seedu/financialplanner/commands/BudgetCommand.java b/src/main/java/seedu/financialplanner/commands/BudgetCommand.java index 9dc8d19547..60f24a66f6 100644 --- a/src/main/java/seedu/financialplanner/commands/BudgetCommand.java +++ b/src/main/java/seedu/financialplanner/commands/BudgetCommand.java @@ -9,12 +9,21 @@ import java.util.logging.Logger; import java.util.ArrayList; +/** + * Represents a command to manage the budget. + */ public class BudgetCommand extends Command { private static final Logger logger = Logger.getLogger("Financial Planner Logger"); private final Ui ui = Ui.getInstance(); private double budget; private String command; + /** + * Constructs a new BudgetCommand and checks if the user input is a valid command. + * + * @param rawCommand The raw command containing the arguments and parameters given by the user. + * @throws FinancialPlannerException If there is an issue with the command provided. + */ public BudgetCommand(RawCommand rawCommand) throws FinancialPlannerException { command = rawCommand.args.get(0); if (command.equals("delete") || command.equals("reset") || command.equals("view")) { @@ -33,6 +42,12 @@ public BudgetCommand(RawCommand rawCommand) throws FinancialPlannerException { } } + /** + * Checks if budget is a positive number and is lower than or equal to total balance. + * + * @param rawCommand The raw command containing arguments and parameters given by the user. + * @throws FinancialPlannerException If there is an issue with budget format. + */ private void validateBudget(RawCommand rawCommand) throws FinancialPlannerException { try { logger.log(Level.INFO, "Parsing budget as double"); @@ -48,10 +63,16 @@ private void validateBudget(RawCommand rawCommand) throws FinancialPlannerExcept if (budget > Cashflow.getBalance()) { logger.log(Level.WARNING, "Invalid value for budget"); - throw new FinancialPlannerException("Budget should be lower than total balance."); + throw new FinancialPlannerException("Budget should be lower than or equal to total balance."); } } + /** + * Checks that the command is valid and in the right format. + * + * @param rawCommand The raw command containing arguments and parameters given by the user. + * @throws FinancialPlannerException If there is an issue with the command or format. + */ private void validateCommandFormat(RawCommand rawCommand) throws FinancialPlannerException { if (!command.equals("set") && !command.equals("update")) { logger.log(Level.WARNING, "Invalid arguments for budget command"); @@ -73,6 +94,9 @@ private void validateCommandFormat(RawCommand rawCommand) throws FinancialPlanne } } + /** + * Executes the budget command based on the specified operation. + */ @Override public void execute() { assert command.equals("set") || command.equals("update") || command.equals("delete") || diff --git a/src/main/java/seedu/financialplanner/commands/Command.java b/src/main/java/seedu/financialplanner/commands/Command.java index 135ccd4e4d..6b7b7e3e74 100644 --- a/src/main/java/seedu/financialplanner/commands/Command.java +++ b/src/main/java/seedu/financialplanner/commands/Command.java @@ -1,5 +1,8 @@ package seedu.financialplanner.commands; +/** + * Represents a generic command that can be inherited. + */ public abstract class Command { public abstract void execute() throws Exception; } diff --git a/src/main/java/seedu/financialplanner/commands/ExitCommand.java b/src/main/java/seedu/financialplanner/commands/ExitCommand.java index 3c331475a6..03b5eb4285 100644 --- a/src/main/java/seedu/financialplanner/commands/ExitCommand.java +++ b/src/main/java/seedu/financialplanner/commands/ExitCommand.java @@ -2,6 +2,9 @@ import java.util.ArrayList; +/** + * Represents a command to exit the program. + */ public class ExitCommand extends Command { public ExitCommand(RawCommand rawCommand) { if (!rawCommand.extraArgs.isEmpty()) { diff --git a/src/main/java/seedu/financialplanner/commands/InvalidCommand.java b/src/main/java/seedu/financialplanner/commands/InvalidCommand.java index 97bc73e9fa..68860c4c1a 100644 --- a/src/main/java/seedu/financialplanner/commands/InvalidCommand.java +++ b/src/main/java/seedu/financialplanner/commands/InvalidCommand.java @@ -2,10 +2,17 @@ import seedu.financialplanner.utils.Ui; +/** + * Represents a command for an invalid input. + */ public class InvalidCommand extends Command { public InvalidCommand() { } + /** + * Executes the command to display an error message when an + * invalid input is received. + */ @Override public void execute() { Ui.getInstance().showMessage("Unknown command. Please try again."); diff --git a/src/main/java/seedu/financialplanner/commands/OverviewCommand.java b/src/main/java/seedu/financialplanner/commands/OverviewCommand.java index 9aa2107a08..5242987f99 100644 --- a/src/main/java/seedu/financialplanner/commands/OverviewCommand.java +++ b/src/main/java/seedu/financialplanner/commands/OverviewCommand.java @@ -12,6 +12,9 @@ import java.text.DecimalFormat; import java.util.ArrayList; +/** + * Represents a command to display overview of user's financials. + */ public class OverviewCommand extends Command { private static final CashflowList cashflowList = CashflowList.getInstance(); @@ -22,8 +25,11 @@ public OverviewCommand(RawCommand rawCommand) { } } + /** + * Executes the command and displays an overview of the user's financials. + */ @Override - public void execute() throws Exception { + public void execute() { String balance = getBalance(); String highestIncome = getHighestIncome(); String highestExpense = getHighestExpense(); diff --git a/src/main/java/seedu/financialplanner/exceptions/FinancialPlannerException.java b/src/main/java/seedu/financialplanner/exceptions/FinancialPlannerException.java index 387c7ddd06..bda7b2ab4b 100644 --- a/src/main/java/seedu/financialplanner/exceptions/FinancialPlannerException.java +++ b/src/main/java/seedu/financialplanner/exceptions/FinancialPlannerException.java @@ -1,5 +1,8 @@ package seedu.financialplanner.exceptions; +/** + * Represents exceptions specific to the Financial Planner. + */ public class FinancialPlannerException extends Exception { public FinancialPlannerException(String message) { super(message); diff --git a/src/main/java/seedu/financialplanner/storage/LoadData.java b/src/main/java/seedu/financialplanner/storage/LoadData.java index 9a9810b014..cab7c5e59e 100644 --- a/src/main/java/seedu/financialplanner/storage/LoadData.java +++ b/src/main/java/seedu/financialplanner/storage/LoadData.java @@ -25,12 +25,22 @@ import java.util.HashMap; import java.util.Scanner; +/** + * Represents the loading of data from storage. + */ public abstract class LoadData { private static final String FILE_PATH = "data/watchlist.json"; private static final CashflowList cashflowList = CashflowList.getInstance(); private static final Ui ui = Ui.getInstance(); + /** + * Loads existing data from the storage file. + * + * @param filePath The file where the data is stored. + * @param date The current date. + * @throws FinancialPlannerException If there is an issue loading data from storage. + */ public static void load(String filePath, LocalDate date) throws FinancialPlannerException { try { Scanner inputFile = new Scanner(new FileReader(filePath)); @@ -148,8 +158,14 @@ private static void handleCorruptedFile(String message) throws FinancialPlannerE } private static void loadBudget(String[] split) throws IllegalArgumentException { - double initial = Double.parseDouble(split[1].trim()); - double current = Double.parseDouble(split[2].trim()); + double initial; + double current; + try { + initial = Double.parseDouble(split[1].trim()); + current = Double.parseDouble(split[2].trim()); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Error parsing budget values."); + } if (initial == 0 && current == 0) { return; } diff --git a/src/main/java/seedu/financialplanner/storage/SaveData.java b/src/main/java/seedu/financialplanner/storage/SaveData.java index b11872d84e..17e49e4e86 100644 --- a/src/main/java/seedu/financialplanner/storage/SaveData.java +++ b/src/main/java/seedu/financialplanner/storage/SaveData.java @@ -12,9 +12,11 @@ import java.io.FileWriter; import java.io.IOException; +/** + * Represents the saving of data to storage. + */ public abstract class SaveData { private static final String FILE_PATH = "data/watchlist.json"; - private static final CashflowList cashflowList = CashflowList.getInstance(); public static void save(String filePath) throws FinancialPlannerException { diff --git a/src/main/java/seedu/financialplanner/storage/Storage.java b/src/main/java/seedu/financialplanner/storage/Storage.java index 95eeaf7100..ef491dc34e 100644 --- a/src/main/java/seedu/financialplanner/storage/Storage.java +++ b/src/main/java/seedu/financialplanner/storage/Storage.java @@ -8,6 +8,9 @@ import java.nio.file.Paths; import java.time.LocalDate; +/** + * Represents the saving and loading of data. + */ public class Storage { private static Storage storage = null; private final Path path = Paths.get("data"); diff --git a/src/main/java/seedu/financialplanner/utils/Ui.java b/src/main/java/seedu/financialplanner/utils/Ui.java index f3231e74de..d183ca2e45 100644 --- a/src/main/java/seedu/financialplanner/utils/Ui.java +++ b/src/main/java/seedu/financialplanner/utils/Ui.java @@ -12,6 +12,9 @@ import java.util.logging.Level; import java.util.logging.Logger; +/** + * Represents the handling of user interactions. + */ public class Ui { private static final Logger logger = Logger.getLogger("Financial Planner Logger"); private static Ui ui = null; diff --git a/src/test/java/seedu/financialplanner/commands/BudgetCommandTest.java b/src/test/java/seedu/financialplanner/commands/BudgetCommandTest.java index 40e05cc636..019b0b4424 100644 --- a/src/test/java/seedu/financialplanner/commands/BudgetCommandTest.java +++ b/src/test/java/seedu/financialplanner/commands/BudgetCommandTest.java @@ -116,7 +116,7 @@ public void testInvalidBudget_throwsException() throws FinancialPlannerException try { BudgetCommand testBudgetExceedBalance = new BudgetCommand(Parser.parseRawCommand("budget set /b 500")); } catch (FinancialPlannerException e) { - assertEquals("Budget should be lower than total balance.", e.getMessage()); + assertEquals("Budget should be lower than or equal to total balance.", e.getMessage()); } } }