FINERACT-2286: Make configurable the outstanding interest strategy during asset owner transfer

This commit is contained in:
Adam Saghy
2025-05-22 13:27:36 +02:00
parent a3a5aabb7f
commit 18a55874ba
28 changed files with 517 additions and 59 deletions
@@ -74,4 +74,10 @@ public class GlobalConfigurationHelper {
boolean isEnabled = BooleanUtils.toBoolean(updatedConfiguration.body().getEnabled());
assertThat(isEnabled).isEqualTo(true);
}
public GlobalConfigurationPropertyData getGlobalConfiguration(String configKey) throws IOException {
Response<GlobalConfigurationPropertyData> configuration = globalConfigurationApi.retrieveOneByName(configKey).execute();
ErrorHelper.checkSuccessfulApiCall(configuration);
return configuration.body();
}
}
@@ -41,6 +41,7 @@ import org.apache.fineract.client.models.GetClientsClientIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdDelinquencyPausePeriod;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
import org.apache.fineract.client.models.GlobalConfigurationPropertyData;
import org.apache.fineract.client.models.PageExternalTransferData;
import org.apache.fineract.client.models.PostClientsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdResponse;
@@ -53,6 +54,7 @@ import org.apache.fineract.test.data.AssetExternalizationTransferStatus;
import org.apache.fineract.test.data.AssetExternalizationTransferStatusReason;
import org.apache.fineract.test.data.TransactionType;
import org.apache.fineract.test.helper.ErrorMessageHelper;
import org.apache.fineract.test.helper.GlobalConfigurationHelper;
import org.apache.fineract.test.messaging.EventAssertion;
import org.apache.fineract.test.messaging.event.assetexternalization.LoanAccountSnapshotEvent;
import org.apache.fineract.test.messaging.event.assetexternalization.LoanOwnershipTransferEvent;
@@ -90,15 +92,14 @@ public class EventCheckHelper {
@Autowired
private ClientApi clientApi;
@Autowired
private LoansApi loansApi;
@Autowired
private EventAssertion eventAssertion;
@Autowired
private ExternalAssetOwnersApi externalAssetOwnersApi;
@Autowired
private GlobalConfigurationHelper configurationHelper;
public void clientEventCheck(Response<PostClientsResponse> clientCreationResponse) throws IOException {
Response<GetClientsClientIdResponse> clientDetails = clientApi.retrieveOne11(clientCreationResponse.body().getClientId(), false)
@@ -412,14 +413,24 @@ public class EventCheckHelper {
ExternalTransferData filtered = content.stream().filter(t -> transferId.equals(t.getTransferId())).reduce((first, second) -> second)
.orElseThrow(() -> new IllegalStateException("No element found"));
BigDecimal totalOutstandingBalanceAmountExpected = zeroConversion(filtered.getDetails().getTotalOutstanding());
BigDecimal outstandingInterestPortionExpected = zeroConversion(filtered.getDetails().getTotalInterestOutstanding());
GlobalConfigurationPropertyData outstandingInterestStrategy = configurationHelper
.getGlobalConfiguration("outstanding-interest-calculation-strategy-for-external-asset-transfer");
if ("PAYABLE_OUTSTANDING_INTEREST".equals(outstandingInterestStrategy.getStringValue())) {
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "all", null, null).execute();
totalOutstandingBalanceAmountExpected = BigDecimal.valueOf(loanDetails.body().getSummary().getTotalOutstanding());
outstandingInterestPortionExpected = BigDecimal.valueOf(loanDetails.body().getSummary().getInterestOutstanding());
}
String ownerExternalIdExpected = filtered.getStatus().getValue().equals("BUYBACK") ? null : filtered.getOwner().getExternalId();
String settlementDateExpected = filtered.getStatus().getValue().equals("BUYBACK") ? null
: FORMATTER_EVENTS.format(filtered.getSettlementDate());
BigDecimal totalOutstandingBalanceAmountExpected = zeroConversion(filtered.getDetails().getTotalOutstanding());
BigDecimal outstandingPrincipalPortionExpected = zeroConversion(filtered.getDetails().getTotalPrincipalOutstanding());
BigDecimal outstandingFeePortionExpected = zeroConversion(filtered.getDetails().getTotalFeeChargesOutstanding());
BigDecimal outstandingPenaltyPortionExpected = zeroConversion(filtered.getDetails().getTotalPenaltyChargesOutstanding());
BigDecimal outstandingInterestPortionExpected = zeroConversion(filtered.getDetails().getTotalInterestOutstanding());
BigDecimal overPaymentPortionExpected = zeroConversion(filtered.getDetails().getTotalOverpaid());
eventAssertion.assertEvent(LoanAccountSnapshotEvent.class, loanId).extractingData(LoanAccountDataV1::getId).isEqualTo(loanId)
@@ -341,11 +341,6 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
}
expectedValues.add(ownerExternalIdStored);
expectedValues.add(loanId == null ? null : String.valueOf(loanId));
expectedValues.add(loanExternalId);
expectedValues.add(transferExternalId);
List<List<String>> actualValuesList = content.stream().map(t -> {
List<String> actualValues = new ArrayList<>();
actualValues.add(t.getSettlementDate() == null ? null : FORMATTER.format(t.getSettlementDate()));
@@ -354,6 +349,31 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
actualValues.add(t.getEffectiveFrom() == null ? null : FORMATTER.format(t.getEffectiveFrom()));
actualValues.add(t.getEffectiveTo() == null ? null : FORMATTER.format(t.getEffectiveTo()));
actualValues.add(transactionType);
if (expectedValues.size() > 6) {
actualValues.add(
t.getDetails() != null ? t.getDetails().getTotalOutstanding().setScale(2, RoundingMode.HALF_DOWN).toString()
: null);
}
if (expectedValues.size() > 7) {
actualValues.add(t.getDetails() != null
? t.getDetails().getTotalPrincipalOutstanding().setScale(2, RoundingMode.HALF_DOWN).toString()
: null);
}
if (expectedValues.size() > 8) {
actualValues.add(t.getDetails() != null
? t.getDetails().getTotalInterestOutstanding().setScale(2, RoundingMode.HALF_DOWN).toString()
: null);
}
if (expectedValues.size() > 9) {
actualValues.add(t.getDetails() != null
? t.getDetails().getTotalFeeChargesOutstanding().setScale(2, RoundingMode.HALF_DOWN).toString()
: null);
}
if (expectedValues.size() > 10) {
actualValues.add(t.getDetails() != null
? t.getDetails().getTotalPenaltyChargesOutstanding().setScale(2, RoundingMode.HALF_DOWN).toString()
: null);
}
actualValues.add(t.getOwner().getExternalId() == null ? null : t.getOwner().getExternalId());
actualValues.add(loanId == null ? null : String.valueOf(t.getLoan().getLoanId()));
actualValues.add(loanExternalId == null ? null : t.getLoan().getExternalId());
@@ -361,6 +381,11 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
return actualValues;
}).collect(Collectors.toList());
expectedValues.add(ownerExternalIdStored);
expectedValues.add(loanId == null ? null : String.valueOf(loanId));
expectedValues.add(loanExternalId);
expectedValues.add(transferExternalId);
boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));
assertThat(numberOfElementsActual)