FINERACT-1971: Added installment level delinquency data to LoanAccountDataV1/CollectionDataV1 avro schema
diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/CollectionDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/CollectionDataV1.avsc
index 36256d2..3fdc726 100644
--- a/fineract-avro-schemas/src/main/avro/loan/v1/CollectionDataV1.avsc
+++ b/fineract-avro-schemas/src/main/avro/loan/v1/CollectionDataV1.avsc
@@ -93,6 +93,17 @@
"items": "org.apache.fineract.avro.loan.v1.DelinquencyPausePeriodV1"
}
]
+ },
+ {
+ "default": null,
+ "name": "installmentDelinquencyBuckets",
+ "type": [
+ "null",
+ {
+ "type": "array",
+ "items": "org.apache.fineract.avro.loan.v1.LoanInstallmentDelinquencyBucketDataV1"
+ }
+ ]
}
]
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountDataMapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountDataMapper.java
index 03b1446..d55a124 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountDataMapper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountDataMapper.java
@@ -36,6 +36,7 @@
@Mapping(target = "externalOwnerId", ignore = true)
@Mapping(target = "settlementDate", ignore = true)
@Mapping(target = "purchasePriceRatio", ignore = true)
+ @Mapping(target = "delinquent.installmentDelinquencyBuckets", ignore = true)
LoanAccountDataV1 map(LoanAccountData source);
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java
index 2ed1594..6844fe2 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java
@@ -19,11 +19,13 @@
package org.apache.fineract.infrastructure.event.external.service.serialization.serializer.loan;
import java.util.Collection;
+import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.avro.generic.GenericContainer;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.fineract.avro.generator.ByteBufferSerializable;
import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
+import org.apache.fineract.avro.loan.v1.LoanInstallmentDelinquencyBucketDataV1;
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBusinessEvent;
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanAccountDataMapper;
@@ -46,6 +48,7 @@
private final LoanAccountDataMapper mapper;
private final LoanChargeReadPlatformService loanChargeReadPlatformService;
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
+ private final LoanInstallmentLevelDelinquencyEventProducer installmentLevelDelinquencyEventProducer;
@Override
public <T> boolean canSerialize(BusinessEvent<T> event) {
@@ -74,7 +77,13 @@
} else {
data.setSummary(LoanSummaryData.withOnlyCurrencyData(data.getCurrency()));
}
- return mapper.map(data);
+
+ List<LoanInstallmentDelinquencyBucketDataV1> installmentsDelinquencyData = installmentLevelDelinquencyEventProducer
+ .calculateInstallmentLevelDelinquencyData(event.get(), data.getCurrency());
+
+ LoanAccountDataV1 result = mapper.map(data);
+ result.getDelinquent().setInstallmentDelinquencyBuckets(installmentsDelinquencyData);
+ return result;
}
@Override
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
index 22a606c..01c7b01 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
@@ -19,12 +19,8 @@
package org.apache.fineract.infrastructure.event.external.service.serialization.serializer.loan;
import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
-import java.util.Map;
import java.util.function.BiFunction;
-import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.apache.avro.generic.GenericContainer;
import org.apache.fineract.avro.generator.ByteBufferSerializable;
@@ -33,7 +29,6 @@
import org.apache.fineract.avro.loan.v1.LoanAmountDataV1;
import org.apache.fineract.avro.loan.v1.LoanChargeDataRangeViewV1;
import org.apache.fineract.avro.loan.v1.LoanInstallmentDelinquencyBucketDataV1;
-import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanDelinquencyRangeChangeBusinessEvent;
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.generic.CurrencyDataMapper;
@@ -42,12 +37,10 @@
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroDateTimeMapper;
import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
-import org.apache.fineract.portfolio.delinquency.data.LoanInstallmentDelinquencyTagData;
import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
import org.apache.fineract.portfolio.loanaccount.data.CollectionData;
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeReadPlatformService;
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
@@ -72,6 +65,7 @@
private final CurrencyDataMapper currencyMapper;
private final AvroDateTimeMapper dataTimeMapper;
+ private final LoanInstallmentLevelDelinquencyEventProducer installmentLevelDelinquencyEventProducer;
@Override
public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
@@ -103,8 +97,8 @@
DelinquencyRangeDataV1 delinquencyRange = mapper.map(data.getDelinquencyRange());
- List<LoanInstallmentDelinquencyBucketDataV1> installmentsDelinquencyData = calculateInstallmentLevelDelinquencyData(event.get(),
- data);
+ List<LoanInstallmentDelinquencyBucketDataV1> installmentsDelinquencyData = installmentLevelDelinquencyEventProducer
+ .calculateInstallmentLevelDelinquencyData(event.get(), data.getCurrency());
LoanAccountDelinquencyRangeDataV1.Builder builder = LoanAccountDelinquencyRangeDataV1.newBuilder();
return builder//
@@ -119,79 +113,6 @@
.setInstallmentDelinquencyBuckets(installmentsDelinquencyData).build();
}
- private List<LoanInstallmentDelinquencyBucketDataV1> calculateInstallmentLevelDelinquencyData(Loan loan, LoanAccountData data) {
- List<LoanInstallmentDelinquencyBucketDataV1> loanInstallmentDelinquencyData = new ArrayList<>();
- if (loan.isEnableInstallmentLevelDelinquency()) {
- Collection<LoanInstallmentDelinquencyTagData> installmentDelinquencyTags = delinquencyReadPlatformService
- .retrieveLoanInstallmentsCurrentDelinquencyTag(loan.getId());
- if (installmentDelinquencyTags != null && installmentDelinquencyTags.size() > 0) {
- // group installments that are in same range
- Map<Long, List<LoanInstallmentDelinquencyTagData>> installmentsInSameRange = installmentDelinquencyTags.stream().collect(
- Collectors.groupingBy(installmentDelnquencyTags -> installmentDelnquencyTags.getDelinquencyRange().getId()));
- // for installments in each range, get details from loan repayment schedule installment, add amounts,
- // list charges
- for (Map.Entry<Long, List<LoanInstallmentDelinquencyTagData>> installmentDelinquencyTagData : installmentsInSameRange
- .entrySet()) {
- // get installments details
- List<LoanRepaymentScheduleInstallment> delinquentInstallmentsInSameRange = loan.getRepaymentScheduleInstallments()
- .stream().filter(installment -> installmentDelinquencyTagData.getValue().stream()
- .anyMatch(installmentTag -> installmentTag.getId().equals(installment.getId())))
- .toList();
- // add amounts
- LoanAmountDataV1 amount = LoanAmountDataV1.newBuilder()//
- .setPrincipalAmount(delinquentInstallmentsInSameRange.stream()
- .map(instlment -> instlment.getPrincipalOutstanding(loan.getCurrency()).getAmount())
- .reduce(BigDecimal.ZERO, BigDecimal::add))//
- .setFeeAmount(delinquentInstallmentsInSameRange.stream()
- .map(instlment -> instlment.getFeeChargesOutstanding(loan.getCurrency()).getAmount())
- .reduce(BigDecimal.ZERO, BigDecimal::add))//
- .setInterestAmount(delinquentInstallmentsInSameRange.stream()
- .map(instlment -> instlment.getInterestOutstanding(loan.getCurrency()).getAmount())
- .reduce(BigDecimal.ZERO, BigDecimal::add))//
- .setPenaltyAmount(delinquentInstallmentsInSameRange.stream()
- .map(instlment -> instlment.getPenaltyChargesOutstanding(loan.getCurrency()).getAmount())
- .reduce(BigDecimal.ZERO, BigDecimal::add))//
- .setTotalAmount(delinquentInstallmentsInSameRange.stream()
- .map(instlment -> instlment.getTotalOutstanding(loan.getCurrency()).getAmount())
- .reduce(BigDecimal.ZERO, BigDecimal::add))//
- .build();
-
- // get list of charges for installments in same range
- List<LoanCharge> chargesForInstallmentsInSameRange = loan.getLoanCharges().stream().filter(loanCharge -> !loanCharge
- .isPaid()
- && delinquentInstallmentsInSameRange.stream().anyMatch(installmentForCharge -> (DateUtils
- .isAfter(loanCharge.getEffectiveDueDate(), installmentForCharge.getFromDate())
- || DateUtils.isEqual(loanCharge.getEffectiveDueDate(), installmentForCharge.getFromDate()))
- && (DateUtils.isBefore(loanCharge.getEffectiveDueDate(), installmentForCharge.getDueDate())
- || DateUtils.isEqual(loanCharge.getEffectiveDueDate(), installmentForCharge.getDueDate()))))
- .toList();
-
- List<LoanChargeDataRangeViewV1> charges = new ArrayList<>();
- for (LoanCharge charge : chargesForInstallmentsInSameRange) {
- LoanChargeDataRangeViewV1 chargeData = LoanChargeDataRangeViewV1.newBuilder().setId(charge.getId())
- .setName(charge.name()).setAmount(charge.amountOutstanding())
- .setCurrency(currencyMapper.map(data.getCurrency())).build();
- charges.add(chargeData);
- }
-
- LoanInstallmentDelinquencyTagData.InstallmentDelinquencyRange delinquencyRange = installmentDelinquencyTagData
- .getValue().get(0).getDelinquencyRange();
-
- DelinquencyRangeDataV1 delinquencyRangeDataV1 = DelinquencyRangeDataV1.newBuilder().setId(delinquencyRange.getId())
- .setClassification(delinquencyRange.getClassification()).setMinimumAgeDays(delinquencyRange.getMinimumAgeDays())
- .setMaximumAgeDays(delinquencyRange.getMaximumAgeDays()).build();
-
- LoanInstallmentDelinquencyBucketDataV1 installmentDelinquencyBucketDataV1 = LoanInstallmentDelinquencyBucketDataV1
- .newBuilder().setDelinquencyRange(delinquencyRangeDataV1).setAmount(amount).setCharges(charges)
- .setCurrency(currencyMapper.map(data.getCurrency())).build();
-
- loanInstallmentDelinquencyData.add(installmentDelinquencyBucketDataV1);
- }
- }
- }
- return loanInstallmentDelinquencyData;
- }
-
private BigDecimal calculateDataSummary(Loan loan, BiFunction<Loan, LoanRepaymentScheduleInstallment, BigDecimal> mapper) {
return loan.getRepaymentScheduleInstallments().stream().map(installment -> mapper.apply(loan, installment)).reduce(BigDecimal.ZERO,
BigDecimal::add);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanInstallmentLevelDelinquencyEventProducer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanInstallmentLevelDelinquencyEventProducer.java
new file mode 100644
index 0000000..59d4175
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanInstallmentLevelDelinquencyEventProducer.java
@@ -0,0 +1,121 @@
+/**
+ * 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.event.external.service.serialization.serializer.loan;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.avro.loan.v1.DelinquencyRangeDataV1;
+import org.apache.fineract.avro.loan.v1.LoanAmountDataV1;
+import org.apache.fineract.avro.loan.v1.LoanChargeDataRangeViewV1;
+import org.apache.fineract.avro.loan.v1.LoanInstallmentDelinquencyBucketDataV1;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
+import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.generic.CurrencyDataMapper;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import org.apache.fineract.portfolio.delinquency.data.LoanInstallmentDelinquencyTagData;
+import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class LoanInstallmentLevelDelinquencyEventProducer {
+
+ private final DelinquencyReadPlatformService delinquencyReadPlatformService;
+ private final CurrencyDataMapper currencyMapper;
+
+ public List<LoanInstallmentDelinquencyBucketDataV1> calculateInstallmentLevelDelinquencyData(Loan loan, CurrencyData currency) {
+ List<LoanInstallmentDelinquencyBucketDataV1> loanInstallmentDelinquencyData = new ArrayList<>();
+ if (loan.isEnableInstallmentLevelDelinquency()) {
+ Collection<LoanInstallmentDelinquencyTagData> installmentDelinquencyTags = delinquencyReadPlatformService
+ .retrieveLoanInstallmentsCurrentDelinquencyTag(loan.getId());
+ if (installmentDelinquencyTags != null && installmentDelinquencyTags.size() > 0) {
+ // group installments that are in same range
+ Map<Long, List<LoanInstallmentDelinquencyTagData>> installmentsInSameRange = installmentDelinquencyTags.stream().collect(
+ Collectors.groupingBy(installmentDelnquencyTags -> installmentDelnquencyTags.getDelinquencyRange().getId()));
+ // for installments in each range, get details from loan repayment schedule installment, add amounts,
+ // list charges
+ for (Map.Entry<Long, List<LoanInstallmentDelinquencyTagData>> installmentDelinquencyTagData : installmentsInSameRange
+ .entrySet()) {
+ // get installments details
+ List<LoanRepaymentScheduleInstallment> delinquentInstallmentsInSameRange = loan.getRepaymentScheduleInstallments()
+ .stream().filter(installment -> installmentDelinquencyTagData.getValue().stream()
+ .anyMatch(installmentTag -> installmentTag.getId().equals(installment.getId())))
+ .toList();
+ // add amounts
+ LoanAmountDataV1 amount = LoanAmountDataV1.newBuilder()//
+ .setPrincipalAmount(delinquentInstallmentsInSameRange.stream()
+ .map(installment -> installment.getPrincipalOutstanding(loan.getCurrency()).getAmount())
+ .reduce(BigDecimal.ZERO, BigDecimal::add))//
+ .setFeeAmount(delinquentInstallmentsInSameRange.stream()
+ .map(installment -> installment.getFeeChargesOutstanding(loan.getCurrency()).getAmount())
+ .reduce(BigDecimal.ZERO, BigDecimal::add))//
+ .setInterestAmount(delinquentInstallmentsInSameRange.stream()
+ .map(installment -> installment.getInterestOutstanding(loan.getCurrency()).getAmount())
+ .reduce(BigDecimal.ZERO, BigDecimal::add))//
+ .setPenaltyAmount(delinquentInstallmentsInSameRange.stream()
+ .map(installment -> installment.getPenaltyChargesOutstanding(loan.getCurrency()).getAmount())
+ .reduce(BigDecimal.ZERO, BigDecimal::add))//
+ .setTotalAmount(delinquentInstallmentsInSameRange.stream()
+ .map(installment -> installment.getTotalOutstanding(loan.getCurrency()).getAmount())
+ .reduce(BigDecimal.ZERO, BigDecimal::add))//
+ .build();
+
+ // get list of charges for installments in same range
+ List<LoanCharge> chargesForInstallmentsInSameRange = loan.getLoanCharges().stream().filter(loanCharge -> !loanCharge
+ .isPaid()
+ && delinquentInstallmentsInSameRange.stream().anyMatch(installmentForCharge -> (DateUtils
+ .isAfter(loanCharge.getEffectiveDueDate(), installmentForCharge.getFromDate())
+ || DateUtils.isEqual(loanCharge.getEffectiveDueDate(), installmentForCharge.getFromDate()))
+ && (DateUtils.isBefore(loanCharge.getEffectiveDueDate(), installmentForCharge.getDueDate())
+ || DateUtils.isEqual(loanCharge.getEffectiveDueDate(), installmentForCharge.getDueDate()))))
+ .toList();
+
+ List<LoanChargeDataRangeViewV1> charges = new ArrayList<>();
+ for (LoanCharge charge : chargesForInstallmentsInSameRange) {
+ LoanChargeDataRangeViewV1 chargeData = LoanChargeDataRangeViewV1.newBuilder().setId(charge.getId())
+ .setName(charge.name()).setAmount(charge.amountOutstanding()).setCurrency(currencyMapper.map(currency))
+ .build();
+ charges.add(chargeData);
+ }
+
+ LoanInstallmentDelinquencyTagData.InstallmentDelinquencyRange delinquencyRange = installmentDelinquencyTagData
+ .getValue().get(0).getDelinquencyRange();
+
+ DelinquencyRangeDataV1 delinquencyRangeDataV1 = DelinquencyRangeDataV1.newBuilder().setId(delinquencyRange.getId())
+ .setClassification(delinquencyRange.getClassification()).setMinimumAgeDays(delinquencyRange.getMinimumAgeDays())
+ .setMaximumAgeDays(delinquencyRange.getMaximumAgeDays()).build();
+
+ LoanInstallmentDelinquencyBucketDataV1 installmentDelinquencyBucketDataV1 = LoanInstallmentDelinquencyBucketDataV1
+ .newBuilder().setDelinquencyRange(delinquencyRangeDataV1).setAmount(amount).setCharges(charges)
+ .setCurrency(currencyMapper.map(currency)).build();
+
+ loanInstallmentDelinquencyData.add(installmentDelinquencyBucketDataV1);
+ }
+ }
+ }
+ return loanInstallmentDelinquencyData;
+ }
+}
diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java
index 22a9aa3..62d8f49 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java
@@ -116,7 +116,8 @@
// given
LoanDelinquencyRangeChangeBusinessEventSerializer serializer = new LoanDelinquencyRangeChangeBusinessEventSerializer(
loanReadPlatformService, new LoanDelinquencyRangeDataMapperImpl(), loanChargeReadPlatformService,
- delinquencyReadPlatformService, new LoanChargeDataMapperImpl(null, null, null), new CurrencyDataMapperImpl(), mapper);
+ delinquencyReadPlatformService, new LoanChargeDataMapperImpl(null, null, null), new CurrencyDataMapperImpl(), mapper,
+ new LoanInstallmentLevelDelinquencyEventProducer(delinquencyReadPlatformService, new CurrencyDataMapperImpl()));
Loan loanForProcessing = Mockito.mock(Loan.class);
LoanAccountData loanAccountData = mock(LoanAccountData.class);
@@ -180,7 +181,8 @@
// given
LoanDelinquencyRangeChangeBusinessEventSerializer serializer = new LoanDelinquencyRangeChangeBusinessEventSerializer(
loanReadPlatformService, new LoanDelinquencyRangeDataMapperImpl(), loanChargeReadPlatformService,
- delinquencyReadPlatformService, new LoanChargeDataMapperImpl(null, null, null), new CurrencyDataMapperImpl(), mapper);
+ delinquencyReadPlatformService, new LoanChargeDataMapperImpl(null, null, null), new CurrencyDataMapperImpl(), mapper,
+ new LoanInstallmentLevelDelinquencyEventProducer(delinquencyReadPlatformService, new CurrencyDataMapperImpl()));
Loan loanForProcessing = Mockito.mock(Loan.class);
LoanAccountData loanAccountData = mock(LoanAccountData.class);