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

adamsaghy 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 e1165e813 FINERACT-1971: added test scenarios to cover repayment 
schedule with large charge amounts
e1165e813 is described below

commit e1165e813af1372cf78e145482a734a029750a3f
Author: Rustam Zeinalov <[email protected]>
AuthorDate: Wed Feb 26 16:16:19 2025 +0100

    FINERACT-1971: added test scenarios to cover repayment schedule with large 
charge amounts
---
 .../main/resources/avro-templates/bigdecimal.avsc  |  2 +-
 .../org/apache/fineract/test/helper/Utils.java     | 22 ++++++
 .../fineract/test/stepdef/loan/LoanStepDef.java    | 27 +++----
 .../src/test/resources/features/LoanCharge.feature | 90 ++++++++++++++++++++++
 4 files changed, 127 insertions(+), 14 deletions(-)

diff --git 
a/fineract-avro-schemas/src/main/resources/avro-templates/bigdecimal.avsc 
b/fineract-avro-schemas/src/main/resources/avro-templates/bigdecimal.avsc
index 9b1cec773..459854141 100644
--- a/fineract-avro-schemas/src/main/resources/avro-templates/bigdecimal.avsc
+++ b/fineract-avro-schemas/src/main/resources/avro-templates/bigdecimal.avsc
@@ -1,6 +1,6 @@
 {
     "logicalType": "decimal",
-    "precision": 20,
+    "precision": 27,
     "scale": 8,
     "type": "bytes"
 }
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java
index 70cfa1802..25c2eeac3 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java
@@ -48,4 +48,26 @@ public final class Utils {
     public static LocalDate now() {
         return LocalDate.now(Clock.systemUTC());
     }
+
+    /**
+     * A record that formats a double value based on whether it's a whole 
number or not.
+     * <p>
+     * If the value is a whole number, the output will have one decimal place 
(e.g., 16.0). Otherwise, it will have two
+     * decimal places (e.g., 16.90), but if the second decimal place is zero, 
it will be removed (so 16.90 becomes
+     * 16.9).
+     */
+    public record DoubleFormatter(double value) {
+
+        public String format() {
+            boolean isWholeNumber = (value % 1.0 == 0);
+
+            String result = isWholeNumber ? String.format("%.1f", value) : 
String.format("%.2f", value);
+
+            // For non-whole numbers, remove trailing '0' if it exists
+            if (!isWholeNumber && result.endsWith("0")) {
+                result = result.substring(0, result.length() - 1);
+            }
+            return result;
+        }
+    }
 }
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
index 8afb6eaac..fcbc8859f 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
@@ -1989,7 +1989,6 @@ public class LoanStepDef extends AbstractStepDef {
     private List<List<String>> 
getActualValuesList(List<GetLoansLoanIdLoanChargeData> charges, String 
paymentDueAtExpected,
             String dueAsOfExpected) {
         List<GetLoansLoanIdLoanChargeData> result;
-
         if (dueAsOfExpected != null) {
             result = charges.stream().filter(t -> {
                 LocalDate dueDate = t.getDueDate();
@@ -1999,7 +1998,6 @@ public class LoanStepDef extends AbstractStepDef {
             result = charges.stream().filter(t -> 
paymentDueAtExpected.equals(t.getChargeTimeType().getValue()))
                     .collect(Collectors.toList());
         }
-
         return result.stream().map(t -> {
             List<String> actualValues = new ArrayList<>();
             actualValues.add(t.getName() == null ? null : t.getName());
@@ -2007,10 +2005,13 @@ public class LoanStepDef extends AbstractStepDef {
             actualValues.add(t.getChargeTimeType().getValue() == null ? null : 
t.getChargeTimeType().getValue());
             actualValues.add(t.getDueDate() == null ? null : 
FORMATTER.format(t.getDueDate()));
             actualValues.add(t.getChargeCalculationType().getValue() == null ? 
null : t.getChargeCalculationType().getValue());
-            actualValues.add(t.getAmount() == null ? null : 
String.valueOf(t.getAmount()));
-            actualValues.add(t.getAmountPaid() == null ? null : 
String.valueOf(t.getAmountPaid()));
-            actualValues.add(t.getAmountWaived() == null ? null : 
String.valueOf(t.getAmountWaived()));
-            actualValues.add(t.getAmountOutstanding() == null ? null : 
String.valueOf(t.getAmountOutstanding()));
+
+            actualValues.add(t.getAmount() == null ? null : new 
Utils.DoubleFormatter(t.getAmount()).format());
+
+            actualValues.add(t.getAmountPaid() == null ? null : new 
Utils.DoubleFormatter(t.getAmountPaid()).format());
+            actualValues.add(t.getAmountWaived() == null ? null : new 
Utils.DoubleFormatter(t.getAmountWaived()).format());
+
+            actualValues.add(t.getAmountOutstanding() == null ? null : new 
Utils.DoubleFormatter(t.getAmountOutstanding()).format());
             return actualValues;
         }).collect(Collectors.toList());
     }
@@ -3203,12 +3204,12 @@ public class LoanStepDef extends AbstractStepDef {
                     actualValues.add(repaymentPeriod.getPrincipalDue() == null 
? null : String.valueOf(repaymentPeriod.getPrincipalDue()));
                 case "Interest" ->
                     actualValues.add(repaymentPeriod.getInterestDue() == null 
? null : String.valueOf(repaymentPeriod.getInterestDue()));
-                case "Fees" -> actualValues
-                        .add(repaymentPeriod.getFeeChargesDue() == null ? null 
: String.valueOf(repaymentPeriod.getFeeChargesDue()));
-                case "Penalties" -> actualValues.add(
-                        repaymentPeriod.getPenaltyChargesDue() == null ? null 
: String.valueOf(repaymentPeriod.getPenaltyChargesDue()));
-                case "Due" -> actualValues.add(
-                        repaymentPeriod.getTotalDueForPeriod() == null ? null 
: String.valueOf(repaymentPeriod.getTotalDueForPeriod()));
+                case "Fees" -> 
actualValues.add(repaymentPeriod.getFeeChargesDue() == null ? null
+                        : new 
Utils.DoubleFormatter(repaymentPeriod.getFeeChargesDue()).format());
+                case "Penalties" -> 
actualValues.add(repaymentPeriod.getPenaltyChargesDue() == null ? null
+                        : new 
Utils.DoubleFormatter(repaymentPeriod.getPenaltyChargesDue()).format());
+                case "Due" -> 
actualValues.add(repaymentPeriod.getTotalDueForPeriod() == null ? null
+                        : new 
Utils.DoubleFormatter(repaymentPeriod.getTotalDueForPeriod()).format());
                 case "Paid" -> actualValues.add(
                         repaymentPeriod.getTotalPaidForPeriod() == null ? null 
: String.valueOf(repaymentPeriod.getTotalPaidForPeriod()));
                 case "In advance" -> 
actualValues.add(repaymentPeriod.getTotalPaidInAdvanceForPeriod() == null ? null
@@ -3218,7 +3219,7 @@ public class LoanStepDef extends AbstractStepDef {
                 case "Waived" -> 
actualValues.add(repaymentPeriod.getTotalWaivedForPeriod() == null ? null
                         : 
String.valueOf(repaymentPeriod.getTotalWaivedForPeriod()));
                 case "Outstanding" -> 
actualValues.add(repaymentPeriod.getTotalOutstandingForPeriod() == null ? null
-                        : 
String.valueOf(repaymentPeriod.getTotalOutstandingForPeriod()));
+                        : new 
Utils.DoubleFormatter(repaymentPeriod.getTotalOutstandingForPeriod()).format());
                 default -> throw new 
IllegalStateException(String.format("Header name %s cannot be found", 
headerName));
             }
         }
diff --git 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
index ad34d6efb..07f36010f 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
@@ -2534,3 +2534,93 @@ Feature: LoanCharge
       | 01 January 2024  | Repayment         | 60.0   | 60.0      | 0.0      | 
0.0  | 0.0       | 40.0         |
       | 01 February 2024 | Charge Adjustment | 20.0   | 0.0       | 0.0      | 
0.0  | 20.0      | 40.0         |
     And LoanChargeAdjustmentPostBusinessEvent is raised on "01 February 2024"
+
+  @TestRailId:C3501
+  Scenario: Verify repayment schedule amounts after large charge amount added 
- UC1
+    When Admin sets the business date to "20 February 2025"
+    And Admin creates a client with random data
+    When Admin creates a fully customized loan with the following data:
+      | LoanProduct                                                   | 
submitted on date | with Principal | ANNUAL interest rate % | interest type     
| interest calculation period | amortization type  | loanTermFrequency | 
loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | 
numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | 
interest free period | Payment strategy            |
+      | LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 20 
December 2024  | 800            | 0                      | DECLINING_BALANCE | 
DAILY                       | EQUAL_INSTALLMENTS | 4                 | MONTHS   
             | 1              | MONTHS                 | 4                  | 0 
                      | 0                      | 0                    | 
ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "20 December 2024" with "800" 
amount and expected disbursement date on "20 December 2024"
+    When Admin successfully disburse the loan on "20 December 2024" with "800" 
EUR transaction amount
+    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 |
+      |    |      | 20 December 2024 |           | 800.0           |           
    |          | 0.0  |           | 0.0      | 0.0  |            |      |       
      |
+      | 1  | 31   | 20 January 2025  |           | 600.0           | 200.0     
    | 0.0      | 0.0  | 0.0       | 200.0    | 0.0  | 0.0        | 0.0  | 200.0 
      |
+      | 2  | 31   | 20 February 2025 |           | 400.0           | 200.0     
    | 0.0      | 0.0  | 0.0       | 200.0    | 0.0  | 0.0        | 0.0  | 200.0 
      |
+      | 3  | 28   | 20 March 2025    |           | 200.0           | 200.0     
    | 0.0      | 0.0  | 0.0       | 200.0    | 0.0  | 0.0        | 0.0  | 200.0 
      |
+      | 4  | 31   | 20 April 2025    |           | 0.0             | 200.0     
    | 0.0      | 0.0  | 0.0       | 200.0    | 0.0  | 0.0        | 0.0  | 200.0 
      |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due   | Paid | In 
advance | Late | Outstanding |
+      | 800.0         | 0.0      | 0.0  | 0.0       | 800.0 | 0.0  | 0.0       
 | 0.0  | 800.0       |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees | Penalties | Loan Balance | Reverted | Replayed |
+      | 20 December 2024 | Disbursement     | 800.0   | 0.0       | 0.0      | 
0.0  | 0.0       | 800.0        | false    | false    |
+    And Admin adds "LOAN_NSF_FEE" due date charge with "25 December 2024" due 
date and 123456789012.12 EUR transaction amount
+    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     |
+      |    |      | 20 December 2024 |           | 800.0           |           
    |          | 0.0  |                 | 0.0             | 0.0  |            | 
     |                 |
+      | 1  | 31   | 20 January 2025  |           | 600.0           | 200.0     
    | 0.0      | 0.0  | 123456789012.12 | 123456789212.12 | 0.0  | 0.0        | 
0.0  | 123456789212.12 |
+      | 2  | 31   | 20 February 2025 |           | 400.0           | 200.0     
    | 0.0      | 0.0  | 0.0             | 200.0           | 0.0  | 0.0        | 
0.0  | 200.0           |
+      | 3  | 28   | 20 March 2025    |           | 200.0           | 200.0     
    | 0.0      | 0.0  | 0.0             | 200.0           | 0.0  | 0.0        | 
0.0  | 200.0           |
+      | 4  | 31   | 20 April 2025    |           | 0.0             | 200.0     
    | 0.0      | 0.0  | 0.0             | 200.0           | 0.0  | 0.0        | 
0.0  | 200.0           |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties       | Due             | 
Paid | In advance | Late | Outstanding     |
+      | 800.0         | 0.0      | 0.0  | 123456789012.12 | 123456789812.12 | 
0.0  | 0.0        | 0.0  | 123456789812.12 |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees | Penalties | Loan Balance | Reverted | Replayed |
+      | 20 December 2024 | Disbursement     | 800.0   | 0.0       | 0.0      | 
0.0  | 0.0       | 800.0        | false    | false    |
+    Then Loan Charges tab has a given charge with the following data:
+      | Name    | isPenalty | Payment due at     | Due as of        | 
Calculation type | Due             | Paid | Waived | Outstanding     |
+      | NSF fee | true      | Specified due date | 25 December 2024 | Flat     
        | 123456789012.12 | 0.0  | 0.0    | 123456789012.12 |
+
+  @TestRailId:C3502
+  Scenario: Verify repayment schedule amounts after a few large charges amount 
added - UC2
+    When Admin sets the business date to "20 February 2025"
+    And Admin creates a client with random data
+    When Admin creates a fully customized loan with the following data:
+      | LoanProduct                                                   | 
submitted on date | with Principal | ANNUAL interest rate % | interest type     
| interest calculation period | amortization type  | loanTermFrequency | 
loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | 
numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | 
interest free period | Payment strategy            |
+      | LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 20 
December 2024  | 800            | 0                      | DECLINING_BALANCE | 
DAILY                       | EQUAL_INSTALLMENTS | 4                 | MONTHS   
             | 1              | MONTHS                 | 4                  | 0 
                      | 0                      | 0                    | 
ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "20 December 2024" with "800" 
amount and expected disbursement date on "20 December 2024"
+    When Admin successfully disburse the loan on "20 December 2024" with "800" 
EUR transaction amount
+    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 |
+      |    |      | 20 December 2024 |           | 800.0           |           
    |          | 0.0  |           | 0.0      | 0.0  |            |      |       
      |
+      | 1  | 31   | 20 January 2025  |           | 600.0           | 200.0     
    | 0.0      | 0.0  | 0.0       | 200.0    | 0.0  | 0.0        | 0.0  | 200.0 
      |
+      | 2  | 31   | 20 February 2025 |           | 400.0           | 200.0     
    | 0.0      | 0.0  | 0.0       | 200.0    | 0.0  | 0.0        | 0.0  | 200.0 
      |
+      | 3  | 28   | 20 March 2025    |           | 200.0           | 200.0     
    | 0.0      | 0.0  | 0.0       | 200.0    | 0.0  | 0.0        | 0.0  | 200.0 
      |
+      | 4  | 31   | 20 April 2025    |           | 0.0             | 200.0     
    | 0.0      | 0.0  | 0.0       | 200.0    | 0.0  | 0.0        | 0.0  | 200.0 
      |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due   | Paid | In 
advance | Late | Outstanding |
+      | 800.0         | 0.0      | 0.0  | 0.0       | 800.0 | 0.0  | 0.0       
 | 0.0  | 800.0       |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees | Penalties | Loan Balance | Reverted | Replayed |
+      | 20 December 2024 | Disbursement     | 800.0   | 0.0       | 0.0      | 
0.0  | 0.0       | 800.0        | false    | false    |
+    And Admin adds "LOAN_NSF_FEE" due date charge with "25 December 2024" due 
date and 123456789012.12 EUR transaction amount
+    When Admin adds "LOAN_SNOOZE_FEE" due date charge with "28 December 2024" 
due date and 1003456789012.12 EUR transaction amount
+    When Admin adds "LOAN_NSF_FEE" due date charge with "31 January 2025" due 
date and 5503456789012.12 EUR transaction amount
+    When Admin adds "LOAN_NSF_FEE" due date charge with "23 February 2025" due 
date and 1003456789012.12 EUR transaction amount
+    When Admin adds "LOAN_NSF_FEE" due date charge with "03 April 2025" due 
date and 1503456789012.12 EUR transaction amount
+    When Admin adds "LOAN_SNOOZE_FEE" due date charge with "09 April 2025" due 
date and 103456789037.12 EUR transaction amount
+    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      |
+      |    |      | 20 December 2024 |           | 800.0           |           
    |          | 0.0              |                  | 0.0              | 0.0  
|            |      |                  |
+      | 1  | 31   | 20 January 2025  |           | 600.0           | 200.0     
    | 0.0      | 1003456789012.12 | 123456789012.12  | 1126913578224.24 | 0.0  
| 0.0        | 0.0  | 1126913578224.24 |
+      | 2  | 31   | 20 February 2025 |           | 400.0           | 200.0     
    | 0.0      | 0.0              | 5503456789012.12 | 5503456789212.12 | 0.0  
| 0.0        | 0.0  | 5503456789212.12 |
+      | 3  | 28   | 20 March 2025    |           | 200.0           | 200.0     
    | 0.0      | 0.0              | 1003456789012.12 | 1003456789212.12 | 0.0  
| 0.0        | 0.0  | 1003456789212.12 |
+      | 4  | 31   | 20 April 2025    |           | 0.0             | 200.0     
    | 0.0      | 103456789037.12  | 1503456789012.12 | 1606913578249.24 | 0.0  
| 0.0        | 0.0  | 1606913578249.24 |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees             | Penalties        | Due   
           | Paid | In advance | Late | Outstanding      |
+      | 800.0         | 0.0      | 1106913578049.24 | 8133827156048.48 | 
9240740734897.72 | 0.0  | 0.0        | 0.0  | 9240740734897.72 |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees | Penalties | Loan Balance | Reverted | Replayed |
+      | 20 December 2024 | Disbursement     | 800.0   | 0.0       | 0.0      | 
0.0  | 0.0       | 800.0        | false    | false    |
+    Then Loan Charges tab has a given charge with the following data:
+      | Name       | isPenalty | Payment due at     | Due as of        | 
Calculation type | Due              | Paid | Waived | Outstanding      |
+      | NSF fee    | true      | Specified due date | 25 December 2024 | Flat  
           | 123456789012.12  | 0.0  | 0.0    | 123456789012.12  |
+      | Snooze fee | false     | Specified due date | 28 December 2024 | Flat  
           | 1003456789012.12 | 0.0  | 0.0    | 1003456789012.12 |
+      | NSF fee    | true      | Specified due date | 31 January 2025  | Flat  
           | 5503456789012.12 | 0.0  | 0.0    | 5503456789012.12 |
+      | NSF fee    | true      | Specified due date | 23 February 2025 | Flat  
           | 1003456789012.12 | 0.0  | 0.0    | 1003456789012.12 |
+      | NSF fee    | true      | Specified due date | 03 April 2025    | Flat  
           | 1503456789012.12 | 0.0  | 0.0    | 1503456789012.12 |
+      | Snooze fee | false     | Specified due date | 09 April 2025    | Flat  
           | 103456789037.12  | 0.0  | 0.0    | 103456789037.12  |

Reply via email to