PaymentCalculator.java
package uk.gov.dhsc.htbhf.claimant.service.payments;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import uk.gov.dhsc.htbhf.claimant.entitlement.PaymentCycleVoucherEntitlement;
import java.time.LocalDateTime;
import static uk.gov.dhsc.htbhf.claimant.entity.PaymentCycleStatus.FULL_PAYMENT_MADE;
import static uk.gov.dhsc.htbhf.claimant.entity.PaymentCycleStatus.PARTIAL_PAYMENT_MADE;
import static uk.gov.dhsc.htbhf.claimant.service.payments.PaymentCalculation.aBalanceTooHighPaymentCalculation;
@Component
public class PaymentCalculator {
private final int maximumBalancePeriod;
public PaymentCalculator(@Value("${payment-cycle.maximum-balance-period}") int maximumBalancePeriod) {
this.maximumBalancePeriod = maximumBalancePeriod;
}
/**
* Calculates the amount to apply to a new payment request.
* Returns the full entitlement amount when the full entitlement amount plus the card balance is less than or equal to the maximum card balance.
* Returns a partial amount when the full entitlement amount plus the card balance is greater than or equal to the maximum card balance.
* Returns zero when the card balance is greater than or equal to the maximum card balance.
*
* @param entitlement a payment cycle voucher entitlement
* @param cardBalanceInPence the card balance in pence
* @return the payment calculation which comprises the amount in pence to apply to the next payment request and the status of the PaymentCycle
*/
public PaymentCalculation calculatePaymentCycleAmountInPence(PaymentCycleVoucherEntitlement entitlement, int cardBalanceInPence) {
int firstWeekEntitlementInPence = entitlement.getFirstVoucherEntitlementForCycle().getTotalVoucherValueInPence();
int maximumAllowedCardBalanceInPence = firstWeekEntitlementInPence * maximumBalancePeriod;
if (isCardBalanceTooHigh(cardBalanceInPence, maximumAllowedCardBalanceInPence)) {
return aBalanceTooHighPaymentCalculation(cardBalanceInPence);
}
int paymentCycleTotalEntitlementInPence = entitlement.getTotalVoucherValueInPence();
if (fullPaymentKeepsBalanceWithinThreshold(cardBalanceInPence, maximumAllowedCardBalanceInPence, paymentCycleTotalEntitlementInPence)) {
return PaymentCalculation.builder()
.paymentAmount(paymentCycleTotalEntitlementInPence)
.paymentCycleStatus(FULL_PAYMENT_MADE)
.availableBalanceInPence(cardBalanceInPence)
.balanceTimestamp(LocalDateTime.now())
.build();
}
return PaymentCalculation.builder()
.paymentAmount(maximumAllowedCardBalanceInPence - cardBalanceInPence)
.paymentCycleStatus(PARTIAL_PAYMENT_MADE)
.availableBalanceInPence(cardBalanceInPence)
.balanceTimestamp(LocalDateTime.now())
.build();
}
private boolean isCardBalanceTooHigh(int cardBalanceInPence, int maximumAllowedCardBalanceInPence) {
return cardBalanceInPence >= maximumAllowedCardBalanceInPence;
}
private boolean fullPaymentKeepsBalanceWithinThreshold(int cardBalanceInPence,
int maxAllowedCardBalanceInPence,
int paymentCycleTotalEntitlementInPence) {
return cardBalanceInPence + paymentCycleTotalEntitlementInPence <= maxAllowedCardBalanceInPence;
}
}