This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 35243ee70 FINERACT-1971: Fix for not using installmentInMultiplesOf 
parameter in case of flat interest for loans
35243ee70 is described below

commit 35243ee70960b22901a18d2ac5795be439976e6b
Author: Arnold Galovics <[email protected]>
AuthorDate: Mon Nov 13 12:17:15 2023 +0100

    FINERACT-1971: Fix for not using installmentInMultiplesOf parameter in case 
of flat interest for loans
---
 .../loanschedule/domain/LoanApplicationTerms.java  |  20 ++
 .../integrationtests/BaseLoanIntegrationTest.java  | 118 +++++++++--
 .../LoanInstallmentMultiplesOfTest.java            | 227 +++++++++++++++++++++
 3 files changed, 346 insertions(+), 19 deletions(-)

diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index e08ca42d6..52e43ac1e 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -867,6 +867,26 @@ public final class LoanApplicationTerms {
                 principalPerPeriod = 
this.principal.zero().plus(currentPeriodFixedPrincipalAmount);
 
             }
+
+            if (this.installmentAmountInMultiplesOf != null) {
+                Money roundedPrincipalPerPeriod = 
Money.roundToMultiplesOf(principalPerPeriod, 
this.installmentAmountInMultiplesOf);
+                if (interestForThisInstallment != null) {
+                    Money roundedInterestForThisInstallment = 
Money.roundToMultiplesOf(interestForThisInstallment,
+                            this.installmentAmountInMultiplesOf);
+
+                    /*
+                     * Thinking is
+                     *
+                     * principalPerPeriod 416.67 -> 417 
interestForThisInstallment 12.50 -> 13
+                     *
+                     * Sum: 417 + 13 - 12.5 = 417.5 as principal so the total 
outstanding amount is in line with the
+                     * installmentAmountInMultiplesOf setting
+                     */
+                    principalPerPeriod = 
roundedPrincipalPerPeriod.add(roundedInterestForThisInstallment).minus(interestForThisInstallment);
+                } else {
+                    principalPerPeriod = roundedPrincipalPerPeriod;
+                }
+            }
         } else {
             principalPerPeriod = Money.of(this.getCurrency(), 
getFixedEmiAmount()).minus(interestForThisInstallment);
             return principalPerPeriod;
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
index 5fae515d8..5a8bfd240 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
@@ -43,6 +43,7 @@ import lombok.ToString;
 import org.apache.fineract.client.models.AllowAttributeOverrides;
 import org.apache.fineract.client.models.BusinessDateRequest;
 import 
org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
+import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
 import org.apache.fineract.client.models.PostLoanProductsRequest;
 import org.apache.fineract.client.models.PostLoansLoanIdRequest;
@@ -183,6 +184,21 @@ public abstract class BaseLoanIntegrationTest {
                 
.incomeFromChargeOffPenaltyAccountId(feeChargeOffAccount.getAccountID().longValue());
     }
 
+    protected PostLoanProductsRequest 
create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
+            int interestType, int amortizationType) {
+        return 
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct().multiDisburseLoan(false)//
+                .disallowExpectedDisbursements(false)//
+                .allowApprovedDisbursedAmountsOverApplied(false)//
+                .overAppliedCalculationType(null)//
+                .overAppliedNumber(null)//
+                .principal(1250.0)//
+                .numberOfRepayments(4)//
+                .repaymentEvery(1)//
+                
.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue())//
+                .interestType(interestType)//
+                .amortizationType(amortizationType);
+    }
+
     private static RequestSpecification createRequestSpecification() {
         RequestSpecification request = new 
RequestSpecBuilder().setContentType(ContentType.JSON).build();
         request.header("Authorization", "Basic " + 
Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
@@ -250,15 +266,35 @@ public abstract class BaseLoanIntegrationTest {
                 "Expected installments are not matching with the installments 
configured on the loan");
 
         for (int i = 1; i < installments.length; i++) {
+            GetLoansLoanIdRepaymentPeriod period = 
loanResponse.getRepaymentSchedule().getPeriods().get(i);
+            Double principalDue = period.getPrincipalDue();
+            Double amount = installments[i].principalAmount;
+
             if (installments[i].completed == null) { // this is for the 
disbursement
-                Assertions.assertEquals(installments[i].amount,
-                        
loanResponse.getRepaymentSchedule().getPeriods().get(i).getPrincipalLoanBalanceOutstanding());
+                Assertions.assertEquals(amount, 
period.getPrincipalLoanBalanceOutstanding(),
+                        "%d. installment's principal due is different, 
expected: %.2f, actual: %.2f".formatted(i, amount,
+                                period.getPrincipalLoanBalanceOutstanding()));
             } else {
-                Assertions.assertEquals(installments[i].amount, 
loanResponse.getRepaymentSchedule().getPeriods().get(i).getPrincipalDue());
+                Assertions.assertEquals(amount, principalDue,
+                        "%d. installment's principal due is different, 
expected: %.2f, actual: %.2f".formatted(i, amount, principalDue));
+
+                Double interestAmount = installments[i].interestAmount;
+                Double interestDue = period.getInterestDue();
+                if (interestAmount != null) {
+                    Assertions.assertEquals(interestAmount, interestDue,
+                            "%d. installment's interest due is different, 
expected: %.2f, actual: %.2f".formatted(i, interestAmount,
+                                    interestDue));
+                }
+                Double outstandingAmount = 
installments[i].totalOutstandingAmount;
+                Double totalOutstanding = 
period.getTotalOutstandingForPeriod();
+                if (outstandingAmount != null) {
+                    Assertions.assertEquals(outstandingAmount, 
totalOutstanding,
+                            "%d. installment's total outstanding is different, 
expected: %.2f, actual: %.2f".formatted(i, outstandingAmount,
+                                    totalOutstanding));
+                }
             }
-            Assertions.assertEquals(installments[i].completed, 
loanResponse.getRepaymentSchedule().getPeriods().get(i).getComplete());
-            Assertions.assertEquals(LocalDate.parse(installments[i].dueDate, 
dateTimeFormatter),
-                    
loanResponse.getRepaymentSchedule().getPeriods().get(i).getDueDate());
+            Assertions.assertEquals(installments[i].completed, 
period.getComplete());
+            Assertions.assertEquals(LocalDate.parse(installments[i].dueDate, 
dateTimeFormatter), period.getDueDate());
         }
     }
 
@@ -275,19 +311,29 @@ public abstract class BaseLoanIntegrationTest {
         }
     }
 
-    protected Long applyAndApproveLoan(Long clientId, Long loanProductId, 
String loanDisbursementDate, Double amount,
+    protected PostLoansRequest applyLoanRequest(Long clientId, Long 
loanProductId, String loanDisbursementDate, Double amount,
             int numberOfRepayments) {
-        PostLoansResponse postLoansResponse = 
loanTransactionHelper.applyLoan(new PostLoansRequest().clientId(clientId)
-                
.productId(loanProductId).expectedDisbursementDate(loanDisbursementDate).dateFormat(DATETIME_PATTERN)
+        return new 
PostLoansRequest().clientId(clientId).productId(loanProductId).expectedDisbursementDate(loanDisbursementDate)
+                .dateFormat(DATETIME_PATTERN)
                 
.transactionProcessingStrategyCode(DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_STRATEGY)
                 
.locale("en").submittedOnDate(loanDisbursementDate).amortizationType(1).interestRatePerPeriod(0)
                 
.interestCalculationPeriodType(1).interestType(0).repaymentFrequencyType(0).repaymentEvery(30).repaymentFrequencyType(0)
                 
.numberOfRepayments(numberOfRepayments).loanTermFrequency(numberOfRepayments * 
30).loanTermFrequencyType(0)
-                
.maxOutstandingLoanBalance(BigDecimal.valueOf(amount)).principal(BigDecimal.valueOf(amount)).loanType("individual"));
+                
.maxOutstandingLoanBalance(BigDecimal.valueOf(amount)).principal(BigDecimal.valueOf(amount)).loanType("individual");
+    }
+
+    protected PostLoansLoanIdRequest approveLoanRequest(Double amount) {
+        return new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(amount)).dateFormat(DATETIME_PATTERN)
+                .approvedOnDate("01 January 2023").locale("en");
+    }
+
+    protected Long applyAndApproveLoan(Long clientId, Long loanProductId, 
String loanDisbursementDate, Double amount,
+            int numberOfRepayments) {
+        PostLoansResponse postLoansResponse = loanTransactionHelper
+                .applyLoan(applyLoanRequest(clientId, loanProductId, 
loanDisbursementDate, amount, numberOfRepayments));
 
         PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
-                new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(amount)).dateFormat(DATETIME_PATTERN)
-                        .approvedOnDate("01 January 2023").locale("en"));
+                approveLoanRequest(amount));
 
         return approvedLoanResult.getLoanId();
     }
@@ -302,16 +348,21 @@ public abstract class BaseLoanIntegrationTest {
                 
.transactionDate(date).locale("en").transactionAmount(amount).externalId(firstRepaymentUUID));
     }
 
-    protected JournalEntry journalEntry(double amount, Account account, String 
type) {
-        return new JournalEntry(amount, account, type);
+    protected JournalEntry journalEntry(double principalAmount, Account 
account, String type) {
+        return new JournalEntry(principalAmount, account, type);
     }
 
-    protected Transaction transaction(double amount, String type, String date) 
{
-        return new Transaction(amount, type, date);
+    protected Transaction transaction(double principalAmount, String type, 
String date) {
+        return new Transaction(principalAmount, type, date);
     }
 
-    protected Installment installment(double amount, Boolean completed, String 
dueDate) {
-        return new Installment(amount, completed, dueDate);
+    protected Installment installment(double principalAmount, Boolean 
completed, String dueDate) {
+        return new Installment(principalAmount, null, null, completed, 
dueDate);
+    }
+
+    protected Installment installment(double principalAmount, double 
interestAmount, double totalOutstandingAmount, Boolean completed,
+            String dueDate) {
+        return new Installment(principalAmount, interestAmount, 
totalOutstandingAmount, completed, dueDate);
     }
 
     @ToString
@@ -336,8 +387,37 @@ public abstract class BaseLoanIntegrationTest {
     @AllArgsConstructor
     public static class Installment {
 
-        Double amount;
+        Double principalAmount;
+        Double interestAmount;
+        Double totalOutstandingAmount;
         Boolean completed;
         String dueDate;
     }
+
+    public static class AmortizationType {
+
+        public static final Integer EQUAL_INSTALLMENTS = 1;
+    }
+
+    public static class InterestType {
+
+        public static final Integer DECLINING_BALANCE = 0;
+        public static final Integer FLAT = 1;
+    }
+
+    public static class RepaymentFrequencyType {
+
+        public static final Integer MONTHS = 2;
+    }
+
+    public static class InterestCalculationPeriodType {
+
+        public static final Integer SAME_AS_REPAYMENT_PERIOD = 1;
+    }
+
+    public static class InterestRateFrequencyType {
+
+        public static final Integer MONTHS = 2;
+        public static final Integer YEARS = 3;
+    }
 }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
new file mode 100644
index 000000000..bfdccced0
--- /dev/null
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
@@ -0,0 +1,227 @@
+/**
+ * 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.integrationtests;
+
+import static 
org.apache.fineract.integrationtests.BaseLoanIntegrationTest.InterestCalculationPeriodType.SAME_AS_REPAYMENT_PERIOD;
+
+import java.math.BigDecimal;
+import java.util.stream.Stream;
+import org.apache.fineract.client.models.PostLoanProductsRequest;
+import org.apache.fineract.client.models.PostLoanProductsResponse;
+import org.apache.fineract.client.models.PostLoansLoanIdResponse;
+import org.apache.fineract.client.models.PostLoansRequest;
+import org.apache.fineract.client.models.PostLoansResponse;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.junit.jupiter.api.Named;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public class LoanInstallmentMultiplesOfTest extends BaseLoanIntegrationTest {
+
+    private final ClientHelper clientHelper = new 
ClientHelper(this.requestSpec, this.responseSpec);
+
+    private static Stream<Arguments> interestTypes() {
+        return Stream.of(Arguments.of(Named.of("DECLINING_BALANCE", 
InterestType.DECLINING_BALANCE)), //
+                Arguments.of(Named.of("FLAT", InterestType.FLAT)));
+    }
+
+    @ParameterizedTest
+    @MethodSource("interestTypes")
+    public void 
test_LoanRepaymentScheduleIsEquallyDistributed_WhenNoInterest_ButInterestTypeIs(int
 interestType) {
+        runAt("01 January 2023", () -> {
+            int amortizationType = AmortizationType.EQUAL_INSTALLMENTS;
+
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+            // Create Loan Product
+            PostLoanProductsRequest product = 
create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
+                    interestType, amortizationType);
+
+            PostLoanProductsResponse loanProductResponse = 
loanProductHelper.createLoanProduct(product);
+            Long loanProductId = loanProductResponse.getResourceId();
+
+            // Apply and Approve Loan
+            double amount = 1250.0;
+
+            PostLoansRequest applicationRequest = applyLoanRequest(clientId, 
loanProductId, "01 January 2023", amount, 4)//
+                    .repaymentEvery(1)//
+                    .loanTermFrequency(4)//
+                    .repaymentFrequencyType(RepaymentFrequencyType.MONTHS)//
+                    .loanTermFrequencyType(RepaymentFrequencyType.MONTHS)//
+                    .interestType(interestType)//
+                    .amortizationType(amortizationType);
+
+            PostLoansResponse postLoansResponse = 
loanTransactionHelper.applyLoan(applicationRequest);
+
+            PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
+                    approveLoanRequest(amount));
+
+            Long loanId = approvedLoanResult.getLoanId();
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(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") //
+            );
+
+            // disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(1250.0), "01 January 
2023");
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(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") //
+            );
+        });
+    }
+
+    @Test
+    public void 
test_LoanRepaymentScheduleIsEquallyDistributed_WhenInterestIsPresent_AndInterestTypeIsFlat()
 {
+        runAt("01 January 2023", () -> {
+            int amortizationType = AmortizationType.EQUAL_INSTALLMENTS;
+            int interestType = InterestType.FLAT;
+
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+            // Create Loan Product
+            PostLoanProductsRequest product = 
create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
+                    interestType, amortizationType)//
+                    .maxInterestRatePerPeriod(12.0)//
+                    .minInterestRatePerPeriod(12.0)//
+                    .interestRatePerPeriod(12.0)//
+                    
.interestRateFrequencyType(InterestRateFrequencyType.YEARS).interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD);
+
+            PostLoanProductsResponse loanProductResponse = 
loanProductHelper.createLoanProduct(product);
+            Long loanProductId = loanProductResponse.getResourceId();
+
+            // Apply and Approve Loan
+            double amount = 1250.0;
+            int numberOfRepayments = 3;
+
+            PostLoansRequest applicationRequest = applyLoanRequest(clientId, 
loanProductId, "01 January 2023", amount, numberOfRepayments)//
+                    .repaymentEvery(1)//
+                    .loanTermFrequency(numberOfRepayments)//
+                    .repaymentFrequencyType(RepaymentFrequencyType.MONTHS)//
+                    .loanTermFrequencyType(RepaymentFrequencyType.MONTHS)//
+                    .interestType(interestType)//
+                    .amortizationType(amortizationType)//
+                    .interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD)//
+                    .interestRatePerPeriod(12);
+
+            PostLoansResponse postLoansResponse = 
loanTransactionHelper.applyLoan(applicationRequest);
+
+            PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
+                    approveLoanRequest(amount));
+
+            Long loanId = approvedLoanResult.getLoanId();
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(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") //
+            );
+
+            // disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(1250.0), "01 January 
2023");
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(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") //
+            );
+        });
+    }
+
+    @Test
+    public void 
test_LoanRepaymentScheduleIsEquallyDistributed_WhenInterestIsPresent_AndInterestTypeIsFlat_AndMultiplesOfIs20()
 {
+        runAt("01 January 2023", () -> {
+            int amortizationType = AmortizationType.EQUAL_INSTALLMENTS;
+            int interestType = InterestType.FLAT;
+
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+            // Create Loan Product
+            PostLoanProductsRequest product = 
create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
+                    interestType, amortizationType)//
+                    .maxInterestRatePerPeriod(12.0)//
+                    .minInterestRatePerPeriod(12.0)//
+                    .interestRatePerPeriod(12.0)//
+                    
.installmentAmountInMultiplesOf(20).interestRateFrequencyType(InterestRateFrequencyType.YEARS)
+                    .interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD);
+
+            PostLoanProductsResponse loanProductResponse = 
loanProductHelper.createLoanProduct(product);
+            Long loanProductId = loanProductResponse.getResourceId();
+
+            // Apply and Approve Loan
+            double amount = 1250.0;
+            int numberOfRepayments = 3;
+
+            PostLoansRequest applicationRequest = applyLoanRequest(clientId, 
loanProductId, "01 January 2023", amount, numberOfRepayments)//
+                    .repaymentEvery(1)//
+                    .loanTermFrequency(numberOfRepayments)//
+                    .repaymentFrequencyType(RepaymentFrequencyType.MONTHS)//
+                    .loanTermFrequencyType(RepaymentFrequencyType.MONTHS)//
+                    .interestType(interestType)//
+                    .amortizationType(amortizationType)//
+                    .interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD)//
+                    .interestRatePerPeriod(12);
+
+            PostLoansResponse postLoansResponse = 
loanTransactionHelper.applyLoan(applicationRequest);
+
+            PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
+                    approveLoanRequest(amount));
+
+            Long loanId = approvedLoanResult.getLoanId();
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(0, null, "01 January 2023"), //
+                    installment(427.5, 12.5, 440.0, false, "01 February 
2023"), //
+                    installment(427.5, 12.5, 440.0, false, "01 March 2023"), //
+                    installment(395.0, 12.5, 407.5, false, "01 April 2023") //
+            );
+
+            // disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(1250.0), "01 January 
2023");
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(0, null, "01 January 2023"), //
+                    installment(427.5, 12.5, 440.0, false, "01 February 
2023"), //
+                    installment(427.5, 12.5, 440.0, false, "01 March 2023"), //
+                    installment(395.0, 12.5, 407.5, false, "01 April 2023") //
+            );
+        });
+    }
+}

Reply via email to