diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanOwnershipTransferDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanOwnershipTransferDataV1.avsc index 985170e4b..28914905e 100644 --- a/fineract-avro-schemas/src/main/avro/loan/v1/LoanOwnershipTransferDataV1.avsc +++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanOwnershipTransferDataV1.avsc @@ -55,6 +55,14 @@ "string" ] }, + { + "default": null, + "name": "previousOwnerExternalId", + "type": [ + "null", + "string" + ] + }, { "default": null, "name": "currency", diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/cob/loan/LoanAccountOwnerTransferBusinessStep.java b/fineract-investor/src/main/java/org/apache/fineract/investor/cob/loan/LoanAccountOwnerTransferBusinessStep.java index 523a0f6c7..7c0285e5e 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/cob/loan/LoanAccountOwnerTransferBusinessStep.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/cob/loan/LoanAccountOwnerTransferBusinessStep.java @@ -279,6 +279,7 @@ public class LoanAccountOwnerTransferBusinessStep implements LoanCOBBusinessStep newExternalAssetOwnerTransfer.setPurchasePriceRatio(externalAssetOwnerTransfer.getPurchasePriceRatio()); newExternalAssetOwnerTransfer.setEffectiveDateFrom(effectiveDateFrom); newExternalAssetOwnerTransfer.setEffectiveDateTo(effectiveDateTo); + newExternalAssetOwnerTransfer.setPreviousOwner(externalAssetOwnerTransfer.getPreviousOwner()); expireTransfer(settlementDate, externalAssetOwnerTransfer); diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/data/ExternalTransferData.java b/fineract-investor/src/main/java/org/apache/fineract/investor/data/ExternalTransferData.java index f899650f6..9e514dee7 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/data/ExternalTransferData.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/data/ExternalTransferData.java @@ -26,6 +26,7 @@ public class ExternalTransferData { private Long transferId; private ExternalTransferOwnerData owner; + private ExternalTransferOwnerData previousOwner; private ExternalTransferLoanData loan; private ExternalTransferDataDetails details; private String transferExternalId; diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransfer.java b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransfer.java index 7d2b488dd..72948bfa1 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransfer.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransfer.java @@ -81,4 +81,8 @@ public class ExternalAssetOwnerTransfer extends AbstractAuditableWithUTCDateTime @Column(name = "external_group_id", length = 100) private ExternalId externalGroupId; + + @ManyToOne + @JoinColumn(name = "previous_owner_id") + private ExternalAssetOwner previousOwner; } diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersTransferMapper.java b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersTransferMapper.java index fe1931f2e..b60e85e06 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersTransferMapper.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersTransferMapper.java @@ -43,6 +43,7 @@ public interface ExternalAssetOwnersTransferMapper { @Mapping(target = "purchasePriceRatio", source = "purchasePriceRatio") @Mapping(target = "settlementDate", source = "settlementDate") @Mapping(target = "status", source = "status") + @Mapping(target = "previousOwner", source = "previousOwner") @Mapping(target = "details", source = "externalAssetOwnerTransferDetails") ExternalTransferData mapTransfer(ExternalAssetOwnerTransfer source); diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java index 19d4be902..56755787a 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java @@ -51,6 +51,7 @@ import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.ExternalIdFactory; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; +import org.apache.fineract.investor.data.ExternalTransferData; import org.apache.fineract.investor.data.ExternalTransferRequestParameters; import org.apache.fineract.investor.data.ExternalTransferStatus; import org.apache.fineract.investor.data.ExternalTransferSubStatus; @@ -80,6 +81,7 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW private final LoanRepository loanRepository; private final DelayedSettlementAttributeService delayedSettlementAttributeService; private final ConfigurationDomainService configurationDomainService; + private final ExternalAssetOwnersReadService externalAssetOwnersReadService; @Override @Transactional @@ -307,6 +309,7 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW externalAssetOwnerTransfer.setEffectiveDateFrom(effectiveDateFrom); externalAssetOwnerTransfer.setEffectiveDateTo(FUTURE_DATE_9999_12_31); externalAssetOwnerTransfer.setPurchasePriceRatio(effectiveTransfer.getPurchasePriceRatio()); + externalAssetOwnerTransfer.setPreviousOwner(effectiveTransfer.getOwner()); return externalAssetOwnerTransfer; } @@ -410,6 +413,9 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW externalAssetOwnerTransfer.setLoanId(loanId); externalAssetOwnerTransfer.setExternalLoanId(externalLoanId); externalAssetOwnerTransfer.setExternalGroupId(getTransferExternalGroupIdFromJson(json)); + + findPreviousAssetOwner(loanId).ifPresent(externalAssetOwnerTransfer::setPreviousOwner); + return externalAssetOwnerTransfer; } @@ -428,9 +434,23 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW externalAssetOwnerTransfer.setLoanId(loanId); externalAssetOwnerTransfer.setExternalLoanId(externalLoanId); externalAssetOwnerTransfer.setExternalGroupId(getTransferExternalGroupIdFromJson(json)); + + findPreviousAssetOwner(loanId).ifPresent(externalAssetOwnerTransfer::setPreviousOwner); + return externalAssetOwnerTransfer; } + private Optional findPreviousAssetOwner(final Long loanId) { + final ExternalTransferData activeTransfer = externalAssetOwnersReadService.retrieveActiveTransferData(loanId, null, null); + + if (activeTransfer != null && activeTransfer.getOwner() != null) { + final String activeOwnerExternalId = activeTransfer.getOwner().getExternalId(); + return externalAssetOwnerRepository.findByExternalId(ExternalIdFactory.produce(activeOwnerExternalId)); + } + + return Optional.empty(); + } + private void validateSaleRequestBody(String apiRequestBodyAsJson) { final Set requestParameters = new HashSet<>(Arrays.asList(ExternalTransferRequestParameters.SETTLEMENT_DATE, ExternalTransferRequestParameters.OWNER_EXTERNAL_ID, ExternalTransferRequestParameters.TRANSFER_EXTERNAL_ID, diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/service/search/mapper/ExternalAssetOwnerSearchDataMapper.java b/fineract-investor/src/main/java/org/apache/fineract/investor/service/search/mapper/ExternalAssetOwnerSearchDataMapper.java index 1a171b4ef..2797cfbd5 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/service/search/mapper/ExternalAssetOwnerSearchDataMapper.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/service/search/mapper/ExternalAssetOwnerSearchDataMapper.java @@ -39,6 +39,7 @@ public interface ExternalAssetOwnerSearchDataMapper { @Mapping(target = "status", source = "source", qualifiedByName = "toStatus") @Mapping(target = "subStatus", source = "source", qualifiedByName = "toSubStatus") @Mapping(target = "details", source = "source", qualifiedByName = "toDetails") + @Mapping(target = "previousOwner", ignore = true) ExternalTransferData map(SearchedExternalAssetOwner source); @Named("toTransferExternalId") diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/service/serialization/serializer/investor/InvestorBusinessEventSerializer.java b/fineract-investor/src/main/java/org/apache/fineract/investor/service/serialization/serializer/investor/InvestorBusinessEventSerializer.java index c9daae352..db6836e1b 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/service/serialization/serializer/investor/InvestorBusinessEventSerializer.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/service/serialization/serializer/investor/InvestorBusinessEventSerializer.java @@ -97,6 +97,8 @@ public class InvestorBusinessEventSerializer extends AbstractBusinessEventWithCu LoanOwnershipTransferDataV1.Builder builder = LoanOwnershipTransferDataV1.newBuilder().setLoanId(transferData.getLoan().getLoanId()) .setLoanExternalId(transferData.getLoan().getExternalId()).setTransferExternalId(transferData.getTransferExternalId()) .setAssetOwnerExternalId(transferData.getOwner().getExternalId()) + .setPreviousOwnerExternalId( + transferData.getPreviousOwner() != null ? transferData.getPreviousOwner().getExternalId() : null) .setTransferExternalGroupId(transferData.getTransferExternalGroupId()) .setPurchasePriceRatio(transferData.getPurchasePriceRatio()).setCurrency(getCurrencyFromEvent(event)) .setSettlementDate(transferData.getSettlementDate().format(DEFAULT_DATE_FORMATTER)) diff --git a/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/module-changelog-master.xml b/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/module-changelog-master.xml index 5e955c664..0a1833ec6 100644 --- a/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/module-changelog-master.xml +++ b/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/module-changelog-master.xml @@ -41,4 +41,5 @@ + diff --git a/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/parts/0020_add_previous_owner_reference.xml b/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/parts/0020_add_previous_owner_reference.xml new file mode 100644 index 000000000..afe8800ca --- /dev/null +++ b/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/parts/0020_add_previous_owner_reference.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + diff --git a/fineract-investor/src/test/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceTest.java b/fineract-investor/src/test/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceTest.java index c058214ba..1276875d5 100644 --- a/fineract-investor/src/test/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceTest.java +++ b/fineract-investor/src/test/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceTest.java @@ -864,6 +864,9 @@ public class ExternalAssetOwnersWriteServiceTest { @Mock private ConfigurationDomainService configurationDomainService; + @Mock + private ExternalAssetOwnersReadService externalAssetOwnersReadService; + @InjectMocks private ExternalAssetOwnersWriteServiceImpl externalAssetOwnersWriteServiceImpl; @@ -934,6 +937,7 @@ public class ExternalAssetOwnersWriteServiceTest { .thenReturn(List.of("ACTIVE", "TRANSFER_IN_PROGRESS", "TRANSFER_ON_HOLD")); lenient().when(configurationDomainService.getAllowedLoanStatusesOfDelayedSettlementForExternalAssetTransfer()) .thenReturn(List.of("ACTIVE", "TRANSFER_IN_PROGRESS", "TRANSFER_ON_HOLD", "OVERPAID", "CLOSED_OBLIGATIONS_MET")); + lenient().when(externalAssetOwnersReadService.retrieveActiveTransferData(any(Long.class), any(), any())).thenReturn(null); } } diff --git a/fineract-investor/src/test/java/org/apache/fineract/investor/service/serialization/serializer/investor/InvestorBusinessEventSerializerTest.java b/fineract-investor/src/test/java/org/apache/fineract/investor/service/serialization/serializer/investor/InvestorBusinessEventSerializerTest.java index 07fad8281..93485af04 100644 --- a/fineract-investor/src/test/java/org/apache/fineract/investor/service/serialization/serializer/investor/InvestorBusinessEventSerializerTest.java +++ b/fineract-investor/src/test/java/org/apache/fineract/investor/service/serialization/serializer/investor/InvestorBusinessEventSerializerTest.java @@ -183,6 +183,7 @@ public class InvestorBusinessEventSerializerTest { assertEquals(1, result.getCurrency().getInMultiplesOf()); assertEquals("1.0", result.getPurchasePriceRatio()); assertEquals(ASSET_OWNER_EXTERNAL_ID, result.getAssetOwnerExternalId()); + assertEquals("previous-owner-123", result.getPreviousOwnerExternalId()); assertEquals(LOAN_EXTERNAL_ID, result.getLoanExternalId()); assertEquals(TRANSFER_EXTERNAL_ID.getValue(), result.getTransferExternalId()); assertEquals(LOAN_ID, result.getLoanId()); @@ -232,6 +233,7 @@ public class InvestorBusinessEventSerializerTest { ExternalTransferData data = new ExternalTransferData(); data.setOwner(new ExternalTransferOwnerData(ASSET_OWNER_EXTERNAL_ID)); + data.setPreviousOwner(new ExternalTransferOwnerData("previous-owner-123")); data.setStatus(status); data.setSubStatus(subStatus); data.setTransferId(123L);