BackDatedPaymentCycleEntitlementCalculator.java
package uk.gov.dhsc.htbhf.claimant.entitlement;
import org.springframework.stereotype.Service;
import uk.gov.dhsc.htbhf.dwp.model.QualifyingReason;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static java.util.Collections.emptyList;
import static java.util.Collections.min;
/**
* Calculates the number of back dated vouchers a claimant is entitlement to.
* The expected due date and the birthdays of children resulting from the pregnancy are used to
* calculate the difference between the number of vouchers that were received for pregnancy and
* the number of vouchers that should have been received for the new children. If the difference in vouchers
* is less than zero, zero is returned.
*/
@Service
public class BackDatedPaymentCycleEntitlementCalculator {
private final Integer entitlementCalculationDurationInDays;
private final EntitlementCalculator entitlementCalculator;
/**
* Constructor for {@link BackDatedPaymentCycleEntitlementCalculator}.
*
* @param paymentCycleConfig configuration for the payment cycle
* @param entitlementCalculator calculates entitlement for a single calculation period
*/
public BackDatedPaymentCycleEntitlementCalculator(PaymentCycleConfig paymentCycleConfig,
EntitlementCalculator entitlementCalculator) {
this.entitlementCalculationDurationInDays = paymentCycleConfig.getEntitlementCalculationDurationInDays();
this.entitlementCalculator = entitlementCalculator;
}
/**
* Calculates the back dated vouchers given the expected due date and the dates of births resulting from the pregnancy.
*
* @param expectedDueDate expected due date
* @param newChildrenDateOfBirths the dates of births of the children resulting from the pregnancy
* @param cycleStartDate the start date of the payment cycle
* @param qualifyingReason overrides the reason that this applicant qualifies for Healthy Start
* @return the number of back dated vouchers the claimant is entitled to
*/
public int calculateBackDatedVouchers(Optional<LocalDate> expectedDueDate,
List<LocalDate> newChildrenDateOfBirths,
LocalDate cycleStartDate,
QualifyingReason qualifyingReason) {
List<LocalDate> backDatedEntitlementDates = getBackDatedEntitlementDates(newChildrenDateOfBirths, cycleStartDate);
int vouchersForChildren = calculateNumberOfVouchers(Optional.empty(), newChildrenDateOfBirths, backDatedEntitlementDates, qualifyingReason);
int vouchersFromPregnancy = calculateNumberOfVouchers(expectedDueDate, emptyList(), backDatedEntitlementDates, qualifyingReason);
int backDatedVouchers = vouchersForChildren - vouchersFromPregnancy;
// do not return negative vouchers
return Math.max(backDatedVouchers, 0);
}
private int calculateNumberOfVouchers(Optional<LocalDate> expectedDueDate,
List<LocalDate> newChildrenDateOfBirths,
List<LocalDate> entitlementDates,
QualifyingReason qualifyingReason) {
return entitlementDates.stream()
.map(date -> entitlementCalculator.calculateVoucherEntitlement(expectedDueDate, newChildrenDateOfBirths, date, qualifyingReason))
.mapToInt(VoucherEntitlement::getTotalVoucherEntitlement)
.sum();
}
// get the list of entitlement dates since the oldest child was born
private List<LocalDate> getBackDatedEntitlementDates(List<LocalDate> newChildrenDatesOfBirth, LocalDate cycleStartDate) {
LocalDate earliestDateOfBirth = min(newChildrenDatesOfBirth);
LocalDate rollingEntitlementDate = cycleStartDate.minusDays(entitlementCalculationDurationInDays);
List<LocalDate> backDatedEntitlementDates = new ArrayList<>();
while (rollingEntitlementDate.isAfter(earliestDateOfBirth) || rollingEntitlementDate.isEqual(earliestDateOfBirth)) {
backDatedEntitlementDates.add(rollingEntitlementDate);
rollingEntitlementDate = rollingEntitlementDate.minusDays(entitlementCalculationDurationInDays);
}
return backDatedEntitlementDates;
}
}