MIFOSX-2227 : added mapping between Loan transaction and repayment schedule

This commit is contained in:
pramod
2015-09-18 16:23:52 +05:30
parent 6914b1ee93
commit 0cb619fa80
13 changed files with 471 additions and 130 deletions
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.loanaccount.domain;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -119,6 +120,11 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
@Column(name = "manually_adjusted_or_reversed", nullable = false)
private boolean manuallyAdjustedOrReversed;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "loan_transaction_id", referencedColumnName= "id" , nullable = false)
private Set<LoanTransactionToRepaymentScheduleMapping> loanTransactionToRepaymentScheduleMappings = new HashSet<>();
protected LoanTransaction() {
this.loan = null;
this.dateOf = null;
@@ -640,9 +646,9 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
private LocalDate getCreatedDate() {
return new LocalDate(this.createdDate);
}
public LocalDateTime getCreatedDateTime() {
return new LocalDateTime(this.createdDate);
return new LocalDateTime(this.createdDate);
}
public boolean isLastTransaction(final LoanTransaction loanTransaction) {
@@ -662,4 +668,40 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
}
return isLatest;
}
public void updateLoanTransactionToRepaymentScheduleMappings(final Collection<LoanTransactionToRepaymentScheduleMapping> mappings) {
Collection<LoanTransactionToRepaymentScheduleMapping> retainMappings = new ArrayList<>();
for (LoanTransactionToRepaymentScheduleMapping updatedrepaymentScheduleMapping : mappings) {
updateMapingDetail(retainMappings, updatedrepaymentScheduleMapping);
}
this.loanTransactionToRepaymentScheduleMappings.retainAll(retainMappings);
}
private boolean updateMapingDetail(final Collection<LoanTransactionToRepaymentScheduleMapping> retainMappings,
final LoanTransactionToRepaymentScheduleMapping updatedrepaymentScheduleMapping) {
boolean isMappingUpdated = false;
for (LoanTransactionToRepaymentScheduleMapping repaymentScheduleMapping : this.loanTransactionToRepaymentScheduleMappings) {
if (updatedrepaymentScheduleMapping.getLoanRepaymentScheduleInstallment().getId() != null
&& repaymentScheduleMapping.getLoanRepaymentScheduleInstallment().getDueDate()
.equals(updatedrepaymentScheduleMapping.getLoanRepaymentScheduleInstallment().getDueDate())) {
repaymentScheduleMapping.setComponents(updatedrepaymentScheduleMapping.getPrincipalPortion(),
updatedrepaymentScheduleMapping.getInterestPortion(), updatedrepaymentScheduleMapping.getFeeChargesPortion(),
updatedrepaymentScheduleMapping.getPenaltyChargesPortion());
isMappingUpdated = true;
retainMappings.add(repaymentScheduleMapping);
break;
}
}
if (!isMappingUpdated) {
this.loanTransactionToRepaymentScheduleMappings.add(updatedrepaymentScheduleMapping);
retainMappings.add(updatedrepaymentScheduleMapping);
}
return isMappingUpdated;
}
public Set<LoanTransactionToRepaymentScheduleMapping> getLoanTransactionToRepaymentScheduleMappings() {
return this.loanTransactionToRepaymentScheduleMappings;
}
}
@@ -0,0 +1,145 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.domain;
import java.math.BigDecimal;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_loan_transaction_repayment_schedule_mapping")
public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistable<Long> {
@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
@JoinColumn(name = "loan_repayment_schedule_id", nullable = false)
private LoanRepaymentScheduleInstallment installment;
@Column(name = "principal_portion_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal principalPortion;
@Column(name = "interest_portion_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal interestPortion;
@Column(name = "fee_charges_portion_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal feeChargesPortion;
@Column(name = "penalty_charges_portion_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal penaltyChargesPortion;
@Column(name = "amount", scale = 6, precision = 19)
private BigDecimal amount;
protected LoanTransactionToRepaymentScheduleMapping() {
}
private LoanTransactionToRepaymentScheduleMapping(final LoanRepaymentScheduleInstallment installment,
final BigDecimal principalPortion, final BigDecimal interestPortion, final BigDecimal feeChargesPortion,
final BigDecimal penaltyChargesPortion, final BigDecimal amount) {
this.installment = installment;
this.principalPortion = principalPortion;
this.interestPortion = interestPortion;
this.feeChargesPortion = feeChargesPortion;
this.penaltyChargesPortion = penaltyChargesPortion;
this.amount = amount;
}
public static LoanTransactionToRepaymentScheduleMapping createFrom(final LoanRepaymentScheduleInstallment installment,
final Money principalPortion, final Money interestPortion, final Money feeChargesPortion, final Money penaltyChargesPortion) {
return new LoanTransactionToRepaymentScheduleMapping(installment, defaultToNullIfZero(principalPortion),
defaultToNullIfZero(interestPortion), defaultToNullIfZero(feeChargesPortion), defaultToNullIfZero(penaltyChargesPortion),
defaultToNullIfZero(principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion)));
}
private static BigDecimal defaultToNullIfZero(final Money value) {
BigDecimal result = value.getAmount();
if (value.isZero()) {
result = null;
}
return result;
}
private BigDecimal defaultToZeroIfNull(final BigDecimal value) {
BigDecimal result = value;
if (value == null) {
result = BigDecimal.ZERO;
}
return result;
}
public LoanRepaymentScheduleInstallment getLoanRepaymentScheduleInstallment() {
return this.installment;
}
public void updateComponents(final Money principal, final Money interest, final Money feeCharges, final Money penaltyCharges) {
final MonetaryCurrency currency = principal.getCurrency();
this.principalPortion = defaultToNullIfZero(getPrincipalPortion(currency).plus(principal));
this.interestPortion = defaultToNullIfZero(getInterestPortion(currency).plus(interest));
updateChargesComponents(feeCharges, penaltyCharges);
updateAmount();
}
private void updateAmount() {
this.amount = defaultToZeroIfNull(getPrincipalPortion()).add(defaultToZeroIfNull(getInterestPortion()))
.add(defaultToZeroIfNull(getFeeChargesPortion())).add(defaultToZeroIfNull(getPenaltyChargesPortion()));
}
public void setComponents(final BigDecimal principal, final BigDecimal interest, final BigDecimal feeCharges,
final BigDecimal penaltyCharges) {
this.principalPortion = principal;
this.interestPortion = interest;
this.feeChargesPortion = feeCharges;
this.penaltyChargesPortion = penaltyCharges;
updateAmount();
}
private void updateChargesComponents(final Money feeCharges, final Money penaltyCharges) {
final MonetaryCurrency currency = feeCharges.getCurrency();
this.feeChargesPortion = defaultToNullIfZero(getFeeChargesPortion(currency).plus(feeCharges));
this.penaltyChargesPortion = defaultToNullIfZero(getPenaltyChargesPortion(currency).plus(penaltyCharges));
}
public Money getPrincipalPortion(final MonetaryCurrency currency) {
return Money.of(currency, this.principalPortion);
}
public Money getInterestPortion(final MonetaryCurrency currency) {
return Money.of(currency, this.interestPortion);
}
public Money getFeeChargesPortion(final MonetaryCurrency currency) {
return Money.of(currency, this.feeChargesPortion);
}
public Money getPenaltyChargesPortion(final MonetaryCurrency currency) {
return Money.of(currency, this.penaltyChargesPortion);
}
public BigDecimal getPrincipalPortion() {
return this.principalPortion;
}
public BigDecimal getInterestPortion() {
return this.interestPortion;
}
public BigDecimal getFeeChargesPortion() {
return this.feeChargesPortion;
}
public BigDecimal getPenaltyChargesPortion() {
return this.penaltyChargesPortion;
}
}
@@ -24,6 +24,7 @@ import org.mifosplatform.portfolio.loanaccount.domain.LoanInstallmentCharge;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionType;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.impl.CreocoreLoanRepaymentScheduleTransactionProcessor;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.impl.HeavensFamilyLoanRepaymentScheduleTransactionProcessor;
@@ -170,7 +171,9 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
* reverse the original transaction and update
* changedTransactionDetail accordingly
**/
if (!LoanTransaction.transactionAmountsMatch(currency, loanTransaction, newLoanTransaction)) {
if (LoanTransaction.transactionAmountsMatch(currency, loanTransaction, newLoanTransaction)) {
loanTransaction.updateLoanTransactionToRepaymentScheduleMappings(newLoanTransaction.getLoanTransactionToRepaymentScheduleMappings());
} else{
loanTransaction.reverse();
loanTransaction.updateExternalId(null);
changedTransactionDetail.getNewTransactionMappings().put(loanTransaction.getId(), newLoanTransaction);
@@ -267,6 +270,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
if (amountToProcess != null) {
transactionAmountUnprocessed = amountToProcess;
}
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings = new ArrayList<>();
for (final LoanRepaymentScheduleInstallment currentInstallment : installments) {
if (transactionAmountUnprocessed.isGreaterThanZero()) {
@@ -277,23 +281,24 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
// current installment?
if (isTransactionInAdvanceOfInstallment(installmentIndex, installments, transactionDate, transactionAmountUnprocessed)) {
transactionAmountUnprocessed = handleTransactionThatIsPaymentInAdvanceOfInstallment(currentInstallment,
installments, loanTransaction, transactionDate, transactionAmountUnprocessed);
installments, loanTransaction, transactionDate, transactionAmountUnprocessed, transactionMappings);
} else if (isTransactionALateRepaymentOnInstallment(installmentIndex, installments,
loanTransaction.getTransactionDate())) {
// does this result in a late payment of existing
// installment?
transactionAmountUnprocessed = handleTransactionThatIsALateRepaymentOfInstallment(currentInstallment, installments,
loanTransaction, transactionAmountUnprocessed);
loanTransaction, transactionAmountUnprocessed, transactionMappings);
} else {
// standard transaction
transactionAmountUnprocessed = handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment,
loanTransaction, transactionAmountUnprocessed);
loanTransaction, transactionAmountUnprocessed, transactionMappings);
}
}
}
installmentIndex++;
}
loanTransaction.updateLoanTransactionToRepaymentScheduleMappings(transactionMappings);
return transactionAmountUnprocessed;
}
@@ -327,7 +332,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
if (loanTransaction.isChargePayment()) {
feeAmount = feeCharges;
}
if(unpaidCharge == null) break ; //All are trache charges
if (unpaidCharge == null) break; // All are trache charges
final Money amountPaidTowardsCharge = unpaidCharge.updatePaidAmountBy(amountRemaining, installmentNumber, feeAmount);
if (!amountPaidTowardsCharge.isZero()) {
Set<LoanChargePaidBy> chargesPaidBies = loanTransaction.getLoanChargesPaid();
@@ -421,10 +426,13 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
/**
* For late repayments, how should components of installment be paid off
*
* @param transactionMappings
* TODO
*/
protected abstract Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed);
final Money transactionAmountUnprocessed, final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings);
/**
* This method is responsible for checking if the current transaction is 'an
@@ -444,16 +452,24 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
/**
* For early/'in advance' repayments.
*
* @param transactionMappings
* TODO
*/
protected abstract Money handleTransactionThatIsPaymentInAdvanceOfInstallment(
final LoanRepaymentScheduleInstallment currentInstallment, final List<LoanRepaymentScheduleInstallment> installments,
final LoanTransaction loanTransaction, final LocalDate transactionDate, final Money paymentInAdvance);
final LoanTransaction loanTransaction, final LocalDate transactionDate, final Money paymentInAdvance,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings);
/**
* For normal on-time repayments.
*
* @param transactionMappings
* TODO
*/
protected abstract Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed);
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings);
/**
* Invoked when a transaction results in an over-payment of the full loan.
@@ -489,7 +505,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
public void handleRefund(LoanTransaction loanTransaction, MonetaryCurrency currency,
List<LoanRepaymentScheduleInstallment> installments, final Set<LoanCharge> charges) {
// TODO Auto-generated method stub
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings = new ArrayList<>();
final Comparator<LoanRepaymentScheduleInstallment> byDate = new Comparator<LoanRepaymentScheduleInstallment>() {
@Override
@@ -506,7 +522,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
if (outstanding.isLessThan(due)) {
transactionAmountUnprocessed = handleRefundTransactionPaymentOfInstallment(currentInstallment, loanTransaction,
transactionAmountUnprocessed);
transactionAmountUnprocessed, transactionMappings);
}
@@ -527,7 +543,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
if (penaltyCharges.isGreaterThanZero()) {
undoChargesPaidAmountBy(loanTransaction, penaltyCharges, loanPenalties, installmentNumber);
}
loanTransaction.updateLoanTransactionToRepaymentScheduleMappings(transactionMappings);
}
/**
@@ -537,9 +553,13 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
* Undoes principal, interest, fees and charges of this transaction based on
* the repayment strategy
*
* @param transactionMappings
* TODO
*
*/
protected abstract Money handleRefundTransactionPaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed);
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings);
private void undoChargesPaidAmountBy(final LoanTransaction loanTransaction, final Money feeCharges, final Set<LoanCharge> charges,
final Integer installmentNumber) {
@@ -12,6 +12,7 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.AbstractLoanRepaymentScheduleTransactionProcessor;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
@@ -52,9 +53,10 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL
@Override
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final LocalDate transactionDate, final Money paymentInAdvance) {
final LocalDate transactionDate, final Money paymentInAdvance,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance, transactionMappings);
}
/**
@@ -65,9 +67,10 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL
@Override
protected Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed) {
final Money transactionAmountUnprocessed, final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed,
transactionMappings);
}
/**
@@ -75,7 +78,8 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL
*/
@Override
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
@@ -119,7 +123,10 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL
principalPortion = currentInstallment.payPrincipalComponent(transactionDate, transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion);
}
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
return transactionAmountRemaining;
}
@@ -129,10 +136,11 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL
protected void onLoanOverpayment(final LoanTransaction loanTransaction, final Money loanOverPaymentAmount) {
// dont do anything for with loan over-payment
}
@Override
protected Money handleRefundTransactionPaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
Money transactionAmountRemaining = transactionAmountUnprocessed;
@@ -140,26 +148,29 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
Money feeChargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
Money penaltyChargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
principalPortion = currentInstallment.unpayPrincipalComponent(transactionDate, transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion);
if(transactionAmountRemaining.isGreaterThanZero()) {
interestPortion = currentInstallment.unpayInterestComponent(transactionDate, transactionAmountRemaining);
if (transactionAmountRemaining.isGreaterThanZero()) {
interestPortion = currentInstallment.unpayInterestComponent(transactionDate, transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion);
}
if(transactionAmountRemaining.isGreaterThanZero()) {
feeChargesPortion = currentInstallment.unpayFeeChargesComponent(transactionDate, transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion);
if (transactionAmountRemaining.isGreaterThanZero()) {
feeChargesPortion = currentInstallment.unpayFeeChargesComponent(transactionDate, transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion);
}
if(transactionAmountRemaining.isGreaterThanZero()) {
penaltyChargesPortion = currentInstallment.unpayPenaltyChargesComponent(transactionDate, transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion);
if (transactionAmountRemaining.isGreaterThanZero()) {
penaltyChargesPortion = currentInstallment.unpayPenaltyChargesComponent(transactionDate, transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion);
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
}
@@ -12,6 +12,7 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.AbstractLoanRepaymentScheduleTransactionProcessor;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
@@ -29,7 +30,8 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr
@Override
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final LocalDate transactionDate, final Money paymentInAdvance) {
final LocalDate transactionDate, final Money paymentInAdvance,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final MonetaryCurrency currency = paymentInAdvance.getCurrency();
Money transactionAmountRemaining = paymentInAdvance;
@@ -69,7 +71,10 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
}
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@@ -82,9 +87,10 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr
@Override
protected Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed) {
final Money transactionAmountUnprocessed, List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed,
transactionMappings);
}
/**
@@ -92,7 +98,8 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr
*/
@Override
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
@@ -134,13 +141,17 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
}
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@Override
protected Money handleRefundTransactionPaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
// final MonetaryCurrency currency =
@@ -172,7 +183,10 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@@ -12,6 +12,7 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.AbstractLoanRepaymentScheduleTransactionProcessor;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
@@ -38,9 +39,10 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
@Override
protected Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed) {
final Money transactionAmountUnprocessed, List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed,
transactionMappings);
}
@Override
@@ -69,7 +71,8 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
@Override
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final LocalDate transactionDate, final Money paymentInAdvance) {
final LocalDate transactionDate, final Money paymentInAdvance,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final MonetaryCurrency currency = paymentInAdvance.getCurrency();
Money transactionAmountRemaining = paymentInAdvance;
@@ -120,6 +123,10 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@@ -128,7 +135,8 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
*/
@Override
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
@@ -176,15 +184,20 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@Override
protected void onLoanOverpayment(final LoanTransaction loanTransaction, final Money loanOverPaymentAmount) {}
@Override
protected Money handleRefundTransactionPaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
@@ -215,7 +228,10 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
}
@@ -12,6 +12,7 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.AbstractLoanRepaymentScheduleTransactionProcessor;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
@@ -30,9 +31,10 @@ public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
@Override
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final LocalDate transactionDate, final Money paymentInAdvance) {
final LocalDate transactionDate, final Money paymentInAdvance,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance, transactionMappings);
}
/**
@@ -43,9 +45,10 @@ public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
@Override
protected Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed) {
final Money transactionAmountUnprocessed, List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed,
transactionMappings);
}
/**
@@ -53,7 +56,8 @@ public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
*/
@Override
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
@@ -101,13 +105,17 @@ public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
}
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@Override
protected Money handleRefundTransactionPaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
Money transactionAmountRemaining = transactionAmountUnprocessed;
@@ -137,7 +145,10 @@ public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
}
@@ -12,6 +12,7 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.AbstractLoanRepaymentScheduleTransactionProcessor;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
@@ -45,9 +46,10 @@ public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends Abstrac
@Override
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final LocalDate transactionDate, final Money paymentInAdvance) {
final LocalDate transactionDate, final Money paymentInAdvance,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance, transactionMappings);
}
/**
@@ -57,9 +59,10 @@ public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends Abstrac
@Override
protected Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed) {
final Money transactionAmountUnprocessed, List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed,
transactionMappings);
}
/**
@@ -67,7 +70,8 @@ public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends Abstrac
*/
@Override
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
@@ -115,7 +119,10 @@ public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends Abstrac
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
}
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@@ -123,10 +130,11 @@ public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends Abstrac
protected void onLoanOverpayment(final LoanTransaction loanTransaction, final Money loanOverPaymentAmount) {
// TODO - KW - dont do anything with loan over-payment for now
}
@Override
protected Money handleRefundTransactionPaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
@@ -154,7 +162,10 @@ public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends Abstrac
transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion);
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
}
@@ -12,6 +12,7 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.AbstractLoanRepaymentScheduleTransactionProcessor;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
@@ -30,9 +31,10 @@ public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
@Override
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final LocalDate transactionDate, final Money paymentInAdvance) {
final LocalDate transactionDate, final Money paymentInAdvance,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance, transactionMappings);
}
/**
@@ -43,9 +45,10 @@ public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
@Override
protected Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed) {
final Money transactionAmountUnprocessed, List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed,
transactionMappings);
}
/**
@@ -53,7 +56,8 @@ public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
*/
@Override
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
@@ -101,16 +105,22 @@ public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
}
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@Override
protected Money handleRefundTransactionPaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
//final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
// final MonetaryCurrency currency =
// transactionAmountUnprocessed.getCurrency();
Money transactionAmountRemaining = transactionAmountUnprocessed;
Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency());
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
@@ -138,7 +148,10 @@ public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@@ -12,6 +12,7 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.AbstractLoanRepaymentScheduleTransactionProcessor;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
@@ -52,9 +53,10 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
@Override
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final LocalDate transactionDate, final Money paymentInAdvance) {
final LocalDate transactionDate, final Money paymentInAdvance,
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance);
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance, transactionMappings);
}
/**
@@ -64,7 +66,7 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
@Override
protected Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed) {
final Money transactionAmountUnprocessed, List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
// pay of overdue and current interest due given transaction date
final LocalDate transactionDate = loanTransaction.getTransactionDate();
@@ -80,6 +82,10 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
final Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency());
loanTransaction.updateComponents(principalPortion, interestWaivedPortion, feeChargesPortion, penaltyChargesPortion);
if (interestWaivedPortion.isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestWaivedPortion, feeChargesPortion, penaltyChargesPortion));
}
} else if (loanTransaction.isChargePayment()) {
final Money principalPortion = Money.zero(currency);
final Money interestPortion = Money.zero(currency);
@@ -91,6 +97,10 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion);
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
} else {
final LoanRepaymentScheduleInstallment currentInstallmentBasedOnTransactionDate = nearestInstallment(
@@ -112,6 +122,10 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
final Money principalPortion = Money.zero(currency);
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(installment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
}
}
@@ -124,6 +138,21 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
final Money interestPortion = Money.zero(currency);
loanTransaction.updateComponents(principalPortion, interestPortion, Money.zero(currency), Money.zero(currency));
boolean isMappingUpdated = false;
for (LoanTransactionToRepaymentScheduleMapping repaymentScheduleMapping : transactionMappings) {
if (repaymentScheduleMapping.getLoanRepaymentScheduleInstallment().getDueDate().equals(installment.getDueDate())) {
repaymentScheduleMapping.updateComponents(principalPortion, principalPortion.zero(), principalPortion.zero(),
principalPortion.zero());
isMappingUpdated = true;
break;
}
}
if (!isMappingUpdated
&& principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion)
.isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(installment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
}
}
}
@@ -150,7 +179,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
*/
@Override
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
@@ -197,6 +227,10 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
@@ -213,7 +247,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
@Override
protected Money handleRefundTransactionPaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed,
final List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
// final MonetaryCurrency currency =
@@ -245,7 +280,10 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion,
interestPortion, feeChargesPortion, penaltyChargesPortion));
}
return transactionAmountRemaining;
}
}
@@ -54,23 +54,23 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, final LocalDate scheduleTillDate) {
final ApplicationCurrency applicationCurrency = loanApplicationTerms.getApplicationCurrency();
// 1. generate list of proposed schedule due dates
// generate list of proposed schedule due dates
final LocalDate loanEndDate = this.scheduledDateGenerator.getLastRepaymentDate(loanApplicationTerms, holidayDetailDTO);
loanApplicationTerms.updateLoanEndDate(loanEndDate);
// 2. determine the total charges due at time of disbursement
// determine the total charges due at time of disbursement
final BigDecimal chargesDueAtTimeOfDisbursement = deriveTotalChargesDueAtTimeOfDisbursement(loanCharges);
// 3. setup variables for tracking important facts required for loan
// setup variables for tracking important facts required for loan
// schedule generation.
Money principalDisbursed ;
if(loanApplicationTerms.isMultiDisburseLoan() && loanApplicationTerms.getApprovedPrincipal().isGreaterThanZero()) {
principalDisbursed = loanApplicationTerms.getApprovedPrincipal();
}else {
principalDisbursed = loanApplicationTerms.getPrincipal();
Money principalToBeScheduled;
if (loanApplicationTerms.isMultiDisburseLoan() && loanApplicationTerms.getApprovedPrincipal().isGreaterThanZero()) {
principalToBeScheduled = loanApplicationTerms.getApprovedPrincipal();
} else {
principalToBeScheduled = loanApplicationTerms.getPrincipal();
}
final MonetaryCurrency currency = principalDisbursed.getCurrency();
final MonetaryCurrency currency = principalToBeScheduled.getCurrency();
final int numberOfRepayments = loanApplicationTerms.getNumberOfRepayments();
// variables for cumulative totals
@@ -80,14 +80,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
BigDecimal totalPenaltyChargesCharged = BigDecimal.ZERO;
BigDecimal totalRepaymentExpected = chargesDueAtTimeOfDisbursement;
final BigDecimal totalOutstanding = BigDecimal.ZERO;
Money totalCumulativePrincipal = principalDisbursed.zero();
Money totalCumulativeInterest = principalDisbursed.zero();
Money totalOutstandingInterestPaymentDueToGrace = principalDisbursed.zero();
Money totalCumulativePrincipal = principalToBeScheduled.zero();
Money totalCumulativeInterest = principalToBeScheduled.zero();
Money totalOutstandingInterestPaymentDueToGrace = principalToBeScheduled.zero();
final Collection<LoanScheduleModelPeriod> periods = createNewLoanScheduleListWithDisbursementDetails(numberOfRepayments,
loanApplicationTerms, chargesDueAtTimeOfDisbursement);
// 4. Determine the total interest owed over the full loan for FLAT
// Determine the total interest owed over the full loan for FLAT
// interest method .
Money totalInterestChargedForFullLoanTerm = loanApplicationTerms.calculateTotalInterestCharged(
this.paymentPeriodsInOneYearCalculator, mc);
@@ -104,10 +104,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
// Actual period Number as per the schedule
int periodNumber = 1;
// Actual period Number and interest only repayments
// Actual period Number plus interest only repayments
int instalmentNumber = 1;
Money outstandingBalance = principalDisbursed;
Money outstandingBalance = principalToBeScheduled;
// Set fixed EMI Amount
updateFixedInstallmentAmount(mc, loanApplicationTerms, actualRepaymentDate, periodNumber, outstandingBalance, holidayDetailDTO);
@@ -120,7 +120,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
// details to map
BigDecimal disburseAmt = getDisbursementAmount(loanApplicationTerms, periodStartDate, periods, chargesDueAtTimeOfDisbursement,
disburseDetailMap, isInterestRecalculationRequired(loanApplicationTerms, transactions));
principalDisbursed = principalDisbursed.zero().plus(disburseAmt);
principalToBeScheduled = principalToBeScheduled.zero().plus(disburseAmt);
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().zero().plus(disburseAmt));
outstandingBalance = outstandingBalance.zero().plus(disburseAmt);
}
@@ -228,16 +228,17 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
// updates actual outstanding balance with new
// disbursement detail
outstandingBalance = outstandingBalance.plus(disburseDetail.getValue());
principalDisbursed = principalDisbursed.plus(disburseDetail.getValue());
principalToBeScheduled = principalToBeScheduled.plus(disburseDetail.getValue());
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().plus(disburseDetail.getValue()));
}
}
}
// Adds new interest repayment to the schedule as per the repayment
// process repayments to the schedule as per the repayment
// transaction processor configuration
// will be added only if there is a loan repayment between the
// period for interest first repayment strategies
// will add a new schedule with interest till the transaction date
// for a loan repayment which falls between the
// two periods for interest first repayment strategies
Money earlyPaidAmount = Money.zero(currency);
LoanScheduleModelPeriod lastInstallment = null;
if (isInterestRecalculationRequired(loanApplicationTerms, transactions)) {
@@ -282,7 +283,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
totalOutstandingInterestPaymentDueToGrace = principalInterestForThisPeriod.interestPaymentDueToGrace();
}
Money principalForThisPeriod = principalDisbursed.zero();
Money principalForThisPeriod = principalToBeScheduled.zero();
// applies all the applicable charges to the
// newly
@@ -290,17 +291,17 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
PrincipalInterest principalInterest = new PrincipalInterest(principalForThisPeriod,
interestForThisinstallment, null);
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(periodStartDate,
detail.getTransactionDate(), loanCharges, currency, principalInterest, principalDisbursed,
detail.getTransactionDate(), loanCharges, currency, principalInterest, principalToBeScheduled,
totalCumulativeInterest, numberOfRepayments, true);
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(periodStartDate,
detail.getTransactionDate(), loanCharges, currency, principalInterest, principalDisbursed,
detail.getTransactionDate(), loanCharges, currency, principalInterest, principalToBeScheduled,
totalCumulativeInterest, numberOfRepayments, true);
// 8. sum up real totalInstallmentDue from
// sum up real totalInstallmentDue from
// components
final Money totalInstallmentDue = principalForThisPeriod.plus(interestForThisinstallment)
.plus(feeChargesForInstallment).plus(penaltyChargesForInstallment);
// 9. create repayment period from parts
// create repayment period from parts
installment = LoanScheduleModelRepaymentPeriod.repayment(instalmentNumber, periodStartDate,
detail.getTransactionDate(), principalForThisPeriod, outstandingBalance,
interestForThisinstallment, feeChargesForInstallment, penaltyChargesForInstallment,
@@ -488,7 +489,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
mergeVariationsToMap(principalPortionMap, latePaymentMap, disburseDetailMap, compoundingMap), compoundingMap,
periodStartDateApplicableForInterest, scheduledDueDate, daysInPeriodApplicableForInterest);
if (loanApplicationTerms.getFixedEmiAmount() != null
if (loanApplicationTerms.getFixedEmiAmount() != null
&& loanApplicationTerms.getFixedEmiAmount().compareTo(principalInterestForThisPeriod.interest().getAmount()) != 1) {
String errorMsg = "EMI amount must be greater than : " + principalInterestForThisPeriod.interest().getAmount();
throw new MultiDisbursementEmiAmountException(errorMsg, principalInterestForThisPeriod.interest().getAmount(),
@@ -520,13 +521,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
BigDecimal fixedEmiAmount = loanApplicationTerms.getFixedEmiAmount();
reducePrincipal = applyEarlyPaymentStrategy(loanApplicationTerms, reducePrincipal, totalCumulativePrincipal,
periodNumber + 1, mc, holidayDetailDTO);
if (loanApplicationTerms.getAmortizationMethod().isEqualInstallment() && fixedEmiAmount.compareTo(loanApplicationTerms.getFixedEmiAmount()) != 0) {
if (loanApplicationTerms.getAmortizationMethod().isEqualInstallment()
&& fixedEmiAmount.compareTo(loanApplicationTerms.getFixedEmiAmount()) != 0) {
isEmiAmountChanged = true;
}
principalForThisPeriod = principalForThisPeriod.plus(earlyPaidAmount);
}
// 6. update outstandingLoanBlance using current period
// update outstandingLoanBlance using current period
// 'principalDue'
outstandingBalance = outstandingBalance.minus(principalForThisPeriod.minus(reducedBalance));
@@ -534,21 +536,21 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
principalForThisPeriod = principalForThisPeriod.plus(outstandingBalance);
outstandingBalance = outstandingBalance.zero();
}
if(!isNextRepaymentAvailable){
disburseDetailMap.clear();
if (!isNextRepaymentAvailable) {
disburseDetailMap.clear();
}
// applies charges for the period
PrincipalInterest principalInterest = new PrincipalInterest(principalForThisPeriod, interestForThisinstallment, null);
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges, currency,
principalInterest, principalDisbursed, totalCumulativeInterest, numberOfRepayments, true);
principalInterest, principalToBeScheduled, totalCumulativeInterest, numberOfRepayments, true);
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges,
currency, principalInterest, principalDisbursed, totalCumulativeInterest, numberOfRepayments, true);
currency, principalInterest, principalToBeScheduled, totalCumulativeInterest, numberOfRepayments, true);
totalFeeChargesCharged = totalFeeChargesCharged.add(feeChargesForInstallment.getAmount());
totalPenaltyChargesCharged = totalPenaltyChargesCharged.add(penaltyChargesForInstallment.getAmount());
// 8. sum up real totalInstallmentDue from components
// sum up real totalInstallmentDue from components
final Money totalInstallmentDue = principalForThisPeriod.plus(interestForThisinstallment).plus(feeChargesForInstallment)
.plus(penaltyChargesForInstallment);
@@ -559,7 +561,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
continue;
}
// 9. create repayment period from parts
// create repayment period from parts
LoanScheduleModelPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(instalmentNumber, periodStartDate,
scheduledDueDate, principalForThisPeriod, outstandingBalance, interestForThisinstallment, feeChargesForInstallment,
penaltyChargesForInstallment, totalInstallmentDue, false);
@@ -614,7 +616,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
final Money totalDue = principalForThisPeriod//
.plus(interestForThisinstallment);
// 9. create and replaces repayment period
// create and replaces repayment period
// from parts
installment = LoanScheduleModelRepaymentPeriod.repayment(instalmentNumber, periodStartDate,
detail.getTransactionDate(), principalForThisPeriod, outstandingBalance,
@@ -643,7 +645,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
reducePrincipal = applyEarlyPaymentStrategy(loanApplicationTerms, reducePrincipal,
totalCumulativePrincipal.plus(principalForThisPeriod.minus(principalProcessed)), periodNumber + 1, mc,
holidayDetailDTO);
if (loanApplicationTerms.getAmortizationMethod().isEqualInstallment() && fixedEmiAmount.compareTo(loanApplicationTerms.getFixedEmiAmount()) != 0) {
if (loanApplicationTerms.getAmortizationMethod().isEqualInstallment()
&& fixedEmiAmount.compareTo(loanApplicationTerms.getFixedEmiAmount()) != 0) {
isEmiAmountChanged = true;
}
@@ -694,18 +697,20 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
totalOutstandingInterestPaymentDueToGrace = totalOutstandingInterestPaymentDueToGrace.zero();
}
// 7. determine fees and penalties for charges which depends on total
// determine fees and penalties for charges which depends on total
// loan interest
for (LoanScheduleModelPeriod loanScheduleModelPeriod : periods) {
if (loanScheduleModelPeriod.isRepaymentPeriod()) {
PrincipalInterest principalInterest = new PrincipalInterest(Money.of(currency, loanScheduleModelPeriod.principalDue()),
Money.of(currency, loanScheduleModelPeriod.interestDue()), null);
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
loanScheduleModelPeriod.periodDueDate(), nonCompoundingCharges, currency, principalInterest, principalDisbursed,
totalCumulativeInterest, numberOfRepayments, !loanScheduleModelPeriod.isRecalculatedInterestComponent());
loanScheduleModelPeriod.periodDueDate(), nonCompoundingCharges, currency, principalInterest,
principalToBeScheduled, totalCumulativeInterest, numberOfRepayments,
!loanScheduleModelPeriod.isRecalculatedInterestComponent());
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
loanScheduleModelPeriod.periodDueDate(), nonCompoundingCharges, currency, principalInterest, principalDisbursed,
totalCumulativeInterest, numberOfRepayments, !loanScheduleModelPeriod.isRecalculatedInterestComponent());
loanScheduleModelPeriod.periodDueDate(), nonCompoundingCharges, currency, principalInterest,
principalToBeScheduled, totalCumulativeInterest, numberOfRepayments,
!loanScheduleModelPeriod.isRecalculatedInterestComponent());
totalFeeChargesCharged = totalFeeChargesCharged.add(feeChargesForInstallment.getAmount());
totalPenaltyChargesCharged = totalPenaltyChargesCharged.add(penaltyChargesForInstallment.getAmount());
totalRepaymentExpected = totalRepaymentExpected.add(feeChargesForInstallment.getAmount()).add(
@@ -730,7 +735,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
loanApplicationTerms.resetFixedEmiAmount();
return LoanScheduleModel.from(periods, applicationCurrency, loanTermInDays, principalDisbursed,
return LoanScheduleModel.from(periods, applicationCurrency, loanTermInDays, principalToBeScheduled,
totalCumulativePrincipal.getAmount(), totalPrincipalPaid, totalCumulativeInterest.getAmount(), totalFeeChargesCharged,
totalPenaltyChargesCharged, totalRepaymentExpected, totalOutstanding);
}
@@ -943,8 +948,9 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
updateFixedInstallmentAmount(mc, loanApplicationTerms, loanApplicationTerms.getExpectedDisbursementDate(),
periodNumber, loanApplicationTerms.getPrincipal().minus(totalCumulativePrincipal), holidayDetailDTO);
}
if(loanApplicationTerms.getAmortizationMethod().isEqualPrincipal()){
loanApplicationTerms.updateFixedPrincipalAmount(mc, periodNumber, loanApplicationTerms.getPrincipal().minus(totalCumulativePrincipal));
if (loanApplicationTerms.getAmortizationMethod().isEqualPrincipal()) {
loanApplicationTerms.updateFixedPrincipalAmount(mc, periodNumber,
loanApplicationTerms.getPrincipal().minus(totalCumulativePrincipal));
}
reducePrincipal = reducePrincipal.zero();
break;
@@ -6,7 +6,6 @@
package org.mifosplatform.portfolio.loanaccount.service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -0,0 +1,15 @@
CREATE TABLE `m_loan_transaction_repayment_schedule_mapping` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`loan_transaction_id` BIGINT(20) NOT NULL,
`loan_repayment_schedule_id` BIGINT(20) NOT NULL,
`amount` DECIMAL(19,6) NOT NULL,
`principal_portion_derived` DECIMAL(19,6) NULL DEFAULT NULL,
`interest_portion_derived` DECIMAL(19,6) NULL DEFAULT NULL,
`fee_charges_portion_derived` DECIMAL(19,6) NULL DEFAULT NULL,
`penalty_charges_portion_derived` DECIMAL(19,6) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `FK_mappings_m_loan_transaction` (`loan_transaction_id`),
INDEX `FK_mappings_m_loan_repayment_schedule` (`loan_repayment_schedule_id`),
CONSTRAINT `FK_mappings_m_loan_repayment_schedule` FOREIGN KEY (`loan_repayment_schedule_id`) REFERENCES `m_loan_repayment_schedule` (`id`),
CONSTRAINT `FK_mappings_m_loan_transaction` FOREIGN KEY (`loan_transaction_id`) REFERENCES `m_loan_transaction` (`id`)
);