Skip to content

Commit

Permalink
FINERACT-2082: New Transaction Type - Interest Payment Waiver
Browse files Browse the repository at this point in the history
  • Loading branch information
somasorosdpc authored and adamsaghy committed Jun 21, 2024
1 parent 1c53fe2 commit 9152408
Show file tree
Hide file tree
Showing 29 changed files with 2,809 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,15 @@ public CommandWrapperBuilder loanGoodwillCreditTransaction(final Long loanId) {
return this;
}

public CommandWrapperBuilder loanInterestPaymentWaiverTransaction(final Long loanId) {
this.actionName = "INTERESTPAYMENTWAIVER";
this.entityName = "LOAN";
this.entityId = null;
this.loanId = loanId;
this.href = "/loans/" + loanId + "/transactions/template?command=interestpaymentwaiver";
return this;
}

public CommandWrapperBuilder refundLoanCharge(final Long loanId) {
this.actionName = "CHARGEREFUND";
this.entityName = "LOAN";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* 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.event.business.domain.loan.transaction;

import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;

public class LoanTransactionInterestPaymentWaiverPostBusinessEvent extends LoanTransactionBusinessEvent {

private static final String TYPE = "LoanTransactionInterestPaymentWaiverPostBusinessEvent";

public LoanTransactionInterestPaymentWaiverPostBusinessEvent(LoanTransaction value) {
super(value);
}

@Override
public String getType() {
return TYPE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* 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.event.business.domain.loan.transaction;

import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBusinessEvent;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;

public class LoanTransactionInterestPaymentWaiverPreBusinessEvent extends LoanBusinessEvent {

private static final String TYPE = "LoanTransactionInterestPaymentWaiverPreBusinessEvent";

public LoanTransactionInterestPaymentWaiverPreBusinessEvent(Loan value) {
super(value);
}

@Override
public String getType() {
return TYPE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class LoanTransactionEnumData {
private final boolean merchantIssuedRefund;
private final boolean payoutRefund;
private final boolean goodwillCredit;
private final boolean interestPaymentWaiver;
private final boolean chargeRefund;
private final boolean contra;
private final boolean waiveInterest;
Expand Down Expand Up @@ -88,6 +89,7 @@ public LoanTransactionEnumData(final Long id, final String code, final String va
this.chargeAdjustment = Long.valueOf(26).equals(this.id);
this.chargeoff = Long.valueOf(27).equals(this.id);
this.downPayment = Long.valueOf(28).equals(this.id);
this.interestPaymentWaiver = Long.valueOf(31).equals(this.id);
this.reAge = Long.valueOf(LoanTransactionType.REAGE.getValue()).equals(this.id);
this.reAmortize = Long.valueOf(LoanTransactionType.REAMORTIZE.getValue()).equals(this.id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,7 @@ public void updateLoanScheduleDependentDerivedFields() {
}
}

private void updateLoanSummaryDerivedFields() {
public void updateLoanSummaryDerivedFields() {
if (isNotDisbursed()) {
this.summary.zeroFields();
this.totalOverpaid = null;
Expand Down Expand Up @@ -2586,9 +2586,10 @@ public ChangedTransactionDetail makeRepayment(final LoanTransaction repaymentTra
}

private void validateRepaymentTypeAccountStatus(LoanTransaction repaymentTransaction, LoanEvent event) {
if (repaymentTransaction.isGoodwillCredit() || repaymentTransaction.isMerchantIssuedRefund()
|| repaymentTransaction.isPayoutRefund() || repaymentTransaction.isChargeRefund() || repaymentTransaction.isRepayment()
|| repaymentTransaction.isDownPayment()) {
if (repaymentTransaction.isGoodwillCredit() || repaymentTransaction.isInterestPaymentWaiver()
|| repaymentTransaction.isMerchantIssuedRefund() || repaymentTransaction.isPayoutRefund()
|| repaymentTransaction.isChargeRefund() || repaymentTransaction.isRepayment() || repaymentTransaction.isDownPayment()) {

if (!(isOpen() || isClosedObligationsMet() || isOverPaid())) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final String defaultUserMessage = "Loan must be Active, Fully Paid or Overpaid";
Expand Down Expand Up @@ -2799,7 +2800,7 @@ private LocalDate extractTransactionDate(LoanTransaction loanTransaction) {
return loanTransactionDate;
}

private LoanRepaymentScheduleInstallment fetchLoanRepaymentScheduleInstallment(LocalDate dueDate) {
public LoanRepaymentScheduleInstallment fetchLoanRepaymentScheduleInstallment(LocalDate dueDate) {
return getRepaymentScheduleInstallments().stream() //
.filter(installment -> dueDate.equals(installment.getDueDate())).findFirst() //
.orElse(null);
Expand Down Expand Up @@ -2887,7 +2888,7 @@ private void handleLoanRepaymentInFull(final LocalDate transactionDate, final Lo
processIncomeAccrualTransactionOnLoanClosure();
}

private void processIncomeAccrualTransactionOnLoanClosure() {
public void processIncomeAccrualTransactionOnLoanClosure() {
if (this.loanInterestRecalculationDetails != null && this.loanInterestRecalculationDetails.isCompoundingToBePostedAsTransaction()
&& this.getStatus().isClosedObligationsMet() && !isNpa() && !isChargedOff()) {

Expand Down Expand Up @@ -3161,7 +3162,7 @@ public LoanTransaction findWriteOffTransaction() {
.orElse(null);
}

private boolean isOverPaid() {
public boolean isOverPaid() {
return calculateTotalOverpayment().isGreaterThanZero();
}

Expand Down Expand Up @@ -3209,7 +3210,7 @@ public Money calculateTotalRecoveredPayments() {
return getTotalRecoveredPayments();
}

private MonetaryCurrency loanCurrency() {
public MonetaryCurrency loanCurrency() {
return this.loanRepaymentScheduleDetail.getCurrency();
}

Expand Down Expand Up @@ -3479,7 +3480,7 @@ public boolean isClosed() {
return getStatus().isClosed() || isCancelled();
}

private boolean isClosedObligationsMet() {
public boolean isClosedObligationsMet() {
return getStatus().isClosedObligationsMet();
}

Expand Down Expand Up @@ -6024,7 +6025,7 @@ public void updateLoanScheduleOnForeclosure(final Collection<LoanRepaymentSchedu
}
}

private boolean isForeclosure() {
public boolean isForeclosure() {
boolean isForeClosure = false;
if (this.loanSubStatus != null) {
isForeClosure = LoanSubStatus.fromInt(loanSubStatus).isForeclosed();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -580,11 +580,12 @@ public void setManuallyAdjustedOrReversed() {

public boolean isRepaymentLikeType() {
return isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() || isGoodwillCredit() || isChargeRefund()
|| isChargeAdjustment() || isDownPayment();
|| isChargeAdjustment() || isDownPayment() || isInterestPaymentWaiver();
}

public boolean isTypeAllowedForChargeback() {
return isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() || isGoodwillCredit() || isDownPayment();
return isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() || isGoodwillCredit() || isDownPayment()
|| isInterestPaymentWaiver();
}

public boolean isRepayment() {
Expand All @@ -607,6 +608,10 @@ public boolean isGoodwillCredit() {
return LoanTransactionType.GOODWILL_CREDIT.equals(getTypeOf()) && isNotReversed();
}

public boolean isInterestPaymentWaiver() {
return LoanTransactionType.INTEREST_PAYMENT_WAIVER.equals(getTypeOf()) && isNotReversed();
}

public boolean isChargeRefund() {
return LoanTransactionType.CHARGE_REFUND.equals(getTypeOf()) && isNotReversed();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public enum LoanTransactionType {
DOWN_PAYMENT(28, "loanTransactionType.downPayment"), //
REAGE(29, "loanTransactionType.reAge"), //
REAMORTIZE(30, "loanTransactionType.reAmortize"), //
INTEREST_PAYMENT_WAIVER(31, "loanTransactionType.interestPaymentWaiver"), //
;

private final Integer value;
Expand Down Expand Up @@ -109,6 +110,7 @@ public static LoanTransactionType fromInt(final Integer transactionType) {
case 28 -> LoanTransactionType.DOWN_PAYMENT;
case 29 -> LoanTransactionType.REAGE;
case 30 -> LoanTransactionType.REAMORTIZE;
case 31 -> LoanTransactionType.INTEREST_PAYMENT_WAIVER;
default -> LoanTransactionType.INVALID;
};
}
Expand All @@ -133,6 +135,10 @@ public boolean isRepayment() {
return this.equals(LoanTransactionType.REPAYMENT);
}

public boolean isInterestPaymentWaiver() {
return this.equals(LoanTransactionType.INTEREST_PAYMENT_WAIVER);
}

public boolean isMerchantIssuedRefund() {
return this.equals(LoanTransactionType.MERCHANT_ISSUED_REFUND);
}
Expand All @@ -150,7 +156,8 @@ public boolean isChargeRefund() {
}

public boolean isRepaymentType() {
return (isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() || isGoodwillCredit() || isChargeRefund() || isDownPayment());
return (isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() || isGoodwillCredit() || isChargeRefund() || isDownPayment()
|| isInterestPaymentWaiver());
}

public boolean isRecoveryRepayment() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ CommandProcessingResult makeLoanRepayment(LoanTransactionType repaymentTransacti
CommandProcessingResult makeLoanRepaymentWithChargeRefundChargeType(LoanTransactionType repaymentTransactionType, Long loanId,
JsonCommand command, boolean isRecoveryRepayment, String chargeRefundChargeType);

@Transactional
CommandProcessingResult makeInterestPaymentWaiver(JsonCommand command);

Map<String, Object> makeLoanBulkRepayment(CollectionSheetBulkRepaymentCommand bulkRepaymentCommand);

CommandProcessingResult adjustLoanTransaction(Long loanId, Long transactionId, JsonCommand command);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public enum PaymentAllocationTransactionType {
CHARGE_ADJUSTMENT(LoanTransactionType.CHARGE_ADJUSTMENT, "Charge adjustment"), //
WAIVE_INTEREST(LoanTransactionType.WAIVE_INTEREST, "Waive interest"), //
CHARGE_PAYMENT(LoanTransactionType.CHARGE_PAYMENT, "Charge payment"), //
REFUND_FOR_ACTIVE_LOAN(LoanTransactionType.REFUND_FOR_ACTIVE_LOAN, "Refund for active loan");
REFUND_FOR_ACTIVE_LOAN(LoanTransactionType.REFUND_FOR_ACTIVE_LOAN, "Refund for active loan"), //
INTEREST_PAYMENT_WAIVER(LoanTransactionType.INTEREST_PAYMENT_WAIVER, "Interest payment waiver");

private final LoanTransactionType loanTransactionType;
private final String humanReadableName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ public static LoanTransactionEnumData transactionType(final LoanTransactionType
LoanTransactionType.PAYOUT_REFUND.getCode(), "Payout Refund");
case GOODWILL_CREDIT -> new LoanTransactionEnumData(LoanTransactionType.GOODWILL_CREDIT.getValue().longValue(),
LoanTransactionType.GOODWILL_CREDIT.getCode(), "Goodwill Credit");
case INTEREST_PAYMENT_WAIVER -> new LoanTransactionEnumData(LoanTransactionType.INTEREST_PAYMENT_WAIVER.getValue().longValue(),
LoanTransactionType.INTEREST_PAYMENT_WAIVER.getCode(), "Interest Payment Waiver");
case CHARGE_REFUND -> new LoanTransactionEnumData(LoanTransactionType.CHARGE_REFUND.getValue().longValue(),
LoanTransactionType.CHARGE_REFUND.getCode(), "Charge Refund");
case CHARGEBACK -> new LoanTransactionEnumData(LoanTransactionType.CHARGEBACK.getValue().longValue(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public void processLatestTransaction(LoanTransaction loanTransaction, Transactio
case CREDIT_BALANCE_REFUND ->
handleCreditBalanceRefund(loanTransaction, ctx.getCurrency(), ctx.getInstallments(), ctx.getOverpaymentHolder());
case REPAYMENT, MERCHANT_ISSUED_REFUND, PAYOUT_REFUND, GOODWILL_CREDIT, CHARGE_REFUND, CHARGE_ADJUSTMENT, DOWN_PAYMENT,
WAIVE_INTEREST, RECOVERY_REPAYMENT ->
WAIVE_INTEREST, RECOVERY_REPAYMENT, INTEREST_PAYMENT_WAIVER ->
handleRepayment(loanTransaction, ctx.getCurrency(), ctx.getInstallments(), ctx.getCharges(), ctx.getOverpaymentHolder());
case CHARGE_OFF -> handleChargeOff(loanTransaction, ctx.getCurrency(), ctx.getInstallments());
case CHARGE_PAYMENT -> handleChargePayment(loanTransaction, ctx.getCurrency(), ctx.getInstallments(), ctx.getCharges(),
Expand Down
Loading

0 comments on commit 9152408

Please sign in to comment.