FINERACT-2203: LoanTransactionsApi add getLoanTransactions
This commit is contained in:
+11
@@ -20,11 +20,15 @@
|
||||
package org.apache.fineract.infrastructure.core.jersey;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.ws.rs.ApplicationPath;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
import org.apache.fineract.infrastructure.core.api.jersey.PageableParamProvider;
|
||||
import org.glassfish.jersey.internal.inject.AbstractBinder;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.glassfish.jersey.server.ServerProperties;
|
||||
import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -35,6 +39,13 @@ public class JerseyConfig extends ResourceConfig {
|
||||
|
||||
JerseyConfig() {
|
||||
register(org.glassfish.jersey.media.multipart.MultiPartFeature.class);
|
||||
register(new AbstractBinder() {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(PageableParamProvider.class).to(ValueParamProvider.class).in(Singleton.class);
|
||||
}
|
||||
});
|
||||
property(ServerProperties.WADL_FEATURE_DISABLE, true);
|
||||
}
|
||||
|
||||
|
||||
+109
@@ -45,12 +45,14 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.api.DateParam;
|
||||
import org.apache.fineract.infrastructure.core.api.jersey.Pagination;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.DateFormat;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
@@ -64,12 +66,15 @@ import org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanRepaymentScheduleInstallmentData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanTransactionTypeException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanChargePaidByReadService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
import org.apache.fineract.portfolio.paymenttype.service.PaymentTypeReadPlatformService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/loans")
|
||||
@@ -224,6 +229,40 @@ public class LoanTransactionsApiResource {
|
||||
return retrieveTransaction(null, loanExternalId, null, externalTransactionId, uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{loanId}/transactions")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Transactions", description = "Retrieves transactions of a loan")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsResponse.class))) })
|
||||
public Page<LoanTransactionData> retrieveTransactionsByLoanId(
|
||||
@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@QueryParam("excludedTypes") @Parameter(description = "excludedTypes", in = ParameterIn.QUERY, schema = @Schema(enumAsRef = true)) final List<LoanTransactionApiConstants.TransactionType> excludedTypes,
|
||||
@QueryParam("page") @Parameter(description = "page") final Integer page,
|
||||
@QueryParam("size") @Parameter(description = "size") final Integer size,
|
||||
@QueryParam("sort") @Parameter(description = "sort") final String sort, @Parameter(hidden = true) @Pagination Pageable pageable,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveTransactions(loanId, null, excludedTypes, pageable, uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}/transactions")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Transactions", description = "Retrieves transactions of a loan")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsResponse.class))) })
|
||||
public Page<LoanTransactionData> retrieveTransactionsByExternalLoanId(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanId", required = true) final String loanExternalId,
|
||||
@QueryParam("excludedTypes") @Parameter(description = "excludedTypes", in = ParameterIn.QUERY, schema = @Schema(enumAsRef = true)) final List<LoanTransactionApiConstants.TransactionType> excludedTypes,
|
||||
@QueryParam("page") @Parameter(description = "page") final Integer page,
|
||||
@QueryParam("size") @Parameter(description = "size") final Integer size,
|
||||
@QueryParam("sort") @Parameter(description = "sort") final String sort, @Parameter(hidden = true) @Pagination Pageable pageable,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveTransactions(null, loanExternalId, excludedTypes, pageable, uriInfo);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{loanId}/transactions")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -439,6 +478,59 @@ public class LoanTransactionsApiResource {
|
||||
return this.toApiJsonSerializer.serialize(settings, transactionData, this.responseDataParameters);
|
||||
}
|
||||
|
||||
private Page<LoanTransactionData> retrieveTransactions(final Long loanId, final String loanExternalIdStr,
|
||||
final List<LoanTransactionApiConstants.TransactionType> excludedTypes, Pageable pageable, final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
Long resolvedLoanId = getResolvedLoanIdWithExistsCheck(loanId, loanExternalId);
|
||||
|
||||
Set<LoanTransactionType> excludedTransactionTypes = new HashSet<>();
|
||||
if (CollectionUtils.isNotEmpty(excludedTypes)) {
|
||||
excludedTypes.forEach(x -> excludedTransactionTypes.add(transactionTypeFromParam(x)));
|
||||
}
|
||||
|
||||
return loanReadPlatformService.retrieveLoanTransactions(resolvedLoanId, excludedTransactionTypes, pageable);
|
||||
}
|
||||
|
||||
private LoanTransactionType transactionTypeFromParam(LoanTransactionApiConstants.TransactionType transactionTypeParam) {
|
||||
return switch (transactionTypeParam) {
|
||||
case disbursement -> LoanTransactionType.DISBURSEMENT;
|
||||
case repayment -> LoanTransactionType.REPAYMENT;
|
||||
case waiver -> LoanTransactionType.WAIVE_INTEREST;
|
||||
case repaymentAtDisbursement -> LoanTransactionType.REPAYMENT_AT_DISBURSEMENT;
|
||||
case writeOff -> LoanTransactionType.WRITEOFF;
|
||||
case markedForRescheduling -> LoanTransactionType.MARKED_FOR_RESCHEDULING;
|
||||
case recoveryRepayment -> LoanTransactionType.RECOVERY_REPAYMENT;
|
||||
case waiveCharges -> LoanTransactionType.WAIVE_CHARGES;
|
||||
case accrual -> LoanTransactionType.ACCRUAL;
|
||||
case initiateTransfer -> LoanTransactionType.INITIATE_TRANSFER;
|
||||
case approveTransfer -> LoanTransactionType.APPROVE_TRANSFER;
|
||||
case withdrawTransfer -> LoanTransactionType.WITHDRAW_TRANSFER;
|
||||
case rejectTransfer -> LoanTransactionType.REJECT_TRANSFER;
|
||||
case refund -> LoanTransactionType.REFUND;
|
||||
case chargePayment -> LoanTransactionType.CHARGE_PAYMENT;
|
||||
case incomePosting -> LoanTransactionType.INCOME_POSTING;
|
||||
case creditBalanceRefund -> LoanTransactionType.CREDIT_BALANCE_REFUND;
|
||||
case merchantIssuedRefund -> LoanTransactionType.MERCHANT_ISSUED_REFUND;
|
||||
case payoutRefund -> LoanTransactionType.PAYOUT_REFUND;
|
||||
case goodwillCredit -> LoanTransactionType.GOODWILL_CREDIT;
|
||||
case chargeRefund -> LoanTransactionType.CHARGE_REFUND;
|
||||
case chargeback -> LoanTransactionType.CHARGEBACK;
|
||||
case chargeAdjustment -> LoanTransactionType.CHARGE_ADJUSTMENT;
|
||||
case chargeOff -> LoanTransactionType.CHARGE_OFF;
|
||||
case reAge -> LoanTransactionType.REAGE;
|
||||
case reAmortize -> LoanTransactionType.REAMORTIZE;
|
||||
case interestPaymentWaiver -> LoanTransactionType.INTEREST_PAYMENT_WAIVER;
|
||||
case accrualActivity -> LoanTransactionType.ACCRUAL_ACTIVITY;
|
||||
case interestRefund -> LoanTransactionType.INTEREST_REFUND;
|
||||
case accrualAdjustment -> LoanTransactionType.ACCRUAL_ADJUSTMENT;
|
||||
default ->
|
||||
throw new InvalidLoanTransactionTypeException("transaction", transactionTypeParam.name(), "Unknown transaction type");
|
||||
};
|
||||
}
|
||||
|
||||
private String executeTransaction(final Long loanId, final String loanExternalIdStr, final String commandParam,
|
||||
final String apiRequestBodyAsJson) {
|
||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
@@ -637,4 +729,21 @@ public class LoanTransactionsApiResource {
|
||||
}
|
||||
return resolvedLoanId;
|
||||
}
|
||||
|
||||
private Long getResolvedLoanIdWithExistsCheck(final Long loanId, final ExternalId loanExternalId) {
|
||||
if (loanId != null) {
|
||||
if (!loanReadPlatformService.existsByLoanId(loanId)) {
|
||||
throw new LoanNotFoundException(loanId);
|
||||
}
|
||||
return loanId;
|
||||
} else if (loanExternalId != null) {
|
||||
final Long resolvedLoanId = loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId);
|
||||
if (resolvedLoanId == null) {
|
||||
throw new LoanNotFoundException(loanExternalId);
|
||||
}
|
||||
return resolvedLoanId;
|
||||
} else {
|
||||
throw new IllegalArgumentException("loanId and loanExternalId cannot be both null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -18,9 +18,11 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
||||
@@ -39,6 +41,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
public interface LoanReadPlatformService {
|
||||
|
||||
@@ -51,6 +54,9 @@ public interface LoanReadPlatformService {
|
||||
|
||||
Collection<LoanTransactionData> retrieveLoanTransactions(Long loanId);
|
||||
|
||||
org.springframework.data.domain.Page<LoanTransactionData> retrieveLoanTransactions(@NotNull Long loanId,
|
||||
Set<LoanTransactionType> excludedTransactionTypes, Pageable pageable);
|
||||
|
||||
LoanAccountData retrieveTemplateWithClientAndProductDetails(Long clientId, Long productId);
|
||||
|
||||
LoanAccountData retrieveTemplateWithGroupAndProductDetails(Long groupId, Long productId);
|
||||
@@ -143,4 +149,6 @@ public interface LoanReadPlatformService {
|
||||
Long retrieveLoanIdByExternalId(ExternalId externalId);
|
||||
|
||||
List<Long> retrieveLoanIdsByExternalIds(List<ExternalId> externalIds);
|
||||
|
||||
boolean existsByLoanId(Long loanId);
|
||||
}
|
||||
|
||||
+30
@@ -21,6 +21,8 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations.interestType;
|
||||
|
||||
import jakarta.persistence.criteria.Join;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@@ -120,6 +122,7 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleP
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanTransactionMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanForeclosureValidator;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.TransactionProcessingStrategyData;
|
||||
@@ -134,6 +137,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
@@ -174,6 +178,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
private final LoanChargePaidByReadService loanChargePaidByReadService;
|
||||
private final LoanTransactionRelationReadService loanTransactionRelationReadService;
|
||||
private final LoanForeclosureValidator loanForeclosureValidator;
|
||||
private final LoanTransactionMapper loanTransactionMapper;
|
||||
|
||||
@Override
|
||||
public LoanAccountData retrieveOne(final Long loanId) {
|
||||
@@ -598,6 +603,27 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.springframework.data.domain.Page<LoanTransactionData> retrieveLoanTransactions(
|
||||
@jakarta.validation.constraints.NotNull Long loanId, Set<LoanTransactionType> excludedTransactionTypes, Pageable pageable) {
|
||||
final org.springframework.data.domain.Page<LoanTransaction> transactionPage = loanTransactionRepository
|
||||
.findAll((root, query, builder) -> {
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
final Join<Object, Object> loanjoin = root.join("loan");
|
||||
predicates.add(builder.equal(loanjoin.get("id"), loanId));
|
||||
|
||||
if (excludedTransactionTypes != null && !excludedTransactionTypes.isEmpty()) {
|
||||
final List<Integer> excludedTransactionTypeValues = excludedTransactionTypes.stream()
|
||||
.map(LoanTransactionType::getValue).toList();
|
||||
predicates.add(builder.not(root.get("typeOf").in(excludedTransactionTypeValues)));
|
||||
}
|
||||
return builder.and(predicates.toArray(new Predicate[] {}));
|
||||
}, pageable);
|
||||
|
||||
return transactionPage.map(loanTransactionMapper::mapLoanTransaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLoanIdByLoanExternalId(String externalId) {
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(externalId);
|
||||
@@ -2182,4 +2208,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
return loanRepositoryWrapper.findIdByExternalIds(externalIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByLoanId(Long loanId) {
|
||||
return loanRepositoryWrapper.existsByLoanId(loanId);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -85,6 +85,7 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanSchedu
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleHistoryWritePlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanChargeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanCollateralManagementMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanTransactionMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanTermVariationsRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanApplicationTransitionValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanApplicationValidator;
|
||||
@@ -325,7 +326,7 @@ public class LoanAccountConfiguration {
|
||||
ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator,
|
||||
DelinquencyReadPlatformService delinquencyReadPlatformService, LoanTransactionRepository loanTransactionRepository,
|
||||
LoanChargePaidByReadService loanChargePaidByReadService, LoanTransactionRelationReadService loanTransactionRelationReadService,
|
||||
LoanForeclosureValidator loanForeclosureValidator) {
|
||||
LoanForeclosureValidator loanForeclosureValidator, LoanTransactionMapper loanTransactionMapper) {
|
||||
return new LoanReadPlatformServiceImpl(jdbcTemplate, context, loanRepositoryWrapper, applicationCurrencyRepository,
|
||||
loanProductReadPlatformService, clientReadPlatformService, groupReadPlatformService, loanDropdownReadPlatformService,
|
||||
fundReadPlatformService, chargeReadPlatformService, codeValueReadPlatformService, calendarReadPlatformService,
|
||||
@@ -333,7 +334,7 @@ public class LoanAccountConfiguration {
|
||||
loanRepaymentScheduleTransactionProcessorFactory, floatingRatesReadPlatformService, loanUtilService,
|
||||
configurationDomainService, accountDetailsReadPlatformService, columnValidator, sqlGenerator,
|
||||
delinquencyReadPlatformService, loanTransactionRepository, loanChargePaidByReadService, loanTransactionRelationReadService,
|
||||
loanForeclosureValidator);
|
||||
loanForeclosureValidator, loanTransactionMapper);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
Reference in New Issue
Block a user