Loan transaction date handling enhancement + Make Loan transaction auditable
This commit is contained in:
committed by
Arnold Gálovics
parent
ad4fa563de
commit
b30d5c5a16
+2
-2
@@ -664,7 +664,7 @@ public class TellerManagementReadPlatformServiceImpl implements TellerManagement
|
||||
sqlBuilder.append(" left join m_loan loan on loan_txn.loan_id = loan.id ");
|
||||
sqlBuilder.append(" left join m_client cl on loan.client_id = cl.id ");
|
||||
sqlBuilder.append(" left join m_office o on cl.office_id = o.id ");
|
||||
sqlBuilder.append(" left join m_appuser user on loan_txn.appuser_id = user.id ");
|
||||
sqlBuilder.append(" left join m_appuser user on loan_txn.createdby_id = user.id ");
|
||||
sqlBuilder.append(" left join m_staff staff on user.staff_id = staff.id ");
|
||||
sqlBuilder.append(" left join m_cashiers c on c.staff_id = staff.id ");
|
||||
sqlBuilder.append(" left join m_payment_detail payDetails on payDetails.id = loan_txn.payment_detail_id ");
|
||||
@@ -829,7 +829,7 @@ public class TellerManagementReadPlatformServiceImpl implements TellerManagement
|
||||
sqlBuilder.append(" left join m_loan loan on loan_txn.loan_id = loan.id ");
|
||||
sqlBuilder.append(" left join m_client cl on loan.client_id = cl.id ");
|
||||
sqlBuilder.append(" left join m_office o on cl.office_id = o.id ");
|
||||
sqlBuilder.append(" left join m_appuser user on loan_txn.appuser_id = user.id ");
|
||||
sqlBuilder.append(" left join m_appuser user on loan_txn.createdby_id = user.id ");
|
||||
sqlBuilder.append(" left join m_staff staff on user.staff_id = staff.id ");
|
||||
sqlBuilder.append(" left join m_cashiers c on c.staff_id = staff.id ");
|
||||
sqlBuilder.append(" left join m_payment_detail payDetails on payDetails.id = loan_txn.payment_detail_id ");
|
||||
|
||||
+78
-92
@@ -688,8 +688,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
* @param suppliedTransactionDate
|
||||
* @return
|
||||
*/
|
||||
public LoanTransaction handleChargeAppliedTransaction(final LoanCharge loanCharge, final LocalDate suppliedTransactionDate,
|
||||
final AppUser currentUser) {
|
||||
public LoanTransaction handleChargeAppliedTransaction(final LoanCharge loanCharge, final LocalDate suppliedTransactionDate) {
|
||||
final Money chargeAmount = loanCharge.getAmount(getCurrency());
|
||||
Money feeCharges = chargeAmount;
|
||||
Money penaltyCharges = Money.zero(loanCurrency());
|
||||
@@ -714,7 +713,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
final LoanTransaction applyLoanChargeTransaction = LoanTransaction.accrueLoanCharge(this, getOffice(), chargeAmount,
|
||||
transactionDate, feeCharges, penaltyCharges, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
transactionDate, feeCharges, penaltyCharges);
|
||||
|
||||
Integer installmentNumber = null;
|
||||
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(applyLoanChargeTransaction, loanCharge,
|
||||
@@ -1009,8 +1008,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
|
||||
public LoanTransaction waiveLoanCharge(final LoanCharge loanCharge, final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
||||
final Map<String, Object> changes, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||
final Integer loanInstallmentNumber, final ScheduleGeneratorDTO scheduleGeneratorDTO, final Money accruedCharge,
|
||||
final AppUser currentUser) {
|
||||
final Integer loanInstallmentNumber, final ScheduleGeneratorDTO scheduleGeneratorDTO, final Money accruedCharge) {
|
||||
|
||||
validateLoanIsNotClosed(loanCharge);
|
||||
|
||||
@@ -1062,14 +1060,14 @@ public class Loan extends AbstractPersistableCustom {
|
||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||
|
||||
final LoanTransaction waiveLoanChargeTransaction = LoanTransaction.waiveLoanCharge(this, getOffice(), amountWaived, transactionDate,
|
||||
feeChargesWaived, penaltyChargesWaived, unrecognizedIncome, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
feeChargesWaived, penaltyChargesWaived, unrecognizedIncome);
|
||||
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(waiveLoanChargeTransaction, loanCharge,
|
||||
waiveLoanChargeTransaction.getAmount(getCurrency()).getAmount(), loanInstallmentNumber);
|
||||
waiveLoanChargeTransaction.getLoanChargesPaid().add(loanChargePaidBy);
|
||||
addLoanTransaction(waiveLoanChargeTransaction);
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()
|
||||
&& (loanCharge.getDueLocalDate() == null || DateUtils.getBusinessLocalDate().isAfter(loanCharge.getDueLocalDate()))) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
}
|
||||
// Waive of charges whose due date falls after latest 'repayment'
|
||||
// transaction dont require entire loan schedule to be reprocessed.
|
||||
@@ -1225,7 +1223,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
this.rates.addAll(loanRates);
|
||||
}
|
||||
|
||||
public void updateLoanSchedule(final LoanScheduleModel modifiedLoanSchedule, AppUser currentUser) {
|
||||
public void updateLoanSchedule(final LoanScheduleModel modifiedLoanSchedule) {
|
||||
this.repaymentScheduleInstallments.clear();
|
||||
for (final LoanScheduleModelPeriod scheduledLoanInstallment : modifiedLoanSchedule.getPeriods()) {
|
||||
|
||||
@@ -1242,11 +1240,11 @@ public class Loan extends AbstractPersistableCustom {
|
||||
|
||||
updateLoanScheduleDependentDerivedFields();
|
||||
updateLoanSummaryDerivedFields();
|
||||
applyAccurals(currentUser);
|
||||
applyAccurals();
|
||||
|
||||
}
|
||||
|
||||
public void updateLoanSchedule(final Collection<LoanRepaymentScheduleInstallment> installments, AppUser currentUser) {
|
||||
public void updateLoanSchedule(final Collection<LoanRepaymentScheduleInstallment> installments) {
|
||||
List<LoanRepaymentScheduleInstallment> existingInstallments = new ArrayList<>(this.repaymentScheduleInstallments);
|
||||
repaymentScheduleInstallments.clear();
|
||||
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
||||
@@ -1262,7 +1260,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
updateLoanScheduleDependentDerivedFields();
|
||||
updateLoanSummaryDerivedFields();
|
||||
applyAccurals(currentUser);
|
||||
applyAccurals();
|
||||
|
||||
}
|
||||
|
||||
@@ -1279,13 +1277,13 @@ public class Loan extends AbstractPersistableCustom {
|
||||
/**
|
||||
* method updates accrual derived fields on installments and reverse the unprocessed transactions
|
||||
*/
|
||||
private void applyAccurals(AppUser currentUser) {
|
||||
private void applyAccurals() {
|
||||
Collection<LoanTransaction> accruals = retreiveListOfAccrualTransactions();
|
||||
if (accruals.size() > 0) {
|
||||
if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
|
||||
applyPeriodicAccruals(accruals);
|
||||
} else if (isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
|
||||
updateAccrualsForNonPeriodicAccruals(accruals, currentUser);
|
||||
updateAccrualsForNonPeriodicAccruals(accruals);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1325,7 +1323,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAccrualsForNonPeriodicAccruals(final Collection<LoanTransaction> accruals, final AppUser currentUser) {
|
||||
private void updateAccrualsForNonPeriodicAccruals(final Collection<LoanTransaction> accruals) {
|
||||
|
||||
final Money interestApplied = Money.of(getCurrency(), this.summary.getTotalInterestCharged());
|
||||
for (LoanTransaction loanTransaction : accruals) {
|
||||
@@ -1334,7 +1332,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
loanTransaction.reverse();
|
||||
final LocalDateTime currentDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||
final LoanTransaction interestAppliedTransaction = LoanTransaction.accrueInterest(getOffice(), this, interestApplied,
|
||||
getDisbursementDate(), currentDateTime, currentUser);
|
||||
getDisbursementDate());
|
||||
addLoanTransaction(interestAppliedTransaction);
|
||||
}
|
||||
} else {
|
||||
@@ -1344,7 +1342,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
Money chargeAmount = loanCharge.getAmount(getCurrency());
|
||||
if (chargeAmount.isNotEqualTo(loanTransaction.getAmount(getCurrency()))) {
|
||||
loanTransaction.reverse();
|
||||
handleChargeAppliedTransaction(loanCharge, loanTransaction.getTransactionDate(), currentUser);
|
||||
handleChargeAppliedTransaction(loanCharge, loanTransaction.getTransactionDate());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2068,7 +2066,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
final LocalDate submittedOn, final String externalId, final boolean allowTransactionsOnHoliday, final List<Holiday> holidays,
|
||||
final WorkingDays workingDays, final boolean allowTransactionsOnNonWorkingDay) {
|
||||
|
||||
updateLoanSchedule(loanSchedule, currentUser);
|
||||
updateLoanSchedule(loanSchedule);
|
||||
|
||||
LoanStatus from = null;
|
||||
if (this.loanStatus != null) {
|
||||
@@ -2483,12 +2481,11 @@ public class Loan extends AbstractPersistableCustom {
|
||||
validateDisbursementDateIsOnHoliday(holidayDetailDTO.isAllowTransactionsOnHoliday(), holidayDetailDTO.getHolidays());
|
||||
|
||||
regenerateRepaymentScheduleWithInterestRecalculationIfNeeded(this.repaymentScheduleDetail().isInterestRecalculationEnabled(),
|
||||
isDisbursementMissed(), scheduleGeneratorDTO, currentUser);
|
||||
isDisbursementMissed(), scheduleGeneratorDTO);
|
||||
|
||||
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
||||
updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate);
|
||||
LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
|
||||
handleDisbursementTransaction(actualDisbursementDate, createdDate, currentUser, paymentDetail);
|
||||
handleDisbursementTransaction(actualDisbursementDate, paymentDetail);
|
||||
updateLoanSummaryDerivedFields();
|
||||
final Money interestApplied = Money.of(getCurrency(), this.summary.getTotalInterestCharged());
|
||||
|
||||
@@ -2500,7 +2497,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
if (((isMultiDisburmentLoan() && getDisbursedLoanDisbursementDetails().size() == 1) || !isMultiDisburmentLoan())
|
||||
&& isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
|
||||
final LoanTransaction interestAppliedTransaction = LoanTransaction.accrueInterest(getOffice(), this, interestApplied,
|
||||
actualDisbursementDate, createdDate, currentUser);
|
||||
actualDisbursementDate);
|
||||
addLoanTransaction(interestAppliedTransaction);
|
||||
}
|
||||
|
||||
@@ -2509,12 +2506,12 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
private void regenerateRepaymentScheduleWithInterestRecalculationIfNeeded(boolean interestRecalculationEnabledParam,
|
||||
boolean disbursementMissedParam, ScheduleGeneratorDTO scheduleGeneratorDTO, AppUser currentUser) {
|
||||
boolean disbursementMissedParam, ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
|
||||
LocalDate firstInstallmentDueDate = fetchRepaymentScheduleInstallment(1).getDueDate();
|
||||
if (interestRecalculationEnabledParam
|
||||
&& (firstInstallmentDueDate.isBefore(DateUtils.getBusinessLocalDate()) || disbursementMissedParam)) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2532,7 +2529,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public void regenerateScheduleOnDisbursement(final ScheduleGeneratorDTO scheduleGeneratorDTO, final boolean recalculateSchedule,
|
||||
final LocalDate actualDisbursementDate, BigDecimal emiAmount, final AppUser currentUser, LocalDate nextPossibleRepaymentDate,
|
||||
final LocalDate actualDisbursementDate, BigDecimal emiAmount, LocalDate nextPossibleRepaymentDate,
|
||||
Date rescheduledRepaymentDate) {
|
||||
boolean isEmiAmountChanged = false;
|
||||
if ((this.loanProduct.isMultiDisburseLoan() || this.loanProduct.canDefineInstallmentAmount()) && emiAmount != null
|
||||
@@ -2565,9 +2562,9 @@ public class Loan extends AbstractPersistableCustom {
|
||||
if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate) || recalculateSchedule || isEmiAmountChanged
|
||||
|| rescheduledRepaymentDate != null) {
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
} else {
|
||||
regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2789,12 +2786,12 @@ public class Loan extends AbstractPersistableCustom {
|
||||
/*
|
||||
* Ability to regenerate the repayment schedule based on the loans current details/state.
|
||||
*/
|
||||
public void regenerateRepaymentSchedule(final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
public void regenerateRepaymentSchedule(final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
final LoanScheduleModel loanSchedule = regenerateScheduleModel(scheduleGeneratorDTO);
|
||||
if (loanSchedule == null) {
|
||||
return;
|
||||
}
|
||||
updateLoanSchedule(loanSchedule, currentUser);
|
||||
updateLoanSchedule(loanSchedule);
|
||||
final Set<LoanCharge> charges = this.charges();
|
||||
for (final LoanCharge loanCharge : charges) {
|
||||
if (!loanCharge.isWaived()) {
|
||||
@@ -2855,8 +2852,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
return interestRate;
|
||||
}
|
||||
|
||||
private void handleDisbursementTransaction(final LocalDate disbursedOn, final LocalDateTime createdDate, final AppUser currentUser,
|
||||
final PaymentDetail paymentDetail) {
|
||||
private void handleDisbursementTransaction(final LocalDate disbursedOn, final PaymentDetail paymentDetail) {
|
||||
|
||||
// add repayment transaction to track incoming money from client to mfi
|
||||
// for (charges due at time of disbursement)
|
||||
@@ -2873,7 +2869,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
|
||||
Money disbursentMoney = Money.zero(getCurrency());
|
||||
final LoanTransaction chargesPayment = LoanTransaction.repaymentAtDisbursement(getOffice(), disbursentMoney, paymentDetail,
|
||||
disbursedOn, null, createdDate, currentUser);
|
||||
disbursedOn, null);
|
||||
final Integer installmentNumber = null;
|
||||
for (final LoanCharge charge : charges()) {
|
||||
Date actualDisbursementDate = getActualDisbursementDate(charge);
|
||||
@@ -2898,7 +2894,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
* create a Charge applied transaction if Up front Accrual, None or Cash based accounting is enabled
|
||||
**/
|
||||
if (isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
|
||||
handleChargeAppliedTransaction(charge, disbursedOn, currentUser);
|
||||
handleChargeAppliedTransaction(charge, disbursedOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2968,7 +2964,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public Map<String, Object> undoDisbursal(final ScheduleGeneratorDTO scheduleGeneratorDTO, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, AppUser currentUser) {
|
||||
final List<Long> existingReversedTransactionIds) {
|
||||
|
||||
validateAccountStatus(LoanEvent.LOAN_DISBURSAL_UNDO);
|
||||
|
||||
@@ -3003,7 +2999,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
// clear off actual disbusrement date so schedule regeneration
|
||||
// uses expected date.
|
||||
|
||||
regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||
if (isDisbursedAmountChanged) {
|
||||
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
||||
}
|
||||
@@ -3070,7 +3066,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
|
||||
public ChangedTransactionDetail waiveInterest(final LoanTransaction waiveInterestTransaction,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
|
||||
validateAccountStatus(LoanEvent.LOAN_REPAYMENT_OR_WAIVER);
|
||||
|
||||
@@ -3082,7 +3078,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||
|
||||
final ChangedTransactionDetail changedTransactionDetail = handleRepaymentOrRecoveryOrWaiverTransaction(waiveInterestTransaction,
|
||||
loanLifecycleStateMachine, null, scheduleGeneratorDTO, currentUser);
|
||||
loanLifecycleStateMachine, null, scheduleGeneratorDTO);
|
||||
|
||||
return changedTransactionDetail;
|
||||
}
|
||||
@@ -3091,7 +3087,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
public ChangedTransactionDetail makeRepayment(final LoanTransaction repaymentTransaction,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, boolean isRecoveryRepayment, final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final AppUser currentUser, Boolean isHolidayValidationDone) {
|
||||
Boolean isHolidayValidationDone) {
|
||||
HolidayDetailDTO holidayDetailDTO = null;
|
||||
LoanEvent event = null;
|
||||
if (isRecoveryRepayment) {
|
||||
@@ -3115,7 +3111,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||
|
||||
final ChangedTransactionDetail changedTransactionDetail = handleRepaymentOrRecoveryOrWaiverTransaction(repaymentTransaction,
|
||||
loanLifecycleStateMachine, null, scheduleGeneratorDTO, currentUser);
|
||||
loanLifecycleStateMachine, null, scheduleGeneratorDTO);
|
||||
|
||||
return changedTransactionDetail;
|
||||
}
|
||||
@@ -3184,7 +3180,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
|
||||
private ChangedTransactionDetail handleRepaymentOrRecoveryOrWaiverTransaction(final LoanTransaction loanTransaction,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
|
||||
ChangedTransactionDetail changedTransactionDetail = null;
|
||||
|
||||
@@ -3289,7 +3285,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
if (reprocess) {
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
}
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
|
||||
@@ -3457,8 +3453,8 @@ public class Loan extends AbstractPersistableCustom {
|
||||
BigDecimal penaltyToPost = cumulativeIncomeFromInstallments.get("penalty")
|
||||
.subtract(cumulativeIncomeFromIncomePosting.get("penalty"));
|
||||
BigDecimal amountToPost = interestToPost.add(feeToPost).add(penaltyToPost);
|
||||
LoanTransaction finalIncomeTransaction = LoanTransaction.incomePosting(this, this.getOffice(), closedDate, amountToPost,
|
||||
interestToPost, feeToPost, penaltyToPost, null);
|
||||
LoanTransaction finalIncomeTransaction = LoanTransaction.incomePosting(this, this.getOffice(), closedLocalDate, amountToPost,
|
||||
interestToPost, feeToPost, penaltyToPost);
|
||||
addLoanTransaction(finalIncomeTransaction);
|
||||
if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
|
||||
List<LoanTransaction> updatedAccrualTransactions = retreiveListOfAccrualTransactions();
|
||||
@@ -3469,7 +3465,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
HashMap<String, Object> feeDetails = new HashMap<>();
|
||||
determineFeeDetails(lastAccruedDate, closedLocalDate, feeDetails);
|
||||
LoanTransaction finalAccrual = LoanTransaction.accrueTransaction(this, this.getOffice(), closedLocalDate, amountToPost,
|
||||
interestToPost, feeToPost, penaltyToPost, null);
|
||||
interestToPost, feeToPost, penaltyToPost);
|
||||
updateLoanChargesPaidBy(finalAccrual, feeDetails, null);
|
||||
addLoanTransaction(finalAccrual);
|
||||
}
|
||||
@@ -3607,7 +3603,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
return loanRepaymentScheduleInstallment;
|
||||
}
|
||||
|
||||
public LoanTransaction deriveDefaultInterestWaiverTransaction(final LocalDateTime createdDate, final AppUser currentUser) {
|
||||
public LoanTransaction deriveDefaultInterestWaiverTransaction() {
|
||||
|
||||
final Money totalInterestOutstanding = getTotalInterestOutstandingOnLoan();
|
||||
Money possibleInterestToWaive = totalInterestOutstanding.copy();
|
||||
@@ -3630,13 +3626,13 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
return LoanTransaction.waiver(getOffice(), this, possibleInterestToWaive, transactionDate, possibleInterestToWaive,
|
||||
possibleInterestToWaive.zero(), createdDate, currentUser);
|
||||
possibleInterestToWaive.zero());
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail adjustExistingTransaction(final LoanTransaction newTransactionDetail,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
|
||||
HolidayDetailDTO holidayDetailDTO = scheduleGeneratorDTO.getHolidayDetailDTO();
|
||||
validateActivityNotBeforeLastTransactionDate(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, transactionForAdjustment.getTransactionDate());
|
||||
@@ -3675,14 +3671,14 @@ public class Loan extends AbstractPersistableCustom {
|
||||
|
||||
if (newTransactionDetail.isRepaymentType() || newTransactionDetail.isInterestWaiver()) {
|
||||
changedTransactionDetail = handleRepaymentOrRecoveryOrWaiverTransaction(newTransactionDetail, loanLifecycleStateMachine,
|
||||
transactionForAdjustment, scheduleGeneratorDTO, currentUser);
|
||||
transactionForAdjustment, scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
return changedTransactionDetail;
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail undoWrittenOff(final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
|
||||
validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO);
|
||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||
@@ -3694,7 +3690,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
}
|
||||
ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(
|
||||
getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(),
|
||||
@@ -3766,7 +3762,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
ChangedTransactionDetail changedTransactionDetail = closeDisbursements(scheduleGeneratorDTO,
|
||||
loanRepaymentScheduleTransactionProcessor, currentUser);
|
||||
loanRepaymentScheduleTransactionProcessor);
|
||||
|
||||
validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING);
|
||||
|
||||
@@ -3805,7 +3801,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), writtenOffOnLocalDate, txnExternalId, createdDate, currentUser);
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), writtenOffOnLocalDate, txnExternalId);
|
||||
LocalDate lastTransactionDate = getLastUserTransactionDate();
|
||||
if (lastTransactionDate.isAfter(writtenOffOnLocalDate)) {
|
||||
final String errorMessage = "The date of the writeoff transaction must occur on or before previous transactions.";
|
||||
@@ -3826,14 +3822,14 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
private ChangedTransactionDetail closeDisbursements(final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, final AppUser currentUser) {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor) {
|
||||
ChangedTransactionDetail changedTransactionDetail = null;
|
||||
if (isDisbursementAllowed() && atleastOnceDisbursed()) {
|
||||
this.loanRepaymentScheduleDetail.setPrincipal(getDisbursedAmount());
|
||||
removeDisbursementDetail();
|
||||
regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
}
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
|
||||
@@ -3862,7 +3858,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
|
||||
public ChangedTransactionDetail close(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
||||
final Map<String, Object> changes, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
|
||||
validateAccountStatus(LoanEvent.LOAN_CLOSED);
|
||||
|
||||
@@ -3890,7 +3886,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
ChangedTransactionDetail changedTransactionDetail = closeDisbursements(scheduleGeneratorDTO,
|
||||
loanRepaymentScheduleTransactionProcessor, currentUser);
|
||||
loanRepaymentScheduleTransactionProcessor);
|
||||
|
||||
LoanTransaction loanTransaction = null;
|
||||
if (isOpen()) {
|
||||
@@ -3904,8 +3900,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
changes.put("status", LoanEnumerations.status(this.loanStatus));
|
||||
}
|
||||
this.closedOnDate = Date.from(closureDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), closureDate, txnExternalId,
|
||||
DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), closureDate, txnExternalId);
|
||||
final boolean isLastTransaction = isChronologicallyLatestTransaction(loanTransaction, getLoanTransactions());
|
||||
if (!isLastTransaction) {
|
||||
final String errorMessage = "The closing date of the loan must be on or after latest transaction date.";
|
||||
@@ -5239,8 +5234,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail updateDisbursementDateAndAmountForTranche(final LoanDisbursementDetails disbursementDetails,
|
||||
final JsonCommand command, final Map<String, Object> actualChanges, final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final AppUser currentUser) {
|
||||
final JsonCommand command, final Map<String, Object> actualChanges, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
final Locale locale = command.extractLocale();
|
||||
validateAccountStatus(LoanEvent.LOAN_EDIT_MULTI_DISBURSE_DATE);
|
||||
final BigDecimal principal = command.bigDecimalValueOfParameterNamed(LoanApiConstants.updatedDisbursementPrincipalParameterName,
|
||||
@@ -5266,9 +5260,9 @@ public class Loan extends AbstractPersistableCustom {
|
||||
|
||||
this.loanRepaymentScheduleDetail.setPrincipal(setPrincipalAmount);
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
} else {
|
||||
regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
|
||||
regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
@@ -5365,7 +5359,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail recalculateScheduleFromLastTransaction(final ScheduleGeneratorDTO generatorDTO,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final AppUser currentUser) {
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||
/*
|
||||
@@ -5376,17 +5370,16 @@ public class Loan extends AbstractPersistableCustom {
|
||||
* loanTransaction.getTransactionDate(); } } generatorDTO.setRecalculateFrom(recalculateFrom);
|
||||
*/
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(generatorDTO, currentUser);
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(generatorDTO);
|
||||
} else {
|
||||
regenerateRepaymentSchedule(generatorDTO, currentUser);
|
||||
regenerateRepaymentSchedule(generatorDTO);
|
||||
}
|
||||
return processTransactions();
|
||||
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail handleRegenerateRepaymentScheduleWithInterestRecalculation(final ScheduleGeneratorDTO generatorDTO,
|
||||
final AppUser currentUser) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(generatorDTO, currentUser);
|
||||
public ChangedTransactionDetail handleRegenerateRepaymentScheduleWithInterestRecalculation(final ScheduleGeneratorDTO generatorDTO) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(generatorDTO);
|
||||
return processTransactions();
|
||||
|
||||
}
|
||||
@@ -5413,14 +5406,14 @@ public class Loan extends AbstractPersistableCustom {
|
||||
return changedTransactionDetail;
|
||||
}
|
||||
|
||||
public void regenerateRepaymentScheduleWithInterestRecalculation(final ScheduleGeneratorDTO generatorDTO, final AppUser currentUser) {
|
||||
public void regenerateRepaymentScheduleWithInterestRecalculation(final ScheduleGeneratorDTO generatorDTO) {
|
||||
|
||||
LocalDate lastTransactionDate = getLastUserTransactionDate();
|
||||
final LoanScheduleDTO loanSchedule = getRecalculatedSchedule(generatorDTO);
|
||||
if (loanSchedule == null) {
|
||||
return;
|
||||
}
|
||||
updateLoanSchedule(loanSchedule.getInstallments(), currentUser);
|
||||
updateLoanSchedule(loanSchedule.getInstallments());
|
||||
this.interestRecalculatedOn = DateUtils.getBusinessDate();
|
||||
LocalDate lastRepaymentDate = this.getLastRepaymentPeriodDueDate(true);
|
||||
Set<LoanCharge> charges = this.charges();
|
||||
@@ -5440,7 +5433,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
processPostDisbursementTransactions();
|
||||
processIncomeTransactions(currentUser);
|
||||
processIncomeTransactions();
|
||||
}
|
||||
|
||||
private void updateLoanChargesPaidBy(LoanTransaction accrual, HashMap<String, Object> feeDetails,
|
||||
@@ -5468,7 +5461,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
}
|
||||
|
||||
public void processIncomeTransactions(AppUser currentUser) {
|
||||
public void processIncomeTransactions() {
|
||||
if (this.loanInterestRecalculationDetails != null && this.loanInterestRecalculationDetails.isCompoundingToBePostedAsTransaction()) {
|
||||
LocalDate lastCompoundingDate = this.getDisbursementDate();
|
||||
List<LoanInterestRecalcualtionAdditionalDetails> compoundingDetails = extractInterestRecalculationAdditionalDetails();
|
||||
@@ -5480,8 +5473,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
LoanTransaction incomeTransaction = getTransactionForDate(incomeTransactions, compoundingDetail.getEffectiveDate());
|
||||
LoanTransaction accrualTransaction = getTransactionForDate(accrualTransactions, compoundingDetail.getEffectiveDate());
|
||||
addUpdateIncomeAndAccrualTransaction(compoundingDetail, lastCompoundingDate, currentUser, incomeTransaction,
|
||||
accrualTransaction);
|
||||
addUpdateIncomeAndAccrualTransaction(compoundingDetail, lastCompoundingDate, incomeTransaction, accrualTransaction);
|
||||
lastCompoundingDate = compoundingDetail.getEffectiveDate();
|
||||
}
|
||||
List<LoanRepaymentScheduleInstallment> installments = getRepaymentScheduleInstallments();
|
||||
@@ -5501,8 +5493,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
private void addUpdateIncomeAndAccrualTransaction(LoanInterestRecalcualtionAdditionalDetails compoundingDetail,
|
||||
LocalDate lastCompoundingDate, AppUser currentUser, LoanTransaction existingIncomeTransaction,
|
||||
LoanTransaction existingAccrualTransaction) {
|
||||
LocalDate lastCompoundingDate, LoanTransaction existingIncomeTransaction, LoanTransaction existingAccrualTransaction) {
|
||||
BigDecimal interest = BigDecimal.ZERO;
|
||||
BigDecimal fee = BigDecimal.ZERO;
|
||||
BigDecimal penalties = BigDecimal.ZERO;
|
||||
@@ -5525,28 +5516,26 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
if (existingIncomeTransaction == null) {
|
||||
LoanTransaction transaction = LoanTransaction.incomePosting(this, this.getOffice(),
|
||||
Date.from(compoundingDetail.getEffectiveDate().atStartOfDay(ZoneId.systemDefault()).toInstant()),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, currentUser);
|
||||
LoanTransaction transaction = LoanTransaction.incomePosting(this, this.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties);
|
||||
addLoanTransaction(transaction);
|
||||
} else if (existingIncomeTransaction.getAmount(getCurrency()).getAmount().compareTo(compoundingDetail.getAmount()) != 0) {
|
||||
existingIncomeTransaction.reverse();
|
||||
LoanTransaction transaction = LoanTransaction.incomePosting(this, this.getOffice(),
|
||||
Date.from(compoundingDetail.getEffectiveDate().atStartOfDay(ZoneId.systemDefault()).toInstant()),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, currentUser);
|
||||
LoanTransaction transaction = LoanTransaction.incomePosting(this, this.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties);
|
||||
addLoanTransaction(transaction);
|
||||
}
|
||||
|
||||
if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
|
||||
if (existingAccrualTransaction == null) {
|
||||
LoanTransaction accrual = LoanTransaction.accrueTransaction(this, this.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, currentUser);
|
||||
compoundingDetail.getAmount(), interest, fee, penalties);
|
||||
updateLoanChargesPaidBy(accrual, feeDetails, null);
|
||||
addLoanTransaction(accrual);
|
||||
} else if (existingAccrualTransaction.getAmount(getCurrency()).getAmount().compareTo(compoundingDetail.getAmount()) != 0) {
|
||||
existingAccrualTransaction.reverse();
|
||||
LoanTransaction accrual = LoanTransaction.accrueTransaction(this, this.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, currentUser);
|
||||
compoundingDetail.getAmount(), interest, fee, penalties);
|
||||
updateLoanChargesPaidBy(accrual, feeDetails, null);
|
||||
addLoanTransaction(accrual);
|
||||
}
|
||||
@@ -6293,7 +6282,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public Map<String, Object> undoLastDisbursal(ScheduleGeneratorDTO scheduleGeneratorDTO, List<Long> existingTransactionIds,
|
||||
List<Long> existingReversedTransactionIds, AppUser currentUser, Loan loan) {
|
||||
List<Long> existingReversedTransactionIds, Loan loan) {
|
||||
|
||||
validateAccountStatus(LoanEvent.LOAN_DISBURSAL_UNDO_LAST);
|
||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||
@@ -6331,8 +6320,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
}
|
||||
reverseExistingTransactionsTillLastDisbursal(actualDisbursementDate);
|
||||
loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, existingTransactionIds, existingReversedTransactionIds,
|
||||
currentUser);
|
||||
loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, existingTransactionIds, existingReversedTransactionIds);
|
||||
actualChanges.put("undolastdisbursal", "true");
|
||||
actualChanges.put("disbursedAmount", this.getDisbursedAmount());
|
||||
updateLoanSummaryDerivedFields();
|
||||
@@ -6671,16 +6659,14 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail handleForeClosureTransactions(final LoanTransaction repaymentTransaction,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final AppUser appUser) {
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
|
||||
LoanEvent event = LoanEvent.LOAN_FORECLOSURE;
|
||||
validateAccountStatus(event);
|
||||
validateForForeclosure(repaymentTransaction.getTransactionDate());
|
||||
this.loanSubStatus = LoanSubStatus.FORECLOSED.getValue();
|
||||
applyAccurals(appUser);
|
||||
return handleRepaymentOrRecoveryOrWaiverTransaction(repaymentTransaction, loanLifecycleStateMachine, null, scheduleGeneratorDTO,
|
||||
appUser);
|
||||
applyAccurals();
|
||||
return handleRepaymentOrRecoveryOrWaiverTransaction(repaymentTransaction, loanLifecycleStateMachine, null, scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
public Money retrieveAccruedAmountAfterDate(final LocalDate tillDate) {
|
||||
|
||||
+11
-21
@@ -178,13 +178,12 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
|
||||
final Money repaymentAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
LoanTransaction newRepaymentTransaction = null;
|
||||
final LocalDateTime currentDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||
if (isRecoveryRepayment) {
|
||||
newRepaymentTransaction = LoanTransaction.recoveryRepayment(loan.getOffice(), repaymentAmount, paymentDetail, transactionDate,
|
||||
txnExternalId, currentDateTime, currentUser);
|
||||
txnExternalId);
|
||||
} else {
|
||||
newRepaymentTransaction = LoanTransaction.repaymentType(repaymentTransactionType, loan.getOffice(), repaymentAmount,
|
||||
paymentDetail, transactionDate, txnExternalId, currentDateTime, currentUser);
|
||||
paymentDetail, transactionDate, txnExternalId);
|
||||
}
|
||||
|
||||
LocalDate recalculateFrom = null;
|
||||
@@ -196,7 +195,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
|
||||
final ChangedTransactionDetail changedTransactionDetail = loan.makeRepayment(newRepaymentTransaction,
|
||||
defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, isRecoveryRepayment,
|
||||
scheduleGeneratorDTO, currentUser, isHolidayValidationDone);
|
||||
scheduleGeneratorDTO, isHolidayValidationDone);
|
||||
|
||||
saveLoanTransactionWithDataIntegrityViolationChecks(newRepaymentTransaction);
|
||||
|
||||
@@ -361,7 +360,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
public LoanTransaction makeChargePayment(final Loan loan, final Long chargeId, final LocalDate transactionDate,
|
||||
final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText, final String txnExternalId,
|
||||
final Integer transactionType, Integer installmentNumber) {
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
boolean isAccountTransfer = true;
|
||||
checkClientOrGroupActive(loan);
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanChargePaymentPreBusinessEvent(loan));
|
||||
@@ -373,7 +371,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final LoanTransactionType loanTransactionType = LoanTransactionType.fromInt(transactionType);
|
||||
|
||||
final LoanTransaction newPaymentTransaction = LoanTransaction.loanPayment(null, loan.getOffice(), paymentAmout, paymentDetail,
|
||||
transactionDate, txnExternalId, loanTransactionType, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
transactionDate, txnExternalId, loanTransactionType);
|
||||
|
||||
if (loanTransactionType.isRepaymentAtDisbursement()) {
|
||||
loan.handlePayDisbursementTransaction(chargeId, newPaymentTransaction, existingTransactionIds, existingReversedTransactionIds);
|
||||
@@ -445,7 +443,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
public LoanTransaction makeRefund(final Long accountId, final CommandProcessingResultBuilder builderResult,
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText,
|
||||
final String txnExternalId) {
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
boolean isAccountTransfer = true;
|
||||
final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
|
||||
checkClientOrGroupActive(loan);
|
||||
@@ -455,7 +452,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
|
||||
final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
final LoanTransaction newRefundTransaction = LoanTransaction.refund(loan.getOffice(), refundAmount, paymentDetail, transactionDate,
|
||||
txnExternalId, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
txnExternalId);
|
||||
final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled();
|
||||
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(),
|
||||
Date.from(transactionDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), HolidayStatusType.ACTIVE.getValue());
|
||||
@@ -492,7 +489,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
@Override
|
||||
public LoanTransaction makeDisburseTransaction(final Long loanId, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||
final PaymentDetail paymentDetail, final String noteText, final String txnExternalId, final boolean isLoanToLoanTransfer) {
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
final Loan loan = this.loanAccountAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
boolean isAccountTransfer = true;
|
||||
@@ -500,7 +496,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
final Money amount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
LoanTransaction disbursementTransaction = LoanTransaction.disbursement(loan.getOffice(), amount, paymentDetail, transactionDate,
|
||||
txnExternalId, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
txnExternalId);
|
||||
|
||||
// Subtract Previous loan outstanding balance from netDisbursalAmount
|
||||
loan.deductFromNetDisbursalAmount(transactionAmount);
|
||||
@@ -646,11 +642,10 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanCreditBalanceRefundPreBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
|
||||
final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
final LoanTransaction newCreditBalanceRefundTransaction = LoanTransaction.creditBalanceRefund(loan, loan.getOffice(), refundAmount,
|
||||
transactionDate, externalId, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
transactionDate, externalId);
|
||||
|
||||
loan.creditBalanceRefund(newCreditBalanceRefundTransaction, defaultLoanLifecycleStateMachine(), existingTransactionIds,
|
||||
existingReversedTransactionIds);
|
||||
@@ -681,11 +676,10 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanRefundPreBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
|
||||
final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
final LoanTransaction newRefundTransaction = LoanTransaction.refundForActiveLoan(loan.getOffice(), refundAmount, paymentDetail,
|
||||
transactionDate, txnExternalId, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
transactionDate, txnExternalId);
|
||||
final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled();
|
||||
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(),
|
||||
Date.from(transactionDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), HolidayStatusType.ACTIVE.getValue());
|
||||
@@ -716,7 +710,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
public Map<String, Object> foreCloseLoan(final Loan loan, final LocalDate foreClosureDate, final String noteText) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanForeClosurePreBusinessEvent(loan));
|
||||
MonetaryCurrency currency = loan.getCurrency();
|
||||
LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
List<LoanTransaction> newTransactions = new ArrayList<>();
|
||||
|
||||
@@ -737,12 +730,11 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
Money total = interestPortion.plus(feePortion).plus(penaltyPortion);
|
||||
if (total.isGreaterThanZero()) {
|
||||
LoanTransaction accrualTransaction = LoanTransaction.accrueTransaction(loan, loan.getOffice(), foreClosureDate,
|
||||
total.getAmount(), interestPortion.getAmount(), feePortion.getAmount(), penaltyPortion.getAmount(), appUser);
|
||||
total.getAmount(), interestPortion.getAmount(), feePortion.getAmount(), penaltyPortion.getAmount());
|
||||
LocalDate fromDate = loan.getDisbursementDate();
|
||||
if (loan.getAccruedTill() != null) {
|
||||
fromDate = loan.getAccruedTill();
|
||||
}
|
||||
createdDate = createdDate.plusSeconds(1);
|
||||
newTransactions.add(accrualTransaction);
|
||||
loan.addLoanTransaction(accrualTransaction);
|
||||
Set<LoanChargePaidBy> accrualCharges = accrualTransaction.getLoanChargesPaid();
|
||||
@@ -771,16 +763,14 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
String externalId = null;
|
||||
final LocalDateTime currentDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||
payment = LoanTransaction.repayment(loan.getOffice(), payPrincipal.plus(interestPayable).plus(feePayable).plus(penaltyPayable),
|
||||
paymentDetail, foreClosureDate, externalId, currentDateTime, appUser);
|
||||
createdDate = createdDate.plusSeconds(1);
|
||||
payment.updateCreatedDate(Date.from(createdDate.atZone(DateUtils.getDateTimeZoneOfTenant()).toInstant()));
|
||||
paymentDetail, foreClosureDate, externalId);
|
||||
payment.updateLoan(loan);
|
||||
newTransactions.add(payment);
|
||||
}
|
||||
|
||||
List<Long> transactionIds = new ArrayList<>();
|
||||
final ChangedTransactionDetail changedTransactionDetail = loan.handleForeClosureTransactions(payment,
|
||||
defaultLoanLifecycleStateMachine(), scheduleGeneratorDTO, appUser);
|
||||
defaultLoanLifecycleStateMachine(), scheduleGeneratorDTO);
|
||||
|
||||
/***
|
||||
* TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the
|
||||
|
||||
+73
-133
@@ -21,10 +21,8 @@ package org.apache.fineract.portfolio.loanaccount.domain;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -38,10 +36,8 @@ import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
@@ -53,7 +49,6 @@ import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionEnumData;
|
||||
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.apache.fineract.portfolio.paymentdetail.data.PaymentDetailData;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
|
||||
/**
|
||||
* All monetary transactions against a loan are modelled through this entity. Disbursements, Repayments, Waivers,
|
||||
@@ -61,7 +56,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "m_loan_transaction", uniqueConstraints = { @UniqueConstraint(columnNames = { "external_id" }, name = "external_id_UNIQUE") })
|
||||
public class LoanTransaction extends AbstractPersistableCustom {
|
||||
public class LoanTransaction extends AbstractAuditableCustom {
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "loan_id", nullable = false)
|
||||
@@ -78,13 +73,11 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
@Column(name = "transaction_type_enum", nullable = false)
|
||||
private Integer typeOf;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "transaction_date", nullable = false)
|
||||
private Date dateOf;
|
||||
private LocalDate dateOf;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "submitted_on_date", nullable = false)
|
||||
private Date submittedOnDate;
|
||||
private LocalDate submittedOnDate;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal amount;
|
||||
@@ -113,14 +106,6 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
@Column(name = "external_id", length = 100, nullable = true, unique = true)
|
||||
private String externalId;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "created_date", nullable = false)
|
||||
private Date createdDate;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "appuser_id", nullable = true)
|
||||
private AppUser appUser;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loanTransaction", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private Set<LoanChargePaidBy> loanChargesPaid = new HashSet<>();
|
||||
|
||||
@@ -136,44 +121,34 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanTransaction")
|
||||
private Set<LoanTransactionToRepaymentScheduleMapping> loanTransactionToRepaymentScheduleMappings = new HashSet<>();
|
||||
|
||||
protected LoanTransaction() {
|
||||
/*
|
||||
* this.loan = null; this.dateOf = null; this.typeOf = null; this.submittedOnDate = DateUtils.getDateOfTenant();
|
||||
* this.createdDate = new Date(); this.appUser = null;
|
||||
*/
|
||||
}
|
||||
protected LoanTransaction() {}
|
||||
|
||||
public static LoanTransaction incomePosting(final Loan loan, final Office office, final Date dateOf, final BigDecimal amount,
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
|
||||
final AppUser appUser) {
|
||||
public static LoanTransaction incomePosting(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion) {
|
||||
final Integer typeOf = LoanTransactionType.INCOME_POSTING.getValue();
|
||||
final BigDecimal principalPortion = BigDecimal.ZERO;
|
||||
final BigDecimal overPaymentPortion = BigDecimal.ZERO;
|
||||
final boolean reversed = false;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final String externalId = null;
|
||||
final LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
|
||||
return new LoanTransaction(loan, office, typeOf, dateOf, amount, principalPortion, interestPortion, feeChargesPortion,
|
||||
penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId, createdDate, appUser);
|
||||
penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction disbursement(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate disbursementDate, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDate disbursementDate, final String externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.DISBURSEMENT, paymentDetail, amount.getAmount(), disbursementDate,
|
||||
externalId, createdDate, appUser);
|
||||
externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction repayment(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REPAYMENT, paymentDetail, amount.getAmount(), paymentDate, externalId,
|
||||
createdDate, appUser);
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REPAYMENT, paymentDetail, amount.getAmount(), paymentDate, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction repaymentType(final LoanTransactionType repaymentType, final Office office, final Money amount,
|
||||
final PaymentDetail paymentDetail, final LocalDate paymentDate, final String externalId, final LocalDateTime createdDate,
|
||||
final AppUser appUser) {
|
||||
return new LoanTransaction(null, office, repaymentType, paymentDetail, amount.getAmount(), paymentDate, externalId, createdDate,
|
||||
appUser);
|
||||
final PaymentDetail paymentDetail, final LocalDate paymentDate, final String externalId) {
|
||||
return new LoanTransaction(null, office, repaymentType, paymentDetail, amount.getAmount(), paymentDate, externalId);
|
||||
}
|
||||
|
||||
public void setLoanTransactionToRepaymentScheduleMappings(final Integer installmentId, final BigDecimal chargePerInstallment) {
|
||||
@@ -189,34 +164,32 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public static LoanTransaction recoveryRepayment(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.RECOVERY_REPAYMENT, paymentDetail, amount.getAmount(), paymentDate,
|
||||
externalId, createdDate, appUser);
|
||||
externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction loanPayment(final Loan loan, final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LoanTransactionType transactionType,
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, transactionType, paymentDetail, amount.getAmount(), paymentDate, externalId, createdDate,
|
||||
appUser);
|
||||
final LocalDate paymentDate, final String externalId, final LoanTransactionType transactionType) {
|
||||
return new LoanTransaction(loan, office, transactionType, paymentDetail, amount.getAmount(), paymentDate, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction repaymentAtDisbursement(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT, paymentDetail, amount.getAmount(),
|
||||
paymentDate, externalId, createdDate, appUser);
|
||||
paymentDate, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction waiver(final Office office, final Loan loan, final Money amount, final LocalDate waiveDate,
|
||||
final Money waived, final Money unrecognizedPortion, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final Money waived, final Money unrecognizedPortion) {
|
||||
LoanTransaction loanTransaction = new LoanTransaction(loan, office, LoanTransactionType.WAIVE_INTEREST, amount.getAmount(),
|
||||
waiveDate, null, createdDate, appUser);
|
||||
waiveDate, null);
|
||||
loanTransaction.updateInterestComponent(waived, unrecognizedPortion);
|
||||
return loanTransaction;
|
||||
}
|
||||
|
||||
public static LoanTransaction accrueInterest(final Office office, final Loan loan, final Money amount,
|
||||
final LocalDate interestAppliedDate, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDate interestAppliedDate) {
|
||||
BigDecimal principalPortion = null;
|
||||
BigDecimal feesPortion = null;
|
||||
BigDecimal penaltiesPortion = null;
|
||||
@@ -225,96 +198,80 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
boolean reversed = false;
|
||||
PaymentDetail paymentDetail = null;
|
||||
String externalId = null;
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL.getValue(),
|
||||
Date.from(interestAppliedDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), interestPortion, principalPortion,
|
||||
interestPortion, feesPortion, penaltiesPortion, overPaymentPortion, reversed, paymentDetail, externalId, createdDate,
|
||||
appUser);
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL.getValue(), interestAppliedDate, interestPortion,
|
||||
principalPortion, interestPortion, feesPortion, penaltiesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction accrual(final Loan loan, final Office office, final Money amount, final Money interest,
|
||||
final Money feeCharges, final Money penaltyCharges, final LocalDate transactionDate) {
|
||||
final AppUser appUser = null;
|
||||
return accrueTransaction(loan, office, transactionDate, amount.getAmount(), interest.getAmount(), feeCharges.getAmount(),
|
||||
penaltyCharges.getAmount(), appUser);
|
||||
penaltyCharges.getAmount());
|
||||
}
|
||||
|
||||
public static LoanTransaction accrueTransaction(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
|
||||
final AppUser appUser) {
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion) {
|
||||
BigDecimal principalPortion = null;
|
||||
BigDecimal overPaymentPortion = null;
|
||||
boolean reversed = false;
|
||||
PaymentDetail paymentDetail = null;
|
||||
String externalId = null;
|
||||
LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL.getValue(),
|
||||
Date.from(dateOf.atStartOfDay(ZoneId.systemDefault()).toInstant()), amount, principalPortion, interestPortion,
|
||||
feeChargesPortion, penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId, createdDate, appUser);
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL.getValue(), dateOf, amount, principalPortion, interestPortion,
|
||||
feeChargesPortion, penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction initiateTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.INITIATE_TRANSFER.getValue(),
|
||||
Date.from(transferDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), loan.getSummary().getTotalOutstanding(),
|
||||
loan.getSummary().getTotalPrincipalOutstanding(), loan.getSummary().getTotalInterestOutstanding(),
|
||||
loan.getSummary().getTotalFeeChargesOutstanding(), loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null,
|
||||
null, createdDate, appUser);
|
||||
public static LoanTransaction initiateTransfer(final Office office, final Loan loan, final LocalDate transferDate) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.INITIATE_TRANSFER.getValue(), transferDate,
|
||||
loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
|
||||
loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, null);
|
||||
}
|
||||
|
||||
public static LoanTransaction approveTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.APPROVE_TRANSFER.getValue(),
|
||||
Date.from(transferDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), loan.getSummary().getTotalOutstanding(),
|
||||
loan.getSummary().getTotalPrincipalOutstanding(), loan.getSummary().getTotalInterestOutstanding(),
|
||||
loan.getSummary().getTotalFeeChargesOutstanding(), loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null,
|
||||
null, createdDate, appUser);
|
||||
public static LoanTransaction approveTransfer(final Office office, final Loan loan, final LocalDate transferDate) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.APPROVE_TRANSFER.getValue(), transferDate,
|
||||
loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
|
||||
loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, null);
|
||||
}
|
||||
|
||||
public static LoanTransaction withdrawTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WITHDRAW_TRANSFER.getValue(),
|
||||
Date.from(transferDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), loan.getSummary().getTotalOutstanding(),
|
||||
loan.getSummary().getTotalPrincipalOutstanding(), loan.getSummary().getTotalInterestOutstanding(),
|
||||
loan.getSummary().getTotalFeeChargesOutstanding(), loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null,
|
||||
null, createdDate, appUser);
|
||||
public static LoanTransaction withdrawTransfer(final Office office, final Loan loan, final LocalDate transferDate) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WITHDRAW_TRANSFER.getValue(), transferDate,
|
||||
loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
|
||||
loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, null);
|
||||
}
|
||||
|
||||
public static LoanTransaction refund(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REFUND, paymentDetail, amount.getAmount(), paymentDate, externalId,
|
||||
createdDate, appUser);
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REFUND, paymentDetail, amount.getAmount(), paymentDate, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction copyTransactionProperties(final LoanTransaction loanTransaction) {
|
||||
return new LoanTransaction(loanTransaction.loan, loanTransaction.office, loanTransaction.typeOf, loanTransaction.dateOf,
|
||||
loanTransaction.amount, loanTransaction.principalPortion, loanTransaction.interestPortion,
|
||||
loanTransaction.feeChargesPortion, loanTransaction.penaltyChargesPortion, loanTransaction.overPaymentPortion,
|
||||
loanTransaction.reversed, loanTransaction.paymentDetail, loanTransaction.externalId,
|
||||
(loanTransaction.createdDate == null) ? LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant())
|
||||
: LocalDateTime.ofInstant(loanTransaction.createdDate.toInstant(), DateUtils.getDateTimeZoneOfTenant()),
|
||||
loanTransaction.appUser);
|
||||
loanTransaction.reversed, loanTransaction.paymentDetail, loanTransaction.externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction accrueLoanCharge(final Loan loan, final Office office, final Money amount, final LocalDate applyDate,
|
||||
final Money feeCharges, final Money penaltyCharges, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final Money feeCharges, final Money penaltyCharges) {
|
||||
String externalId = null;
|
||||
final LoanTransaction applyCharge = new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL, amount.getAmount(), applyDate,
|
||||
externalId, createdDate, appUser);
|
||||
externalId);
|
||||
applyCharge.updateChargesComponents(feeCharges, penaltyCharges);
|
||||
return applyCharge;
|
||||
}
|
||||
|
||||
public static LoanTransaction creditBalanceRefund(final Loan loan, final Office office, final Money amount, final LocalDate paymentDate,
|
||||
final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final String externalId) {
|
||||
final PaymentDetail paymentDetail = null;
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.CREDIT_BALANCE_REFUND, paymentDetail, amount.getAmount(), paymentDate,
|
||||
externalId, createdDate, appUser);
|
||||
externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction refundForActiveLoan(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REFUND_FOR_ACTIVE_LOAN, paymentDetail, amount.getAmount(), paymentDate,
|
||||
externalId, createdDate, appUser);
|
||||
externalId);
|
||||
}
|
||||
|
||||
public static boolean transactionAmountsMatch(final MonetaryCurrency currency, final LoanTransaction loanTransaction,
|
||||
@@ -330,10 +287,10 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
return false;
|
||||
}
|
||||
|
||||
private LoanTransaction(final Loan loan, final Office office, final Integer typeOf, final Date dateOf, final BigDecimal amount,
|
||||
private LoanTransaction(final Loan loan, final Office office, final Integer typeOf, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal principalPortion, final BigDecimal interestPortion, final BigDecimal feeChargesPortion,
|
||||
final BigDecimal penaltyChargesPortion, final BigDecimal overPaymentPortion, final boolean reversed,
|
||||
final PaymentDetail paymentDetail, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final PaymentDetail paymentDetail, final String externalId) {
|
||||
|
||||
this.loan = loan;
|
||||
this.typeOf = typeOf;
|
||||
@@ -348,52 +305,43 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
this.paymentDetail = paymentDetail;
|
||||
this.office = office;
|
||||
this.externalId = externalId;
|
||||
this.submittedOnDate = DateUtils.getBusinessDate();
|
||||
this.createdDate = Date.from(createdDate.atZone(DateUtils.getDateTimeZoneOfTenant()).toInstant());
|
||||
this.appUser = appUser;
|
||||
this.submittedOnDate = DateUtils.getBusinessLocalDate();
|
||||
}
|
||||
|
||||
public static LoanTransaction waiveLoanCharge(final Loan loan, final Office office, final Money waived, final LocalDate waiveDate,
|
||||
final Money feeChargesWaived, final Money penaltyChargesWaived, final Money unrecognizedCharge, final LocalDateTime createdDate,
|
||||
final AppUser appUser) {
|
||||
final Money feeChargesWaived, final Money penaltyChargesWaived, final Money unrecognizedCharge) {
|
||||
final LoanTransaction waiver = new LoanTransaction(loan, office, LoanTransactionType.WAIVE_CHARGES, waived.getAmount(), waiveDate,
|
||||
null, createdDate, appUser);
|
||||
null);
|
||||
waiver.updateChargesComponents(feeChargesWaived, penaltyChargesWaived, unrecognizedCharge);
|
||||
|
||||
return waiver;
|
||||
}
|
||||
|
||||
public static LoanTransaction writeoff(final Loan loan, final Office office, final LocalDate writeOffDate, final String externalId,
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WRITEOFF, null, writeOffDate, externalId, createdDate, appUser);
|
||||
public static LoanTransaction writeoff(final Loan loan, final Office office, final LocalDate writeOffDate, final String externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WRITEOFF, null, writeOffDate, externalId);
|
||||
}
|
||||
|
||||
private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final BigDecimal amount,
|
||||
final LocalDate date, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDate date, final String externalId) {
|
||||
this.loan = loan;
|
||||
this.typeOf = type.getValue();
|
||||
this.amount = amount;
|
||||
this.dateOf = Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
this.dateOf = date;
|
||||
this.externalId = externalId;
|
||||
this.office = office;
|
||||
this.submittedOnDate = DateUtils.getBusinessDate();
|
||||
this.createdDate = Date.from(createdDate.atZone(DateUtils.getDateTimeZoneOfTenant()).toInstant());
|
||||
this.appUser = appUser;
|
||||
this.submittedOnDate = DateUtils.getBusinessLocalDate();
|
||||
}
|
||||
|
||||
private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final PaymentDetail paymentDetail,
|
||||
final BigDecimal amount, final LocalDate date, final String externalId, final LocalDateTime createdDate,
|
||||
final AppUser appUser) {
|
||||
final BigDecimal amount, final LocalDate date, final String externalId) {
|
||||
this.loan = loan;
|
||||
this.typeOf = type.getValue();
|
||||
this.paymentDetail = paymentDetail;
|
||||
this.amount = amount;
|
||||
this.dateOf = Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
this.dateOf = date;
|
||||
this.externalId = externalId;
|
||||
this.office = office;
|
||||
this.submittedOnDate = DateUtils.getBusinessDate();
|
||||
this.createdDate = Date.from(createdDate.atZone(DateUtils.getDateTimeZoneOfTenant()).toInstant());
|
||||
this.appUser = appUser;
|
||||
this.submittedOnDate = DateUtils.getBusinessLocalDate();
|
||||
}
|
||||
|
||||
public void reverse() {
|
||||
@@ -504,10 +452,10 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public LocalDate getTransactionDate() {
|
||||
return LocalDate.ofInstant(this.dateOf.toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||
return this.dateOf;
|
||||
}
|
||||
|
||||
public Date getDateOf() {
|
||||
public LocalDate getDateOf() {
|
||||
return this.dateOf;
|
||||
}
|
||||
|
||||
@@ -778,14 +726,10 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
this.manuallyAdjustedOrReversed = true;
|
||||
}
|
||||
|
||||
private LocalDate getCreatedDate() {
|
||||
return (this.createdDate == null) ? LocalDate.now(DateUtils.getDateTimeZoneOfTenant())
|
||||
: LocalDate.ofInstant(this.createdDate.toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedDateTime() {
|
||||
return (this.createdDate == null) ? LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant())
|
||||
: LocalDateTime.ofInstant(this.createdDate.toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||
return (this.getCreatedDate().isPresent()
|
||||
? LocalDateTime.ofInstant(this.getCreatedDate().get(), DateUtils.getDateTimeZoneOfTenant())
|
||||
: DateUtils.getLocalDateTimeOfTenant());
|
||||
}
|
||||
|
||||
public boolean isLastTransaction(final LoanTransaction loanTransaction) {
|
||||
@@ -793,7 +737,7 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
if (loanTransaction != null) {
|
||||
isLatest = this.getTransactionDate().isBefore(loanTransaction.getTransactionDate())
|
||||
|| (this.getTransactionDate().isEqual(loanTransaction.getTransactionDate())
|
||||
&& this.getCreatedDate().isBefore(loanTransaction.getCreatedDate()));
|
||||
&& this.getCreatedDateTime().isBefore(loanTransaction.getCreatedDateTime()));
|
||||
}
|
||||
return isLatest;
|
||||
}
|
||||
@@ -801,7 +745,7 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
public boolean isLatestTransaction(final LoanTransaction loanTransaction) {
|
||||
boolean isLatest = false;
|
||||
if (loanTransaction != null) {
|
||||
isLatest = this.getCreatedDate().isBefore(loanTransaction.getCreatedDate());
|
||||
isLatest = this.getCreatedDateTime().isBefore(loanTransaction.getCreatedDateTime());
|
||||
}
|
||||
return isLatest;
|
||||
}
|
||||
@@ -845,10 +789,6 @@ public class LoanTransaction extends AbstractPersistableCustom {
|
||||
return isDisbursement() || isAccrual() || isRepaymentAtDisbursement();
|
||||
}
|
||||
|
||||
public void updateCreatedDate(Date createdDate) {
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
|
||||
public boolean isAccrualTransaction() {
|
||||
return isAccrual();
|
||||
}
|
||||
|
||||
+3
-3
@@ -881,14 +881,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
currentPeriodParams.minusEarlyPaidAmount(unprocessed);
|
||||
updateMapWithAmount(scheduleParams.getPrincipalPortionMap(), unprocessed.negated(), applicableDate);
|
||||
LoanTransaction loanTransaction = LoanTransaction.repayment(null, unprocessed, null,
|
||||
transactionDate, null, DateUtils.getLocalDateTimeOfTenant(), null);
|
||||
transactionDate, null);
|
||||
RecalculationDetail recalculationDetail = new RecalculationDetail(transactionDate, loanTransaction);
|
||||
unprocessedTransactions.add(recalculationDetail);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LoanTransaction loanTransaction = LoanTransaction.repayment(null, unprocessed, null, scheduledDueDate, null,
|
||||
DateUtils.getLocalDateTimeOfTenant(), null);
|
||||
LoanTransaction loanTransaction = LoanTransaction.repayment(null, unprocessed, null, scheduledDueDate,
|
||||
null);
|
||||
RecalculationDetail recalculationDetail = new RecalculationDetail(scheduledDueDate, loanTransaction);
|
||||
unprocessedTransactions.add(recalculationDetail);
|
||||
checkForOutstanding = false;
|
||||
|
||||
+1
-3
@@ -116,7 +116,6 @@ import org.apache.fineract.portfolio.loanproduct.domain.LoanProductVariableInsta
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -878,8 +877,7 @@ public class LoanScheduleAssembler {
|
||||
}
|
||||
final LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
AppUser currentUser = this.context.getAuthenticatedUserIfPresent();
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
private List<LoanTermVariations> adjustExistingVariations(List<LoanTermVariations> variations, List<LoanTermVariations> newVariations,
|
||||
|
||||
+1
-3
@@ -34,7 +34,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -104,8 +103,7 @@ public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePl
|
||||
loan.getLoanTermVariations().clear();
|
||||
final LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
AppUser currentUser = this.context.getAuthenticatedUserIfPresent();
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||
this.loanAccountDomainService.saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withLoanId(loanId) //
|
||||
|
||||
+1
-1
@@ -487,7 +487,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
final LoanScheduleDTO loanSchedule = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms, loan,
|
||||
loanApplicationTerms.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
|
||||
|
||||
loan.updateLoanSchedule(loanSchedule.getInstallments(), appUser);
|
||||
loan.updateLoanSchedule(loanSchedule.getInstallments());
|
||||
loan.recalculateAllCharges();
|
||||
ChangedTransactionDetail changedTransactionDetail = loan.processTransactions();
|
||||
|
||||
|
||||
+1
-1
@@ -499,7 +499,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||
loan.processIncomeTransactions(this.userRepository.fetchSystemUser());
|
||||
loan.processIncomeTransactions();
|
||||
this.loanRepositoryWrapper.saveAndFlush(loan);
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
}
|
||||
|
||||
+3
-3
@@ -1050,7 +1050,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
final JsonQuery query = JsonQuery.from(command.json(), parsedQuery, this.fromJsonHelper);
|
||||
|
||||
final LoanScheduleModel loanSchedule = this.calculationPlatformService.calculateLoanSchedule(query, false);
|
||||
existingLoanApplication.updateLoanSchedule(loanSchedule, currentUser);
|
||||
existingLoanApplication.updateLoanSchedule(loanSchedule);
|
||||
existingLoanApplication.recalculateAllCharges();
|
||||
}
|
||||
|
||||
@@ -1449,7 +1449,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
|| changes.containsKey("expectedDisbursementDate")) {
|
||||
LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
if (loan.isTopup() && loan.getClientId() != null) {
|
||||
@@ -1553,7 +1553,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
|| changes.containsKey(LoanApiConstants.disbursementPrincipalParameterName)) {
|
||||
LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
loan.adjustNetDisbursalAmount(loan.getProposedPrincipal());
|
||||
|
||||
+1
-2
@@ -503,8 +503,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
|
||||
final CurrencyData currencyData = applicationCurrency.toData();
|
||||
|
||||
final LoanTransaction waiveOfInterest = loan.deriveDefaultInterestWaiverTransaction(DateUtils.getLocalDateTimeOfTenant(),
|
||||
currentUser);
|
||||
final LoanTransaction waiveOfInterest = loan.deriveDefaultInterestWaiverTransaction();
|
||||
|
||||
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WAIVE_INTEREST);
|
||||
|
||||
|
||||
+24
-35
@@ -448,7 +448,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||
LoanTransaction disbursementTransaction = LoanTransaction.disbursement(loan.getOffice(), amountToDisburse, paymentDetail,
|
||||
actualDisbursementDate, txnExternalId, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
actualDisbursementDate, txnExternalId);
|
||||
disbursementTransaction.updateLoan(loan);
|
||||
loan.addLoanTransaction(disbursementTransaction);
|
||||
}
|
||||
@@ -713,7 +713,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||
LoanTransaction disbursementTransaction = LoanTransaction.disbursement(loan.getOffice(), disburseAmount, paymentDetail,
|
||||
actualDisbursementDate, txnExternalId, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
actualDisbursementDate, txnExternalId);
|
||||
disbursementTransaction.updateLoan(loan);
|
||||
loan.addLoanTransaction(disbursementTransaction);
|
||||
}
|
||||
@@ -826,8 +826,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
// Remove post dated checks if added.
|
||||
loan.removePostDatedChecks();
|
||||
|
||||
final Map<String, Object> changes = loan.undoDisbursal(scheduleGeneratorDTO, existingTransactionIds, existingReversedTransactionIds,
|
||||
currentUser);
|
||||
final Map<String, Object> changes = loan.undoDisbursal(scheduleGeneratorDTO, existingTransactionIds,
|
||||
existingReversedTransactionIds);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
if (loan.isTopup() && loan.getClientId() != null) {
|
||||
@@ -1050,7 +1050,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final Money transactionAmountAsMoney = Money.of(loan.getCurrency(), transactionAmount);
|
||||
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createPaymentDetail(command, changes);
|
||||
LoanTransaction newTransactionDetail = LoanTransaction.repayment(loan.getOffice(), transactionAmountAsMoney, paymentDetail,
|
||||
transactionDate, txnExternalId, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
transactionDate, txnExternalId);
|
||||
if (transactionToAdjust.isInterestWaiver()) {
|
||||
Money unrecognizedIncome = transactionAmountAsMoney.zero();
|
||||
Money interestComponent = transactionAmountAsMoney;
|
||||
@@ -1062,7 +1062,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
newTransactionDetail = LoanTransaction.waiver(loan.getOffice(), loan, transactionAmountAsMoney, transactionDate,
|
||||
interestComponent, unrecognizedIncome, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
interestComponent, unrecognizedIncome);
|
||||
}
|
||||
|
||||
LocalDate recalculateFrom = null;
|
||||
@@ -1076,7 +1076,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
final ChangedTransactionDetail changedTransactionDetail = loan.adjustExistingTransaction(newTransactionDetail,
|
||||
defaultLoanLifecycleStateMachine(), transactionToAdjust, existingTransactionIds, existingReversedTransactionIds,
|
||||
scheduleGeneratorDTO, currentUser);
|
||||
scheduleGeneratorDTO);
|
||||
|
||||
if (newTransactionDetail.isGreaterThanZero(loan.getPrincpal().getCurrency())) {
|
||||
if (paymentDetail != null) {
|
||||
@@ -1176,7 +1176,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
final LoanTransaction waiveInterestTransaction = LoanTransaction.waiver(loan.getOffice(), loan, transactionAmountAsMoney,
|
||||
transactionDate, interestComponent, unrecognizedIncome, DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
transactionDate, interestComponent, unrecognizedIncome);
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanWaiveInterestBusinessEvent(waiveInterestTransaction));
|
||||
LocalDate recalculateFrom = null;
|
||||
if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
@@ -1185,8 +1185,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
final ChangedTransactionDetail changedTransactionDetail = loan.waiveInterest(waiveInterestTransaction,
|
||||
defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO,
|
||||
currentUser);
|
||||
defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO);
|
||||
|
||||
this.loanTransactionRepository.saveAndFlush(waiveInterestTransaction);
|
||||
|
||||
@@ -1312,7 +1311,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
ChangedTransactionDetail changedTransactionDetail = loan.close(command, defaultLoanLifecycleStateMachine(), changes,
|
||||
existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO, currentUser);
|
||||
existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO);
|
||||
final LoanTransaction possibleClosingTransaction = changedTransactionDetail.getNewTransactionMappings().remove(0L);
|
||||
if (possibleClosingTransaction != null) {
|
||||
this.loanTransactionRepository.saveAndFlush(possibleClosingTransaction);
|
||||
@@ -1561,11 +1560,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
public void runScheduleRecalculation(final Loan loan, final LocalDate recalculateFrom) {
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
ChangedTransactionDetail changedTransactionDetail = loan
|
||||
.handleRegenerateRepaymentScheduleWithInterestRecalculation(generatorDTO, currentUser);
|
||||
.handleRegenerateRepaymentScheduleWithInterestRecalculation(generatorDTO);
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
if (changedTransactionDetail != null) {
|
||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
||||
@@ -1615,7 +1613,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
* the loan product uses Upfront Accruals
|
||||
**/
|
||||
if (loan.status().isActive() && loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
|
||||
final LoanTransaction applyLoanChargeTransaction = loan.handleChargeAppliedTransaction(loanCharge, null, currentUser);
|
||||
final LoanTransaction applyLoanChargeTransaction = loan.handleChargeAppliedTransaction(loanCharge, null);
|
||||
this.loanTransactionRepository.saveAndFlush(applyLoanChargeTransaction);
|
||||
}
|
||||
boolean isAppliedOnBackDate = false;
|
||||
@@ -1868,8 +1866,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
final LoanTransaction waiveTransaction = loan.waiveLoanCharge(loanCharge, defaultLoanLifecycleStateMachine(), changes,
|
||||
existingTransactionIds, existingReversedTransactionIds, loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge,
|
||||
currentUser);
|
||||
existingTransactionIds, existingReversedTransactionIds, loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge);
|
||||
|
||||
this.loanTransactionRepository.saveAndFlush(waiveTransaction);
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
@@ -2113,7 +2110,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Override
|
||||
public LoanTransaction initiateLoanTransfer(final Loan loan, final LocalDate transferDate) {
|
||||
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
this.loanAssembler.setHelpers(loan);
|
||||
checkClientOrGroupActive(loan);
|
||||
validateTransactionsForTransfer(loan, transferDate);
|
||||
@@ -2123,8 +2119,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds());
|
||||
|
||||
final LoanTransaction newTransferTransaction = LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate,
|
||||
DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
final LoanTransaction newTransferTransaction = LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate);
|
||||
loan.addLoanTransaction(newTransferTransaction);
|
||||
loan.setLoanStatus(LoanStatus.TRANSFER_IN_PROGRESS.getValue());
|
||||
|
||||
@@ -2140,14 +2135,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Override
|
||||
public LoanTransaction acceptLoanTransfer(final Loan loan, final LocalDate transferDate, final Office acceptedInOffice,
|
||||
final Staff loanOfficer) {
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
this.loanAssembler.setHelpers(loan);
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanAcceptTransferBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds());
|
||||
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate,
|
||||
DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate);
|
||||
loan.addLoanTransaction(newTransferAcceptanceTransaction);
|
||||
if (loan.getTotalOverpaid() != null) {
|
||||
loan.setLoanStatus(LoanStatus.OVERPAID.getValue());
|
||||
@@ -2170,15 +2163,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Transactional
|
||||
@Override
|
||||
public LoanTransaction withdrawLoanTransfer(final Loan loan, final LocalDate transferDate) {
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
this.loanAssembler.setHelpers(loan);
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanWithdrawTransferBusinessEvent(loan));
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds());
|
||||
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate,
|
||||
DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate);
|
||||
loan.addLoanTransaction(newTransferAcceptanceTransaction);
|
||||
loan.setLoanStatus(LoanStatus.ACTIVE.getValue());
|
||||
|
||||
@@ -2375,7 +2366,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
loan.setHelpers(null, this.loanSummaryWrapper, this.transactionProcessingStrategy);
|
||||
loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, existingTransactionIds,
|
||||
existingReversedTransactionIds, currentUser);
|
||||
existingReversedTransactionIds);
|
||||
createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
||||
} else if (reschedulebasedOnMeetingDates != null && reschedulebasedOnMeetingDates) {
|
||||
loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled,
|
||||
@@ -2786,7 +2777,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
|
||||
ChangedTransactionDetail changedTransactionDetail = loan.undoWrittenOff(existingTransactionIds, existingReversedTransactionIds,
|
||||
scheduleGeneratorDTO, currentUser);
|
||||
scheduleGeneratorDTO);
|
||||
if (changedTransactionDetail != null) {
|
||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
||||
this.loanTransactionRepository.save(mapEntry.getValue());
|
||||
@@ -2914,7 +2905,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
if (command.entityId() != null) {
|
||||
|
||||
changedTransactionDetail = loan.updateDisbursementDateAndAmountForTranche(loanDisbursementDetails, command, changes,
|
||||
scheduleGeneratorDTO, currentUser);
|
||||
scheduleGeneratorDTO);
|
||||
} else {
|
||||
// BigDecimal setAmount = loan.getApprovedPrincipal();
|
||||
Collection<LoanDisbursementDetails> loanDisburseDetails = loan.getDisbursementDetails();
|
||||
@@ -2928,9 +2919,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loan.repaymentScheduleDetail().setPrincipal(setAmount);
|
||||
|
||||
if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
loan.regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
|
||||
loan.regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
} else {
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
|
||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||
loan.processPostDisbursementTransactions();
|
||||
}
|
||||
}
|
||||
@@ -3049,7 +3040,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
public void recalculateInterest(final long loanId) {
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
LocalDate recalculateFrom = loan.fetchInterestRecalculateFromDate();
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanInterestRecalculationBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
@@ -3057,7 +3047,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
|
||||
ChangedTransactionDetail changedTransactionDetail = loan.recalculateScheduleFromLastTransaction(generatorDTO,
|
||||
existingTransactionIds, existingReversedTransactionIds, currentUser);
|
||||
existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
@@ -3101,7 +3091,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
||||
BigDecimal emiAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.emiAmountParameterName);
|
||||
loan.regenerateScheduleOnDisbursement(scheduleGeneratorDTO, recalculateSchedule, actualDisbursementDate, emiAmount, currentUser,
|
||||
loan.regenerateScheduleOnDisbursement(scheduleGeneratorDTO, recalculateSchedule, actualDisbursementDate, emiAmount,
|
||||
nextPossibleRepaymentDate, rescheduledRepaymentDate);
|
||||
}
|
||||
|
||||
@@ -3213,7 +3203,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Override
|
||||
@Transactional
|
||||
public CommandProcessingResult undoLastLoanDisbursal(Long loanId, JsonCommand command) {
|
||||
final AppUser currentUser = getAppUserIfPresent();
|
||||
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
final LocalDate recalculateFromDate = loan.getLastRepaymentDate();
|
||||
@@ -3229,7 +3218,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFromDate);
|
||||
|
||||
final Map<String, Object> changes = loan.undoLastDisbursal(scheduleGeneratorDTO, existingTransactionIds,
|
||||
existingReversedTransactionIds, currentUser, loan);
|
||||
existingReversedTransactionIds, loan);
|
||||
if (!changes.isEmpty()) {
|
||||
saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
String noteText = null;
|
||||
|
||||
@@ -38,4 +38,5 @@
|
||||
<include file="parts/0016_changed_unique_constraint_of_ref_no.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0017_fix_stretchy_reports.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0018_pentaho_reports_to_table.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0019_refactor_loan_transaction.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<changeSet author="fineract" id="1">
|
||||
<addColumn tableName="m_loan_transaction">
|
||||
<column name="createdby_id" type="BIGINT" valueComputed="appuser_id"/>
|
||||
<column name="lastmodifiedby_id" type="BIGINT" valueComputed="appuser_id"/>
|
||||
<column name="lastmodified_date" type="DATETIME" valueComputed="created_date"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
<changeSet id="2" author="fineract">
|
||||
<dropColumn tableName="m_loan_transaction">
|
||||
<column name="appuser_id"/>
|
||||
</dropColumn>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="3" context="postgresql">
|
||||
<update tableName="stretchy_report">
|
||||
<column name="report_sql" value="SELECT mc.id AS id, mc.firstname AS firstName, mc.middlename AS middleName, mc.lastname AS lastName, mc.display_name AS fullName, mc.mobile_no AS mobileNo, ml.principal_amount AS loanAmount, (COALESCE(ml.principal_outstanding_derived, 0) + COALESCE(ml.interest_outstanding_derived, 0) + COALESCE(ml.fee_charges_outstanding_derived, 0) + COALESCE(ml.penalty_charges_outstanding_derived, 0)) AS loanOutstanding, ounder.id AS officeNumber, ml.account_no AS loanAccountNumber, SUM(lt.amount) AS repaymentAmount FROM m_office mo JOIN m_office ounder ON ounder.hierarchy LIKE CONCAT(mo.hierarchy, '%') INNER JOIN m_client mc ON mc.office_id = ounder.id INNER JOIN m_loan ml ON ml.client_id = mc.id INNER JOIN r_enum_value rev ON rev.enum_id = ml.loan_status_id AND rev.enum_name = 'loan_status_id' INNER JOIN m_loan_transaction lt ON lt.loan_id = ml.id INNER JOIN m_appuser au ON au.id = lt.createdby_id LEFT JOIN m_loan_arrears_aging laa ON laa.loan_id = ml.id LEFT JOIN m_payment_detail mpd ON mpd.id = lt.payment_detail_id LEFT JOIN m_currency cur ON cur.code = ml.currency_code LEFT JOIN m_group_client gc ON gc.client_id = mc.id LEFT JOIN m_group g ON g.id = gc.group_id LEFT JOIN m_staff lo ON lo.id = ml.loan_officer_id LEFT JOIN m_guarantor gua ON gua.loan_id = ml.id WHERE ml.loan_status_id = 300 AND mo.id = '${officeId}' AND (COALESCE(ml.loan_officer_id, -10) = ${loanOfficerId} OR '-1' = ${loanOfficerId}) AND (EXTRACT(DAY FROM (CURRENT_DATE - lt.transaction_date::TIMESTAMP)) BETWEEN 9${fromX} AND ${toY}) AND lt.is_reversed = false AND lt.transaction_type_enum = 2 AND laa.loan_id IS NULL GROUP BY ml.id, mc.id, ounder.id ORDER BY ounder.hierarchy, ml.currency_code, mc.account_no, ml.account_no"/>
|
||||
<where>id='174' AND report_name='Loan payments received (Active Loans)'</where>
|
||||
</update>
|
||||
<update tableName="stretchy_report">
|
||||
<column name="report_sql" value="SELECT ml.id AS loanId, mc.id AS id, mc.firstname AS firstName, mc.middlename AS middleName, mc.lastname AS lastName, mc.display_name AS fullName, mc.mobile_no AS mobileNo, ml.principal_amount AS loanAmount, (COALESCE(ml.principal_outstanding_derived, 0) + COALESCE(ml.interest_outstanding_derived, 0) + COALESCE(ml.fee_charges_outstanding_derived, 0) + COALESCE(ml.penalty_charges_outstanding_derived, 0)) AS loanOutstanding, ounder.id AS officeNumber, ml.account_no AS loanAccountNumber, SUM(lt.amount) AS repaymentAmount FROM m_office mo JOIN m_office ounder ON ounder.hierarchy LIKE CONCAT(mo.hierarchy, '%') INNER JOIN m_client mc ON mc.office_id = ounder.id INNER JOIN m_loan ml ON ml.client_id = mc.id INNER JOIN r_enum_value rev ON rev.enum_id = ml.loan_status_id AND rev.enum_name = 'loan_status_id' INNER JOIN m_loan_arrears_aging laa ON laa.loan_id = ml.id INNER JOIN m_loan_transaction lt ON lt.loan_id = ml.id INNER JOIN m_appuser au ON au.id = lt.createdby_id LEFT JOIN m_payment_detail mpd ON mpd.id = lt.payment_detail_id LEFT JOIN m_currency cur ON cur.code = ml.currency_code LEFT JOIN m_group_client gc ON gc.client_id = mc.id LEFT JOIN m_group g ON g.id = gc.group_id LEFT JOIN m_staff lo ON lo.id = ml.loan_officer_id LEFT JOIN m_guarantor gua ON gua.loan_id = ml.id WHERE ml.loan_status_id = 300 AND mo.id = '${officeId}' AND (COALESCE(ml.loan_officer_id, -10) = ${loanOfficerId} OR '-1' = ${loanOfficerId}) AND (EXTRACT(DAY FROM(CURRENT_DATE - lt.transaction_date::TIMESTAMP)) BETWEEN ${fromX} AND ${toY}) AND (EXTRACT(DAY FROM(CURRENT_DATE - laa.overdue_since_date_derived::TIMESTAMP)) BETWEEN ${overdueX} AND ${overdueY}) AND lt.is_reversed = false AND lt.transaction_type_enum = 2 GROUP BY ml.id, mc.id, ounder.id ORDER BY ounder.hierarchy, ml.currency_code, mc.account_no, ml.account_no"/>
|
||||
<where>id='175' AND report_name='Loan payments received (Overdue Loans)'</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="4" context="mysql">
|
||||
<update tableName="stretchy_report">
|
||||
<column name="report_sql"
|
||||
value="SELECT mc.id AS "id", mc.firstname AS "firstName", mc.middlename AS "middleName", mc.lastname AS "lastName", mc.display_name AS "fullName", mc.mobile_no AS "mobileNo", ml.principal_amount AS "loanAmount", (IFNULL(ml.principal_outstanding_derived, 0) + IFNULL(ml.interest_outstanding_derived, 0) + IFNULL(ml.fee_charges_outstanding_derived, 0) + IFNULL(ml.penalty_charges_outstanding_derived, 0)) AS "loanOutstanding", ounder.id AS "officeNumber", ml.account_no AS "loanAccountNumber", SUM(lt.amount) AS "repaymentAmount" FROM m_office mo JOIN m_office ounder ON ounder.hierarchy LIKE CONCAT(mo.hierarchy, '%') INNER JOIN m_client mc ON mc.office_id=ounder.id INNER JOIN m_loan ml ON ml.client_id = mc.id INNER JOIN r_enum_value rev ON rev.enum_id=ml.loan_status_id AND rev.enum_name = 'loan_status_id' INNER JOIN m_loan_transaction lt ON lt.loan_id = ml.id INNER JOIN m_appuser au ON au.id = lt.createdby_id LEFT JOIN m_loan_arrears_aging laa ON laa.loan_id=ml.id LEFT JOIN m_payment_detail mpd ON mpd.id=lt.payment_detail_id LEFT JOIN m_currency cur ON cur.code = ml.currency_code LEFT JOIN m_group_client gc ON gc.client_id = mc.id LEFT JOIN m_group g ON g.id = gc.group_id LEFT JOIN m_staff lo ON lo.id = ml.loan_officer_id LEFT JOIN m_guarantor gua ON gua.loan_id = ml.id WHERE ml.loan_status_id=300 AND mo.id=${officeId} AND (IFNULL(ml.loan_officer_id, -10) = ${loanOfficerId} OR "-1" = ${loanOfficerId}) AND (DATEDIFF(CURDATE(), lt.transaction_date) BETWEEN ${fromX} AND ${toY}) AND lt.is_reversed=0 AND lt.transaction_type_enum=2 AND laa.loan_id IS NULL GROUP BY ml.id ORDER BY ounder.hierarchy, ml.currency_code, mc.account_no, ml.account_no"/>
|
||||
<where>id='174' AND report_name='Loan payments received (Active Loans)'</where>
|
||||
</update>
|
||||
<update tableName="stretchy_report">
|
||||
<column name="report_sql"
|
||||
value="SELECT ml.id AS "loanId", mc.id AS "id", mc.firstname AS "firstName", mc.middlename AS "middleName", mc.lastname AS "lastName", mc.display_name AS "fullName", mc.mobile_no AS "mobileNo", ml.principal_amount AS "loanAmount", (IFNULL(ml.principal_outstanding_derived, 0) + IFNULL(ml.interest_outstanding_derived, 0) + IFNULL(ml.fee_charges_outstanding_derived, 0) + IFNULL(ml.penalty_charges_outstanding_derived, 0)) AS "loanOutstanding", ounder.id AS "officeNumber", ml.account_no AS "loanAccountNumber", SUM(lt.amount) AS "repaymentAmount" FROM m_office mo JOIN m_office ounder ON ounder.hierarchy LIKE CONCAT(mo.hierarchy, '%') INNER JOIN m_client mc ON mc.office_id=ounder.id INNER JOIN m_loan ml ON ml.client_id = mc.id INNER JOIN r_enum_value rev ON rev.enum_id=ml.loan_status_id AND rev.enum_name = 'loan_status_id' INNER JOIN m_loan_arrears_aging laa ON laa.loan_id=ml.id INNER JOIN m_loan_transaction lt ON lt.loan_id = ml.id INNER JOIN m_appuser au ON au.id = lt.createdby_id LEFT JOIN m_payment_detail mpd ON mpd.id=lt.payment_detail_id LEFT JOIN m_currency cur ON cur.code = ml.currency_code LEFT JOIN m_group_client gc ON gc.client_id = mc.id LEFT JOIN m_group g ON g.id = gc.group_id LEFT JOIN m_staff lo ON lo.id = ml.loan_officer_id LEFT JOIN m_guarantor gua ON gua.loan_id = ml.id WHERE ml.loan_status_id=300 AND mo.id=${officeId} AND (IFNULL(ml.loan_officer_id, -10) = ${loanOfficerId} OR "-1" = ${loanOfficerId}) AND (DATEDIFF(CURDATE(), lt.transaction_date) BETWEEN ${fromX} AND ${toY}) AND (DATEDIFF(CURDATE(), laa.overdue_since_date_derived) BETWEEN ${overdueX} AND ${overdueY}) AND lt.is_reversed=0 AND lt.transaction_type_enum=2 GROUP BY ml.id ORDER BY ounder.hierarchy, ml.currency_code, mc.account_no, ml.account_no"/>
|
||||
<where>id='175' AND report_name='Loan payments received (Overdue Loans)'</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user