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 d80aa77c0 FINERACT-1734-LoanRepaymentDue-Event-Enhancements-1
d80aa77c0 is described below

commit d80aa77c02c58d56f1fd5f4ec662716ffec2b750
Author: Ruchi Dhamankar <[email protected]>
AuthorDate: Thu Dec 15 21:04:15 2022 +0530

    FINERACT-1734-LoanRepaymentDue-Event-Enhancements-1
---
 .../main/avro/loan/v1/LoanRepaymentDueDataV1.avsc  | 38 ++++------------
 .../src/main/avro/loan/v1/RepaymentDueDataV1.avsc  |  8 ++++
 ...tDueDataV1.avsc => RepaymentPastDueDataV1.avsc} | 20 +++-----
 .../CheckLoanRepaymentOverdueBusinessStep.java     |  4 +-
 .../loan/LoanRepaymentBusinessEventSerializer.java | 15 ++++--
 .../CheckLoanRepaymentOverdueBusinessStepTest.java | 12 ++---
 .../LoanRepaymentBusinessEventSerializerTest.java  | 53 ++++++++++++++++++++--
 7 files changed, 91 insertions(+), 59 deletions(-)

diff --git 
a/fineract-avro-schemas/src/main/avro/loan/v1/LoanRepaymentDueDataV1.avsc 
b/fineract-avro-schemas/src/main/avro/loan/v1/LoanRepaymentDueDataV1.avsc
index 50c05f577..87efc7499 100644
--- a/fineract-avro-schemas/src/main/avro/loan/v1/LoanRepaymentDueDataV1.avsc
+++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanRepaymentDueDataV1.avsc
@@ -4,32 +4,16 @@
     "type": "record",
     "fields": [
         {
-            "default": null,
-            "name": "id",
-            "type": [
-                "null",
-                "long"
-            ]
-        },
-        {
-            "default": null,
-            "name": "accountNo",
-            "type": [
-                "null",
-                "string"
-            ]
+            "name": "loanId",
+            "type": ["long"]
         },
         {
-            "default": null,
-            "name": "externalId",
-            "type": [
-                "null",
-                "string"
-            ]
+            "name": "loanAccountNo",
+            "type": ["string"]
         },
         {
             "default": null,
-            "name": "dueDate",
+            "name": "loanExternalId",
             "type": [
                 "null",
                 "string"
@@ -44,19 +28,15 @@
             ]
         },
         {
-            "default": null,
-            "name": "totalLoanAmountDue",
-            "type": [
-                "null",
-                "bigdecimal"
-            ]
+            "name": "installment",
+            "type": ["org.apache.fineract.avro.loan.v1.RepaymentDueDataV1"]
         },
         {
             "default": null,
-            "name": "repaymentDue",
+            "name": "pastDueAmount",
             "type": [
                 "null",
-                "org.apache.fineract.avro.loan.v1.RepaymentDueDataV1"
+                "org.apache.fineract.avro.loan.v1.RepaymentPastDueDataV1"
             ]
         }
     ]
diff --git 
a/fineract-avro-schemas/src/main/avro/loan/v1/RepaymentDueDataV1.avsc 
b/fineract-avro-schemas/src/main/avro/loan/v1/RepaymentDueDataV1.avsc
index d33076511..6a95e6efd 100644
--- a/fineract-avro-schemas/src/main/avro/loan/v1/RepaymentDueDataV1.avsc
+++ b/fineract-avro-schemas/src/main/avro/loan/v1/RepaymentDueDataV1.avsc
@@ -11,6 +11,14 @@
                 "int"
             ]
         },
+        {
+            "default": null,
+            "name": "installmentDueDate",
+            "type": [
+                "null",
+                "string"
+            ]
+        },
         {
             "default": null,
             "name": "principalAmountDue",
diff --git 
a/fineract-avro-schemas/src/main/avro/loan/v1/RepaymentDueDataV1.avsc 
b/fineract-avro-schemas/src/main/avro/loan/v1/RepaymentPastDueDataV1.avsc
similarity index 65%
copy from fineract-avro-schemas/src/main/avro/loan/v1/RepaymentDueDataV1.avsc
copy to fineract-avro-schemas/src/main/avro/loan/v1/RepaymentPastDueDataV1.avsc
index d33076511..41dc1f5f5 100644
--- a/fineract-avro-schemas/src/main/avro/loan/v1/RepaymentDueDataV1.avsc
+++ b/fineract-avro-schemas/src/main/avro/loan/v1/RepaymentPastDueDataV1.avsc
@@ -1,19 +1,11 @@
 {
-    "name": "RepaymentDueDataV1",
+    "name": "RepaymentPastDueDataV1",
     "namespace": "org.apache.fineract.avro.loan.v1",
     "type": "record",
     "fields": [
         {
             "default": null,
-            "name": "installmentNumber",
-            "type": [
-                "null",
-                "int"
-            ]
-        },
-        {
-            "default": null,
-            "name": "principalAmountDue",
+            "name": "totalAmount",
             "type": [
                 "null",
                 "bigdecimal"
@@ -21,7 +13,7 @@
         },
         {
             "default": null,
-            "name": "interestAmountDue",
+            "name": "principalAmount",
             "type": [
                 "null",
                 "bigdecimal"
@@ -29,7 +21,7 @@
         },
         {
             "default": null,
-            "name": "feeChargeAmountDue",
+            "name": "interestAmount",
             "type": [
                 "null",
                 "bigdecimal"
@@ -37,7 +29,7 @@
         },
         {
             "default": null,
-            "name": "penaltyChargeAmountDue",
+            "name": "feeAmount",
             "type": [
                 "null",
                 "bigdecimal"
@@ -45,7 +37,7 @@
         },
         {
             "default": null,
-            "name": "totalAmountDue",
+            "name": "penaltyAmount",
             "type": [
                 "null",
                 "bigdecimal"
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStep.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStep.java
index 531720bfb..9c46f4e2d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStep.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStep.java
@@ -23,7 +23,7 @@ import java.util.List;
 import lombok.RequiredArgsConstructor;
 import 
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
-import 
org.apache.fineract.infrastructure.event.business.domain.loan.repayment.LoanRepaymentOverdueBusinessEvent;
+import 
org.apache.fineract.infrastructure.event.business.domain.loan.repayment.LoanRepaymentDueBusinessEvent;
 import 
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
@@ -45,7 +45,7 @@ public class CheckLoanRepaymentOverdueBusinessStep implements 
LoanCOBBusinessSte
             if (!repaymentSchedule.isObligationsMet()) {
                 LocalDate installmentDueDate = repaymentSchedule.getDueDate();
                 if 
(installmentDueDate.plusDays(numberOfDaysAfterDueDateToRaiseEvent).equals(currentDate))
 {
-                    businessEventNotifierService.notifyPostBusinessEvent(new 
LoanRepaymentOverdueBusinessEvent(repaymentSchedule));
+                    businessEventNotifierService.notifyPostBusinessEvent(new 
LoanRepaymentDueBusinessEvent(repaymentSchedule));
                     break;
                 }
             }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializer.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializer.java
index 6e04102fe..d196e609c 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializer.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializer.java
@@ -25,6 +25,7 @@ import 
org.apache.fineract.avro.generator.ByteBufferSerializable;
 import org.apache.fineract.avro.generic.v1.CurrencyDataV1;
 import org.apache.fineract.avro.loan.v1.LoanRepaymentDueDataV1;
 import org.apache.fineract.avro.loan.v1.RepaymentDueDataV1;
+import org.apache.fineract.avro.loan.v1.RepaymentPastDueDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import 
org.apache.fineract.infrastructure.event.business.domain.loan.repayment.LoanRepaymentBusinessEvent;
 import 
org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroDateTimeMapper;
@@ -46,25 +47,31 @@ public class LoanRepaymentBusinessEventSerializer extends 
AbstractBusinessEventS
         LoanRepaymentBusinessEvent event = (LoanRepaymentBusinessEvent) 
rawEvent;
         LoanRepaymentScheduleInstallment repaymentInstallment = event.get();
         Loan loan = repaymentInstallment.getLoan();
+
         Long id = loan.getId();
         String accountNo = loan.getAccountNumber();
         String externalId = loan.getExternalId().getValue();
-        String dueDate = 
dataTimeMapper.mapLocalDate(repaymentInstallment.getDueDate());
         MonetaryCurrency loanCurrency = loan.getCurrency();
         CurrencyDataV1 currency = 
CurrencyDataV1.newBuilder().setCode(loanCurrency.getCode())
                 
.setDecimalPlaces(loanCurrency.getDigitsAfterDecimal()).setInMultiplesOf(loanCurrency.getCurrencyInMultiplesOf()).build();
-        BigDecimal totalLoanAmountDue = 
loan.getLoanSummary().getTotalOutstanding();
 
         Integer installmentNumber = 
repaymentInstallment.getInstallmentNumber();
+        String dueDate = 
dataTimeMapper.mapLocalDate(repaymentInstallment.getDueDate());
         BigDecimal principalAmountDue = 
repaymentInstallment.getPrincipalOutstanding(loanCurrency).getAmount();
         BigDecimal interestAmountDue = 
repaymentInstallment.getInterestOutstanding(loanCurrency).getAmount();
         BigDecimal feeChargeAmountDue = 
repaymentInstallment.getFeeChargesOutstanding(loanCurrency).getAmount();
         BigDecimal penaltyChargeAmountDue = 
repaymentInstallment.getPenaltyChargesOutstanding(loanCurrency).getAmount();
         BigDecimal totalAmountDue = 
repaymentInstallment.getTotalOutstanding(loanCurrency).getAmount();
 
-        RepaymentDueDataV1 repaymentDue = new 
RepaymentDueDataV1(installmentNumber, principalAmountDue, interestAmountDue,
+        RepaymentDueDataV1 repaymentDue = new 
RepaymentDueDataV1(installmentNumber, dueDate, principalAmountDue, 
interestAmountDue,
                 feeChargeAmountDue, penaltyChargeAmountDue, totalAmountDue);
-        return new LoanRepaymentDueDataV1(id, accountNo, externalId, dueDate, 
currency, totalLoanAmountDue, repaymentDue);
+
+        RepaymentPastDueDataV1 pastDue = new 
RepaymentPastDueDataV1(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, 
BigDecimal.ZERO,
+                BigDecimal.ZERO);
+
+        LoanRepaymentDueDataV1 loanRepaymentDueDataV1 = 
LoanRepaymentDueDataV1.newBuilder().setLoanId(id).setLoanAccountNo(accountNo)
+                
.setLoanExternalId(externalId).setCurrency(currency).setInstallment(repaymentDue).setPastDueAmount(pastDue).build();
+        return loanRepaymentDueDataV1;
     }
 
     @Override
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStepTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStepTest.java
index 7e9c38dab..46e2e7602 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStepTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStepTest.java
@@ -37,7 +37,7 @@ import 
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDoma
 import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
-import 
org.apache.fineract.infrastructure.event.business.domain.loan.repayment.LoanRepaymentOverdueBusinessEvent;
+import 
org.apache.fineract.infrastructure.event.business.domain.loan.repayment.LoanRepaymentDueBusinessEvent;
 import 
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
@@ -68,8 +68,8 @@ public class CheckLoanRepaymentOverdueBusinessStepTest {
 
     @Test
     public void 
givenLoanWithInstallmentOverdueAfterConfiguredDaysWhenStepExecutionThenBusinessEventIsRaised()
 {
-        ArgumentCaptor<LoanRepaymentOverdueBusinessEvent> 
loanRepaymentOverdueBusinessEventArgumentCaptor = ArgumentCaptor
-                .forClass(LoanRepaymentOverdueBusinessEvent.class);
+        ArgumentCaptor<LoanRepaymentDueBusinessEvent> 
loanRepaymentDueBusinessEventArgumentCaptor = ArgumentCaptor
+                .forClass(LoanRepaymentDueBusinessEvent.class);
         // given
         
when(configurationDomainService.retrieveRepaymentOverdueDays()).thenReturn(1L);
         LocalDate loanInstallmentRepaymentDueDate = 
DateUtils.getBusinessLocalDate().minusDays(1);
@@ -83,8 +83,8 @@ public class CheckLoanRepaymentOverdueBusinessStepTest {
         // when
         Loan processedLoan = underTest.execute(loanForProcessing);
         // then
-        verify(businessEventNotifierService, 
times(1)).notifyPostBusinessEvent(loanRepaymentOverdueBusinessEventArgumentCaptor.capture());
-        LoanRepaymentScheduleInstallment loanPayloadForEvent = 
loanRepaymentOverdueBusinessEventArgumentCaptor.getValue().get();
+        verify(businessEventNotifierService, 
times(1)).notifyPostBusinessEvent(loanRepaymentDueBusinessEventArgumentCaptor.capture());
+        LoanRepaymentScheduleInstallment loanPayloadForEvent = 
loanRepaymentDueBusinessEventArgumentCaptor.getValue().get();
         assertEquals(repaymentInstallment, loanPayloadForEvent);
         assertEquals(processedLoan, loanForProcessing);
     }
@@ -110,8 +110,6 @@ public class CheckLoanRepaymentOverdueBusinessStepTest {
 
     @Test
     public void 
givenLoanWithInstallmentOverdueAfterConfiguredDaysButInstallmentPaidOffWhenStepExecutionThenNoBusinessEvent()
 {
-        ArgumentCaptor<LoanRepaymentOverdueBusinessEvent> 
loanRepaymentOverdueBusinessEventArgumentCaptor = ArgumentCaptor
-                .forClass(LoanRepaymentOverdueBusinessEvent.class);
         // given
         
when(configurationDomainService.retrieveRepaymentOverdueDays()).thenReturn(1L);
         LocalDate loanInstallmentRepaymentDueDate = 
DateUtils.getBusinessLocalDate().minusDays(1);
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializerTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializerTest.java
index 6415adf81..4fddeac00 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializerTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializerTest.java
@@ -19,6 +19,8 @@
 package 
org.apache.fineract.infrastructure.event.external.service.serialization.serializer.loan;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 
@@ -31,9 +33,11 @@ import java.time.format.DateTimeFormatter;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
+import org.apache.avro.AvroRuntimeException;
 import org.apache.fineract.avro.generic.v1.CurrencyDataV1;
 import org.apache.fineract.avro.loan.v1.LoanRepaymentDueDataV1;
 import org.apache.fineract.avro.loan.v1.RepaymentDueDataV1;
+import org.apache.fineract.avro.loan.v1.RepaymentPastDueDataV1;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
@@ -54,8 +58,11 @@ import org.mockito.Mock;
 import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
 
 @ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
 public class LoanRepaymentBusinessEventSerializerTest {
 
     @Mock
@@ -103,12 +110,52 @@ public class LoanRepaymentBusinessEventSerializerTest {
 
         // then
         CurrencyDataV1 currency = 
CurrencyDataV1.newBuilder().setCode("CODE").setDecimalPlaces(1).setInMultiplesOf(1).build();
-        RepaymentDueDataV1 repaymentDue = new RepaymentDueDataV1(1, 
BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0),
+        RepaymentDueDataV1 repaymentDue = new RepaymentDueDataV1(1, 
loanInstallmentRepaymentDueDate.format(DateTimeFormatter.ISO_DATE),
+                BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0), 
BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0),
+                BigDecimal.valueOf(0.0));
+        RepaymentPastDueDataV1 pastDue = new 
RepaymentPastDueDataV1(BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0),
                 BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0), 
BigDecimal.valueOf(0.0));
-        LoanRepaymentDueDataV1 expectedSerializedData = new 
LoanRepaymentDueDataV1(1L, "0001", "externalId",
-                
loanInstallmentRepaymentDueDate.format(DateTimeFormatter.ISO_DATE), currency, 
BigDecimal.valueOf(0.0), repaymentDue);
+        LoanRepaymentDueDataV1 expectedSerializedData = new 
LoanRepaymentDueDataV1(1L, "0001", "externalId", currency, repaymentDue,
+                pastDue);
 
         assertEquals(data, expectedSerializedData);
         moneyHelper.close();
     }
+
+    @Test
+    public void testLoanRepaymentEventLoanIdMandatoryFieldValidation() {
+        // given
+        LoanRepaymentBusinessEventSerializer serializer = new 
LoanRepaymentBusinessEventSerializer(mapper);
+
+        LocalDate loanInstallmentRepaymentDueDate = 
DateUtils.getBusinessLocalDate().plusDays(1);
+
+        Loan loanForProcessing = Mockito.mock(Loan.class);
+        LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
+        LoanSummary loanSummary = Mockito.mock(LoanSummary.class);
+        MonetaryCurrency loanCurrency = Mockito.mock(MonetaryCurrency.class);
+        MockedStatic<MoneyHelper> moneyHelper = 
Mockito.mockStatic(MoneyHelper.class);
+
+        LoanRepaymentScheduleInstallment repaymentInstallment = new 
LoanRepaymentScheduleInstallment(loanForProcessing, 1,
+                LocalDate.now(ZoneId.systemDefault()), 
loanInstallmentRepaymentDueDate, BigDecimal.valueOf(0.0), 
BigDecimal.valueOf(0.0),
+                BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0), false, new 
HashSet<>(), BigDecimal.valueOf(0.0));
+        LoanRepaymentDueBusinessEvent event = new 
LoanRepaymentDueBusinessEvent(repaymentInstallment);
+
+        // set mandatory loanID field as null
+        when(loanForProcessing.getId()).thenReturn(null);
+        when(loanForProcessing.getAccountNumber()).thenReturn("0001");
+        
when(loanForProcessing.getExternalId()).thenReturn(ExternalIdFactory.produce("externalId"));
+        when(loanForProcessing.getLoanSummary()).thenReturn(loanSummary);
+        
when(loanSummary.getTotalOutstanding()).thenReturn(BigDecimal.valueOf(0.0));
+        when(loanForProcessing.getCurrency()).thenReturn(loanCurrency);
+        when(loanCurrency.getCode()).thenReturn("CODE");
+        when(loanCurrency.getCurrencyInMultiplesOf()).thenReturn(1);
+        when(loanCurrency.getDigitsAfterDecimal()).thenReturn(1);
+        
when(mapper.mapLocalDate(any())).thenReturn(loanInstallmentRepaymentDueDate.format(DateTimeFormatter.ISO_DATE));
+        moneyHelper.when(() -> 
MoneyHelper.getRoundingMode()).thenReturn(RoundingMode.UP);
+
+        // when
+        AvroRuntimeException exceptionThrown = 
assertThrows(AvroRuntimeException.class, () -> serializer.toAvroDTO(event));
+        assertTrue(exceptionThrown.getMessage().contains("does not accept null 
values"));
+        moneyHelper.close();
+    }
 }

Reply via email to