diff --git a/src/main/java/com/odde/tdd/BudgetPlan.java b/src/main/java/com/odde/tdd/BudgetPlan.java new file mode 100644 index 0000000..67e0db8 --- /dev/null +++ b/src/main/java/com/odde/tdd/BudgetPlan.java @@ -0,0 +1,58 @@ +package com.odde.tdd; + +import java.time.YearMonth; +import java.util.Calendar; +import java.util.Date; + +public class BudgetPlan { + private final BudgetRepo budgetRepo; + + public BudgetPlan(BudgetRepo budgetRepo) { + + this.budgetRepo = budgetRepo; + } + + public double getBudget(Date from, Date to) { + if (from.compareTo(to) > 0) { + return 0; + } + YearMonth fromYearMonth = getYearMonth(from); + YearMonth toYearMonth = getYearMonth(to); + int fromYear = fromYearMonth.getYear(); + int fromMonth = fromYearMonth.getMonthValue(); + int toYear = toYearMonth.getYear(); + int toMonth = toYearMonth.getMonthValue(); + double amount = 0.0; + for (int year = fromYear; year <= toYear; year++) { + for (int i = 1; i <= 12; i++) { + amount += getMonthlyBudget(YearMonth.of(year, i)); + } + } + for (int i = 1; i < fromMonth; i++) { + amount -= getMonthlyBudget(YearMonth.of(fromYear, i)); + } + for (int i = toMonth + 1; i <= 12; i++) { + amount -= getMonthlyBudget(YearMonth.of(toYear, i)); + } + amount -= getMonthlyBudget(fromYearMonth) / fromYearMonth.lengthOfMonth() * (getDayOfMonth(from) - 1); + amount -= getMonthlyBudget(toYearMonth) / toYearMonth.lengthOfMonth() * (toYearMonth.lengthOfMonth() - getDayOfMonth(to)); + return amount; + } + + private double getMonthlyBudget(YearMonth yearMonth) { + return (double) this.budgetRepo.findAll().stream().filter(budget -> + budget.getMonth().equals(yearMonth)).findFirst().map(Budget::getAmount).orElse(0L); + } + + private YearMonth getYearMonth(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return YearMonth.of(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1); + } + + private int getDayOfMonth(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return calendar.get(Calendar.DAY_OF_MONTH); + } +} diff --git a/src/test/java/com/odde/tdd/BudgetPlanTest.java b/src/test/java/com/odde/tdd/BudgetPlanTest.java new file mode 100644 index 0000000..cd2078f --- /dev/null +++ b/src/test/java/com/odde/tdd/BudgetPlanTest.java @@ -0,0 +1,108 @@ +package com.odde.tdd; + +import org.junit.Test; + +import java.time.YearMonth; +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class BudgetPlanTest { + MockBudgetRepo budgetRepo = new MockBudgetRepo(); + BudgetPlan target = new BudgetPlan(budgetRepo); + Calendar calendar = new GregorianCalendar(); + + @Test + public void budge_of_22_01_01() { + calendar.set(2022, Calendar.JANUARY, 1); + Date from = calendar.getTime(); + Date to = calendar.getTime(); + double amount = target.getBudget(from, to); + assertEquals(1.0, amount, 0.0); + } + + @Test + public void budge_from_22_01_01_to_22_01_02() { + calendar.set(2022, Calendar.JANUARY, 1); + Date from = calendar.getTime(); + calendar.set(2022, Calendar.JANUARY, 3); + Date to = calendar.getTime(); + double amount = target.getBudget(from, to); + assertEquals(3.0, amount, 0.0); + } + + @Test + public void budge_from_22_01_31_to_22_02_01() { + calendar.set(2022, Calendar.JANUARY, 31); + Date from = calendar.getTime(); + calendar.set(2022, Calendar.FEBRUARY, 1); + Date to = calendar.getTime(); + double amount = target.getBudget(from, to); + assertEquals(3.0, amount, 0.0); + } + + @Test + public void budget_from_22_01_31_to_22_03_01() { + calendar.set(2022, Calendar.JANUARY, 31); + Date from = calendar.getTime(); + calendar.set(2022, Calendar.MARCH, 1); + Date to = calendar.getTime(); + double amount = target.getBudget(from, to); + assertEquals(60.0, amount, 0.0); + } + + @Test + public void budget_from_21_12_31_to_22_02_01() { + calendar.set(2021, Calendar.DECEMBER, 31); + Date from = calendar.getTime(); + calendar.set(2022, Calendar.FEBRUARY, 1); + Date to = calendar.getTime(); + double amount = target.getBudget(from, to); + assertEquals(34.0, amount, 0.0); + } + + @Test + public void budge_from_21_12_31_to_23_01_01() { + calendar.set(2021, Calendar.DECEMBER, 31); + Date from = calendar.getTime(); + calendar.set(2023, Calendar.JANUARY, 1); + Date to = calendar.getTime(); + double amount = target.getBudget(from, to); + assertEquals(2384.0, amount, 0); + } + + @Test + public void budget_from_20_01_01_to_20_12_31() { + calendar.set(2020, Calendar.JANUARY, 1); + Date from = calendar.getTime(); + calendar.set(2020, Calendar.DECEMBER, 31); + Date to = calendar.getTime(); + double amount = target.getBudget(from, to); + assertEquals(0, amount, 0); + } + +} + +class MockBudgetRepo implements BudgetRepo { + + @Override + public List findAll() { + return Arrays.asList( + new Budget(YearMonth.of(2021, 12), 31), + new Budget(YearMonth.of(2022, 1), 31), + new Budget(YearMonth.of(2022, 2), 56), + new Budget(YearMonth.of(2022, 3), 93), + new Budget(YearMonth.of(2022, 4), 120), + new Budget(YearMonth.of(2022, 5), 155), + new Budget(YearMonth.of(2022, 6), 180), + new Budget(YearMonth.of(2022, 7), 217), + new Budget(YearMonth.of(2022, 8), 248), + new Budget(YearMonth.of(2022, 9), 270), + new Budget(YearMonth.of(2022, 10), 310), + new Budget(YearMonth.of(2022, 11), 330), + new Budget(YearMonth.of(2022, 12), 372), + new Budget(YearMonth.of(2023, 1), 31) + ); + } + +}