FINERACT-2279: Contract Termination - Undo
This commit is contained in:
committed by
Adam Saghy
parent
11cecb0d45
commit
ee29ce23ac
+2
@@ -1234,6 +1234,8 @@ public class LoansApiResource {
|
||||
commandRequest = builder.assignDelinquency(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, LoanApiConstants.CONTRACT_TERMINATION_COMMAND)) {
|
||||
commandRequest = builder.applyContractTermination(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, LoanApiConstants.UNDO_CONTRACT_TERMINATION_COMMAND)) {
|
||||
commandRequest = builder.undoContractTermination(resolvedLoanId).build();
|
||||
}
|
||||
|
||||
if (commandRequest == null) {
|
||||
|
||||
+2
@@ -733,6 +733,8 @@ final class LoansApiResourceSwagger {
|
||||
public boolean capitalizedIncomeAmortization;
|
||||
@Schema(example = "false")
|
||||
public boolean capitalizedIncomeAdjustment;
|
||||
@Schema(example = "false")
|
||||
public boolean contractTermination;
|
||||
}
|
||||
|
||||
static final class GetLoansLoanIdPaymentDetailData {
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.portfolio.loanaccount.handler.loan.contracttermination;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.contracttermination.LoanContractTerminationServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CommandType(entity = "LOAN", action = "CONTRACT_TERMINATION_UNDO")
|
||||
public class UndoLoanContractTerminationCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final LoanContractTerminationServiceImpl loanContractTerminationService;
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return loanContractTerminationService.undoContractTermination(command);
|
||||
}
|
||||
}
|
||||
+8
@@ -1081,4 +1081,12 @@ public final class LoanTransactionValidatorImpl implements LoanTransactionValida
|
||||
baseDataValidator.reset().parameter("externalId").value(externalId).notExceedingLengthOf(100);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateReversalExternalId(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
final String reversalExternalId = this.fromApiJsonHelper.extractStringNamed("reversalExternalId", element);
|
||||
if (StringUtils.isNotBlank(reversalExternalId)) {
|
||||
baseDataValidator.reset().parameter("reversalExternalId").value(reversalExternalId).notExceedingLengthOf(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+70
@@ -32,19 +32,25 @@ import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBalanceChangedBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionContractTerminationPostBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanUndoContractTerminationBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSubStatus;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanScheduleService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanTransactionValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
|
||||
import org.apache.fineract.portfolio.note.domain.Note;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||
@@ -65,6 +71,9 @@ public class LoanContractTerminationServiceImpl {
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final LoanTransactionService loanTransactionService;
|
||||
private final LoanScheduleService loanScheduleService;
|
||||
private final LoanChargeValidator loanChargeValidator;
|
||||
private final ProgressiveLoanTransactionValidator loanTransactionValidator;
|
||||
|
||||
public CommandProcessingResult applyContractTermination(final JsonCommand command) {
|
||||
final Loan loan = loanAssembler.assembleFrom(command.getLoanId());
|
||||
@@ -116,6 +125,67 @@ public class LoanContractTerminationServiceImpl {
|
||||
.with(changes).build();
|
||||
}
|
||||
|
||||
public CommandProcessingResult undoContractTermination(final JsonCommand command) {
|
||||
final Long loanId = command.getLoanId();
|
||||
|
||||
loanTransactionValidator.validateContractTerminationUndo(command, loanId);
|
||||
|
||||
final Loan loan = loanAssembler.assembleFrom(loanId);
|
||||
final LoanTransaction contractTerminationTransaction = loan.findContractTerminationTransaction();
|
||||
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanUndoContractTerminationBusinessEvent(contractTerminationTransaction));
|
||||
businessEventNotifierService.notifyPreBusinessEvent(
|
||||
new LoanAdjustTransactionBusinessEvent(new LoanAdjustTransactionBusinessEvent.Data(contractTerminationTransaction)));
|
||||
|
||||
// check if reversalExternalId is provided
|
||||
final String reversalExternalId = command.stringValueOfParameterNamedAllowingNull(LoanApiConstants.REVERSAL_EXTERNAL_ID_PARAMNAME);
|
||||
final ExternalId reversalTxnExternalId = ExternalIdFactory.produce(reversalExternalId);
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
|
||||
// Add note if provided
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
changes.put("note", noteText);
|
||||
final Note note = Note.loanTransactionNote(loan, contractTerminationTransaction, noteText);
|
||||
noteRepository.save(note);
|
||||
}
|
||||
|
||||
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(contractTerminationTransaction.getLoan(),
|
||||
contractTerminationTransaction, "reversed");
|
||||
contractTerminationTransaction.reverse(reversalTxnExternalId);
|
||||
contractTerminationTransaction.manuallyAdjustedOrReversed();
|
||||
|
||||
loan.liftContractTerminationSubStatus();
|
||||
changes.put(LoanApiConstants.subStatusAttributeName, loan.getLoanSubStatus());
|
||||
loanTransactionRepository.saveAndFlush(contractTerminationTransaction);
|
||||
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
||||
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||
} else if (loan.isProgressiveSchedule()) {
|
||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoContractTerminationBusinessEvent(contractTerminationTransaction));
|
||||
|
||||
final LoanAdjustTransactionBusinessEvent.Data eventData = new LoanAdjustTransactionBusinessEvent.Data(
|
||||
contractTerminationTransaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(eventData));
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withLoanId(loanId) //
|
||||
.withEntityId(contractTerminationTransaction.getId()) //
|
||||
.withEntityExternalId(contractTerminationTransaction.getExternalId()) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
}
|
||||
|
||||
public void validateContractTermination(final Loan loan) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
|
||||
|
||||
+2
-2
@@ -109,7 +109,7 @@ public class ExternalEventConfigurationValidationServiceTest {
|
||||
"LoanCapitalizedIncomeAmortizationTransactionCreatedBusinessEvent",
|
||||
"LoanCapitalizedIncomeAdjustmentTransactionCreatedBusinessEvent", "LoanTransactionContractTerminationPostBusinessEvent",
|
||||
"LoanCapitalizedIncomeAmortizationAdjustmentTransactionCreatedBusinessEvent",
|
||||
"LoanCapitalizedIncomeTransactionCreatedBusinessEvent");
|
||||
"LoanCapitalizedIncomeTransactionCreatedBusinessEvent", "LoanUndoContractTerminationBusinessEvent");
|
||||
|
||||
List<FineractPlatformTenant> tenants = Arrays
|
||||
.asList(new FineractPlatformTenant(1L, "default", "Default Tenant", "Europe/Budapest", null));
|
||||
@@ -199,7 +199,7 @@ public class ExternalEventConfigurationValidationServiceTest {
|
||||
"LoanCapitalizedIncomeAmortizationTransactionCreatedBusinessEvent",
|
||||
"LoanCapitalizedIncomeAdjustmentTransactionCreatedBusinessEvent", "LoanTransactionContractTerminationPostBusinessEvent",
|
||||
"LoanCapitalizedIncomeAmortizationAdjustmentTransactionCreatedBusinessEvent",
|
||||
"LoanCapitalizedIncomeTransactionCreatedBusinessEvent");
|
||||
"LoanCapitalizedIncomeTransactionCreatedBusinessEvent", "LoanUndoContractTerminationBusinessEvent");
|
||||
|
||||
List<FineractPlatformTenant> tenants = Arrays
|
||||
.asList(new FineractPlatformTenant(1L, "default", "Default Tenant", "Europe/Budapest", null));
|
||||
|
||||
Reference in New Issue
Block a user