From 28baf1fb5aef785f8206e3e1735b5ed09a2cbc47 Mon Sep 17 00:00:00 2001 From: Andreas Kluge Svendsrud <andreksv@stud.ntnu.no> Date: Thu, 20 Apr 2023 10:57:18 +0200 Subject: [PATCH] Savings and SavingsGoal classes with tests, implemented into GeneralBudget --- .../demo/data/Budget/GeneralBudget.java | 52 ++++- .../idatt1002/demo/data/Budget/Savings.java | 187 ++++++++++++++++++ .../demo/data/Budget/SavingsGoal.java | 129 ++++++++++++ .../demo/data/Budget/GeneralBudgetTest.java | 6 + .../demo/data/Budget/SavingsGoalTest.java | 80 ++++++++ .../demo/data/Budget/SavingsTest.java | 50 +++++ 6 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 src/main/java/no/ntnu/idatt1002/demo/data/Budget/Savings.java create mode 100644 src/main/java/no/ntnu/idatt1002/demo/data/Budget/SavingsGoal.java create mode 100644 src/test/java/no/ntnu/idatt1002/demo/data/Budget/SavingsGoalTest.java create mode 100644 src/test/java/no/ntnu/idatt1002/demo/data/Budget/SavingsTest.java diff --git a/src/main/java/no/ntnu/idatt1002/demo/data/Budget/GeneralBudget.java b/src/main/java/no/ntnu/idatt1002/demo/data/Budget/GeneralBudget.java index 04fb19f7..94d2a707 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/data/Budget/GeneralBudget.java +++ b/src/main/java/no/ntnu/idatt1002/demo/data/Budget/GeneralBudget.java @@ -30,6 +30,22 @@ public class GeneralBudget { */ private final double maxAmount; + /** + * The savings of budget. + */ + private final Savings savings; + + + public GeneralBudget(List<BudgetItem> budgetItems, double maxAmount, Savings savings) { + if (maxAmount < 0) { + throw new IllegalArgumentException("The max amount of the budget cant be less than zero"); + } else { + this.maxAmount = maxAmount; + this.budgetItems = budgetItems; + this.savings = savings; + } + } + /** * Class constructor. * @@ -43,6 +59,7 @@ public class GeneralBudget { } else { this.maxAmount = maxAmount; this.budgetItems = budgetItems; + this.savings = new Savings(); } } @@ -58,6 +75,7 @@ public class GeneralBudget { } else { this.maxAmount = maxAmount; this.budgetItems = new ArrayList<>(); + this.savings = new Savings(); } } @@ -90,6 +108,15 @@ public class GeneralBudget { return budgetItems; } + /** + * Method for getting Savings + * + * @return savings of Budget. + */ + public Savings getSavings() { + return savings; + } + /** * Method for getting a Specific BudgetItem * from budgetItems @@ -146,7 +173,7 @@ public class GeneralBudget { * @param category A category from ExpenseCategory */ public void addToBudget(double budgetAmount, String description, ExpenseCategory category) { - if ((totalSum() + budgetAmount) > maxAmount) { + if ((totalSumAndSavings() + budgetAmount) > maxAmount) { throw new IllegalArgumentException("Amount to be added goes over the max value of the budget"); } if (!hasBudgetCategory(category)) { @@ -212,6 +239,29 @@ public class GeneralBudget { budgetItems.removeIf(item -> item.getBudgetCategory() == category); } + /** + * Method returns totalSum of budgetItems and totalSum of savings. + * + * @return totalSum of budgetItems and totalSum of savings. + */ + public double totalSumAndSavings() { + return totalSum() + savings.getTotalSavings(); + } + + /** + * Assign an amount to savings. + * The amount plus other assigned amounts cannot be more than the maxAmount. + * + * @param amount the amount you want to assign to savings. + * @throws IllegalArgumentException if amount plus totalSumAndSavings is more than maxAmount + */ + public void addToSavings(double amount) { + if((totalSumAndSavings() + amount) > maxAmount) { + throw new IllegalArgumentException("Amount to be added goes over the max value of the budget"); + } + savings.addToSavings(amount); + } + @Override public String toString() { StringBuilder budgetItemsString = new StringBuilder(); diff --git a/src/main/java/no/ntnu/idatt1002/demo/data/Budget/Savings.java b/src/main/java/no/ntnu/idatt1002/demo/data/Budget/Savings.java new file mode 100644 index 00000000..2bd4d476 --- /dev/null +++ b/src/main/java/no/ntnu/idatt1002/demo/data/Budget/Savings.java @@ -0,0 +1,187 @@ +package no.ntnu.idatt1002.demo.data.Budget; + +import java.util.ArrayList; +import java.util.List; + +/** + * Savings is a class that has an amount + * that is given to it, which can further can be + * given to different savingsGoals. + */ +public class Savings { + /** + * List of SavingsGoals + */ + private final List<SavingsGoal> savingsGoals; + /** + * An amount not used on any SavingsGoal. + */ + private double amount; + + /** + * Class constructor that sets + * savingsGoals to an empty ArrayList and + * amount to zero. + */ + public Savings() { + this.savingsGoals = new ArrayList<>(); + this.amount = 0; + } + + /** + * Class constructor that sets + * savingsGoals to an empty ArrayList and + * amount to a given double. + * + * @param amount the double you want to assign amount + */ + public Savings(double amount) { + this.savingsGoals = new ArrayList<>(); + this.amount = amount; + } + + /** + * Class constructor that sets + * savingsGoals to a given ArrayList and + * amount to zero. + * + * @param savingsGoals the ArrayList you want to assign savingsGoals + */ + public Savings(ArrayList<SavingsGoal> savingsGoals) { + this.savingsGoals = savingsGoals; + this.amount = 0; + } + + /** + * Class constructor that sets + * savingsGoals to a given ArrayList and + * amount to a given double. + * + * @param savingsGoals the ArrayList you want to assign savingsGoals + * @param amount + */ + public Savings(ArrayList<SavingsGoal> savingsGoals, double amount) { + this.savingsGoals = savingsGoals; + this.amount = amount; + } + + /** + * Get List of SavingsGoals. + * + * @return List of SavingsGoals + */ + public List<SavingsGoal> getSavingsGoals() { + return savingsGoals; + } + + /** + * Get the amount. + * + * @return savings amount + */ + public double getAmount() { + return amount; + } + + /** + * Get the total amount invested into SavingsGoals + * and the amount that is unused. + * + * @return amount invested into SavingsGoals and amount not used. + */ + public double getTotalSavings() { + double totalSavings = 0; + for(SavingsGoal savingsGoal : savingsGoals) { + totalSavings += savingsGoal.getAmountInvested(); + } + totalSavings += getAmount(); + return totalSavings; + } + + /** + * Get a specific SavingsGoal from + * savingsGoals + * + * @param savingsGoal the SavingsGoal you want to get + * @throws IllegalArgumentException if the SavingsGoal is not in the List + * @return the SavingsGoal you wanted to find if it exists + */ + public SavingsGoal getSavingsGoal(SavingsGoal savingsGoal) { + for(SavingsGoal aSavingsGoal : savingsGoals) { + if(savingsGoal == aSavingsGoal) { + return aSavingsGoal; + } + } + throw new IllegalArgumentException("The SavingsGoal is not in the List"); + } + + /** + * Method to check if savingsGoals + * contains a specific SavingsGoal + * + * @param savingsGoal the SavingsGoal you want to check. + * @return boolean depending on if savingsGoals contains the savingsGoal. + */ + public boolean hasSavingsGoal(SavingsGoal savingsGoal) { + return savingsGoals.contains(savingsGoal); + } + + /** + * A List of all SavingsGoal that are achieved. + * A SavingsGoal is achieved if its amount is zero. + * + * @return List of achieved SavingsGoal + */ + public List<SavingsGoal> getAchievedSavingsGoal() { + List<SavingsGoal> achievedSavingsGoals = new ArrayList<>(); + for(SavingsGoal aSavingsGoal : savingsGoals) { + if(aSavingsGoal.isAchieved()) { + achievedSavingsGoals.add(aSavingsGoal); + } + } + return achievedSavingsGoals; + } + + /** + * Method for adding an amount to a + * SavingsGoal. + * + * @param amount the amount you want to add + * @param savingsGoal the SavingsGoal you want to add to + * @throws IllegalArgumentException if the amount is higher than the Savings amount. + * @throws IllegalArgumentException if SavingsGoal is not in savingsGoal. + */ + public void addToSavingsGoal(int amount, SavingsGoal savingsGoal) { + if(amount > this.amount) { + throw new IllegalArgumentException("The amount cannot be higher than the Savings amount"); + } + if(!hasSavingsGoal(savingsGoal)) { + throw new IllegalArgumentException("The SavingsGoal is not in savingsGoals"); + } + getSavingsGoal(savingsGoal).addAmountInvested(amount); + this.amount -= amount; + } + + /** + * Add an amount to Savings + * + * @param amount the amount you want to add. + */ + public void addToSavings(double amount) { + this.amount += amount; + } + + /** + * Add a SavingsGoal to Savings. + * + * @param savingsGoal the SavingsGoal you want to add. + * @throws IllegalArgumentException if the SavingsGoal already exists in the Savings. + */ + public void addSavingsGoal(SavingsGoal savingsGoal) { + if(savingsGoals.contains(savingsGoal)) { + throw new IllegalArgumentException("SavingsGoal already in Savings"); + } else { + savingsGoals.add(savingsGoal); + } + } +} \ No newline at end of file diff --git a/src/main/java/no/ntnu/idatt1002/demo/data/Budget/SavingsGoal.java b/src/main/java/no/ntnu/idatt1002/demo/data/Budget/SavingsGoal.java new file mode 100644 index 00000000..ce7fd18e --- /dev/null +++ b/src/main/java/no/ntnu/idatt1002/demo/data/Budget/SavingsGoal.java @@ -0,0 +1,129 @@ +package no.ntnu.idatt1002.demo.data.Budget; + +/** + * SavingsGoal is a specific goal that you are + * saving towards, for example a car or holiday. + */ +public class SavingsGoal { + /** + * A description of what the SavingsGoal is for. + */ + private String description; + /** + * The monetary amount invested into the SavingsGoal + */ + private double amountInvested; + + /** + * The monetary amount needed to achieve the SavingsGoal + */ + private double amountGoal; + + /** + * Boolean to check if the SavingsGoal has been achieved. + * SavingsGoal has been achieved when amount is zero. + */ + private boolean achieved = false; + + /** + * The class constructor for a SavingsGoal. + * + * @param description a String the explains what the SavingsGoal is for. + * @param amountInvested the monetary amount invested into the SavingsGoal. + * @param amountGoal the monetary amount needed to achieve the SavingsGoal. + */ + public SavingsGoal(String description, double amountInvested, double amountGoal) throws IllegalArgumentException{ + this.description = description; + if(amountGoal < 0) { + amountGoal = 0; + } + if(amountInvested < 0) { + amountInvested = 0; + } + this.amountGoal = amountGoal; + this.amountInvested = amountInvested; + achieved = amountInvested >= amountGoal; + + } + + /** + * The class constructor for a SavingsGoal, + * amountInvested is set to zero. + * + * @param description a String the explains what the SavingsGoal is for. + * @param amountGoal the monetary amount needed to achieve the SavingsGoal. + */ + public SavingsGoal(String description, double amountGoal) { + this.description = description; + if(amountGoal < 0) { + amountGoal = 0; + } + this.amountGoal = amountGoal; + this.amountInvested = 0; + } + /** + * Getting the description of the SavingsGoal + * @return the SavingsGoal´s description. + */ + public String getDescription() { + return description; + } + + /** + * Getting the amount needed to achieve the SavingsGoal + * @return the SavingsGoal´s needed amount. + */ + public double getAmountGoal() { + return amountGoal; + } + + /** + * Getting the amount invested into the SavingsGoal. + * @return the SavingsGoal´s amount invested. + */ + public double getAmountInvested() { + return amountInvested; + } + + /** + * Check if the SavingsGoal is achieved. + * + * @return boolean + */ + public boolean isAchieved() { + return achieved; + } + /** + * Setting the description of the SavingsGoal. + * + * @param description the new description you want to use. + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Setting the amountGoal of the SavingsGoal. + * + * @param amount the new amount you want to use. + */ + public void setAmountGoal(double amount) throws IllegalArgumentException{ + if(amount < 0) { + this.amountGoal = 0; + } else { + this.amountGoal = amount; + } + achieved = amountInvested >= amountGoal; + + } + + /** + * Adding an amount to the amountInvested of the SavingsGoal. + * + * @param amount the amount you want to add. + */ + public void addAmountInvested(double amount) throws IllegalArgumentException{ + this.amountInvested += amount; + achieved = amountInvested >= amountGoal; + } +} diff --git a/src/test/java/no/ntnu/idatt1002/demo/data/Budget/GeneralBudgetTest.java b/src/test/java/no/ntnu/idatt1002/demo/data/Budget/GeneralBudgetTest.java index 55ea6e9f..22467b8e 100644 --- a/src/test/java/no/ntnu/idatt1002/demo/data/Budget/GeneralBudgetTest.java +++ b/src/test/java/no/ntnu/idatt1002/demo/data/Budget/GeneralBudgetTest.java @@ -122,6 +122,12 @@ class GeneralBudgetTest { } + @Test + void addToSavingsThrowsExceptionWhenItShould() { + GeneralBudget generalBudget = new GeneralBudget(1000); + assertThrows(IllegalArgumentException.class, () -> generalBudget.addToSavings(1500)); + } + /* @Test @DisplayName("Gets the number of days left in the month. 17 has to be changed to the actual number of days left in the month.") diff --git a/src/test/java/no/ntnu/idatt1002/demo/data/Budget/SavingsGoalTest.java b/src/test/java/no/ntnu/idatt1002/demo/data/Budget/SavingsGoalTest.java new file mode 100644 index 00000000..1429a517 --- /dev/null +++ b/src/test/java/no/ntnu/idatt1002/demo/data/Budget/SavingsGoalTest.java @@ -0,0 +1,80 @@ +package no.ntnu.idatt1002.demo.data.Budget; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.time.Month; + +import static org.junit.jupiter.api.Assertions.*; + +public class SavingsGoalTest { + + @Test + void constructorSetsAmountToZeroIfAmountInvestedIsNegative() { + SavingsGoal savingsGoal = new SavingsGoal("",-50,0); + assertEquals(0, savingsGoal.getAmountInvested()); + } + + @Test + void constructorSetsAmountToZeroIfAmountGoalIsNegative() { + SavingsGoal savingsGoal = new SavingsGoal("",0,-50); + assertEquals(0, savingsGoal.getAmountGoal()); + } + + @Test + void setAmountGoalWillSetToZeroIfItGetsANegativeValue() { + SavingsGoal savingsGoal = new SavingsGoal("",50); + savingsGoal.setAmountGoal(-50); + assertEquals(0, savingsGoal.getAmountGoal()); + } + + @Nested + class testIfSavingsGoalIsAchievedWhenItsSupposedTo{ + SavingsGoal savingsGoalNotAchieved; + SavingsGoal savingsGoalAchieved; + @BeforeEach + void createSavingsGoals() { + savingsGoalNotAchieved = new SavingsGoal("", 50, 100); + savingsGoalAchieved = new SavingsGoal("", 100, 50); + } + + + @Test + void savingsGoalIsAchievedWhenItsSupposedTo() { + assertTrue(savingsGoalAchieved.isAchieved()); + } + + @Test + void savingsGoalIsNotAchievedWhenItsSupposedTo() { + assertFalse(savingsGoalNotAchieved.isAchieved()); + } + + @Test + void addAmountInvestedSoItsHigherThanAmountGoalWillMakeItAchieved() { + savingsGoalNotAchieved.addAmountInvested(100); + assertTrue(savingsGoalNotAchieved.isAchieved()); + } + + @Test + void setAmountGoalLowerThanAmountInvestedWillMakeItAchieved() { + savingsGoalNotAchieved.setAmountGoal(25); + assertTrue(savingsGoalNotAchieved.isAchieved()); + } + + @Test + void addAmountInvestedSoItsLowerThanAmountGoalWillMakeItNotAchieved() { + savingsGoalAchieved.addAmountInvested(-75); + assertFalse(savingsGoalAchieved.isAchieved()); + } + + @Test + void setAmountGoalHigherThanAmountInvestedWillMakeItNotAchieved() { + savingsGoalAchieved.setAmountGoal(150); + assertFalse(savingsGoalAchieved.isAchieved()); + } + + } +} diff --git a/src/test/java/no/ntnu/idatt1002/demo/data/Budget/SavingsTest.java b/src/test/java/no/ntnu/idatt1002/demo/data/Budget/SavingsTest.java new file mode 100644 index 00000000..76b03cfb --- /dev/null +++ b/src/test/java/no/ntnu/idatt1002/demo/data/Budget/SavingsTest.java @@ -0,0 +1,50 @@ +package no.ntnu.idatt1002.demo.data.Budget; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +public class SavingsTest { + SavingsGoal savingsGoal1; + SavingsGoal savingsGoal2; + SavingsGoal savingsGoal3; + Savings savings; + @BeforeEach + void addSavingsGoalToSavings() { + savingsGoal1 = new SavingsGoal("", 50, 20); + savingsGoal2 = new SavingsGoal("", 75, 50); + savingsGoal3 = new SavingsGoal("", 20, 100); + + savings = new Savings(100); + savings.addSavingsGoal(savingsGoal1); + savings.addSavingsGoal(savingsGoal2); + savings.addSavingsGoal(savingsGoal3); + } + @Test + void getTotalSavingsGivesExpectedAmount() { + assertEquals(245, savings.getTotalSavings()); + } + + @Test + void getAchievedSavingsGoalGivesExpected() { + List<SavingsGoal> savingsGoalsAchieved = new ArrayList<>(); + savingsGoalsAchieved.add(savingsGoal1); + savingsGoalsAchieved.add(savingsGoal2); + + assertEquals(savingsGoalsAchieved, savings.getAchievedSavingsGoal()); + } + + @Test + void addToSavingsGoalThrowsExceptionWhenTryingToAddMoreThanIsAvailable() { + assertThrows(IllegalArgumentException.class, () -> savings.addToSavingsGoal(1000, savingsGoal1)); + } + + @Test + void addToSavingsGoalThrowsExceptionWhenTryingToAddToASavingGoalThatIsNotAddedToSavings() { + assertThrows(IllegalArgumentException.class, () -> savings.addToSavingsGoal(0, new SavingsGoal("not exist",50))); + } +} + -- GitLab