FINERACT-2286: Make configurable the outstanding interest strategy during asset owner transfer
This commit is contained in:
+9
-9
@@ -21,7 +21,6 @@ package org.apache.fineract.investor.cob.loan;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -42,6 +41,7 @@ import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferRepository;
|
||||
import org.apache.fineract.investor.domain.LoanOwnershipTransferBusinessEvent;
|
||||
import org.apache.fineract.investor.service.AccountingService;
|
||||
import org.apache.fineract.investor.service.DelayedSettlementAttributeService;
|
||||
import org.apache.fineract.investor.service.ExternalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
import org.apache.fineract.investor.service.LoanTransferabilityService;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
@@ -65,6 +65,7 @@ public class LoanAccountOwnerTransferBusinessStep implements LoanCOBBusinessStep
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final LoanTransferabilityService loanTransferabilityService;
|
||||
private final DelayedSettlementAttributeService delayedSettlementAttributeService;
|
||||
private final ExternalAssetOwnerTransferOutstandingInterestCalculation externalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
|
||||
@Override
|
||||
public Loan execute(Loan loan) {
|
||||
@@ -220,14 +221,13 @@ public class LoanAccountOwnerTransferBusinessStep implements LoanCOBBusinessStep
|
||||
ExternalAssetOwnerTransfer externalAssetOwnerTransfer) {
|
||||
ExternalAssetOwnerTransferDetails details = new ExternalAssetOwnerTransferDetails();
|
||||
details.setExternalAssetOwnerTransfer(externalAssetOwnerTransfer);
|
||||
details.setTotalOutstanding(Objects.requireNonNullElse(loan.getSummary().getTotalOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalPrincipalOutstanding(Objects.requireNonNullElse(loan.getSummary().getTotalPrincipalOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalInterestOutstanding(Objects.requireNonNullElse(loan.getSummary().getTotalInterestOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalFeeChargesOutstanding(
|
||||
Objects.requireNonNullElse(loan.getSummary().getTotalFeeChargesOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalPenaltyChargesOutstanding(
|
||||
Objects.requireNonNullElse(loan.getSummary().getTotalPenaltyChargesOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalOverpaid(Objects.requireNonNullElse(loan.getTotalOverpaid(), BigDecimal.ZERO));
|
||||
details.setTotalPrincipalOutstanding(loan.getSummary().getTotalPrincipalOutstanding());
|
||||
// We have different strategies to calculate oustanding interest
|
||||
final BigDecimal interestAmount = externalAssetOwnerTransferOutstandingInterestCalculation.calculateOutstandingInterest(loan);
|
||||
details.setTotalInterestOutstanding(interestAmount);
|
||||
details.setTotalFeeChargesOutstanding(loan.getSummary().getTotalFeeChargesOutstanding());
|
||||
details.setTotalPenaltyChargesOutstanding(loan.getSummary().getTotalPenaltyChargesOutstanding());
|
||||
details.setTotalOverpaid(loan.getTotalOverpaid());
|
||||
return details;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.investor.domain;
|
||||
|
||||
public interface AttributeKey {
|
||||
|
||||
String getKey();
|
||||
|
||||
String getValue();
|
||||
|
||||
String getDescription();
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.investor.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class ExternalAssetOwnerLoanProductAttribute implements AttributeKey {
|
||||
|
||||
public static final ExternalAssetOwnerLoanProductAttribute TOTAL_OUTSTANDING_INTEREST_STRATEGY = new ExternalAssetOwnerLoanProductAttribute(
|
||||
"OUTSTANDING_INTEREST_STRATEGY", "TOTAL_OUTSTANDING",
|
||||
"During external owner transfer the total (due + not yet due + projected) interest participate");
|
||||
public static final ExternalAssetOwnerLoanProductAttribute PAYABLE_OUTSTANDING_INTEREST_STRATEGY = new ExternalAssetOwnerLoanProductAttribute(
|
||||
"OUTSTANDING_INTEREST_STRATEGY", "PAYABLE_OUTSTANDING",
|
||||
"During external owner transfer the total (due + not yet due) interest participate");
|
||||
|
||||
private final String key;
|
||||
private final String value;
|
||||
private final String description;
|
||||
}
|
||||
+32
-1
@@ -25,18 +25,20 @@ import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name = "m_external_asset_owner_transfer_details")
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
public class ExternalAssetOwnerTransferDetails extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
|
||||
@Setter
|
||||
@OneToOne(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "asset_owner_transfer_id", referencedColumnName = "id")
|
||||
private ExternalAssetOwnerTransfer externalAssetOwnerTransfer;
|
||||
@@ -58,4 +60,33 @@ public class ExternalAssetOwnerTransferDetails extends AbstractAuditableWithUTCD
|
||||
|
||||
@Column(name = "total_overpaid_derived", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal totalOverpaid;
|
||||
|
||||
public void setTotalPrincipalOutstanding(BigDecimal totalPrincipalOutstanding) {
|
||||
this.totalPrincipalOutstanding = Objects.requireNonNullElse(totalPrincipalOutstanding, BigDecimal.ZERO);
|
||||
updateTotalOutstanding();
|
||||
}
|
||||
|
||||
public void setTotalInterestOutstanding(BigDecimal totalInterestOutstanding) {
|
||||
this.totalInterestOutstanding = Objects.requireNonNullElse(totalInterestOutstanding, BigDecimal.ZERO);
|
||||
updateTotalOutstanding();
|
||||
}
|
||||
|
||||
public void setTotalFeeChargesOutstanding(BigDecimal totalFeeChargesOutstanding) {
|
||||
this.totalFeeChargesOutstanding = Objects.requireNonNullElse(totalFeeChargesOutstanding, BigDecimal.ZERO);
|
||||
updateTotalOutstanding();
|
||||
}
|
||||
|
||||
public void setTotalPenaltyChargesOutstanding(BigDecimal totalPenaltyChargesOutstanding) {
|
||||
this.totalPenaltyChargesOutstanding = Objects.requireNonNullElse(totalPenaltyChargesOutstanding, BigDecimal.ZERO);
|
||||
updateTotalOutstanding();
|
||||
}
|
||||
|
||||
private void updateTotalOutstanding() {
|
||||
this.totalOutstanding = MathUtil.add(getTotalPrincipalOutstanding(), getTotalInterestOutstanding(), getTotalFeeChargesOutstanding(),
|
||||
getTotalPenaltyChargesOutstanding());
|
||||
}
|
||||
|
||||
public void setTotalOverpaid(BigDecimal totalOverpaid) {
|
||||
this.totalOverpaid = Objects.requireNonNullElse(totalOverpaid, BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -55,6 +55,7 @@ public class AccountingServiceImpl implements AccountingService {
|
||||
private final ExternalAssetOwnerTransferJournalEntryMappingRepository externalAssetOwnerTransferJournalEntryMappingRepository;
|
||||
private final ExternalAssetOwnerJournalEntryMappingRepository externalAssetOwnerJournalEntryMappingRepository;
|
||||
private final FinancialActivityAccountRepositoryWrapper financialActivityAccountRepository;
|
||||
private final ExternalAssetOwnerTransferOutstandingInterestCalculation externalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
|
||||
@Override
|
||||
public void createJournalEntriesForSaleAssetTransfer(final Loan loan, final ExternalAssetOwnerTransfer transfer,
|
||||
@@ -104,7 +105,8 @@ public class AccountingServiceImpl implements AccountingService {
|
||||
final Long transactionId = transfer.getId();
|
||||
final LocalDate transactionDate = transfer.getSettlementDate();
|
||||
final BigDecimal principalAmount = loan.getSummary().getTotalPrincipalOutstanding();
|
||||
final BigDecimal interestAmount = loan.getSummary().getTotalInterestOutstanding();
|
||||
// We have different strategies to calculate oustanding interest
|
||||
final BigDecimal interestAmount = externalAssetOwnerTransferOutstandingInterestCalculation.calculateOutstandingInterest(loan);
|
||||
final BigDecimal feesAmount = loan.getSummary().getTotalFeeChargesOutstanding();
|
||||
final BigDecimal penaltiesAmount = loan.getSummary().getTotalPenaltyChargesOutstanding();
|
||||
final BigDecimal overPaymentAmount = loan.getTotalOverpaid();
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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.investor.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
import org.apache.fineract.investor.config.InvestorModuleIsEnabledCondition;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanSummaryDataProvider;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanSummaryProviderDelegate;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Conditional(InvestorModuleIsEnabledCondition.class)
|
||||
public class ExternalAssetOwnerTransferOutstandingInterestCalculation {
|
||||
|
||||
private final LoanSummaryProviderDelegate loanSummaryDataProvider;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final LoanReadPlatformService loanReadPlatformService;
|
||||
|
||||
private LoanSummaryDataProvider fetchLoanSummaryDataProvider(Loan loan) {
|
||||
return this.loanSummaryDataProvider.resolveLoanSummaryDataProvider(loan.getTransactionProcessingStrategyCode());
|
||||
}
|
||||
|
||||
public BigDecimal calculateOutstandingInterest(Loan loan) {
|
||||
String outstandingInterestCalculationStrategy = configurationDomainService.getAssetOwnerTransferOustandingInterestStrategy();
|
||||
return switch (outstandingInterestCalculationStrategy) {
|
||||
case "TOTAL_OUTSTANDING_INTEREST" -> loan.getSummary().getTotalInterestOutstanding();
|
||||
case "PAYABLE_OUTSTANDING_INTEREST" -> {
|
||||
LoanAccountData data = loanReadPlatformService.retrieveOne(loan.getId());
|
||||
data = loanReadPlatformService.fetchRepaymentScheduleData(data);
|
||||
Money duePayableAmount = loan
|
||||
.getRepaymentScheduleInstallments(i -> !i.getDueDate().isAfter(DateUtils.getBusinessLocalDate())).stream()
|
||||
.map(i -> i.getInterestOutstanding(loan.getCurrency())).reduce(Money.zero(loan.getCurrency()), MathUtil::plus);
|
||||
BigDecimal notDuePayableAmount = fetchLoanSummaryDataProvider(loan)
|
||||
.computeTotalUnpaidPayableNotDueInterestAmountOnActualPeriod(loan, data.getRepaymentSchedule().getPeriods(),
|
||||
DateUtils.getBusinessLocalDate(), loan.getCurrency().toData(), duePayableAmount.getAmount());
|
||||
|
||||
yield MathUtil.add(duePayableAmount.getAmount(), notDuePayableAmount);
|
||||
}
|
||||
default -> throw new UnsupportedOperationException(
|
||||
"Unknown outstanding interest calculation: " + outstandingInterestCalculationStrategy);
|
||||
};
|
||||
}
|
||||
}
|
||||
+8
-9
@@ -35,7 +35,6 @@ import static org.apache.fineract.investor.data.ExternalTransferSubStatus.UNSOLD
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
@@ -63,6 +62,7 @@ public class LoanAccountOwnerTransferServiceImpl implements LoanAccountOwnerTran
|
||||
private final ExternalAssetOwnerTransferLoanMappingRepository externalAssetOwnerTransferLoanMappingRepository;
|
||||
private final AccountingService accountingService;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final ExternalAssetOwnerTransferOutstandingInterestCalculation externalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
|
||||
@Override
|
||||
public void handleLoanClosedOrOverpaid(Loan loan) {
|
||||
@@ -166,14 +166,13 @@ public class LoanAccountOwnerTransferServiceImpl implements LoanAccountOwnerTran
|
||||
ExternalAssetOwnerTransfer externalAssetOwnerTransfer) {
|
||||
ExternalAssetOwnerTransferDetails details = new ExternalAssetOwnerTransferDetails();
|
||||
details.setExternalAssetOwnerTransfer(externalAssetOwnerTransfer);
|
||||
details.setTotalOutstanding(Objects.requireNonNullElse(loan.getSummary().getTotalOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalPrincipalOutstanding(Objects.requireNonNullElse(loan.getSummary().getTotalPrincipalOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalInterestOutstanding(Objects.requireNonNullElse(loan.getSummary().getTotalInterestOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalFeeChargesOutstanding(
|
||||
Objects.requireNonNullElse(loan.getSummary().getTotalFeeChargesOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalPenaltyChargesOutstanding(
|
||||
Objects.requireNonNullElse(loan.getSummary().getTotalPenaltyChargesOutstanding(), BigDecimal.ZERO));
|
||||
details.setTotalOverpaid(Objects.requireNonNullElse(loan.getTotalOverpaid(), BigDecimal.ZERO));
|
||||
details.setTotalPrincipalOutstanding(loan.getSummary().getTotalPrincipalOutstanding());
|
||||
// We have different strategies to calculate oustanding interest
|
||||
final BigDecimal interestAmount = externalAssetOwnerTransferOutstandingInterestCalculation.calculateOutstandingInterest(loan);
|
||||
details.setTotalInterestOutstanding(interestAmount);
|
||||
details.setTotalFeeChargesOutstanding(loan.getSummary().getTotalFeeChargesOutstanding());
|
||||
details.setTotalPenaltyChargesOutstanding(loan.getSummary().getTotalPenaltyChargesOutstanding());
|
||||
details.setTotalOverpaid(loan.getTotalOverpaid());
|
||||
return details;
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -39,4 +39,5 @@
|
||||
<include relativeToChangelogFile="true" file="parts/0015_add_intermediary_sale_command.xml"/>
|
||||
<include relativeToChangelogFile="true" file="parts/0016_add_external_reference_id.xml"/>
|
||||
<include relativeToChangelogFile="true" file="parts/0017_add_external_asset_owner_loan_product_attr_index.xml"/>
|
||||
<include relativeToChangelogFile="true" file="parts/0018_add_external_asset_owner_transfer_outstanding_interest_strategy.xml"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
|
||||
|
||||
<changeSet author="fineract" id="1" context="postgresql">
|
||||
<sql>
|
||||
SELECT SETVAL('c_configuration_id_seq', COALESCE(MAX(id), 0)+1, false ) FROM c_configuration;
|
||||
</sql>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="2">
|
||||
<insert tableName="c_configuration">
|
||||
<column name="name" value="outstanding-interest-calculation-strategy-for-external-asset-transfer"/>
|
||||
<column name="value"/>
|
||||
<column name="date_value"/>
|
||||
<column name="string_value" value="TOTAL_OUTSTANDING_INTEREST"/>
|
||||
<column name="enabled" valueBoolean="true"/>
|
||||
<column name="is_trap_door" valueBoolean="false"/>
|
||||
<column name="description" value=" Available options: TOTAL_OUTSTANDING_INTEREST, PAYABLE_OUTSTANDING_INTEREST. Define whether total outstanding interest (due + not yet due + projected) or payable till transfer date ( due + not yet due) should be involved in the asset transfer."/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+24
-1
@@ -24,6 +24,7 @@ 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.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -31,6 +32,8 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.HashMap;
|
||||
@@ -55,12 +58,16 @@ import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferRepository;
|
||||
import org.apache.fineract.investor.domain.LoanOwnershipTransferBusinessEvent;
|
||||
import org.apache.fineract.investor.service.AccountingService;
|
||||
import org.apache.fineract.investor.service.DelayedSettlementAttributeService;
|
||||
import org.apache.fineract.investor.service.ExternalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
import org.apache.fineract.investor.service.LoanTransferabilityService;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummary;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -69,6 +76,7 @@ import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -80,6 +88,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
public static final LocalDate FUTURE_DATE_9999_12_31 = LocalDate.of(9999, 12, 31);
|
||||
private static final Long LOAN_PRODUCT_ID = 2L;
|
||||
private final LocalDate actualDate = LocalDate.now(ZoneId.systemDefault());
|
||||
private static final MockedStatic<MoneyHelper> MONEY_HELPER = mockStatic(MoneyHelper.class);
|
||||
|
||||
@Mock
|
||||
private ExternalAssetOwnerTransferRepository externalAssetOwnerTransferRepository;
|
||||
@@ -99,8 +108,22 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
@Mock
|
||||
private DelayedSettlementAttributeService delayedSettlementAttributeService;
|
||||
|
||||
@Mock
|
||||
private ExternalAssetOwnerTransferOutstandingInterestCalculation externalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
|
||||
private LoanAccountOwnerTransferBusinessStep underTest;
|
||||
|
||||
@BeforeAll
|
||||
public static void init() {
|
||||
MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
|
||||
MONEY_HELPER.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.HALF_EVEN));
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void destruct() {
|
||||
MONEY_HELPER.close();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
||||
@@ -108,7 +131,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, actualDate)));
|
||||
underTest = new LoanAccountOwnerTransferBusinessStep(externalAssetOwnerTransferRepository,
|
||||
externalAssetOwnerTransferLoanMappingRepository, accountingService, businessEventNotifierService,
|
||||
loanTransferabilityService, delayedSettlementAttributeService);
|
||||
loanTransferabilityService, delayedSettlementAttributeService, externalAssetOwnerTransferOutstandingInterestCalculation);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
||||
+23
-1
@@ -27,11 +27,14 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -51,16 +54,20 @@ import org.apache.fineract.investor.domain.ExternalAssetOwnerJournalEntryMapping
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransfer;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferJournalEntryMapping;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferJournalEntryMappingRepository;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummary;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
@@ -68,6 +75,19 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class AccountingServiceImplTest {
|
||||
|
||||
private static final MockedStatic<MoneyHelper> MONEY_HELPER = mockStatic(MoneyHelper.class);
|
||||
|
||||
@BeforeAll
|
||||
public static void init() {
|
||||
MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
|
||||
MONEY_HELPER.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.HALF_EVEN));
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void destruct() {
|
||||
MONEY_HELPER.close();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BUSINESS_DATE, LocalDate.of(2024, 9, 27))));
|
||||
@@ -517,6 +537,9 @@ class AccountingServiceImplTest {
|
||||
@Mock
|
||||
private FinancialActivityAccountRepositoryWrapper financialActivityAccountRepository;
|
||||
|
||||
@Mock
|
||||
private ExternalAssetOwnerTransferOutstandingInterestCalculation externalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
|
||||
@InjectMocks
|
||||
private AccountingServiceImpl testSubject;
|
||||
|
||||
@@ -540,7 +563,6 @@ class AccountingServiceImplTest {
|
||||
|
||||
LoanSummary loanSummary = Mockito.mock(LoanSummary.class);
|
||||
when(loanSummary.getTotalPrincipalOutstanding()).thenReturn(BigDecimal.ONE);
|
||||
when(loanSummary.getTotalInterestOutstanding()).thenReturn(BigDecimal.ONE);
|
||||
when(loanSummary.getTotalFeeChargesOutstanding()).thenReturn(BigDecimal.ONE);
|
||||
when(loanSummary.getTotalPenaltyChargesOutstanding()).thenReturn(BigDecimal.ONE);
|
||||
when(loan.getSummary()).thenReturn(loanSummary);
|
||||
|
||||
+24
-3
@@ -23,11 +23,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.domain.Sort.Direction.ASC;
|
||||
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.HashMap;
|
||||
@@ -44,9 +47,12 @@ import org.apache.fineract.investor.domain.ExternalAssetOwnerTransfer;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferLoanMappingRepository;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferRepository;
|
||||
import org.apache.fineract.investor.domain.LoanOwnershipTransferBusinessEvent;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummary;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -54,7 +60,9 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -63,6 +71,7 @@ import org.springframework.data.jpa.domain.Specification;
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class LoanAccountOwnerTransferServiceTest {
|
||||
|
||||
private static final MockedStatic<MoneyHelper> MONEY_HELPER = mockStatic(MoneyHelper.class);
|
||||
@Mock
|
||||
private ExternalAssetOwnerTransferRepository externalAssetOwnerTransferRepository;
|
||||
@Mock
|
||||
@@ -71,15 +80,27 @@ public class LoanAccountOwnerTransferServiceTest {
|
||||
private AccountingService accountingService;
|
||||
@Mock
|
||||
private BusinessEventNotifierService businessEventNotifierService;
|
||||
@Mock
|
||||
private ExternalAssetOwnerTransferOutstandingInterestCalculation externalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
|
||||
private LoanAccountOwnerTransferService underTest;
|
||||
@InjectMocks
|
||||
private LoanAccountOwnerTransferServiceImpl underTest;
|
||||
private final LocalDate actualDate = LocalDate.now(ZoneId.systemDefault());
|
||||
|
||||
@BeforeAll
|
||||
public static void init() {
|
||||
MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
|
||||
MONEY_HELPER.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.HALF_EVEN));
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void destruct() {
|
||||
MONEY_HELPER.close();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BUSINESS_DATE, actualDate)));
|
||||
underTest = new LoanAccountOwnerTransferServiceImpl(externalAssetOwnerTransferRepository,
|
||||
externalAssetOwnerTransferLoanMappingRepository, accountingService, businessEventNotifierService);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user