FINERACT-1971: Down payment (auto) transaction using installment multiples of setting

This commit is contained in:
Jose Alberto Hernandez
2024-05-07 11:45:10 +02:00
committed by Adam Saghy
parent 7499859d39
commit 849790ea46
18 changed files with 582 additions and 371 deletions
@@ -124,7 +124,7 @@ public class Money implements Comparable<Money> {
BigDecimal amountScaled = existingVal;
BigDecimal inMultiplesOfValue = BigDecimal.valueOf(inMultiplesOf.intValue());
if (inMultiplesOfValue.compareTo(BigDecimal.ZERO) > 0) {
amountScaled = existingVal.divide(inMultiplesOfValue, 0, RoundingMode.HALF_UP).multiply(inMultiplesOfValue);
amountScaled = existingVal.divide(inMultiplesOfValue, 0, MoneyHelper.getRoundingMode()).multiply(inMultiplesOfValue);
}
return amountScaled;
}
@@ -133,7 +133,7 @@ public class Money implements Comparable<Money> {
BigDecimal amountScaled = existingVal.getAmount();
BigDecimal inMultiplesOfValue = BigDecimal.valueOf(inMultiplesOf.intValue());
if (inMultiplesOfValue.compareTo(BigDecimal.ZERO) > 0) {
amountScaled = amountScaled.divide(inMultiplesOfValue, 0, RoundingMode.HALF_UP).multiply(inMultiplesOfValue);
amountScaled = amountScaled.divide(inMultiplesOfValue, 0, MoneyHelper.getRoundingMode()).multiply(inMultiplesOfValue);
}
return Money.of(existingVal.getCurrency(), amountScaled);
}
@@ -22,10 +22,12 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.PostConstruct;
import java.math.MathContext;
import java.math.RoundingMode;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class MoneyHelper {
@@ -59,4 +61,10 @@ public class MoneyHelper {
}
return mathContext;
}
public static void fetchRoundingModeFromGlobalConfig() {
roundingMode = RoundingMode.valueOf(staticConfigurationDomainService.getRoundingMode());
log.info("Fetch Rounding Mode from Global Config {}", roundingMode.name());
}
}
@@ -1581,23 +1581,23 @@ Feature: LoanCharge
Then Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
| 01 January 2023 | Disbursement | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 750.0 |
| 01 January 2023 | Down Payment | 187.5 | 187.5 | 0.0 | 0.0 | 0.0 | 562.5 |
| 01 February 2023 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 312.5 |
| 01 March 2023 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 62.5 |
| 01 April 2023 | Repayment | 250.0 | 62.5 | 0.0 | 0.0 | 0.0 | 0.0 |
| 05 April 2023 | Waive loan charges | 10.0 | 0.0 | 0.0 | 0.0 | 0.0 | 62.5 |
| 01 January 2023 | Down Payment | 188.0 | 188.0 | 0.0 | 0.0 | 0.0 | 562.0 |
| 01 February 2023 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 312.0 |
| 01 March 2023 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 62.0 |
| 01 April 2023 | Repayment | 250.0 | 62.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 05 April 2023 | Waive loan charges | 10.0 | 0.0 | 0.0 | 0.0 | 0.0 | 62.0 |
Then On Loan Transactions tab the "Repayment" Transaction with date "01 April 2023" is reverted
Then Loan Repayment schedule has 5 periods, with the following data for periods:
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Waived | Outstanding |
| | | 01 January 2023 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
| 1 | 0 | 01 January 2023 | 01 February 2023 | 562.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 188.0 | 0.0 | 0.5 | 0.0 | 0.0 |
| 1 | 0 | 01 January 2023 | 01 January 2023 | 562.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 188.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2 | 15 | 16 January 2023 | 01 February 2023 | 375.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 187.0 | 0.0 | 187.0 | 0.0 | 0.0 |
| 3 | 15 | 31 January 2023 | 01 March 2023 | 188.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 187.0 | 0.0 | 187.0 | 0.0 | 0.0 |
| 4 | 15 | 15 February 2023 | | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 125.5 | 0.0 | 125.5 | 0.0 | 62.5 |
| 4 | 15 | 15 February 2023 | | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 126.0 | 0.0 | 126.0 | 0.0 | 62.0 |
| 5 | 49 | 05 April 2023 | 05 April 2023 | 0.0 | 0.0 | 0.0 | 0.0 | 10.0 | 10.0 | 0.0 | 0.0 | 0.0 | 10.0 | 0.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Waived | Outstanding |
| 750 | 0 | 0 | 10 | 760 | 687.5 | 0 | 500 | 10 | 62.5 |
| 750 | 0 | 0 | 10 | 760 | 688.0 | 0 | 500 | 10 | 62.0 |
@TestRailId:C2994
Scenario: Waive charge on PIN4 progressive loan
@@ -2032,10 +2032,10 @@ Feature: Loan DownPayment
Then Loan Repayment schedule has 4 periods, with the following data for periods:
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2022 | | 1250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2022 | | 937.0 | 313.0 | 0.0 | 0.0 | 0.0 | 313.0 | 0.0 | 0.0 | 0.0 | 313.0 |
| 2 | 31 | 01 February 2022 | | 625.0 | 312.0 | 0.0 | 0.0 | 0.0 | 312.0 | 0.0 | 0.0 | 0.0 | 312.0 |
| 3 | 28 | 01 March 2022 | | 313.0 | 312.0 | 0.0 | 0.0 | 0.0 | 312.0 | 0.0 | 0.0 | 0.0 | 312.0 |
| 4 | 31 | 01 April 2022 | | 0.0 | 313.0 | 0.0 | 0.0 | 0.0 | 313.0 | 0.0 | 0.0 | 0.0 | 313.0 |
| 1 | 0 | 01 January 2022 | | 938.0 | 312.0 | 0.0 | 0.0 | 0.0 | 312.0 | 0.0 | 0.0 | 0.0 | 312.0 |
| 2 | 31 | 01 February 2022 | | 625.0 | 313.0 | 0.0 | 0.0 | 0.0 | 313.0 | 0.0 | 0.0 | 0.0 | 313.0 |
| 3 | 28 | 01 March 2022 | | 312.0 | 313.0 | 0.0 | 0.0 | 0.0 | 313.0 | 0.0 | 0.0 | 0.0 | 313.0 |
| 4 | 31 | 01 April 2022 | | 0.0 | 312.0 | 0.0 | 0.0 | 0.0 | 312.0 | 0.0 | 0.0 | 0.0 | 312.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 1250.0 | 0 | 0 | 0 | 1250.0 | 0.0 | 0 | 0 | 1250 |
@@ -2446,8 +2446,8 @@ Feature: Loan DownPayment
| 2 | 15 | 16 February 2024 | 16 February 2024 | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
| | | 20 February 2024 | | 625.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 3 | 0 | 20 February 2024 | 20 February 2024 | 719.0 | 156.0 | 0.0 | 0.0 | 0.0 | 156.0 | 156.0 | 0.0 | 0.0 | 0.0 |
| 4 | 15 | 02 March 2024 | 20 February 2024 | 359.0 | 360.0 | 0.0 | 0.0 | 0.0 | 360.0 | 360.0 | 360.0 | 0.0 | 0.0 |
| 5 | 15 | 17 March 2024 | 20 February 2024 | 0.0 | 359.0 | 0.0 | 0.0 | 0.0 | 359.0 | 359.0 | 359.0 | 0.0 | 0.0 |
| 4 | 15 | 02 March 2024 | 20 February 2024 | 360.0 | 359.0 | 0.0 | 0.0 | 0.0 | 359.0 | 359.0 | 359.0 | 0.0 | 0.0 |
| 5 | 15 | 17 March 2024 | 20 February 2024 | 0.0 | 360.0 | 0.0 | 0.0 | 0.0 | 360.0 | 360.0 | 360.0 | 0.0 | 0.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 1125.0 | 0.0 | 0.0 | 0.0 | 1125.0 | 1125.0 | 719.0 | 0.0 | 0.0 |
@@ -32,8 +32,8 @@ Feature: LoanReAmortization
| | | 01 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
| 2 | 15 | 16 January 2024 | 25 January 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | 15 | 31 January 2024 | | 187.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
| 4 | 15 | 15 February 2024 | | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
| 3 | 15 | 31 January 2024 | | 188.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
| 4 | 15 | 15 February 2024 | | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
@@ -74,8 +74,8 @@ Feature: LoanReAmortization
| | | 01 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
| 2 | 15 | 16 January 2024 | 25 January 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | 15 | 31 January 2024 | | 187.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
| 4 | 15 | 15 February 2024 | | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
| 3 | 15 | 31 January 2024 | | 188.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
| 4 | 15 | 15 February 2024 | | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
@@ -102,8 +102,8 @@ Feature: LoanReAmortization
| | | 01 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
| 2 | 15 | 16 January 2024 | 25 January 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | 15 | 31 January 2024 | | 187.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
| 4 | 15 | 15 February 2024 | | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
| 3 | 15 | 31 January 2024 | | 188.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
| 4 | 15 | 15 February 2024 | | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
@@ -167,8 +167,8 @@ Feature: LoanReAmortization
| | | 01 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
| 2 | 15 | 16 January 2024 | | 375.0 | 0.0 | 0.0 | 0.0 | 10.0 | 10.0 | 0.0 | 0.0 | 0.0 | 10.0 |
| 3 | 15 | 31 January 2024 | | 187.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
| 4 | 15 | 15 February 2024 | | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
| 3 | 15 | 31 January 2024 | | 188.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
| 4 | 15 | 15 February 2024 | | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 500.0 | 0.0 | 0.0 | 10.0 | 510.0 | 125.0 | 0.0 | 0.0 | 385.0 |
@@ -3139,10 +3139,10 @@ Feature: LoanRepayment
Then Loan Repayment schedule has 4 periods, with the following data for periods:
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 September 2023 | | 1250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 30 | 01 October 2023 | | 936.62 | 313.38 | 15.62 | 0.0 | 0.0 | 329.0 | 0.0 | 0.0 | 0.0 | 329.0 |
| 2 | 31 | 01 November 2023 | | 623.24 | 313.38 | 15.62 | 0.0 | 0.0 | 329.0 | 0.0 | 0.0 | 0.0 | 329.0 |
| 3 | 30 | 01 December 2023 | | 309.86 | 313.38 | 15.62 | 0.0 | 0.0 | 329.0 | 0.0 | 0.0 | 0.0 | 329.0 |
| 4 | 31 | 01 January 2024 | | 0.0 | 309.86 | 15.64 | 0.0 | 0.0 | 325.5 | 0.0 | 0.0 | 0.0 | 325.5 |
| 1 | 30 | 01 October 2023 | | 937.62 | 312.38 | 15.62 | 0.0 | 0.0 | 328.0 | 0.0 | 0.0 | 0.0 | 328.0 |
| 2 | 31 | 01 November 2023 | | 625.24 | 312.38 | 15.62 | 0.0 | 0.0 | 328.0 | 0.0 | 0.0 | 0.0 | 328.0 |
| 3 | 30 | 01 December 2023 | | 312.86 | 312.38 | 15.62 | 0.0 | 0.0 | 328.0 | 0.0 | 0.0 | 0.0 | 328.0 |
| 4 | 31 | 01 January 2024 | | 0.0 | 312.86 | 15.64 | 0.0 | 0.0 | 328.5 | 0.0 | 0.0 | 0.0 | 328.5 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 1250.0 | 62.50 | 0.0 | 0.0 | 1312.50 | 0.0 | 0.0 | 0.0 | 1312.50 |
@@ -2968,7 +2968,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
}
Money downPaymentMoney = Money.of(getCurrency(),
MathUtil.percentageOf(disbursementTransaction.getAmount(), disbursedAmountPercentageForDownPayment, 19));
if (getLoanProduct().getInstallmentAmountInMultiplesOf() != null) {
downPaymentMoney = Money.roundToMultiplesOf(downPaymentMoney, getLoanProduct().getInstallmentAmountInMultiplesOf());
}
Money adjustedDownPaymentMoney = switch (getLoanProductRelatedDetail().getLoanScheduleType()) {
// For Cumulative loan: To check whether the loan was overpaid when the disbursement happened and to get the
// proper amount after the disbursement we are using two balances:
@@ -1206,10 +1206,11 @@ public final class LoanApplicationTerms {
double installmentAmount = FinanicalFunctions.pmt(periodicInterestRate.doubleValue(), periodsRemaining.doubleValue(),
principalDouble, futureValue, false);
BigDecimal fixedEmiAmount = BigDecimal.valueOf(installmentAmount);
if (this.installmentAmountInMultiplesOf != null) {
installmentAmount = Money.roundToMultiplesOf(installmentAmount, this.installmentAmountInMultiplesOf);
fixedEmiAmount = Money.roundToMultiplesOf(fixedEmiAmount, this.installmentAmountInMultiplesOf);
}
setFixedEmiAmount(BigDecimal.valueOf(installmentAmount));
setFixedEmiAmount(fixedEmiAmount);
}
return getFixedEmiAmount().doubleValue();
}
@@ -0,0 +1,88 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.fineract.infrastructure.configuration.api;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.configuration.domain.GlobalConfigurationProperty;
import org.apache.fineract.infrastructure.configuration.domain.GlobalConfigurationRepositoryWrapper;
import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
@Profile(FineractProfiles.TEST)
@Component
@Path("/v1/internal/configurations")
@RequiredArgsConstructor
@Slf4j
public class InternalConfigurationsApiResource implements InitializingBean {
private final GlobalConfigurationRepositoryWrapper repository;
@Override
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
public void afterPropertiesSet() throws Exception {
log.warn("------------------------------------------------------------");
log.warn(" ");
log.warn("DO NOT USE THIS IN PRODUCTION!");
log.warn("Internal Config services mode is enabled");
log.warn("DO NOT USE THIS IN PRODUCTION!");
log.warn(" ");
log.warn("------------------------------------------------------------");
}
@POST
@Path("{configId}/value/{configValue}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
public Response updateGlobalConfiguration(@Context final UriInfo uriInfo, @PathParam("configId") Long configId,
@PathParam("configValue") Long configValue, @RequestBody(required = false) String error) {
log.warn("------------------------------------------------------------");
log.warn(" ");
log.warn("Update trap-door config: {}", configId);
log.warn(" ");
log.warn("------------------------------------------------------------");
final GlobalConfigurationProperty config = repository.findOneWithNotFoundDetection(configId);
log.warn("Config to be updated {} original value {}", config.getName(), config.getValue());
config.setValue(configValue);
repository.save(config);
log.warn("Config to be updated to {}", config.getValue());
repository.removeFromCache(config.getName());
MoneyHelper.fetchRoundingModeFromGlobalConfig();
return Response.status(Response.Status.OK).build();
}
}
@@ -488,7 +488,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
.getDisbursedAmountPercentageForDownPayment();
Money downPaymentMoney = Money.of(loan.getCurrency(),
MathUtil.percentageOf(amountToDisburse.getAmount(), disbursedAmountPercentageForDownPayment, 19));
if (loan.getLoanProduct().getInstallmentAmountInMultiplesOf() != null) {
downPaymentMoney = Money.roundToMultiplesOf(downPaymentMoney,
loan.getLoanProduct().getInstallmentAmountInMultiplesOf());
}
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate,
downPaymentMoney.getAmount(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
linkedSavingsAccountData.getId(), loan.getId(),
@@ -60,6 +60,7 @@ import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
import org.apache.fineract.integrationtests.common.LoanRescheduleRequestHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.accounting.Account;
@@ -1802,7 +1803,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC103: Advanced payment allocation, add charge after maturity -> N+1 installment, repay the loan
// UC103: Advanced payment allocation, add charge after maturity -> N+1
// installment, repay the loan
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (500)
// 2. Add charge after maturity date
@@ -1872,7 +1874,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
// 1. Disburse the loan (500)
// 2. Add charge for 3rd and 4th installments
// 3. Pay little more than the charge of 1st installment
// 4. Pay little more than the principal of 1st installment and charge of 2nd installment
// 4. Pay little more than the principal of 1st installment and charge of 2nd
// installment
@Test
public void uc104() {
runAt("22 February 2023", () -> {
@@ -2026,9 +2029,11 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC106: Advanced payment allocation, horizontal repayment processing, mixed grouping of allocation rules
// UC106: Advanced payment allocation, horizontal repayment processing, mixed
// grouping of allocation rules
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, but the allocation rules are mixed -> expect validation error
// 1. Create a Loan product, but the allocation rules are mixed -> expect
// validation error
@Test
public void uc106() {
runAt("22 February 2023", () -> {
@@ -2048,11 +2053,15 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC107: Advanced payment allocation, vertical repayment processing, mixed grouping of allocation rules
// UC107: Advanced payment allocation, vertical repayment processing, mixed
// grouping of allocation rules
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, but the allocation rules are mixed -> no validation error
// 2. Change transaction processor while submitting loan -> expect validation error
// 3. Change to HORIZONTAL loan schedule processing and allocation rules are mixed - > expect validation error
// 1. Create a Loan product, but the allocation rules are mixed -> no validation
// error
// 2. Change transaction processor while submitting loan -> expect validation
// error
// 3. Change to HORIZONTAL loan schedule processing and allocation rules are
// mixed - > expect validation error
@Test
public void uc107() {
runAt("22 February 2023", () -> {
@@ -2087,7 +2096,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC108: Advanced payment allocation, progressive loan schedule handling, rounding test
// UC108: Advanced payment allocation, progressive loan schedule handling,
// rounding test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, 1000 principal, across 3 installment
// 2. Submit the loan, and check the generated repayment schedule
@@ -2175,7 +2185,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC109: Advanced payment allocation, progressive loan schedule handling, rounding test
// UC109: Advanced payment allocation, progressive loan schedule handling,
// rounding test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, 1000 principal, across 3 installment
// 2. Submit the loan, and check the generated repayment schedule
@@ -2263,9 +2274,11 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC110: Advanced payment allocation, progressive loan schedule handling, rounding test
// UC110: Advanced payment allocation, progressive loan schedule handling,
// rounding test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, 40.50 principal, across 4 installment (1 down payment, 3 normal installment)
// 1. Create a Loan product, 40.50 principal, across 4 installment (1 down
// payment, 3 normal installment)
// 2. Submit the loan, and check the generated repayment schedule
@Test
public void uc110() {
@@ -2314,9 +2327,11 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC111: Advanced payment allocation, progressive loan schedule handling, rounding test
// UC111: Advanced payment allocation, progressive loan schedule handling,
// rounding test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, 40.50 principal, across 4 installment (1 down payment, 3 normal installment)
// 1. Create a Loan product, 40.50 principal, across 4 installment (1 down
// payment, 3 normal installment)
// 2. Submit the loan, and check the generated repayment schedule
@Test
public void uc111() {
@@ -2785,7 +2800,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC116: Advanced payment allocation, horizontal repayment processing, disbursement on due date of an installment
// UC116: Advanced payment allocation, horizontal repayment processing,
// disbursement on due date of an installment
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
// 2. Add charge on disbursement date(50)
@@ -2869,7 +2885,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC117: Advanced payment allocation, horizontal repayment processing, multi disbursement on due date of an
// UC117: Advanced payment allocation, horizontal repayment processing, multi
// disbursement on due date of an
// installment
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
@@ -2962,7 +2979,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC118: Advanced payment allocation, horizontal repayment processing, multi disbursement on disbursement date
// UC118: Advanced payment allocation, horizontal repayment processing, multi
// disbursement on disbursement date
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
// 2. Disburse on disbursement date (400)
@@ -3019,7 +3037,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
// UC119: Advanced payment allocation with Loan Schedule as Cumulative
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc., but the loan schedule as Cumulative -> expect validation error
// 1. Create a Loan product with Adv. Pment. Alloc., but the loan schedule as
// Cumulative -> expect validation error
@Test
public void uc119() {
runAt("02 February 2023", () -> {
@@ -3038,7 +3057,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC120: Advanced payment allocation with auto down payment and multiple disbursement on the first day
// UC120: Advanced payment allocation with auto down payment and multiple
// disbursement on the first day
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc., and auto down payment
// 2. Submit Loan and approve
@@ -3095,7 +3115,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC121: Advanced payment allocation, horizontal repayment processing product and Loan application
// UC121: Advanced payment allocation, horizontal repayment processing product
// and Loan application
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
@Test
public void uc121() {
@@ -3542,7 +3563,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC126: Advanced payment allocation with Fixed Length for 40 days and Loan Term for 45 days (3 repayments every 15
// UC126: Advanced payment allocation with Fixed Length for 40 days and Loan
// Term for 45 days (3 repayments every 15
// days)
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc. and No Interest
@@ -3587,7 +3609,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC127: Advanced payment allocation with Fixed Length for 5 weeks and Loan Term for 6 weeks (3 repayments every 2
// UC127: Advanced payment allocation with Fixed Length for 5 weeks and Loan
// Term for 6 weeks (3 repayments every 2
// weeks)
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc. and No Interest
@@ -3636,7 +3659,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC128: Advanced payment allocation with Fixed Length for 11 months and Loan Term for 12 months (6 repayments each
// UC128: Advanced payment allocation with Fixed Length for 11 months and Loan
// Term for 12 months (6 repayments each
// 2 months)
// every 2 months)
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
@@ -3690,7 +3714,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC129: Advanced payment allocation with Fixed Length for 5 months and Loan Term for 6 months (6 repayments
// UC129: Advanced payment allocation with Fixed Length for 5 months and Loan
// Term for 6 months (6 repayments
// every month)
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc. and No Interest
@@ -3714,11 +3739,13 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC130: Advanced payment allocation with Fixed Length for 5 months and Loan Term for 6 months (6 repayments
// UC130: Advanced payment allocation with Fixed Length for 5 months and Loan
// Term for 6 months (6 repayments
// every month)
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc. and No Interest
// 2. Submit Loan and approve -> expect validation error - Fixed Length without Advanced Payment Allocation
// 2. Submit Loan and approve -> expect validation error - Fixed Length without
// Advanced Payment Allocation
@Test
public void uc130() {
final String operationDate = "22 November 2023";
@@ -3730,7 +3757,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
.numberOfRepayments(6).repaymentEvery(1).repaymentFrequencyType(repaymentFrequencyType.longValue()).fixedLength(6);
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
// Try to use Fixed Length without Advanced Payment Allocation as transaction processing strategy code
// Try to use Fixed Length without Advanced Payment Allocation as transaction
// processing strategy code
LOG.info("Try to use Fixed Length without Advanced Payment Allocation as transaction processing strategy code");
CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class,
() -> loanTransactionHelper.applyLoan(new PostLoansRequest().clientId(client.getClientId())
@@ -3749,11 +3777,13 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC131: Advanced payment allocation with Fixed Length for 5 months and Loan Term for 6 months (6 repayments
// UC131: Advanced payment allocation with Fixed Length for 5 months and Loan
// Term for 6 months (6 repayments
// every month)
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc. and No Interest
// 2. Submit Loan and approve -> expect validation error - Interest Rate value higher than Zero
// 2. Submit Loan and approve -> expect validation error - Interest Rate value
// higher than Zero
@Test
public void uc131() {
final String operationDate = "22 November 2023";
@@ -3784,11 +3814,13 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC132: Advanced payment allocation with Fixed Length for 5 months and Loan Term for 6 months (3 repayments
// UC132: Advanced payment allocation with Fixed Length for 5 months and Loan
// Term for 6 months (3 repayments
// every 2 months)
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc. and No Interest
// 2. Submit Loan and approve -> expect validation error - Loan acount Fixed Length with a wrong Loan Term setup
// 2. Submit Loan and approve -> expect validation error - Loan acount Fixed
// Length with a wrong Loan Term setup
@Test
public void uc132() {
final String operationDate = "22 November 2023";
@@ -3819,7 +3851,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC133: Advanced payment allocation with higher Fixed Length for 50 days than Loan Term for 45 days (3 repayments
// UC133: Advanced payment allocation with higher Fixed Length for 50 days than
// Loan Term for 45 days (3 repayments
// every 15 days)
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc. and No Interest
@@ -3867,7 +3900,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC134: Advanced payment allocation with Fixed Length for 119 days and Loan Term for 120 days (4 repayments every
// UC134: Advanced payment allocation with Fixed Length for 119 days and Loan
// Term for 120 days (4 repayments every
// 30
// days) and Reschedule
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
@@ -3939,7 +3973,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC135: Advanced payment allocation with Fixed Length for 119 days and Loan Term for 120 days (4 repayments every
// UC135: Advanced payment allocation with Fixed Length for 119 days and Loan
// Term for 120 days (4 repayments every
// 30
// days) and Reschedule
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
@@ -4011,6 +4046,72 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
});
}
// UC136: Advanced payment allocation, using auto downpayment with installment
// amount in multiples of 1
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc.
// 2. Submit Loan and approve
// 3. Disburse the loan and validate downpayment
@Test
public void uc136() {
AtomicLong createdLoanId = new AtomicLong();
runAt("23 March 2024", () -> {
// Rounding mode - HALF_DOWN
GlobalConfigurationHelper.updateValueForGlobalConfigurationInternal(requestSpec, responseSpec, "23", 5);
createLoanForRoundingMethodValidation(true);
// Rounding mode - HALF_UP
GlobalConfigurationHelper.updateValueForGlobalConfigurationInternal(requestSpec, responseSpec, "23", 4);
createLoanForRoundingMethodValidation(false);
// Rounding mode - HALF_EVEN - Default
GlobalConfigurationHelper.updateValueForGlobalConfigurationInternal(requestSpec, responseSpec, "23", 6);
});
}
private void createLoanForRoundingMethodValidation(boolean isHalfDown) {
LOG.info("------------------------------ROUNDING HALF DOWN {} ---------------------------------------", isHalfDown);
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProductWithAdvancedPaymentAllocation()
.installmentAmountInMultiplesOf(null).numberOfRepayments(3).repaymentEvery(15).enableDownPayment(true)
.enableAutoRepaymentForDownPayment(true).disbursedAmountPercentageForDownPayment(BigDecimal.valueOf(25)).minPrincipal(10.0)
.installmentAmountInMultiplesOf(1);
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
PostLoansRequest applicationRequest = applyLoanRequest(client.getClientId(), loanProductResponse.getResourceId(), "23 March 2024",
10.0, 4);
applicationRequest = applicationRequest.numberOfRepayments(3).loanTermFrequency(45)
.transactionProcessingStrategyCode(LoanProductTestBuilder.ADVANCED_PAYMENT_ALLOCATION_STRATEGY).repaymentEvery(15);
PostLoansResponse loanResponse = loanTransactionHelper.applyLoan(applicationRequest);
loanTransactionHelper.approveLoan(loanResponse.getLoanId(), new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(10))
.dateFormat(DATETIME_PATTERN).approvedOnDate("23 March 2024").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(), new PostLoansLoanIdRequest().actualDisbursementDate("23 March 2024")
.dateFormat(DATETIME_PATTERN).transactionAmount(BigDecimal.valueOf(10.0)).locale("en"));
// verify schedule
if (isHalfDown) {
verifyRepaymentSchedule(loanResponse.getLoanId(), //
installment(10, null, "23 March 2024"), //
installment(2, 0, 0, 0, 0.0, true, "23 March 2024", 8), //
installment(3, 0, 0, 0, 3, false, "07 April 2024", 5), //
installment(3, 0, 0, 0, 3, false, "22 April 2024", 2), //
installment(2, 0, 0, 0, 2, false, "07 May 2024", 0.0) //
);
} else {
LOG.info("Loan Id {}", loanResponse.getLoanId());
verifyRepaymentSchedule(loanResponse.getLoanId(), //
installment(10, null, "23 March 2024"), //
installment(3, 0, 0, 0, 0.0, true, "23 March 2024", 7), //
installment(2, 0, 0, 0, 2, false, "07 April 2024", 5), //
installment(2, 0, 0, 0, 2, false, "22 April 2024", 3), //
installment(3, 0, 0, 0, 3, false, "07 May 2024", 0.0) //
);
}
}
private static List<PaymentAllocationOrder> getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) {
AtomicInteger integer = new AtomicInteger(1);
return Arrays.stream(paymentAllocationTypes).map(pat -> {
@@ -76,10 +76,10 @@ public class CustomSnapshotEventIntegrationTest extends BaseLoanIntegrationTest
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "31 January 2023"), //
installment(313.0, false, "02 March 2023"), //
installment(313.0, false, "01 April 2023"), //
installment(311.0, false, "01 May 2023") //
installment(312.0, false, "31 January 2023"), //
installment(312.0, false, "02 March 2023"), //
installment(312.0, false, "01 April 2023"), //
installment(314.0, false, "01 May 2023") //
);
// delete all external events
@@ -124,10 +124,10 @@ public class CustomSnapshotEventIntegrationTest extends BaseLoanIntegrationTest
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "31 January 2023"), //
installment(313.0, false, "02 March 2023"), //
installment(313.0, false, "01 April 2023"), //
installment(311.0, false, "01 May 2023") //
installment(312.0, false, "31 January 2023"), //
installment(312.0, false, "02 March 2023"), //
installment(312.0, false, "01 April 2023"), //
installment(314.0, false, "01 May 2023") //
);
addRepaymentForLoan(loanId, 313.0, "31 January 2023");
@@ -135,10 +135,10 @@ public class CustomSnapshotEventIntegrationTest extends BaseLoanIntegrationTest
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, true, "31 January 2023"), //
installment(313.0, false, "02 March 2023"), //
installment(313.0, false, "01 April 2023"), //
installment(311.0, false, "01 May 2023") //
installment(312.0, true, "31 January 2023"), //
installment(312.0, false, "02 March 2023"), //
installment(312.0, false, "01 April 2023"), //
installment(314.0, false, "01 May 2023") //
);
// delete all external events
@@ -181,10 +181,10 @@ public class CustomSnapshotEventIntegrationTest extends BaseLoanIntegrationTest
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "31 January 2023"), //
installment(313.0, false, "02 March 2023"), //
installment(313.0, false, "01 April 2023"), //
installment(311.0, false, "01 May 2023") //
installment(312.0, false, "31 January 2023"), //
installment(312.0, false, "02 March 2023"), //
installment(312.0, false, "01 April 2023"), //
installment(314.0, false, "01 May 2023") //
);
// delete all external events
@@ -227,10 +227,10 @@ public class CustomSnapshotEventIntegrationTest extends BaseLoanIntegrationTest
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "31 January 2023"), //
installment(313.0, false, "02 March 2023"), //
installment(313.0, false, "01 April 2023"), //
installment(311.0, false, "01 May 2023") //
installment(312.0, false, "31 January 2023"), //
installment(312.0, false, "02 March 2023"), //
installment(312.0, false, "01 April 2023"), //
installment(314.0, false, "01 May 2023") //
);
// delete all external events
@@ -271,10 +271,10 @@ public class CustomSnapshotEventIntegrationTest extends BaseLoanIntegrationTest
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "31 January 2023"), //
installment(313.0, false, "02 March 2023"), //
installment(313.0, false, "01 April 2023"), //
installment(311.0, false, "01 May 2023") //
installment(312.0, false, "31 January 2023"), //
installment(312.0, false, "02 March 2023"), //
installment(312.0, false, "01 April 2023"), //
installment(314.0, false, "01 May 2023") //
);
// delete all external events
@@ -74,31 +74,31 @@ public class InstallmentLevelDelinquencyAPIIntegrationTests extends BaseLoanInte
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "31 January 2023"), // 120 days delinquent -> range4
installment(313.0, false, "02 March 2023"), // 90 days delinquent -> range4
installment(313.0, false, "01 April 2023"), // 60 days delinquent -> range3
installment(311.0, false, "01 May 2023") // 30 days delinquent -> range2
installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range4
installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range4
installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range3
installment(314.0, false, "01 May 2023") // 30 days delinquent -> range2
);
// since the current day is 31 May 2023, therefore all the installments are delinquent
verifyDelinquency(loanId, 120, "1250.0", //
delinquency(11, 30, "311.0"), // 4th installment
delinquency(31, 60, "313.0"), // 3rd installment
delinquency(61, null, "626.0") // 1st installment + 2nd installment
delinquency(11, 30, "314.0"), // 4th installment
delinquency(31, 60, "312.0"), // 3rd installment
delinquency(61, null, "624.0") // 1st installment + 2nd installment
);
// Repayment of the first two installments
addRepaymentForLoan(loanId, 626.0, "31 May 2023");
verifyDelinquency(loanId, 60, "624.0", //
delinquency(11, 30, "311.0"), // 4th installment
delinquency(31, 60, "313.0") // 3rd installment
delinquency(11, 30, "314.0"), // 4th installment
delinquency(31, 60, "310.0") // 3rd installment
);
// Partial repayment
addRepaymentForLoan(loanId, 100.0, "31 May 2023");
verifyDelinquency(loanId, 60, "524.0", //
delinquency(11, 30, "311.0"), // 4th installment
delinquency(31, 60, "213.0") // 3rd installment
delinquency(11, 30, "314.0"), // 4th installment
delinquency(31, 60, "210.0") // 3rd installment
);
// Repay the loan fully
@@ -135,23 +135,23 @@ public class InstallmentLevelDelinquencyAPIIntegrationTests extends BaseLoanInte
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "31 January 2023"), // 120 days delinquent -> range2
installment(313.0, false, "02 March 2023"), // 90 days delinquent -> range2
installment(313.0, false, "01 April 2023"), // 60 days delinquent -> range1
installment(311.0, false, "01 May 2023") // 30 days delinquent -> range1
installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range2
installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range2
installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range1
installment(314.0, false, "01 May 2023") // 30 days delinquent -> range1
);
verifyDelinquency(loanId, 120, "1250.0", //
delinquency(1, 60, "624.0"), // 4th installment
delinquency(61, null, "626.0") // 1st installment + 2nd installment
delinquency(1, 60, "626.0"), // 4th installment
delinquency(61, null, "624.0") // 1st installment + 2nd installment
);
// repay the first installment
addRepaymentForLoan(loanId, 313.0, "31 May 2023");
verifyDelinquency(loanId, 90, "937.0", //
delinquency(1, 60, "624.0"), // 4th installment
delinquency(61, null, "313.0") // 1st installment + 2nd installment
delinquency(1, 60, "626.0"), // 4th installment
delinquency(61, null, "311.0") // 1st installment + 2nd installment
);
});
@@ -185,10 +185,10 @@ public class InstallmentLevelDelinquencyAPIIntegrationTests extends BaseLoanInte
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "31 January 2023"), // 120 days delinquent -> range2
installment(313.0, false, "02 March 2023"), // 90 days delinquent -> range2
installment(313.0, false, "01 April 2023"), // 60 days delinquent -> range1
installment(311.0, false, "01 May 2023") // 30 days delinquent -> range1
installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range2
installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range2
installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range1
installment(314.0, false, "01 May 2023") // 30 days delinquent -> range1
);
// this should be empty as the installment level delinquency is not enabled for this loan
@@ -223,21 +223,21 @@ public class InstallmentLevelDelinquencyAPIIntegrationTests extends BaseLoanInte
// Verify Repayment Schedule and Due Dates
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), installment(313.0, false, "31 January 2023"),
installment(313.0, false, "02 March 2023"), installment(313.0, false, "01 April 2023"),
installment(311.0, false, "01 May 2023"));
installment(1250.0, null, "01 January 2023"), installment(312.0, false, "31 January 2023"),
installment(312.0, false, "02 March 2023"), installment(312.0, false, "01 April 2023"),
installment(314.0, false, "01 May 2023"));
// The first installment falls into the first range
verifyDelinquency(loanId, 1, "313.0", //
delinquency(1, 1, "313.0") // 4th installment
verifyDelinquency(loanId, 1, "312.0", //
delinquency(1, 1, "312.0") // 4th installment
);
// Let's go one day ahead in the time
updateBusinessDateAndExecuteCOBJob("2 February 2023");
// The first installment is not two days delinquent and therefore falls into the second range
verifyDelinquency(loanId, 2, "313.0", //
delinquency(2, null, "313.0") // 4th installment
verifyDelinquency(loanId, 2, "312.0", //
delinquency(2, null, "312.0") // 4th installment
);
});
}
@@ -205,19 +205,19 @@ public class LoanAccountRepaymentCalculationTest {
assertNotNull(loanDetails.getRepaymentSchedule());
// first period [2023-03-03 to 2023-03-03] down payment installment
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 313.0, 1, LocalDate.of(2023, 3, 3),
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 312.0, 1, LocalDate.of(2023, 3, 3),
LocalDate.of(2023, 3, 3), false);
// second period [2023-03-03 to 2023-04-03] regular installment
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 312.0, 2, LocalDate.of(2023, 3, 3),
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 313.0, 2, LocalDate.of(2023, 3, 3),
LocalDate.of(2023, 4, 3), false);
// third period [2023-04-03 to 2023-05-03] regular installment
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 312.0, 3, LocalDate.of(2023, 4, 3),
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 313.0, 3, LocalDate.of(2023, 4, 3),
LocalDate.of(2023, 5, 3), false);
// fourth period [2023-05-03 to 2023-06-03] regular installment
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 313.0, 4, LocalDate.of(2023, 5, 3),
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 312.0, 4, LocalDate.of(2023, 5, 3),
LocalDate.of(2023, 6, 3), false);
// disbursement
@@ -228,19 +228,19 @@ public class LoanAccountRepaymentCalculationTest {
assertNotNull(loanDetails.getRepaymentSchedule());
// first period [2023-03-03 to 2023-03-03] down payment installment
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 313.0, 1, LocalDate.of(2023, 3, 3),
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 312.0, 1, LocalDate.of(2023, 3, 3),
LocalDate.of(2023, 3, 3), false);
// second period [2023-03-03 to 2023-04-03] regular installment
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 312.0, 2, LocalDate.of(2023, 3, 3),
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 313.0, 2, LocalDate.of(2023, 3, 3),
LocalDate.of(2023, 4, 3), false);
// third period [2023-04-03 to 2023-05-03] regular installment
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 312.0, 3, LocalDate.of(2023, 4, 3),
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 313.0, 3, LocalDate.of(2023, 4, 3),
LocalDate.of(2023, 5, 3), false);
// fourth period [2023-05-03 to 2023-06-03] regular installment
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 313.0, 4, LocalDate.of(2023, 5, 3),
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 312.0, 4, LocalDate.of(2023, 5, 3),
LocalDate.of(2023, 6, 3), false);
} finally {
@@ -70,24 +70,24 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
updateBusinessDate("20 January 2023");
// Add Repayment
Long repaymentTransaction = addRepaymentForLoan(loanId, 383.0, "20 January 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 382.0, "20 January 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Add Chargeback
@@ -96,17 +96,17 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(343.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(342.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
});
}
@@ -133,24 +133,24 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
updateBusinessDate("20 January 2023");
// Add Repayment
Long repaymentTransaction = addRepaymentForLoan(loanId, 383.0, "20 January 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 382.0, "20 January 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
updateBusinessDate("01 February 2023");
@@ -161,17 +161,17 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "01 February 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "01 February 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0, true, "01 February 2023"), //
installment(343.0, 0, 50, 20, 413.0, false, "01 March 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0, true, "01 February 2023"), //
installment(342.0, 0, 50, 20, 412.0, false, "01 March 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
});
}
@@ -198,24 +198,24 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
updateBusinessDate("20 January 2023");
// Add Repayment
Long repaymentTransaction = addRepaymentForLoan(loanId, 383.0, "20 January 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 382.0, "20 January 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
updateBusinessDate("01 May 2023");
@@ -226,17 +226,17 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "01 May 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "01 May 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(341.0, 0, 50, 20, 411.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(344.0, 0, 50, 20, 414.0, false, "01 May 2023") //
);
});
}
@@ -259,36 +259,36 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 0, 0, 312.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date + and make a full repayment for the first installment
updateBusinessDate("20 January 2023");
addRepaymentForLoan(loanId, 313.0, "20 January 2023");
addRepaymentForLoan(loanId, 312.0, "20 January 2023");
// Update Business Date + and make a full repayment for the second installment
updateBusinessDate("20 February 2023");
addRepaymentForLoan(loanId, 313.0, "20 February 2023");
addRepaymentForLoan(loanId, 312.0, "20 February 2023");
// Update Business Date + and make a full repayment for the third installment
updateBusinessDate("20 March 2023");
addRepaymentForLoan(loanId, 313.0, "20 March 2023");
addRepaymentForLoan(loanId, 312.0, "20 March 2023");
// Add some charges Update Business Date + and make a full repayment for the fourth installment
updateBusinessDate("20 April 2023");
addCharge(loanId, false, 50, "20 April 2023");
addCharge(loanId, true, 20, "20 April 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 381.0, "20 April 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 384.0, "20 April 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(311.0, 0, 50, 20, 0.0, true, "01 May 2023") //
installment(312.0, 0, 0, 0, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(314.0, 0, 50, 20, 0.0, true, "01 May 2023") //
);
// Let's move over the maturity date and chargeback some money
@@ -299,20 +299,20 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(313.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(313.0, "Repayment", "20 February 2023", 624.0, 313.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(313.0, "Repayment", "20 March 2023", 311.0, 313.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(381.0, "Repayment", "20 April 2023", 0.0, 311.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(312.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(312.0, "Repayment", "20 February 2023", 626.0, 312.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(312.0, "Repayment", "20 March 2023", 314.0, 312.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(384.0, "Repayment", "20 April 2023", 0.0, 314.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(70.0, "Accrual", "20 April 2023", 0.0, 0.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "02 May 2023", 30.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(311.0, 0, 50, 20, 0.0, true, "01 May 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(314.0, 0, 50, 20, 0.0, true, "01 May 2023"), //
installment(30.0, 0, 50, 20, 100.0, false, "02 May 2023") //
);
});
@@ -340,24 +340,24 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
updateBusinessDate("20 January 2023");
// Add Repayment
Long repaymentTransaction = addRepaymentForLoan(loanId, 383.0, "20 January 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 382.0, "20 January 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
updateBusinessDate("21 January 2023");
@@ -367,17 +367,17 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(343.0, 0, 100, 40, 100.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(342.0, 0, 100, 40, 100.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// let's add a backdated repayment on 19th of January to trigger reverse replaying the chargeback, that will
@@ -387,8 +387,8 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(200.0, "Repayment", "19 January 2023", 1120.0, 130.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 737.0, 383.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 837.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 738.0, 382.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 838.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
);
});
}
@@ -415,24 +415,24 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
updateBusinessDate("20 January 2023");
// Add Repayment
Long repaymentTransaction = addRepaymentForLoan(loanId, 383.0, "20 January 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 382.0, "20 January 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
updateBusinessDate("22 January 2023");
@@ -442,17 +442,17 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "22 January 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "22 January 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(343.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(342.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// let's add a backdated repayment on 21th of January that will reverse replay the chargeback transaction
@@ -462,12 +462,12 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(200.0, "Repayment", "21 January 2023", 737.0, 200.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "22 January 2023", 767.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(200.0, "Repayment", "21 January 2023", 738.0, 200.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "22 January 2023", 768.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
verifyLoanSummaryAmounts(loanId, 30.0, 50.0, 20.0, 837.0);
verifyLoanSummaryAmounts(loanId, 30.0, 50.0, 20.0, 838.0);
});
}
@@ -495,24 +495,24 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
updateBusinessDate("20 January 2023");
// Add Repayment
Long repaymentTransaction = addRepaymentForLoan(loanId, 383.0, "20 January 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 382.0, "20 January 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Add Chargeback
@@ -520,20 +520,20 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 1037.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 1038.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(413.0, 0, 50, 20, 100.0, false, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(412.0, 0, 50, 20, 100.0, false, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
verifyLoanSummaryAmounts(loanId, 100.0, 0.0, 0.0, 1037);
verifyLoanSummaryAmounts(loanId, 100.0, 0.0, 0.0, 1038);
});
}
@@ -559,10 +559,10 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
@@ -574,10 +574,10 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(311.0, 0, 0, 0, 0.0, true, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(314.0, 0, 0, 0, 0.0, true, "01 May 2023") //
);
updateBusinessDate("02 May 2023");
@@ -596,10 +596,10 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
// DEFAULT payment allocation is ..., DUE_PENALTY, DUE_FEE, DUE_PRINCIPAL, ...
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 0, true, "01 March 2023"), //
installment(313.0, 0, 0, 0, 0, true, "01 April 2023"), //
installment(311.0, 0, 0, 0, 0, true, "01 May 2023"), //
installment(312.0, 0, 50, 20, 0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 0, true, "01 March 2023"), //
installment(312.0, 0, 0, 0, 0, true, "01 April 2023"), //
installment(314.0, 0, 0, 0, 0, true, "01 May 2023"), //
installment(100.0, 0, 0, 0, outstanding(50.0, 0d, 0d, 50.0), false, "02 May 2023") //
);
});
@@ -627,10 +627,10 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
@@ -642,10 +642,10 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(311.0, 0, 0, 0, 0.0, true, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(314.0, 0, 0, 0, 0.0, true, "01 May 2023") //
);
// Add Chargeback
@@ -662,10 +662,10 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
// DEFAULT payment allocation is ..., DUE_PENALTY, DUE_FEE, DUE_PRINCIPAL, ...
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(343.0, 0, 100, 40, outstanding(30.0, 20.0, 0.0, 50.0), false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(311.0, 0, 0, 0, 0.0, true, "01 May 2023") //
installment(342.0, 0, 100, 40, outstanding(30.0, 20.0, 0.0, 50.0), false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(314.0, 0, 0, 0, 0.0, true, "01 May 2023") //
);
verifyLoanSummaryAmounts(loanId, 30.0, 50.0, 20.0, 50.0);
@@ -694,10 +694,10 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
@@ -709,10 +709,10 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(311.0, 0, 0, 0, 0.0, true, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(314.0, 0, 0, 0, 0.0, true, "01 May 2023") //
);
// Add Chargeback
@@ -729,10 +729,10 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
// DEFAULT payment allocation is ..., DUE_PRINCIPAL, DUE_FEE, DUE_PENALTY ...
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(343.0, 0, 100, 40, outstanding(0.0, 30.0, 20.0, 50.0), false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(313.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(311.0, 0, 0, 0, 0.0, true, "01 May 2023") //
installment(342.0, 0, 100, 40, outstanding(0.0, 30.0, 20.0, 50.0), false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 March 2023"), //
installment(312.0, 0, 0, 0, 0.0, true, "01 April 2023"), //
installment(314.0, 0, 0, 0, 0.0, true, "01 May 2023") //
);
verifyLoanSummaryAmounts(loanId, 30.0, 50.0, 20.0, 50.0);
@@ -761,24 +761,24 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
updateBusinessDate("20 January 2023");
// Add Repayment
Long repaymentTransaction = addRepaymentForLoan(loanId, 383.0, "20 January 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 382.0, "20 January 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Add Chargeback
@@ -787,17 +787,17 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(343.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(342.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
updateBusinessDate("21 January 2023");
@@ -806,18 +806,18 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 967, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 1067.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 1068.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(443.0, 0, 100, 40, 200.0, false, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(442.0, 0, 100, 40, 200.0, false, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
});
@@ -845,24 +845,24 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
updateBusinessDate("20 January 2023");
// Add Repayment
Long repaymentTransaction = addRepaymentForLoan(loanId, 383.0, "20 January 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 382.0, "20 January 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Add Chargeback
@@ -871,17 +871,17 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(343.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(342.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
updateBusinessDate("21 January 2023");
@@ -890,18 +890,18 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 1067.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 1068.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(443.0, 0, 100, 40, 200.0, false, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(442.0, 0, 100, 40, 200.0, false, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Let's add repayment to trigger reverse replay for both chargebacks
@@ -910,9 +910,9 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(200.0, "Repayment", "19 January 2023", 1120.0, 130.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 737.0, 383.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 837.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 937.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 738.0, 382.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 838.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 938.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
);
});
}
@@ -939,24 +939,24 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 383.0, false, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 382.0, false, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Update Business Date
updateBusinessDate("20 January 2023");
// Add Repayment
Long repaymentTransaction = addRepaymentForLoan(loanId, 383.0, "20 January 2023");
Long repaymentTransaction = addRepaymentForLoan(loanId, 382.0, "20 January 2023");
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(312.0, 0, 50, 20, 0.0, true, "01 February 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Add Chargeback
@@ -965,17 +965,17 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(343.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(342.0, 0, 100, 40, 100.0, false, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
updateBusinessDate("21 January 2023");
@@ -984,18 +984,18 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 937.0, 313.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 967.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 1067.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 938.0, 312.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 968.0, 30.0, 0.0, 50.0, 20.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 1068.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(443.0, 0, 100, 40, 200.0, false, "01 February 2023"),
installment(313.0, 0, 0, 0, 313.0, false, "01 March 2023"), //
installment(313.0, 0, 0, 0, 313.0, false, "01 April 2023"), //
installment(311.0, 0, 0, 0, 311.0, false, "01 May 2023") //
installment(442.0, 0, 100, 40, 200.0, false, "01 February 2023"),
installment(312.0, 0, 0, 0, 312.0, false, "01 March 2023"), //
installment(312.0, 0, 0, 0, 312.0, false, "01 April 2023"), //
installment(314.0, 0, 0, 0, 314.0, false, "01 May 2023") //
);
// Let's add repayment to trigger reverse replay for both chargebacks
@@ -1004,9 +1004,9 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
verifyTransactions(loanId, //
transaction(1250.0, "Disbursement", "01 January 2023", 1250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(20.0, "Repayment", "19 January 2023", 1250.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0), //
transaction(383.0, "Repayment", "20 January 2023", 917.0, 333.0, 0.0, 50.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 967.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 1067.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
transaction(382.0, "Repayment", "20 January 2023", 918.0, 332.0, 0.0, 50.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "20 January 2023", 968.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0), //
transaction(100.0, "Chargeback", "21 January 2023", 1068.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
);
});
}
@@ -78,10 +78,10 @@ public class LoanInstallmentMultiplesOfTest extends BaseLoanIntegrationTest {
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "01 February 2023"), //
installment(313.0, false, "01 March 2023"), //
installment(313.0, false, "01 April 2023"), //
installment(311.0, false, "01 May 2023") //
installment(312.0, false, "01 February 2023"), //
installment(312.0, false, "01 March 2023"), //
installment(312.0, false, "01 April 2023"), //
installment(314.0, false, "01 May 2023") //
);
// disburse Loan
@@ -89,11 +89,11 @@ public class LoanInstallmentMultiplesOfTest extends BaseLoanIntegrationTest {
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(313.0, false, "01 February 2023"), //
installment(313.0, false, "01 March 2023"), //
installment(313.0, false, "01 April 2023"), //
installment(311.0, false, "01 May 2023") //
installment(1250, null, "01 January 2023"), //
installment(312.0, false, "01 February 2023"), //
installment(312.0, false, "01 March 2023"), //
installment(312.0, false, "01 April 2023"), //
installment(314.0, false, "01 May 2023") //
);
});
}
@@ -142,9 +142,9 @@ public class LoanInstallmentMultiplesOfTest extends BaseLoanIntegrationTest {
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(417.5, 12.5, 430.0, false, "01 February 2023"), //
installment(417.5, 12.5, 430.0, false, "01 March 2023"), //
installment(415.0, 12.5, 427.5, false, "01 April 2023") //
installment(416.5, 12.5, 429.0, false, "01 February 2023"), //
installment(416.5, 12.5, 429.0, false, "01 March 2023"), //
installment(417.0, 12.5, 429.5, false, "01 April 2023") //
);
// disburse Loan
@@ -152,10 +152,10 @@ public class LoanInstallmentMultiplesOfTest extends BaseLoanIntegrationTest {
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1250.0, null, "01 January 2023"), //
installment(417.5, 12.5, 430.0, false, "01 February 2023"), //
installment(417.5, 12.5, 430.0, false, "01 March 2023"), //
installment(415.0, 12.5, 427.5, false, "01 April 2023") //
installment(1250, null, "01 January 2023"), //
installment(416.5, 12.5, 429.0, false, "01 February 2023"), //
installment(416.5, 12.5, 429.0, false, "01 March 2023"), //
installment(417.0, 12.5, 429.5, false, "01 April 2023") //
);
});
}
@@ -59,8 +59,8 @@ public class LoanRescheduleTestWithDownpayment extends BaseLoanIntegrationTest {
verifyRepaymentSchedule(loanId, //
installment(1500.0, null, "01 January 2023"), //
installment(375.0, false, "01 January 2023"), //
installment(563.0, false, "31 January 2023"), //
installment(562.0, false, "02 March 2023") //
installment(562.0, false, "31 January 2023"), //
installment(563.0, false, "02 March 2023") //
);
// 1st Disburse Loan
@@ -614,6 +614,14 @@ public class GlobalConfigurationHelper {
updateGlobalConfigUpdateEnabledFlagAsJSON(enabled), "resourceId");
}
public static void updateValueForGlobalConfigurationInternal(final RequestSpecification requestSpec,
final ResponseSpecification responseSpec, final String configId, final int value) {
final String GLOBAL_CONFIG_UPDATE_URL = "/fineract-provider/api/v1/internal/configurations/" + configId + "/value/" + value + "?"
+ Utils.TENANT_IDENTIFIER;
log.info("---------------------------UPDATE VALUE FOR GLOBAL CONFIG (internal) ---------------------------------------");
Utils.performServerPost(requestSpec, responseSpec, GLOBAL_CONFIG_UPDATE_URL, Utils.emptyJson());
}
// Deprecated because it's using configId as a String
@Deprecated
public static Integer updateEnabledFlagForGlobalConfiguration(final RequestSpecification requestSpec,