FINERACT-1926: Fineract Asset Externalization models

- [x] JPA Model changes
- [x] External Asset Owner Platform services
- [x] External Asset Owner Swagger
- [x] Core changes
This commit is contained in:
Janos Haber
2023-05-19 12:41:21 +02:00
committed by Adam Saghy
parent f647d10a01
commit f045752d7d
14 changed files with 313 additions and 22 deletions
@@ -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 {}
@@ -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) {
@@ -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);
}
}
@@ -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;
}
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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);
}
@@ -0,0 +1,27 @@
/**
* 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 org.apache.fineract.investor.data.ExternalTransferData;
public interface ExternalAssetOwnersReadService {
List<ExternalTransferData> retrieveTransferData(Long loanId, String externalLoanId, String transferExternalId);
}
@@ -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();
}
}
@@ -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);
}
@@ -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>
@@ -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 {}