[FINERACT-1958] Business events for down payment installments

This commit is contained in:
taskain7
2023-09-29 13:08:05 +02:00
committed by Adam Saghy
parent 98b7c2948a
commit 1b31d932ca
6 changed files with 51 additions and 29 deletions
@@ -330,6 +330,14 @@
"null", "null",
"bigdecimal" "bigdecimal"
] ]
},
{
"default": null,
"name": "downPaymentPeriod",
"type": [
"null",
"boolean"
]
} }
] ]
} }
@@ -2946,34 +2946,31 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
} }
public void handleDownPayment(final BigDecimal disbursedAmount, final JsonCommand command, public LoanTransaction handleDownPayment(final BigDecimal disbursedAmount, final JsonCommand command,
final ScheduleGeneratorDTO scheduleGeneratorDTO) { final ScheduleGeneratorDTO scheduleGeneratorDTO) {
if (isAutoRepaymentForDownPaymentEnabled()) { LocalDate disbursedOn = command.localDateValueOfParameterNamed(ACTUAL_DISBURSEMENT_DATE);
LocalDate disbursedOn = command.localDateValueOfParameterNamed(ACTUAL_DISBURSEMENT_DATE); BigDecimal disbursedAmountPercentageForDownPayment = this.loanRepaymentScheduleDetail.getDisbursedAmountPercentageForDownPayment();
BigDecimal disbursedAmountPercentageForDownPayment = this.loanRepaymentScheduleDetail ExternalId externalId = ExternalId.empty();
.getDisbursedAmountPercentageForDownPayment(); if (TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
ExternalId externalId = ExternalId.empty(); externalId = ExternalId.generate();
if (TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
externalId = ExternalId.generate();
}
Money downPaymentMoney = Money.of(getCurrency(),
MathUtil.percentageOf(disbursedAmount, disbursedAmountPercentageForDownPayment, 19));
LoanTransaction downPaymentTransaction = LoanTransaction.downPayment(getOffice(), downPaymentMoney, null, disbursedOn,
externalId);
LoanEvent event = LoanEvent.LOAN_REPAYMENT_OR_WAIVER;
validateRepaymentTypeAccountStatus(downPaymentTransaction, event);
HolidayDetailDTO holidayDetailDTO = scheduleGeneratorDTO.getHolidayDetailDTO();
validateRepaymentDateIsOnHoliday(downPaymentTransaction.getTransactionDate(), holidayDetailDTO.isAllowTransactionsOnHoliday(),
holidayDetailDTO.getHolidays());
validateRepaymentDateIsOnNonWorkingDay(downPaymentTransaction.getTransactionDate(), holidayDetailDTO.getWorkingDays(),
holidayDetailDTO.isAllowTransactionsOnNonWorkingDay());
handleRepaymentOrRecoveryOrWaiverTransaction(downPaymentTransaction, loanLifecycleStateMachine, null, scheduleGeneratorDTO);
} }
Money downPaymentMoney = Money.of(getCurrency(),
MathUtil.percentageOf(disbursedAmount, disbursedAmountPercentageForDownPayment, 19));
LoanTransaction downPaymentTransaction = LoanTransaction.downPayment(getOffice(), downPaymentMoney, null, disbursedOn, externalId);
LoanEvent event = LoanEvent.LOAN_REPAYMENT_OR_WAIVER;
validateRepaymentTypeAccountStatus(downPaymentTransaction, event);
HolidayDetailDTO holidayDetailDTO = scheduleGeneratorDTO.getHolidayDetailDTO();
validateRepaymentDateIsOnHoliday(downPaymentTransaction.getTransactionDate(), holidayDetailDTO.isAllowTransactionsOnHoliday(),
holidayDetailDTO.getHolidays());
validateRepaymentDateIsOnNonWorkingDay(downPaymentTransaction.getTransactionDate(), holidayDetailDTO.getWorkingDays(),
holidayDetailDTO.isAllowTransactionsOnNonWorkingDay());
handleRepaymentOrRecoveryOrWaiverTransaction(downPaymentTransaction, loanLifecycleStateMachine, null, scheduleGeneratorDTO);
return downPaymentTransaction;
} }
private boolean isAutoRepaymentForDownPaymentEnabled() { public boolean isAutoRepaymentForDownPaymentEnabled() {
return this.loanRepaymentScheduleDetail.isEnableDownPayment() return this.loanRepaymentScheduleDetail.isEnableDownPayment()
&& this.loanRepaymentScheduleDetail.isEnableAutoRepaymentForDownPayment(); && this.loanRepaymentScheduleDetail.isEnableAutoRepaymentForDownPayment();
} }
@@ -72,6 +72,7 @@ public final class LoanSchedulePeriodData {
private final BigDecimal totalActualCostOfLoanForPeriod; private final BigDecimal totalActualCostOfLoanForPeriod;
private final BigDecimal totalInstallmentAmountForPeriod; private final BigDecimal totalInstallmentAmountForPeriod;
private final BigDecimal totalCredits; private final BigDecimal totalCredits;
private final Boolean downPaymentPeriod;
public static LoanSchedulePeriodData disbursementOnlyPeriod(final LocalDate disbursementDate, final BigDecimal principalDisbursed, public static LoanSchedulePeriodData disbursementOnlyPeriod(final LocalDate disbursementDate, final BigDecimal principalDisbursed,
final BigDecimal feeChargesDueAtTimeOfDisbursement, final boolean isDisbursed) { final BigDecimal feeChargesDueAtTimeOfDisbursement, final boolean isDisbursed) {
@@ -205,6 +206,7 @@ public final class LoanSchedulePeriodData {
this.totalOverdue = null; this.totalOverdue = null;
} }
this.totalCredits = BigDecimal.ZERO; this.totalCredits = BigDecimal.ZERO;
this.downPaymentPeriod = false;
} }
/* /*
@@ -268,9 +270,13 @@ public final class LoanSchedulePeriodData {
this.totalOverdue = null; this.totalOverdue = null;
} }
this.totalCredits = BigDecimal.ZERO; this.totalCredits = BigDecimal.ZERO;
this.downPaymentPeriod = false;
} }
// TODO refactor the class to builder pattern // TODO refactor the class to builder pattern
/*
* used for down payment only period when creating an empty loan schedule for preview etc
*/
private LoanSchedulePeriodData(Integer periodNumber, LocalDate fromDate, LocalDate dueDate, BigDecimal principalDue, private LoanSchedulePeriodData(Integer periodNumber, LocalDate fromDate, LocalDate dueDate, BigDecimal principalDue,
BigDecimal principalOutstanding) { BigDecimal principalOutstanding) {
this.period = periodNumber; this.period = periodNumber;
@@ -323,6 +329,7 @@ public final class LoanSchedulePeriodData {
this.totalOverdue = null; this.totalOverdue = null;
} }
this.totalCredits = BigDecimal.ZERO; this.totalCredits = BigDecimal.ZERO;
this.downPaymentPeriod = true;
} }
/* /*
@@ -396,6 +403,7 @@ public final class LoanSchedulePeriodData {
this.totalOverdue = null; this.totalOverdue = null;
} }
this.totalCredits = totalCredits; this.totalCredits = totalCredits;
this.downPaymentPeriod = false;
} }
private BigDecimal defaultToZeroIfNull(final BigDecimal possibleNullValue) { private BigDecimal defaultToZeroIfNull(final BigDecimal possibleNullValue) {
@@ -375,6 +375,8 @@ final class LoansApiResourceSwagger {
public Double totalInstallmentAmountForPeriod; public Double totalInstallmentAmountForPeriod;
@Schema(example = "2.000000") @Schema(example = "2.000000")
public Double totalCredits; public Double totalCredits;
@Schema(example = "true")
public Boolean downPaymentPeriod;
} }
static final class GetLoansLoanIdDisbursementDetails { static final class GetLoansLoanIdDisbursementDetails {
@@ -53,8 +53,6 @@ import org.apache.fineract.infrastructure.event.business.domain.loan.transaction
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanRefundPostBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanRefundPostBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanRefundPreBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanRefundPreBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionDownPaymentPostBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionDownPaymentPreBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionGoodwillCreditPostBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionGoodwillCreditPostBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionGoodwillCreditPreBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionGoodwillCreditPreBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionMakeRepaymentPostBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionMakeRepaymentPostBusinessEvent;
@@ -292,7 +290,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
} else if (isRecoveryRepayment) { } else if (isRecoveryRepayment) {
repaymentEvent = new LoanTransactionRecoveryPaymentPreBusinessEvent(loan); repaymentEvent = new LoanTransactionRecoveryPaymentPreBusinessEvent(loan);
} else if (repaymentTransactionType.isDownPayment()) { } else if (repaymentTransactionType.isDownPayment()) {
repaymentEvent = new LoanTransactionDownPaymentPreBusinessEvent(loan); repaymentEvent = new LoanTransactionMakeRepaymentPreBusinessEvent(loan);
} }
return repaymentEvent; return repaymentEvent;
} }
@@ -313,7 +311,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
} else if (isRecoveryRepayment) { } else if (isRecoveryRepayment) {
repaymentEvent = new LoanTransactionRecoveryPaymentPostBusinessEvent(transaction); repaymentEvent = new LoanTransactionRecoveryPaymentPostBusinessEvent(transaction);
} else if (repaymentTransactionType.isDownPayment()) { } else if (repaymentTransactionType.isDownPayment()) {
repaymentEvent = new LoanTransactionDownPaymentPostBusinessEvent(transaction); repaymentEvent = new LoanTransactionMakeRepaymentPostBusinessEvent(transaction);
} }
return repaymentEvent; return repaymentEvent;
} }
@@ -82,6 +82,8 @@ import org.apache.fineract.infrastructure.event.business.domain.loan.transaction
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanChargeOffPostBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanChargeOffPostBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanChargeOffPreBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanChargeOffPreBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanDisbursalTransactionBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanDisbursalTransactionBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionMakeRepaymentPostBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionMakeRepaymentPreBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanUndoChargeOffBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanUndoChargeOffBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanUndoWrittenOffBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanUndoWrittenOffBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanWaiveInterestBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanWaiveInterestBusinessEvent;
@@ -456,7 +458,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
changedTransactionDetail = loan.disburse(currentUser, command, changes, scheduleGeneratorDTO, null, downPaymentEnabled); changedTransactionDetail = loan.disburse(currentUser, command, changes, scheduleGeneratorDTO, null, downPaymentEnabled);
} }
loan.adjustNetDisbursalAmount(amountToDisburse.getAmount()); loan.adjustNetDisbursalAmount(amountToDisburse.getAmount());
loan.handleDownPayment(amountToDisburse.getAmount(), command, scheduleGeneratorDTO); if (loan.isAutoRepaymentForDownPaymentEnabled()) {
businessEventNotifierService.notifyPreBusinessEvent(new LoanTransactionMakeRepaymentPreBusinessEvent(loan));
LoanTransaction downPaymentTransaction = loan.handleDownPayment(amountToDisburse.getAmount(), command,
scheduleGeneratorDTO);
businessEventNotifierService
.notifyPostBusinessEvent(new LoanTransactionMakeRepaymentPostBusinessEvent(downPaymentTransaction));
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
}
} }
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
if (changedTransactionDetail != null) { if (changedTransactionDetail != null) {