wip:improving tracebililty for loan transaction updates
This commit is contained in:
+26
-6
@@ -29,8 +29,9 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
* existing in which case the entire loan schedule needs to be re-processed.
|
* existing in which case the entire loan schedule needs to be re-processed.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void handleTransaction(final LocalDate disbursementDate, final List<LoanTransaction> transactionsPostDisbursement,
|
public ChangedTransactionDetail handleTransaction(final LocalDate disbursementDate,
|
||||||
final MonetaryCurrency currency, final List<LoanRepaymentScheduleInstallment> installments, final Set<LoanCharge> charges) {
|
final List<LoanTransaction> transactionsPostDisbursement, final MonetaryCurrency currency,
|
||||||
|
final List<LoanRepaymentScheduleInstallment> installments, final Set<LoanCharge> charges) {
|
||||||
|
|
||||||
if (charges != null) {
|
if (charges != null) {
|
||||||
for (LoanCharge loanCharge : charges) {
|
for (LoanCharge loanCharge : charges) {
|
||||||
@@ -49,16 +50,36 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper();
|
LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper();
|
||||||
wrapper.reprocess(currency, disbursementDate, installments, charges);
|
wrapper.reprocess(currency, disbursementDate, installments, charges);
|
||||||
|
|
||||||
|
ChangedTransactionDetail changedTransactionDetail = new ChangedTransactionDetail();
|
||||||
for (LoanTransaction loanTransaction : transactionsPostDisbursement) {
|
for (LoanTransaction loanTransaction : transactionsPostDisbursement) {
|
||||||
|
|
||||||
if (loanTransaction.isRepayment() || loanTransaction.isInterestWaiver()) {
|
if (loanTransaction.isRepayment() || loanTransaction.isInterestWaiver()) {
|
||||||
loanTransaction.resetDerivedComponents();
|
// pass through for new transactions
|
||||||
handleTransaction(loanTransaction, currency, installments, charges);
|
if (loanTransaction.getId() == null) {
|
||||||
|
loanTransaction.resetDerivedComponents();
|
||||||
|
handleTransaction(loanTransaction, currency, installments, charges);
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* reverse existing transactions and create new transactions
|
||||||
|
* in their Lieu
|
||||||
|
**/
|
||||||
|
LoanTransaction newLoanTransaction = LoanTransaction.copyTransactionProperties(loanTransaction);
|
||||||
|
|
||||||
|
// Reverse the original loan transaction
|
||||||
|
loanTransaction.reverse();
|
||||||
|
changedTransactionDetail.getReversedTransactions().add(loanTransaction);
|
||||||
|
// Reset derived component of new loan transaction
|
||||||
|
newLoanTransaction.resetDerivedComponents();
|
||||||
|
changedTransactionDetail.getNewTransactions().add(newLoanTransaction);
|
||||||
|
handleTransaction(newLoanTransaction, currency, installments, charges);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (loanTransaction.isWriteOff()) {
|
} else if (loanTransaction.isWriteOff()) {
|
||||||
loanTransaction.resetDerivedComponents();
|
loanTransaction.resetDerivedComponents();
|
||||||
handleWriteOff(loanTransaction, currency, installments);
|
handleWriteOff(loanTransaction, currency, installments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return changedTransactionDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,8 +170,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
|
|
||||||
for (LoanCharge loanCharge : charges) {
|
for (LoanCharge loanCharge : charges) {
|
||||||
if (loanCharge.isNotFullyPaid() && !loanCharge.isDueAtDisbursement()) {
|
if (loanCharge.isNotFullyPaid() && !loanCharge.isDueAtDisbursement()) {
|
||||||
if (earliestUnpaidCharge == null
|
if (earliestUnpaidCharge == null || loanCharge.getDueLocalDate().isBefore(earliestUnpaidCharge.getDueLocalDate())) {
|
||||||
|| loanCharge.getDueLocalDate().isBefore(earliestUnpaidCharge.getDueLocalDate())) {
|
|
||||||
earliestUnpaidCharge = loanCharge;
|
earliestUnpaidCharge = loanCharge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package org.mifosplatform.portfolio.loanaccount.domain;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ChangedTransactionDetail {
|
||||||
|
|
||||||
|
private List<LoanTransaction> newTransactions = new ArrayList<LoanTransaction>();
|
||||||
|
|
||||||
|
private List<LoanTransaction> reversedTransactions = new ArrayList<LoanTransaction>();
|
||||||
|
|
||||||
|
public List<LoanTransaction> getNewTransactions() {
|
||||||
|
return this.newTransactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewTransactions(List<LoanTransaction> newTransactions) {
|
||||||
|
this.newTransactions = newTransactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<LoanTransaction> getReversedTransactions() {
|
||||||
|
return this.reversedTransactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReversedTransactions(List<LoanTransaction> reversedTransactions) {
|
||||||
|
this.reversedTransactions = reversedTransactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+37
-24
@@ -378,8 +378,9 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
this.accountNumberRequiresAutoGeneration = accountNumberRequiresAutoGeneration;
|
this.accountNumberRequiresAutoGeneration = accountNumberRequiresAutoGeneration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanTransaction addLoanCharge(final LoanCharge loanCharge, final List<Long> existingTransactionIds,
|
public ChangedTransactionDetail addLoanCharge(final LoanCharge loanCharge, final List<Long> existingTransactionIds,
|
||||||
final List<Long> existingReversedTransactionIds) {
|
final List<Long> existingReversedTransactionIds) {
|
||||||
|
ChangedTransactionDetail changedTransactionDetail = null;
|
||||||
|
|
||||||
validateLoanIsNotClosed(loanCharge);
|
validateLoanIsNotClosed(loanCharge);
|
||||||
|
|
||||||
@@ -412,8 +413,11 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
if (!loanCharge.isDueAtDisbursement()) {
|
if (!loanCharge.isDueAtDisbursement()) {
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
|
||||||
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
|
for (LoanTransaction transaction : changedTransactionDetail.getNewTransactions()) {
|
||||||
|
transaction.updateLoan(this);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// just reprocess the loan schedule only for now.
|
// just reprocess the loan schedule only for now.
|
||||||
LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper();
|
LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper();
|
||||||
@@ -424,9 +428,8 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||||
final LoanTransaction applyLoanChargeTransaction = getChargeAppliedTransaction(loanCharge, null);
|
|
||||||
|
|
||||||
return applyLoanChargeTransaction;
|
return changedTransactionDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -441,7 +444,7 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
* @param suppliedTransactionDate
|
* @param suppliedTransactionDate
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private LoanTransaction getChargeAppliedTransaction(final LoanCharge loanCharge, final LocalDate suppliedTransactionDate) {
|
public LoanTransaction getChargeAppliedTransaction(final LoanCharge loanCharge, final LocalDate suppliedTransactionDate) {
|
||||||
final Money chargeAmount = loanCharge.getAmount(getCurrency());
|
final Money chargeAmount = loanCharge.getAmount(getCurrency());
|
||||||
Money feeCharges = chargeAmount;
|
Money feeCharges = chargeAmount;
|
||||||
Money penaltyCharges = Money.zero(loanCurrency());
|
Money penaltyCharges = Money.zero(loanCurrency());
|
||||||
@@ -615,6 +618,14 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||||
.determineProcessor(this.transactionProcessingStrategy);
|
.determineProcessor(this.transactionProcessingStrategy);
|
||||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
||||||
|
/****
|
||||||
|
* TODO vishwas Currently we do not allow waiving fully paid loan
|
||||||
|
* charge and waiving partially paid loan charges only waives the
|
||||||
|
* remaining amount.
|
||||||
|
*
|
||||||
|
* Consider removing this block of code or logically completing it
|
||||||
|
* for the future by getting the list of affected Transactions
|
||||||
|
***/
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||||
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
@@ -1396,24 +1407,24 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return waiveInterestTransaction;
|
return waiveInterestTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanTransaction makeRepayment(final LocalDate transactionDate, final BigDecimal transactionAmount,
|
public ChangedTransactionDetail makeRepayment(final LoanTransaction repaymentTransaction,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
||||||
final List<Long> existingReversedTransactionIds) {
|
final List<Long> existingReversedTransactionIds) {
|
||||||
|
|
||||||
final Money repayment = Money.of(loanCurrency(), transactionAmount);
|
|
||||||
final LoanTransaction loanTransaction = LoanTransaction.repayment(repayment, transactionDate);
|
|
||||||
|
|
||||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||||
|
|
||||||
handleRepaymentOrWaiverTransaction(loanTransaction, loanLifecycleStateMachine, null);
|
ChangedTransactionDetail changedTransactionDetail = handleRepaymentOrWaiverTransaction(repaymentTransaction,
|
||||||
|
loanLifecycleStateMachine, null);
|
||||||
|
|
||||||
return loanTransaction;
|
return changedTransactionDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRepaymentOrWaiverTransaction(final LoanTransaction loanTransaction,
|
private ChangedTransactionDetail handleRepaymentOrWaiverTransaction(final LoanTransaction loanTransaction,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction) {
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction) {
|
||||||
|
|
||||||
|
ChangedTransactionDetail changedTransactionDetail = null;
|
||||||
|
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
|
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
LoanStatus.fromInt(this.loanStatus));
|
||||||
this.loanStatus = statusEnum.getValue();
|
this.loanStatus = statusEnum.getValue();
|
||||||
@@ -1463,13 +1474,18 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
setOfLoanCharges());
|
setOfLoanCharges());
|
||||||
} else {
|
} else {
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
|
||||||
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
|
for (LoanTransaction newLoanTransaction : changedTransactionDetail.getNewTransactions()) {
|
||||||
|
newLoanTransaction.updateLoan(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLoanSummaryDerivedFields();
|
updateLoanSummaryDerivedFields();
|
||||||
|
|
||||||
doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
||||||
|
|
||||||
|
return changedTransactionDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<LoanTransaction> retreiveListOfTransactionsPostDisbursement() {
|
private List<LoanTransaction> retreiveListOfTransactionsPostDisbursement() {
|
||||||
@@ -1614,19 +1630,15 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return LoanTransaction.waiver(this, possibleInterestToWaive, transactionDate);
|
return LoanTransaction.waiver(this, possibleInterestToWaive, transactionDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanTransaction adjustExistingTransaction(final LocalDate transactionDate, final BigDecimal transactionAmountValue,
|
public ChangedTransactionDetail adjustExistingTransaction(final LoanTransaction newTransactionDetail,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment,
|
||||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||||
|
|
||||||
|
ChangedTransactionDetail changedTransactionDetail = null;
|
||||||
|
|
||||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||||
|
|
||||||
final Money transactionAmount = Money.of(loanCurrency(), transactionAmountValue);
|
|
||||||
LoanTransaction newTransactionDetail = LoanTransaction.repayment(transactionAmount, transactionDate);
|
|
||||||
if (transactionForAdjustment.isInterestWaiver()) {
|
|
||||||
newTransactionDetail = LoanTransaction.waiver(this, transactionAmount, transactionDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transactionForAdjustment.isNotRepayment() && transactionForAdjustment.isNotWaiver()) {
|
if (transactionForAdjustment.isNotRepayment() && transactionForAdjustment.isNotWaiver()) {
|
||||||
final String errorMessage = "Only transactions of type repayment or waiver can be adjusted.";
|
final String errorMessage = "Only transactions of type repayment or waiver can be adjusted.";
|
||||||
throw new InvalidLoanTransactionTypeException("transaction", "adjustment.is.only.allowed.to.repayment.or.waiver.transaction",
|
throw new InvalidLoanTransactionTypeException("transaction", "adjustment.is.only.allowed.to.repayment.or.waiver.transaction",
|
||||||
@@ -1640,10 +1652,11 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
transactionForAdjustment.reverse();
|
transactionForAdjustment.reverse();
|
||||||
if (newTransactionDetail.isRepayment() || newTransactionDetail.isInterestWaiver()) {
|
if (newTransactionDetail.isRepayment() || newTransactionDetail.isInterestWaiver()) {
|
||||||
handleRepaymentOrWaiverTransaction(newTransactionDetail, loanLifecycleStateMachine, transactionForAdjustment);
|
changedTransactionDetail = handleRepaymentOrWaiverTransaction(newTransactionDetail, loanLifecycleStateMachine,
|
||||||
|
transactionForAdjustment);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newTransactionDetail;
|
return changedTransactionDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isOverPaid() {
|
private boolean isOverPaid() {
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ public interface LoanRepaymentScheduleTransactionProcessor {
|
|||||||
void handleTransaction(LoanTransaction loanTransaction, MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> installments,
|
void handleTransaction(LoanTransaction loanTransaction, MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> installments,
|
||||||
Set<LoanCharge> charges);
|
Set<LoanCharge> charges);
|
||||||
|
|
||||||
void handleTransaction(LocalDate disbursementDate, List<LoanTransaction> repaymentsOrWaivers, MonetaryCurrency currency,
|
ChangedTransactionDetail handleTransaction(LocalDate disbursementDate, List<LoanTransaction> repaymentsOrWaivers, MonetaryCurrency currency,
|
||||||
List<LoanRepaymentScheduleInstallment> repaymentScheduleInstallments, Set<LoanCharge> charges);
|
List<LoanRepaymentScheduleInstallment> repaymentScheduleInstallments, Set<LoanCharge> charges);
|
||||||
|
|
||||||
void handleWriteOff(LoanTransaction loanTransaction, MonetaryCurrency loanCurrency,
|
void handleWriteOff(LoanTransaction loanTransaction, MonetaryCurrency loanCurrency,
|
||||||
|
|||||||
+22
-3
@@ -86,14 +86,34 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
|||||||
return new LoanTransaction(loan, LoanTransactionType.WAIVE_INTEREST, waived.getAmount(), waiveDate);
|
return new LoanTransaction(loan, LoanTransactionType.WAIVE_INTEREST, waived.getAmount(), waiveDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoanTransaction applyLoanCharge(final Loan loan, final Money amount, final LocalDate applyDate,
|
public static LoanTransaction copyTransactionProperties(LoanTransaction loanTransaction) {
|
||||||
final Money feeCharges, final Money penaltyCharges) {
|
return new LoanTransaction(loanTransaction.loan, loanTransaction.typeOf, loanTransaction.dateOf, loanTransaction.amount,
|
||||||
|
loanTransaction.principalPortion, loanTransaction.interestPortion, loanTransaction.feeChargesPortion,
|
||||||
|
loanTransaction.penaltyChargesPortion, loanTransaction.reversed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LoanTransaction applyLoanCharge(final Loan loan, final Money amount, final LocalDate applyDate, final Money feeCharges,
|
||||||
|
final Money penaltyCharges) {
|
||||||
LoanTransaction applyCharge = new LoanTransaction(loan, LoanTransactionType.APPLY_CHARGES, amount.getAmount(), applyDate);
|
LoanTransaction applyCharge = new LoanTransaction(loan, LoanTransactionType.APPLY_CHARGES, amount.getAmount(), applyDate);
|
||||||
applyCharge.updateChargesComponents(feeCharges, penaltyCharges);
|
applyCharge.updateChargesComponents(feeCharges, penaltyCharges);
|
||||||
|
|
||||||
return applyCharge;
|
return applyCharge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LoanTransaction(Loan loan, Integer typeOf, Date dateOf, BigDecimal amount, BigDecimal principalPortion,
|
||||||
|
BigDecimal interestPortion, BigDecimal feeChargesPortion, BigDecimal penaltyChargesPortion, boolean reversed) {
|
||||||
|
super();
|
||||||
|
this.loan = loan;
|
||||||
|
this.typeOf = typeOf;
|
||||||
|
this.dateOf = dateOf;
|
||||||
|
this.amount = amount;
|
||||||
|
this.principalPortion = principalPortion;
|
||||||
|
this.interestPortion = interestPortion;
|
||||||
|
this.feeChargesPortion = feeChargesPortion;
|
||||||
|
this.penaltyChargesPortion = penaltyChargesPortion;
|
||||||
|
this.reversed = reversed;
|
||||||
|
}
|
||||||
|
|
||||||
public static LoanTransaction waiveLoanCharge(final Loan loan, final Money waived, final LocalDate waiveDate,
|
public static LoanTransaction waiveLoanCharge(final Loan loan, final Money waived, final LocalDate waiveDate,
|
||||||
final Money feeChargesWaived, final Money penaltyChargesWaived) {
|
final Money feeChargesWaived, final Money penaltyChargesWaived) {
|
||||||
LoanTransaction waiver = new LoanTransaction(loan, LoanTransactionType.WAIVE_CHARGES, waived.getAmount(), waiveDate);
|
LoanTransaction waiver = new LoanTransaction(loan, LoanTransactionType.WAIVE_CHARGES, waived.getAmount(), waiveDate);
|
||||||
@@ -305,7 +325,6 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
|||||||
return thisTransactionData;
|
return thisTransactionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Loan getLoan() {
|
public Loan getLoan() {
|
||||||
return this.loan;
|
return this.loan;
|
||||||
}
|
}
|
||||||
|
|||||||
+59
-8
@@ -21,6 +21,7 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder
|
|||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepository;
|
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepository;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
import org.mifosplatform.organisation.staff.domain.Staff;
|
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||||
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
|
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||||
@@ -32,6 +33,7 @@ import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedExce
|
|||||||
import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException.LOAN_CHARGE_CANNOT_BE_WAIVED_REASON;
|
import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException.LOAN_CHARGE_CANNOT_BE_WAIVED_REASON;
|
||||||
import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException;
|
import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException;
|
||||||
import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand;
|
import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand;
|
||||||
|
import org.mifosplatform.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
|
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
|
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
|
||||||
@@ -207,15 +209,31 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
|
|
||||||
final LoanTransaction loanRepayment = loan.makeRepayment(transactionDate, transactionAmount, defaultLoanLifecycleStateMachine(),
|
final Money repaymentAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||||
existingTransactionIds, existingReversedTransactionIds);
|
final LoanTransaction newRepaymentTransaction = LoanTransaction.repayment(repaymentAmount, transactionDate);
|
||||||
this.loanTransactionRepository.save(loanRepayment);
|
|
||||||
|
final ChangedTransactionDetail changedTransactionDetail = loan.makeRepayment(newRepaymentTransaction,
|
||||||
|
defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
|
||||||
|
this.loanTransactionRepository.save(newRepaymentTransaction);
|
||||||
|
/***
|
||||||
|
* TODO Vishwas Batch save is giving me a
|
||||||
|
* HibernateOptimisticLockingFailureException, looping and saving for
|
||||||
|
* the time being, not a major issue for now as this loop is entered
|
||||||
|
* only in edge cases (when a payment is made before the latest payment
|
||||||
|
* recorded against the loan)
|
||||||
|
***/
|
||||||
|
if (changedTransactionDetail != null) {
|
||||||
|
for (LoanTransaction loanTransaction : changedTransactionDetail.getNewTransactions()) {
|
||||||
|
this.loanTransactionRepository.save(loanTransaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.loanRepository.save(loan);
|
this.loanRepository.save(loan);
|
||||||
|
|
||||||
final String noteText = command.stringValueOfParameterNamed("note");
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
if (StringUtils.isNotBlank(noteText)) {
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
changes.put("note", noteText);
|
changes.put("note", noteText);
|
||||||
Note note = Note.loanTransactionNote(loan, loanRepayment, noteText);
|
Note note = Note.loanTransactionNote(loan, newRepaymentTransaction, noteText);
|
||||||
this.noteRepository.save(note);
|
this.noteRepository.save(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +241,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withCommandId(command.commandId()) //
|
.withCommandId(command.commandId()) //
|
||||||
.withEntityId(loanRepayment.getId()) //
|
.withEntityId(newRepaymentTransaction.getId()) //
|
||||||
.withOfficeId(loan.getOfficeId()) //
|
.withOfficeId(loan.getOfficeId()) //
|
||||||
.withClientId(loan.getClientId()) //
|
.withClientId(loan.getClientId()) //
|
||||||
.withGroupId(loan.getGroupId()) //
|
.withGroupId(loan.getGroupId()) //
|
||||||
@@ -257,13 +275,32 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
|
|
||||||
final LoanTransaction newTransactionDetail = loan.adjustExistingTransaction(transactionDate, transactionAmount,
|
final Money transactionAmountAsMoney = Money.of(loan.getCurrency(), transactionAmount);
|
||||||
|
LoanTransaction newTransactionDetail = LoanTransaction.repayment(transactionAmountAsMoney, transactionDate);
|
||||||
|
if (transactionToAdjust.isInterestWaiver()) {
|
||||||
|
newTransactionDetail = LoanTransaction.waiver(loan, transactionAmountAsMoney, transactionDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
final ChangedTransactionDetail changedTransactionDetail = loan.adjustExistingTransaction(newTransactionDetail,
|
||||||
defaultLoanLifecycleStateMachine(), transactionToAdjust, existingTransactionIds, existingReversedTransactionIds);
|
defaultLoanLifecycleStateMachine(), transactionToAdjust, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
|
||||||
if (newTransactionDetail.isGreaterThanZero(loan.getPrincpal().getCurrency())) {
|
if (newTransactionDetail.isGreaterThanZero(loan.getPrincpal().getCurrency())) {
|
||||||
this.loanTransactionRepository.save(newTransactionDetail);
|
this.loanTransactionRepository.save(newTransactionDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* TODO Vishwas Batch save is giving me a
|
||||||
|
* HibernateOptimisticLockingFailureException, looping and saving for
|
||||||
|
* the time being, not a major issue for now as this loop is entered
|
||||||
|
* only in edge cases (when a payment is made before the latest payment
|
||||||
|
* recorded against the loan)
|
||||||
|
***/
|
||||||
|
if (changedTransactionDetail != null) {
|
||||||
|
for (LoanTransaction loanTransaction : changedTransactionDetail.getNewTransactions()) {
|
||||||
|
this.loanTransactionRepository.save(loanTransaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.loanRepository.save(loan);
|
this.loanRepository.save(loan);
|
||||||
|
|
||||||
final String noteText = command.stringValueOfParameterNamed("note");
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
@@ -495,12 +532,26 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
this.loanChargeRepository.save(loanCharge);
|
this.loanChargeRepository.save(loanCharge);
|
||||||
|
|
||||||
LoanTransaction applyChargeTransaction = loan.addLoanCharge(loanCharge, existingTransactionIds, existingReversedTransactionIds);
|
final LoanTransaction applyLoanChargeTransaction = loan.getChargeAppliedTransaction(loanCharge, null);
|
||||||
|
final ChangedTransactionDetail changedTransactionDetail = loan.addLoanCharge(loanCharge, existingTransactionIds,
|
||||||
|
existingReversedTransactionIds);
|
||||||
|
|
||||||
// we want to apply charge transactions only for those loans charges
|
// we want to apply charge transactions only for those loans charges
|
||||||
// that are applied when a loan is active
|
// that are applied when a loan is active
|
||||||
if (loan.status().isActive()) {
|
if (loan.status().isActive()) {
|
||||||
this.loanTransactionRepository.save(applyChargeTransaction);
|
this.loanTransactionRepository.save(applyLoanChargeTransaction);
|
||||||
|
/***
|
||||||
|
* TODO Vishwas Batch save is giving me a
|
||||||
|
* HibernateOptimisticLockingFailureException, looping and saving
|
||||||
|
* for the time being, not a major issue for now as this loop is
|
||||||
|
* entered only in edge cases (when a payment is made before the
|
||||||
|
* latest payment recorded against the loan)
|
||||||
|
***/
|
||||||
|
if (changedTransactionDetail != null) {
|
||||||
|
for (LoanTransaction loanTransaction : changedTransactionDetail.getNewTransactions()) {
|
||||||
|
this.loanTransactionRepository.save(loanTransaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loanRepository.save(loan);
|
this.loanRepository.save(loan);
|
||||||
|
|||||||
Reference in New Issue
Block a user