FINERACT-2326: Not implemented exception handling
This commit is contained in:
+10
@@ -25,6 +25,7 @@ import static org.apache.http.HttpStatus.SC_FORBIDDEN;
|
|||||||
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
|
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
|
||||||
import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
|
import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
|
||||||
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
|
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
|
||||||
|
import static org.apache.http.HttpStatus.SC_NOT_IMPLEMENTED;
|
||||||
import static org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE;
|
import static org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE;
|
||||||
import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
|
import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
|
||||||
|
|
||||||
@@ -139,6 +140,15 @@ public class ApiGlobalErrorResponse {
|
|||||||
"Errors contain reason for domain rule violation.", errors);
|
"Errors contain reason for domain rule violation.", errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ApiGlobalErrorResponse notImplemented(final String globalisationMessageCode, final String defaultUserMessage,
|
||||||
|
final Object... defaultUserMessageArgs) {
|
||||||
|
final List<ApiParameterError> errors = new ArrayList<>();
|
||||||
|
errors.add(ApiParameterError.generalError(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs));
|
||||||
|
|
||||||
|
return create(SC_NOT_IMPLEMENTED, "validation.msg.not.implemented", "Request was understood but not implemented.",
|
||||||
|
"Errors contain reason for not implemented violation.", errors);
|
||||||
|
}
|
||||||
|
|
||||||
public static ApiGlobalErrorResponse dataIntegrityError(final String globalisationMessageCode, final String defaultUserMessage,
|
public static ApiGlobalErrorResponse dataIntegrityError(final String globalisationMessageCode, final String defaultUserMessage,
|
||||||
final String parameterName, final Object... defaultUserMessageArgs) {
|
final String parameterName, final Object... defaultUserMessageArgs) {
|
||||||
final List<ApiParameterError> errors = new ArrayList<>();
|
final List<ApiParameterError> errors = new ArrayList<>();
|
||||||
|
|||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* 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.infrastructure.core.exceptionmapper;
|
||||||
|
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import jakarta.ws.rs.core.Response.Status;
|
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper;
|
||||||
|
import jakarta.ws.rs.ext.Provider;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse;
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link ExceptionMapper} to map {@link UnsupportedOperationException} thrown by platform into a HTTP API friendly
|
||||||
|
* format.
|
||||||
|
*
|
||||||
|
* The {@link UnsupportedOperationException} is thrown when an operation was not yet implemented.
|
||||||
|
*/
|
||||||
|
@Provider
|
||||||
|
@Component
|
||||||
|
@Scope("singleton")
|
||||||
|
@Slf4j
|
||||||
|
public class UnsupporterOperationExceptionMapper implements FineractExceptionMapper, ExceptionMapper<UnsupportedOperationException> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response toResponse(final UnsupportedOperationException exception) {
|
||||||
|
log.warn("Exception occurred", ErrorHandler.findMostSpecificException(exception));
|
||||||
|
final ApiGlobalErrorResponse notFoundErrorResponse = ApiGlobalErrorResponse.notImplemented("not.implemented",
|
||||||
|
exception.getMessage());
|
||||||
|
return Response.status(Status.NOT_IMPLEMENTED).entity(notFoundErrorResponse).type(MediaType.APPLICATION_JSON).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int errorCode() {
|
||||||
|
return 5010;
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -538,4 +538,21 @@ public class LoanReAgingStepDef extends AbstractStepDef {
|
|||||||
}
|
}
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@When("Admin creates a Loan re-aging transaction by Loan external ID with the following data, but fails with {int} error code:")
|
||||||
|
public void adminCreatesALoanReAgingTransactionByLoanExternalIDWithTheFollowingDataButFailsWithErrorCode(int errorCode,
|
||||||
|
DataTable table) {
|
||||||
|
PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
String loanExternalId = loanResponse.getResourceExternalId();
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest reAgingRequest = setReAgeingRequestProperties(//
|
||||||
|
LoanRequestFactory.defaultReAgingRequest(), //
|
||||||
|
table.row(0), //
|
||||||
|
table.row(1) //
|
||||||
|
);
|
||||||
|
|
||||||
|
CallFailedRuntimeException response = fail(() -> fineractClient.loanTransactions().executeLoanTransaction1(loanExternalId,
|
||||||
|
reAgingRequest, Map.<String, Object>of("command", "reAge")));
|
||||||
|
assertThat(response.getStatus()).isEqualTo(errorCode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12320,7 +12320,6 @@ Feature: LoanReAging
|
|||||||
| 01 February 2024 | Repayment | 17.01 | 16.43 | 0.58 | 0.0 | 0.0 | 83.57 | false | false |
|
| 01 February 2024 | Repayment | 17.01 | 16.43 | 0.58 | 0.0 | 0.0 | 83.57 | false | false |
|
||||||
| 01 March 2024 | Repayment | 17.01 | 16.52 | 0.49 | 0.0 | 0.0 | 67.05 | true | false |
|
| 01 March 2024 | Repayment | 17.01 | 16.52 | 0.49 | 0.0 | 0.0 | 67.05 | true | false |
|
||||||
| 15 March 2024 | Re-age | 85.08 | 83.57 | 1.51 | 0.0 | 0.0 | 0.0 | false | true |
|
| 15 March 2024 | Re-age | 85.08 | 83.57 | 1.51 | 0.0 | 0.0 | 0.0 | false | true |
|
||||||
|
|
||||||
When Loan Pay-off is made on "01 April 2024"
|
When Loan Pay-off is made on "01 April 2024"
|
||||||
Then Loan is closed with zero outstanding balance and it's all installments have obligations met
|
Then Loan is closed with zero outstanding balance and it's all installments have obligations met
|
||||||
|
|
||||||
@@ -14537,4 +14536,34 @@ Feature: LoanReAging
|
|||||||
When Loan Pay-off is made on "01 April 2024"
|
When Loan Pay-off is made on "01 April 2024"
|
||||||
Then Loan is closed with zero outstanding balance and it's all installments have obligations met
|
Then Loan is closed with zero outstanding balance and it's all installments have obligations met
|
||||||
|
|
||||||
|
@TestRailId:C4272 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Re-aging on interest bearing, no interest recalculation loan is not allowed (not implemented)
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_CHARGEBACK_PRINCIPAL_INTEREST_FEE" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_CHARGEBACK_PRINCIPAL_INTEREST_FEE | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 6 periods, with the following data for periods:
|
||||||
|
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 February 2024| | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 |
|
||||||
|
| 2 | 29 | 01 March 2024 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 |
|
||||||
|
| 3 | 31 | 01 April 2024 | | 50.43 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 |
|
||||||
|
| 4 | 30 | 01 May 2024 | | 33.71 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 |
|
||||||
|
| 5 | 31 | 01 June 2024 | | 16.9 | 16.81 | 0.2 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 |
|
||||||
|
| 6 | 30 | 01 July 2024 | | 0.0 | 16.9 | 0.1 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 100.0 | 2.05 | 0.0 | 0.0 | 102.05 | 0.0 | 0.0 | 0.0 | 102.05 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false |
|
||||||
|
When Admin creates a Loan re-aging transaction by Loan external ID with the following data, but fails with 501 error code:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 1 | MONTHS | 16 January 2025 | 5 |
|
||||||
|
When Loan Pay-off is made on "01 January 2024"
|
||||||
|
Then Loan is closed with zero outstanding balance and it's all installments have obligations met
|
||||||
|
|
||||||
|
|||||||
+7
-8
@@ -62,7 +62,6 @@ import lombok.Getter;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.NotImplementedException;
|
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||||
@@ -165,34 +164,34 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
protected Money handleTransactionThatIsALateRepaymentOfInstallment(LoanRepaymentScheduleInstallment currentInstallment,
|
protected Money handleTransactionThatIsALateRepaymentOfInstallment(LoanRepaymentScheduleInstallment currentInstallment,
|
||||||
List<LoanRepaymentScheduleInstallment> installments, LoanTransaction loanTransaction, Money transactionAmountUnprocessed,
|
List<LoanRepaymentScheduleInstallment> installments, LoanTransaction loanTransaction, Money transactionAmountUnprocessed,
|
||||||
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings, Set<LoanCharge> charges) {
|
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings, Set<LoanCharge> charges) {
|
||||||
throw new NotImplementedException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(LoanRepaymentScheduleInstallment currentInstallment,
|
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(LoanRepaymentScheduleInstallment currentInstallment,
|
||||||
List<LoanRepaymentScheduleInstallment> installments, LoanTransaction loanTransaction, Money paymentInAdvance,
|
List<LoanRepaymentScheduleInstallment> installments, LoanTransaction loanTransaction, Money paymentInAdvance,
|
||||||
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings, Set<LoanCharge> charges) {
|
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings, Set<LoanCharge> charges) {
|
||||||
throw new NotImplementedException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(LoanRepaymentScheduleInstallment currentInstallment,
|
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(LoanRepaymentScheduleInstallment currentInstallment,
|
||||||
LoanTransaction loanTransaction, Money transactionAmountUnprocessed,
|
LoanTransaction loanTransaction, Money transactionAmountUnprocessed,
|
||||||
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings, Set<LoanCharge> charges) {
|
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings, Set<LoanCharge> charges) {
|
||||||
throw new NotImplementedException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Money handleRefundTransactionPaymentOfInstallment(LoanRepaymentScheduleInstallment currentInstallment,
|
protected Money handleRefundTransactionPaymentOfInstallment(LoanRepaymentScheduleInstallment currentInstallment,
|
||||||
LoanTransaction loanTransaction, Money transactionAmountUnprocessed,
|
LoanTransaction loanTransaction, Money transactionAmountUnprocessed,
|
||||||
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
|
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
|
||||||
throw new NotImplementedException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Money handleRepaymentSchedule(List<LoanTransaction> transactionsPostDisbursement, MonetaryCurrency currency,
|
public Money handleRepaymentSchedule(List<LoanTransaction> transactionsPostDisbursement, MonetaryCurrency currency,
|
||||||
List<LoanRepaymentScheduleInstallment> installments, Set<LoanCharge> loanCharges) {
|
List<LoanRepaymentScheduleInstallment> installments, Set<LoanCharge> loanCharges) {
|
||||||
throw new NotImplementedException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// only for progressive loans
|
// only for progressive loans
|
||||||
@@ -2957,12 +2956,12 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
handleReAgeWithInterestRecalculationEnabled(loanTransaction, progressiveTransactionCtx);
|
handleReAgeWithInterestRecalculationEnabled(loanTransaction, progressiveTransactionCtx);
|
||||||
} else if (loanTransaction.getLoan().isInterestBearing() && !loanTransaction.getLoan().isInterestRecalculationEnabled()) {
|
} else if (loanTransaction.getLoan().isInterestBearing() && !loanTransaction.getLoan().isInterestRecalculationEnabled()) {
|
||||||
// TODO: implement interestRecalculation = false logic
|
// TODO: implement interestRecalculation = false logic
|
||||||
throw new NotImplementedException(
|
throw new UnsupportedOperationException(
|
||||||
"Logic for re-aging when interest bearing loan has interestRecalculation disabled is not implemented");
|
"Logic for re-aging when interest bearing loan has interestRecalculation disabled is not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (LoanReAgeInterestHandlingType.WAIVE_INTEREST.equals(loanReAgeParameter.getInterestHandlingType())) {
|
} else if (LoanReAgeInterestHandlingType.WAIVE_INTEREST.equals(loanReAgeParameter.getInterestHandlingType())) {
|
||||||
throw new NotImplementedException("WAIVE_INTEREST interest handling strategy for re-aging is not implemented");
|
throw new UnsupportedOperationException("WAIVE_INTEREST interest handling strategy for re-aging is not implemented");
|
||||||
} else {
|
} else {
|
||||||
if (LoanReAgeInterestHandlingType.EQUAL_AMORTIZATION_FULL_INTEREST.equals(loanReAgeParameter.getInterestHandlingType())) {
|
if (LoanReAgeInterestHandlingType.EQUAL_AMORTIZATION_FULL_INTEREST.equals(loanReAgeParameter.getInterestHandlingType())) {
|
||||||
CommonReAgeSettings settings = new CommonReAgeSettings(false, true, true, true);
|
CommonReAgeSettings settings = new CommonReAgeSettings(false, true, true, true);
|
||||||
|
|||||||
Reference in New Issue
Block a user