This is an automated email from the ASF dual-hosted git repository.
adamsaghy 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 f045752d7 FINERACT-1926: Fineract Asset Externalization models - [x]
JPA Model changes - [x] External Asset Owner Platform services - [x] External
Asset Owner Swagger - [x] Core changes
f045752d7 is described below
commit f045752d7ded5bd476218cb5099104ebd9cfa72b
Author: Janos Haber <[email protected]>
AuthorDate: Fri May 19 08:05:41 2023 +0200
FINERACT-1926: Fineract Asset Externalization models
- [x] JPA Model changes
- [x] External Asset Owner Platform services
- [x] External Asset Owner Swagger
- [x] Core changes
---
.../core/config/MapstructMapperConfig.java | 4 +-
.../mapper/support/ExternalIdMapper.java | 2 +-
.../api/ExternalAssetOwnersApiResource.java | 33 ++++++--
.../api/ExternalAssetOwnersApiResourceSwagger.java | 90 ++++++++++++++++++++++
.../investor/data/ExternalTransferData.java | 20 +++--
.../investor/domain/ExternalAssetOwner.java | 3 +-
.../domain/ExternalAssetOwnerTransfer.java | 9 ++-
.../ExternalAssetOwnerTransferLoanMapping.java | 2 +-
.../ExternalAssetOwnerTransferRepository.java | 6 ++
.../ExternalAssetOwnersReadService.java} | 10 +--
.../ExternalAssetOwnersReadServiceImpl.java | 44 +++++++++++
.../service/ExternalAssetOwnersTransferMapper.java | 46 +++++++++++
.../module/investor/parts/0003_asset_schemas.xml | 47 +++++++++++
.../mapper/support/AvroMapperConfig.java | 2 +-
14 files changed, 291 insertions(+), 27 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/MapstructMapperConfig.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/MapstructMapperConfig.java
similarity index 86%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/MapstructMapperConfig.java
rename to
fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/MapstructMapperConfig.java
index 653659c2d..705d5f6a6 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/MapstructMapperConfig.java
+++
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/MapstructMapperConfig.java
@@ -18,10 +18,12 @@
*/
package org.apache.fineract.infrastructure.core.config;
+import
org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.ExternalIdMapper;
import org.mapstruct.Builder;
import org.mapstruct.MapperConfig;
import org.mapstruct.MappingConstants;
import org.mapstruct.ReportingPolicy;
-@MapperConfig(componentModel = MappingConstants.ComponentModel.SPRING,
unmappedTargetPolicy = ReportingPolicy.ERROR, builder = @Builder(disableBuilder
= true))
+@MapperConfig(componentModel = MappingConstants.ComponentModel.SPRING,
unmappedTargetPolicy = ReportingPolicy.ERROR, builder = @Builder(disableBuilder
= true), uses = {
+ ExternalIdMapper.class })
public class MapstructMapperConfig {}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroExternalIdMapper.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/ExternalIdMapper.java
similarity index 97%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroExternalIdMapper.java
rename to
fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/ExternalIdMapper.java
index 6900a92d3..0bb3354ad 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroExternalIdMapper.java
+++
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/ExternalIdMapper.java
@@ -22,7 +22,7 @@ import
org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.springframework.stereotype.Component;
@Component
-public class AvroExternalIdMapper {
+public class ExternalIdMapper {
public String mapExternalId(ExternalId source) {
if (source == null) {
diff --git
a/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
b/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
index 09744ce19..6c9f55bac 100644
---
a/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
+++
b/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
@@ -18,8 +18,14 @@
*/
package org.apache.fineract.investor.api;
+import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -27,10 +33,17 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.NotImplementedException;
+import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
+import
org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
+import
org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import
org.apache.fineract.infrastructure.security.service.PlatformUserRightsContext;
+import org.apache.fineract.investor.data.ExternalTransferData;
+import org.apache.fineract.investor.service.ExternalAssetOwnersReadService;
import org.springframework.stereotype.Component;
@Path("/v1/external-asset-owners")
@@ -40,6 +53,9 @@ import org.springframework.stereotype.Component;
public class ExternalAssetOwnersApiResource {
private final PlatformUserRightsContext platformUserRightsContext;
+ private final ExternalAssetOwnersReadService
externalAssetOwnersReadService;
+ private final ApiRequestParameterHelper apiRequestParameterHelper;
+ private final DefaultToApiJsonSerializer<ExternalTransferData>
apiJsonSerializerService;
@POST
@Path("/transfers/loans/{loanId}")
@@ -54,7 +70,7 @@ public class ExternalAssetOwnersApiResource {
}
@POST
- @Path("/transfers/loans//external-id/{loanExternalId}")
+ @Path("/transfers/loans/external-id/{loanExternalId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String
transferRequestWithLoanExternalId(@PathParam("loanExternalId") final Long
loanId,
@@ -68,12 +84,19 @@ public class ExternalAssetOwnersApiResource {
@GET
@Path("/transfers")
@Produces({ MediaType.APPLICATION_JSON })
+ @Operation(tags = {
+ "External Asset Owners" }, summary = "Retrieve External Asset
Owner Transfers", description = "Retrieve External Asset Owner Transfer items
by transferExternalId, loanId or loanExternalId")
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "OK", content =
@Content(schema = @Schema(implementation =
ExternalAssetOwnersApiResourceSwagger.GetExternalTransferResponse.class))) })
public String getTransfer(
@QueryParam("transferExternalId") @Parameter(description =
"transferExternalId") final String transferExternalId,
- @QueryParam("loanId") @Parameter(description = "loanId") final
String loanId,
- @QueryParam("loanExternalId") @Parameter(description =
"loanExternalId") final String loanExternalId) {
+ @QueryParam("loanId") @Parameter(description = "loanId") final
Long loanId,
+ @QueryParam("loanExternalId") @Parameter(description =
"loanExternalId") final String loanExternalId,
+ @Context final UriInfo uriInfo) {
platformUserRightsContext.isAuthenticated();
-
- throw new NotImplementedException("Not implemented yet");
+ List<ExternalTransferData> transferDataList =
externalAssetOwnersReadService.retrieveTransferData(loanId, loanExternalId,
+ transferExternalId);
+ ApiRequestJsonSerializationSettings settings =
this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+ return apiJsonSerializerService.serialize(settings, transferDataList);
}
}
diff --git
a/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResourceSwagger.java
b/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResourceSwagger.java
new file mode 100644
index 000000000..43976241e
--- /dev/null
+++
b/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResourceSwagger.java
@@ -0,0 +1,90 @@
+/**
+ * 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.api;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Set;
+import org.apache.fineract.investor.data.ExternalTransferStatus;
+
+@SuppressWarnings({ "MemberName" })
+final class ExternalAssetOwnersApiResourceSwagger {
+
+ private ExternalAssetOwnersApiResourceSwagger() {}
+
+ @Schema(description = "ExternalTransferResponse")
+ public static final class GetExternalTransferResponse {
+
+ private GetExternalTransferResponse() {}
+
+ static final class GetExternalTransferPageItems {
+
+ private GetExternalTransferPageItems() {}
+
+ static final class GetExternalTransferOwner {
+
+ private GetExternalTransferOwner() {}
+
+ @Schema(example = "e1156fbe-38bb-42f8-b491-fca02075f40e")
+ public String externalId;
+ }
+
+ static final class GetExternalTransferLoan {
+
+ private GetExternalTransferLoan() {}
+
+ @Schema(example = "1")
+ public Long loanId;
+
+ @Schema(example = "e1156fbe-38bb-42f8-b491-fca02075f40e")
+ public String externalId;
+ }
+
+ @Schema(example = "1")
+ public Long transferId;
+
+ public GetExternalTransferOwner owner;
+
+ public GetExternalTransferLoan loan;
+
+ @Schema(example = "e1156fbe-38bb-42f8-b491-fca02075f40e")
+ public String transferExternalId;
+
+ @Schema(example = "1")
+ public BigDecimal purchasePriceRatio;
+
+ @Schema(example = "[2023, 5, 23]")
+ public LocalDate settlementDate;
+
+ @Schema(example = "PENDING")
+ public ExternalTransferStatus status;
+
+ @Schema(example = "[2023, 5, 1]")
+ public LocalDate effectiveFrom;
+
+ @Schema(example = "[2023, 5, 23]")
+ public LocalDate effectiveTo;
+ }
+
+ @Schema(example = "20")
+ public Integer totalFilteredRecords;
+ public Set<GetExternalTransferPageItems> pageItems;
+ }
+}
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 83dec6e34..23f2bb861 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
@@ -25,15 +25,13 @@ import lombok.Data;
@Data
public class ExternalTransferData {
- private final Long transferId;
- private final ExternalTransferOwnerData owner;
- private final ExternalTransferLoanMappingData loan;
- private final String transferExternalId;
- private final BigDecimal purchasePriceRatio;
- private final LocalDate settlementDate;
- private final ExternalTransferStatus status;
- private final LocalDate effectiveFrom;
- private final LocalDate effectiveTo;
- private final String dateFormat;
- private final String locale;
+ private Long transferId;
+ private ExternalTransferOwnerData owner;
+ private ExternalTransferLoanMappingData loan;
+ private String transferExternalId;
+ private BigDecimal purchasePriceRatio;
+ private LocalDate settlementDate;
+ private ExternalTransferStatus status;
+ private LocalDate effectiveFrom;
+ private LocalDate effectiveTo;
}
diff --git
a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwner.java
b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwner.java
index 774018991..fd7c4d3de 100644
---
a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwner.java
+++
b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwner.java
@@ -25,6 +25,7 @@ import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
@Getter
@Setter
@@ -34,6 +35,6 @@ import lombok.Setter;
public class ExternalAssetOwner extends AbstractAuditableWithUTCDateTimeCustom
{
@Column(name = "external_id", nullable = false, length = 100, unique =
true)
- private String externalId;
+ private ExternalId externalId;
}
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 10108fcba..e292ba6c0 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
@@ -29,6 +29,7 @@ import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
@Getter
@Setter
@@ -45,7 +46,7 @@ public class ExternalAssetOwnerTransfer extends
AbstractAuditableWithUTCDateTime
private ExternalAssetOwner owner;
@Column(name = "external_id", length = 100)
- private String externalId;
+ private ExternalId externalId;
@Column(name = "status", length = 50)
private String status;
@@ -62,4 +63,10 @@ public class ExternalAssetOwnerTransfer extends
AbstractAuditableWithUTCDateTime
@Column(name = "effective_date_to")
private LocalDate effectiveDateTo;
+ @Column(name = "loan_id", nullable = false)
+ private Long loanId;
+
+ @Column(name = "external_loan_id", length = 100)
+ private ExternalId externalLoanId;
+
}
diff --git
a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferLoanMapping.java
b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferLoanMapping.java
index 86aea1f14..c0add21d2 100644
---
a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferLoanMapping.java
+++
b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferLoanMapping.java
@@ -39,7 +39,7 @@ public class ExternalAssetOwnerTransferLoanMapping extends
AbstractAuditableWith
private Long loanId;
@ManyToOne
- @JoinColumn(name = "owner_transfer_id", insertable = false, updatable =
false)
+ @JoinColumn(name = "owner_transfer_id")
private ExternalAssetOwnerTransfer ownerTransfer;
}
diff --git
a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
index 68675d870..556c33fe6 100644
---
a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
+++
b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
@@ -18,10 +18,16 @@
*/
package org.apache.fineract.investor.domain;
+import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
public interface ExternalAssetOwnerTransferRepository
extends JpaRepository<ExternalAssetOwnerTransfer, Long>,
JpaSpecificationExecutor<ExternalAssetOwnerTransfer> {
+ @Query("select e from ExternalAssetOwnerTransfer e where (:loanId is null
or e.loanId = :loanId) and (:loanExternalId is null or e.externalLoanId =
:loanExternalId) and (:transferExternalId is null or e.externalId =
:transferExternalId)")
+ List<ExternalAssetOwnerTransfer> findAllByIncomingId(@Param("loanId") Long
loanId, @Param("loanExternalId") String loanExternalId,
+ @Param("transferExternalId") String transferExternalId);
}
diff --git
a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersReadService.java
similarity index 69%
copy from
fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
copy to
fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersReadService.java
index 68675d870..8f5f56d85 100644
---
a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
+++
b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersReadService.java
@@ -16,12 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.investor.domain;
+package org.apache.fineract.investor.service;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import java.util.List;
+import org.apache.fineract.investor.data.ExternalTransferData;
-public interface ExternalAssetOwnerTransferRepository
- extends JpaRepository<ExternalAssetOwnerTransfer, Long>,
JpaSpecificationExecutor<ExternalAssetOwnerTransfer> {
+public interface ExternalAssetOwnersReadService {
+ List<ExternalTransferData> retrieveTransferData(Long loanId, String
externalLoanId, String transferExternalId);
}
diff --git
a/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersReadServiceImpl.java
b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersReadServiceImpl.java
new file mode 100644
index 000000000..b5b61db38
--- /dev/null
+++
b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersReadServiceImpl.java
@@ -0,0 +1,44 @@
+/**
+ * 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.util.List;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.investor.data.ExternalTransferData;
+import org.apache.fineract.investor.domain.ExternalAssetOwnerTransfer;
+import
org.apache.fineract.investor.domain.ExternalAssetOwnerTransferRepository;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@RequiredArgsConstructor
+@Transactional(readOnly = true)
+public class ExternalAssetOwnersReadServiceImpl implements
ExternalAssetOwnersReadService {
+
+ private final ExternalAssetOwnerTransferRepository
externalAssetOwnerTransferRepository;
+ private final ExternalAssetOwnersTransferMapper mapper;
+ private final ExternalAssetOwnersTransferMapper
externalAssetOwnersTransferMapper;
+
+ @Override
+ public List<ExternalTransferData> retrieveTransferData(Long loanId, String
externalLoanId, String transferExternalId) {
+ List<ExternalAssetOwnerTransfer> result =
externalAssetOwnerTransferRepository.findAllByIncomingId(loanId, externalLoanId,
+ transferExternalId);
+ return result.stream().map(mapper::mapTransfer).toList();
+ }
+}
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
new file mode 100644
index 000000000..a29ba4167
--- /dev/null
+++
b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersTransferMapper.java
@@ -0,0 +1,46 @@
+/**
+ * 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 org.apache.fineract.infrastructure.core.config.MapstructMapperConfig;
+import org.apache.fineract.investor.data.ExternalTransferData;
+import org.apache.fineract.investor.data.ExternalTransferOwnerData;
+import org.apache.fineract.investor.domain.ExternalAssetOwner;
+import org.apache.fineract.investor.domain.ExternalAssetOwnerTransfer;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+@Mapper(config = MapstructMapperConfig.class)
+public interface ExternalAssetOwnersTransferMapper {
+
+ @Mapping(target = "transferId", source = "id")
+ @Mapping(target = "owner", source = "owner")
+ @Mapping(target = "loan.loanId", source = "loanId")
+ @Mapping(target = "loan.externalId", source = "externalLoanId")
+ @Mapping(target = "transferExternalId", source = "externalId")
+ @Mapping(target = "effectiveFrom", source = "effectiveDateFrom")
+ @Mapping(target = "effectiveTo", source = "effectiveDateTo")
+ @Mapping(target = "purchasePriceRatio", source = "purchasePriceRatio")
+ @Mapping(target = "settlementDate", source = "settlementDate")
+ @Mapping(target = "status", source = "status")
+ ExternalTransferData mapTransfer(ExternalAssetOwnerTransfer source);
+
+ ExternalTransferOwnerData mapOwner(ExternalAssetOwner source);
+
+}
diff --git
a/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/parts/0003_asset_schemas.xml
b/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/parts/0003_asset_schemas.xml
new file mode 100644
index 000000000..bd12acd21
--- /dev/null
+++
b/fineract-investor/src/main/resources/db/changelog/tenant/module/investor/parts/0003_asset_schemas.xml
@@ -0,0 +1,47 @@
+<?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
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
+
+ <!-- Create the m_external_asset_owner table -->
+ <changeSet author="fineract" id="1" context="postgresql">
+
+ <addColumn tableName="m_external_asset_owner_transfer">
+ <column name="external_loan_id" type="varchar(100)"/>
+ <column name="loan_id" type="bigint" remarks="Loan ID">
+ <constraints nullable="false"/>
+ </column>
+ </addColumn>
+ </changeSet>
+ <changeSet author="fineract" id="2" context="postgresql">
+
+ <addForeignKeyConstraint baseColumnNames="loan_id"
+ baseTableName="m_external_asset_owner_transfer"
+ constraintName="FK_external_asset_owner_transfer_loan_id"
deferrable="false"
+ initiallyDeferred="false"
+ onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="id"
+ referencedTableName="m_loan" validate="true"/>
+
+ </changeSet>
+
+</databaseChangeLog>
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroMapperConfig.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroMapperConfig.java
index 8ee66be99..7de3ca674 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroMapperConfig.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroMapperConfig.java
@@ -24,5 +24,5 @@ import org.mapstruct.MappingConstants;
import org.mapstruct.ReportingPolicy;
@MapperConfig(componentModel = MappingConstants.ComponentModel.SPRING,
unmappedTargetPolicy = ReportingPolicy.ERROR, builder = @Builder(disableBuilder
= true), uses = {
- AvroDateTimeMapper.class, AvroMonthDayMapper.class,
AvroExternalIdMapper.class })
+ AvroDateTimeMapper.class, AvroMonthDayMapper.class,
ExternalIdMapper.class })
public class AvroMapperConfig {}