diff --git a/.gitignore b/.gitignore index 14c9e65..1d8854f 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,5 @@ yarn-error.log /.idea/ /.gradle/ credentials.properties -gradlew.bat \ No newline at end of file +gradlew.bat +local.properties \ No newline at end of file diff --git a/README.md b/README.md index 2364f25..032ca3b 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,31 @@ This will returns an object of type `CalculatorResponse`. This provide headline * `endOfPeriod2Savings: Double` * `endOfPeriod2Total: Double` +### For existing accounts in first term +```kotlin +FirstBonusTermCalculator.runFirstBonusCalculator(input) +``` +Where `input` have the following object: +``` +regularPayment: Double, // 25.0 +currentBalance: Double, // 25.0 +paidInThisMonth: Double, // 50.0 +accountStartDate: YearMonthDayInput, // YearMonthDayInput(2020, 3) +firstTermEndDate: YearMonthDayInput, // YearMonthDayInput(2022, 2, 28) +secondTermEndDate: YearMonthDayInput, // YearMonthDayInput(2024, 2, 28) +balanceMustBeMoreThanForBonus: Double // 50.0 +``` + +## Response +This will returns an object of type `FirstBonusCalculatorResponse`. +* `totalProjectedSavingsIncludingBonuses: Double` +* `totalProjectedSavings: Double` +* `totalProjectedBonuses: Double` +* `projectedSavingsFirstBonusPeriod: Double` +* `projectedFirstBonus: Double` +* `projectedAdditionalSavingsFinalBonusPeriod: Double` +* `projectedFinalBonus: Double` + ## Validation To validate the monthly contributions: diff --git a/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/FirstBonusTermCalculation.kt b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/FirstBonusTermCalculation.kt new file mode 100644 index 0000000..cdda6d7 --- /dev/null +++ b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/FirstBonusTermCalculation.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2020 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.gov.hmrc.helptosavecalculator + +import uk.gov.hmrc.helptosavecalculator.models.FirstBonusInput +import uk.gov.hmrc.helptosavecalculator.utils.monthsSince + +internal class FirstBonusTermCalculation { + + fun calculateTotalProjectedSavingsIncludeBonuses( + totalProjectedSavings: Double, + totalProjectedBonuses: Double + ): Double { + return totalProjectedSavings + totalProjectedBonuses + } + + fun calculateAdditionalSavingsThisMonth(input: FirstBonusInput): Double { + return if (input.regularPayment > input.paidInThisMonth) { + input.regularPayment - input.paidInThisMonth + } else { + 0.0 + } + } + + fun calculateTotalProjectedSavings( + input: FirstBonusInput, + additionalSavingsThisMonth: Double, + monthsLeftInScheme: Int + ): Double { + return input.currentBalance + additionalSavingsThisMonth + (input.regularPayment * monthsLeftInScheme) + } + + fun calculateTotalProjectedBonuses( + projectedFirstBonus: Double, + projectedFinalBonus: Double + ): Double { + return projectedFirstBonus + projectedFinalBonus + } + + fun calculateProjectedSavingsFirstBonusPeriod( + input: FirstBonusInput, + additionalSavingsThisMonth: Double, + monthsLeftInFirstTerm: Int + ): Double { + return input.currentBalance + additionalSavingsThisMonth + (input.regularPayment * monthsLeftInFirstTerm) + } + + fun calculateHighestBalanceFirstBonusPeriod( + input: FirstBonusInput, + projectedSavingsFirstBonusPeriod: Double + ): Double { + return input.balanceMustBeMoreThanForBonus.takeIf { + it > projectedSavingsFirstBonusPeriod + } ?: projectedSavingsFirstBonusPeriod + } + + fun calculateProjectedFirstBonus(highestBalanceFirstBonusPeriod: Double): Double { + return highestBalanceFirstBonusPeriod / 2 + } + + fun calculateProjectedAdditionalSavingsFinalBonusPeriod(input: FirstBonusInput): Double { + return input.regularPayment * 24 + } + + fun calculateProjectedFinalBonus( + highestBalanceFinalBonusPeriod: Double, + highestBalanceFirstBonusPeriod: Double + ): Double { + return if (highestBalanceFinalBonusPeriod > highestBalanceFirstBonusPeriod) { + (highestBalanceFinalBonusPeriod - highestBalanceFirstBonusPeriod) / 2 + } else { + 0.0 + } + } + + fun calculateMonthsLeftInScheme(input: FirstBonusInput): Pair { + val startDate = input.accountStartDate.convertToDateTime() + val secondTermEndDate = input.secondTermEndDate.convertToDateTime() + val firstTermEndDate = input.firstTermEndDate.convertToDateTime() + val monthsLeftInScheme = startDate.monthsSince(secondTermEndDate) + val monthsLeftInFirstTerm = startDate.monthsSince(firstTermEndDate) + return Pair(monthsLeftInScheme, monthsLeftInFirstTerm) + } +} diff --git a/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/FirstBonusTermCalculator.kt b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/FirstBonusTermCalculator.kt new file mode 100644 index 0000000..471bfea --- /dev/null +++ b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/FirstBonusTermCalculator.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2020 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.gov.hmrc.helptosavecalculator + +import uk.gov.hmrc.helptosavecalculator.exceptions.InvalidRegularPaymentException +import uk.gov.hmrc.helptosavecalculator.models.FirstBonusCalculatorResponse +import uk.gov.hmrc.helptosavecalculator.models.FirstBonusInput +import uk.gov.hmrc.helptosavecalculator.validation.RegularPaymentValidators + +object FirstBonusTermCalculator { + + private val calculation = FirstBonusTermCalculation() + + fun runFirstBonusCalculator(input: FirstBonusInput): FirstBonusCalculatorResponse { + return calculateFirstBonus(input) + } + + private fun calculateFirstBonus(input: FirstBonusInput): FirstBonusCalculatorResponse { + validateUserInput(input.regularPayment) + + val (monthLeftInScheme, monthLeftInFirstTerm) = calculation.calculateMonthsLeftInScheme(input) + val additionalSavingsThisMonth = calculation.calculateAdditionalSavingsThisMonth(input) + val totalProjectedSavings = calculation.calculateTotalProjectedSavings(input, + additionalSavingsThisMonth, + monthLeftInScheme) + val projectedSavingsFirstBonusPeriod = calculation.calculateProjectedSavingsFirstBonusPeriod(input, + additionalSavingsThisMonth, + monthLeftInFirstTerm) + val highestBalanceFirstBonusPeriod = calculation.calculateHighestBalanceFirstBonusPeriod(input, + projectedSavingsFirstBonusPeriod) + val projectedFirstBonus = calculation.calculateProjectedFirstBonus(highestBalanceFirstBonusPeriod) + val projectedAdditionalSavingsFinalBonusPeriod = + calculation.calculateProjectedAdditionalSavingsFinalBonusPeriod(input) + val projectedFinalBonus = calculation.calculateProjectedFinalBonus(totalProjectedSavings, + highestBalanceFirstBonusPeriod) + val totalProjectedBonuses = calculation.calculateTotalProjectedBonuses(projectedFirstBonus, + projectedFinalBonus) + val totalProjectedSavingsIncludingBonuses = + calculation.calculateTotalProjectedSavingsIncludeBonuses(totalProjectedSavings, + totalProjectedBonuses) + + return FirstBonusCalculatorResponse( + totalProjectedSavingsIncludingBonuses, + totalProjectedSavings, + totalProjectedBonuses, + projectedSavingsFirstBonusPeriod, + projectedFirstBonus, + projectedAdditionalSavingsFinalBonusPeriod, + projectedFinalBonus + ) + } + + private fun validateUserInput(regularPayment: Double) { + if (!RegularPaymentValidators.isValidRegularPayments(regularPayment)) { + throw InvalidRegularPaymentException(regularPayment) + } + } +} diff --git a/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/CalculatorResponse.kt b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/CalculatorResponse.kt index 070ff8b..9f64fb0 100644 --- a/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/CalculatorResponse.kt +++ b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/CalculatorResponse.kt @@ -38,3 +38,13 @@ data class MonthlyBreakdown( ) { val bonusToDate: Double = period1Bonus + period2Bonus } + +data class FirstBonusCalculatorResponse( + val totalProjectedSavingsIncludingBonuses: Double, + val totalProjectedSavings: Double, + val totalProjectedBonuses: Double, + val projectedSavingsFirstBonusPeriod: Double, + val projectedFirstBonus: Double, + val projectedAdditionalSavingsFinalBonusPeriod: Double, + val projectedFinalBonus: Double +) diff --git a/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/FirstBonusInput.kt b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/FirstBonusInput.kt new file mode 100644 index 0000000..1cb19c8 --- /dev/null +++ b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/FirstBonusInput.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2020 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.gov.hmrc.helptosavecalculator.models + +data class FirstBonusInput( + val regularPayment: Double, + val currentBalance: Double, + val paidInThisMonth: Double, + val accountStartDate: YearMonthDayInput, + val firstTermEndDate: YearMonthDayInput, + val secondTermEndDate: YearMonthDayInput, + val balanceMustBeMoreThanForBonus: Double +) diff --git a/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/YearMonthDayInput.kt b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/YearMonthDayInput.kt new file mode 100644 index 0000000..18d8cda --- /dev/null +++ b/src/commonMain/kotlin/uk/gov/hmrc/helptosavecalculator/models/YearMonthDayInput.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2020 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.gov.hmrc.helptosavecalculator.models + +import com.soywiz.klock.DateTime + +data class YearMonthDayInput( + val year: Int, + val month: Int, + val day: Int = 1 +) { + internal fun convertToDateTime(): DateTime { + return DateTime(year, month, day) + } +} diff --git a/src/commonTest/kotlin/uk/gov/hmrc/FirstBonusTermCalculationTest.kt b/src/commonTest/kotlin/uk/gov/hmrc/FirstBonusTermCalculationTest.kt new file mode 100644 index 0000000..300492c --- /dev/null +++ b/src/commonTest/kotlin/uk/gov/hmrc/FirstBonusTermCalculationTest.kt @@ -0,0 +1,189 @@ +/* + * Copyright 2020 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.gov.hmrc + +import kotlin.test.Test +import kotlin.test.assertEquals +import uk.gov.hmrc.helptosavecalculator.FirstBonusTermCalculation +import uk.gov.hmrc.helptosavecalculator.models.FirstBonusInput +import uk.gov.hmrc.helptosavecalculator.models.YearMonthDayInput + +class FirstBonusTermCalculationTest { + + @Test + fun `GIVEN calculateTotalProjectedSavingsIncludeBonuses called THEN return the total`() { + val valueOne = 1.0 + val valueTwo = 2.0 + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateTotalProjectedSavingsIncludeBonuses(valueOne, valueTwo) + + assertEquals(3.0, result) + } + + @Test + fun `GIVEN regular payment is above paid in this month WHEN calculateAdditionalSavingsThisMonth called THEN return the total`() { + val input = FirstBonusInput(50.0, + 25.0, + 25.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 50.0) + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateAdditionalSavingsThisMonth(input) + + assertEquals(25.0, result) + } + + @Test + fun `GIVEN regular payment is below paid in this month WHEN calculateAdditionalSavingsThisMonth called THEN return zero`() { + val input = FirstBonusInput(25.0, + 25.0, + 50.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 50.0) + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateAdditionalSavingsThisMonth(input) + + assertEquals(0.0, result) + } + + @Test + fun `GIVEN calculateTotalProjectedSavings called THEN return the total`() { + val input = FirstBonusInput(25.0, + 25.0, + 50.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 50.0) + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateTotalProjectedSavings(input, 2.0, 10) + + assertEquals(277.0, result) + } + + @Test + fun `GIVEN calculateTotalProjectedBonuses called THEN return the total`() { + val valueOne = 1.0 + val valueTwo = 2.0 + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateTotalProjectedBonuses(valueOne, valueTwo) + + assertEquals(3.0, result) + } + + @Test + fun `GIVEN calculateProjectedSavingsFirstBonusPeriod called THEN return the total`() { + val input = FirstBonusInput(25.0, + 25.0, + 50.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 50.0) + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateProjectedSavingsFirstBonusPeriod(input, 2.0, 10) + + assertEquals(277.0, result) + } + + @Test + fun `GIVEN balanceMustBeMoreThanForBonus is above projectedSavingsFirstBonusPeriod WHEN calculateHighestBalanceFirstBonusPeriod called THEN return balanceMustBeMoreThanForBonus`() { + val input = FirstBonusInput(25.0, + 25.0, + 50.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 50.0) + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateHighestBalanceFirstBonusPeriod(input, 2.0) + + assertEquals(50.0, result) + } + + @Test + fun `GIVEN balanceMustBeMoreThanForBonus is below projectedSavingsFirstBonusPeriod WHEN calculateHighestBalanceFirstBonusPeriod called THEN return projectedSavingsFirstBonusPeriod`() { + val input = FirstBonusInput(25.0, + 25.0, + 50.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 1.0) + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateHighestBalanceFirstBonusPeriod(input, 2.0) + + assertEquals(2.0, result) + } + + @Test + fun `GIVEN calculateProjectedFirstBonus called THEN return the total`() { + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateProjectedFirstBonus(10.0) + + assertEquals(5.0, result) + } + + @Test + fun `GIVEN calculateProjectedAdditionalSavingsFinalBonusPeriod called THEN return the total`() { + val input = FirstBonusInput(10.0, + 25.0, + 50.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 1.0) + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateProjectedAdditionalSavingsFinalBonusPeriod(input) + + assertEquals(240.0, result) + } + + @Test + fun `GIVEN highestBalanceFinalBonusPeriod is above highestBalanceFirstBonusPeriod WHEN calculateProjectedFinalBonus called THEN return the total`() { + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateProjectedFinalBonus(10.0, 5.0) + + assertEquals(2.5, result) + } + + @Test + fun `GIVEN highestBalanceFinalBonusPeriod is below highestBalanceFirstBonusPeriod WHEN calculateProjectedFinalBonus called THEN return zero`() { + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateProjectedFinalBonus(5.0, 10.0) + + assertEquals(0.0, result) + } + + @Test + fun `GIVEN calculateMonthsLeftInScheme called THEN return the remaining months left in scheme`() { + val input = FirstBonusInput(10.0, + 25.0, + 50.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 1.0) + val calculation = FirstBonusTermCalculation() + val result = calculation.calculateMonthsLeftInScheme(input) + + assertEquals(Pair(47, 23), result) + } +} diff --git a/src/commonTest/kotlin/uk/gov/hmrc/FirstBonusTermCalculatorTest.kt b/src/commonTest/kotlin/uk/gov/hmrc/FirstBonusTermCalculatorTest.kt new file mode 100644 index 0000000..1dc47b2 --- /dev/null +++ b/src/commonTest/kotlin/uk/gov/hmrc/FirstBonusTermCalculatorTest.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2020 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.gov.hmrc + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import uk.gov.hmrc.helptosavecalculator.FirstBonusTermCalculator.runFirstBonusCalculator +import uk.gov.hmrc.helptosavecalculator.exceptions.InvalidRegularPaymentException +import uk.gov.hmrc.helptosavecalculator.models.FirstBonusInput +import uk.gov.hmrc.helptosavecalculator.models.YearMonthDayInput + +class FirstBonusTermCalculatorTest { + @Test + fun `GIVEN regular payment is below 1 THEN InvalidRegularPaymentException thrown`() { + val input = FirstBonusInput(0.0, + 0.0, + 0.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 0.0) + assertFailsWith { + runFirstBonusCalculator(input) + } + } + + @Test + fun `GIVEN regular payment is above 50 THEN InvalidRegularPaymentException thrown`() { + val input = FirstBonusInput(51.0, + 0.0, + 0.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 0.0) + assertFailsWith { + runFirstBonusCalculator(input) + } + } + + @Test + fun `GIVEN new account with no payment WHEN 1 pound regular payment added THEN correct calculation displayed`() { + val input = FirstBonusInput(1.0, + 0.0, + 0.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 0.0) + val calculator = runFirstBonusCalculator(input) + + assertEquals(72.00, calculator.totalProjectedSavingsIncludingBonuses) + assertEquals(48.00, calculator.totalProjectedSavings) + assertEquals(24.00, calculator.totalProjectedBonuses) + assertEquals(24.00, calculator.projectedSavingsFirstBonusPeriod) + assertEquals(12.00, calculator.projectedFirstBonus) + assertEquals(24.00, calculator.projectedAdditionalSavingsFinalBonusPeriod) + assertEquals(12.00, calculator.projectedFinalBonus) + } + + @Test + fun `GIVEN new account with no payment WHEN 25 pound regular payment added THEN correct calculation displayed`() { + val input = FirstBonusInput(25.0, + 0.0, + 0.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 0.0) + val calculator = runFirstBonusCalculator(input) + + assertEquals(1800.00, calculator.totalProjectedSavingsIncludingBonuses) + assertEquals(1200.00, calculator.totalProjectedSavings) + assertEquals(600.00, calculator.totalProjectedBonuses) + assertEquals(600.00, calculator.projectedSavingsFirstBonusPeriod) + assertEquals(300.00, calculator.projectedFirstBonus) + assertEquals(600.00, calculator.projectedAdditionalSavingsFinalBonusPeriod) + assertEquals(300.00, calculator.projectedFinalBonus) + } + + @Test + fun `GIVEN new account with no payment WHEN 50 pound regular payment added THEN correct calculation displayed`() { + val input = FirstBonusInput(50.0, + 0.0, + 0.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 0.0) + val calculator = runFirstBonusCalculator(input) + + assertEquals(3600.00, calculator.totalProjectedSavingsIncludingBonuses) + assertEquals(2400.00, calculator.totalProjectedSavings) + assertEquals(1200.00, calculator.totalProjectedBonuses) + assertEquals(1200.00, calculator.projectedSavingsFirstBonusPeriod) + assertEquals(600.00, calculator.projectedFirstBonus) + assertEquals(1200.00, calculator.projectedAdditionalSavingsFinalBonusPeriod) + assertEquals(600.00, calculator.projectedFinalBonus) + } + + @Test + fun `GIVEN new account with 50 pounds first month AND withdrawn 25 WHEN 25 pound regular payment added THEN correct calculation displayed`() { + val input = FirstBonusInput(25.0, + 25.0, + 50.0, + YearMonthDayInput(2020, 3), + YearMonthDayInput(2022, 2, 28), + YearMonthDayInput(2024, 2, 28), + 50.0) + val calculator = runFirstBonusCalculator(input) + + assertEquals(1800.00, calculator.totalProjectedSavingsIncludingBonuses) + assertEquals(1200.00, calculator.totalProjectedSavings) + assertEquals(600.00, calculator.totalProjectedBonuses) + assertEquals(600.00, calculator.projectedSavingsFirstBonusPeriod) + assertEquals(300.00, calculator.projectedFirstBonus) + assertEquals(600.00, calculator.projectedAdditionalSavingsFinalBonusPeriod) + assertEquals(300.00, calculator.projectedFinalBonus) + } +}