enabled percentage of interrest for loans
This commit is contained in:
+6
-1
@@ -29,7 +29,12 @@ public enum ChargeCalculationType {
|
|||||||
return this.code;
|
return this.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object[] validValues() {
|
public static Object[] validValuesForLoan() {
|
||||||
|
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue(),
|
||||||
|
ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getValue(),ChargeCalculationType.PERCENT_OF_INTEREST.getValue() };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object[] validValuesForSavings() {
|
||||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
|
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-6
@@ -67,6 +67,9 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
|||||||
baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).isOneOfTheseValues(ChargeAppliesTo.validValues());
|
baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).isOneOfTheseValues(ChargeAppliesTo.validValues());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeCalculationType", element);
|
||||||
|
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).notNull();
|
||||||
|
|
||||||
final ChargeAppliesTo appliesTo = ChargeAppliesTo.fromInt(chargeAppliesTo);
|
final ChargeAppliesTo appliesTo = ChargeAppliesTo.fromInt(chargeAppliesTo);
|
||||||
if (appliesTo.isLoanCharge()) {
|
if (appliesTo.isLoanCharge()) {
|
||||||
// loan applicable validation
|
// loan applicable validation
|
||||||
@@ -81,6 +84,10 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
|||||||
if (chargePaymentMode != null) {
|
if (chargePaymentMode != null) {
|
||||||
baseDataValidator.reset().parameter("chargePaymentMode").value(chargePaymentMode).isOneOfTheseValues(ChargePaymentMode.validValues());
|
baseDataValidator.reset().parameter("chargePaymentMode").value(chargePaymentMode).isOneOfTheseValues(ChargePaymentMode.validValues());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chargeCalculationType != null) {
|
||||||
|
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).isOneOfTheseValues(ChargeCalculationType.validValuesForLoan());
|
||||||
|
}
|
||||||
|
|
||||||
} else if (appliesTo.isSavingsCharge()) {
|
} else if (appliesTo.isSavingsCharge()) {
|
||||||
// savings applicable validation
|
// savings applicable validation
|
||||||
@@ -103,6 +110,10 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
|||||||
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed("feeOnMonthDay", element);
|
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed("feeOnMonthDay", element);
|
||||||
baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull();
|
baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chargeCalculationType != null) {
|
||||||
|
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).isOneOfTheseValues(ChargeCalculationType.validValuesForSavings());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
|
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
|
||||||
@@ -124,12 +135,6 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
|||||||
baseDataValidator.reset().parameter("active").value(active).notNull();
|
baseDataValidator.reset().parameter("active").value(active).notNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeCalculationType", element);
|
|
||||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).notNull();
|
|
||||||
if (chargeCalculationType != null) {
|
|
||||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).isOneOfTheseValues(ChargeCalculationType.validValues());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists("minCap", element)) {
|
if (this.fromApiJsonHelper.parameterExists("minCap", element)) {
|
||||||
final BigDecimal minCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("minCap", element.getAsJsonObject());
|
final BigDecimal minCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("minCap", element.getAsJsonObject());
|
||||||
baseDataValidator.reset().parameter("minCap").value(minCap).notNull().positiveAmount();
|
baseDataValidator.reset().parameter("minCap").value(minCap).notNull().positiveAmount();
|
||||||
|
|||||||
+10
-3
@@ -691,12 +691,11 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
amount = getPrincpal().getAmount();
|
amount = getPrincpal().getAmount();
|
||||||
break;
|
break;
|
||||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||||
final BigDecimal totalInterestCharged = this.loanSummaryWrapper.calculateTotalInterestCharged(
|
final BigDecimal totalInterestCharged = getTotalInterest();
|
||||||
this.repaymentScheduleInstallments, getCurrency()).getAmount();
|
|
||||||
amount = getPrincpal().getAmount().add(totalInterestCharged);
|
amount = getPrincpal().getAmount().add(totalInterestCharged);
|
||||||
break;
|
break;
|
||||||
case PERCENT_OF_INTEREST:
|
case PERCENT_OF_INTEREST:
|
||||||
amount = getSummary().getTotalInterestCharged();
|
amount = getTotalInterest();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -704,6 +703,14 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public BigDecimal getTotalInterest() {
|
||||||
|
return this.loanSummaryWrapper.calculateTotalInterestCharged(
|
||||||
|
this.repaymentScheduleInstallments, getCurrency()).getAmount();
|
||||||
|
}
|
||||||
|
|
||||||
private BigDecimal calculatePerInstallmentChargeAmount(final LoanCharge loanCharge) {
|
private BigDecimal calculatePerInstallmentChargeAmount(final LoanCharge loanCharge) {
|
||||||
return calculatePerInstallmentChargeAmount(loanCharge.getChargeCalculation(), loanCharge.getPercentage());
|
return calculatePerInstallmentChargeAmount(loanCharge.getChargeCalculation(), loanCharge.getPercentage());
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-2
@@ -72,6 +72,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
@Column(name = "calculation_on_amount", scale = 6, precision = 19, nullable = true)
|
@Column(name = "calculation_on_amount", scale = 6, precision = 19, nullable = true)
|
||||||
private BigDecimal amountPercentageAppliedTo;
|
private BigDecimal amountPercentageAppliedTo;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
@Column(name = "charge_amount_or_percentage", scale = 6, precision = 19, nullable = false)
|
@Column(name = "charge_amount_or_percentage", scale = 6, precision = 19, nullable = false)
|
||||||
private BigDecimal amountOrPercentage;
|
private BigDecimal amountOrPercentage;
|
||||||
|
|
||||||
@@ -123,10 +124,10 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
amountPercentageAppliedTo = loan.getPrincpal().getAmount();
|
amountPercentageAppliedTo = loan.getPrincpal().getAmount();
|
||||||
break;
|
break;
|
||||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||||
amountPercentageAppliedTo = loan.getPrincpal().getAmount().add(loan.getSummary().getTotalInterestCharged());
|
amountPercentageAppliedTo = loan.getPrincpal().getAmount().add(loan.getTotalInterest());
|
||||||
break;
|
break;
|
||||||
case PERCENT_OF_INTEREST:
|
case PERCENT_OF_INTEREST:
|
||||||
amountPercentageAppliedTo = loan.getSummary().getTotalInterestCharged();
|
amountPercentageAppliedTo = loan.getTotalInterest();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -367,6 +368,26 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void update(final BigDecimal amount, final LocalDate dueDate, Integer numberOfRepayments){
|
||||||
|
BigDecimal amountPercentageAppliedTo = BigDecimal.ZERO;
|
||||||
|
if(this.loan!=null){
|
||||||
|
switch (ChargeCalculationType.fromInt(this.chargeCalculation)) {
|
||||||
|
case PERCENT_OF_AMOUNT:
|
||||||
|
amountPercentageAppliedTo = loan.getPrincpal().getAmount();
|
||||||
|
break;
|
||||||
|
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||||
|
amountPercentageAppliedTo = loan.getPrincpal().getAmount().add(loan.getTotalInterest());
|
||||||
|
break;
|
||||||
|
case PERCENT_OF_INTEREST:
|
||||||
|
amountPercentageAppliedTo = loan.getTotalInterest();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update(amount, dueDate, amountPercentageAppliedTo, numberOfRepayments, BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String, Object> update(final JsonCommand command, final BigDecimal amount) {
|
public Map<String, Object> update(final JsonCommand command, final BigDecimal amount) {
|
||||||
|
|
||||||
|
|||||||
+14
-10
@@ -22,18 +22,22 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
public void reprocess(final MonetaryCurrency currency, final LocalDate disbursementDate,
|
public void reprocess(final MonetaryCurrency currency, final LocalDate disbursementDate,
|
||||||
final List<LoanRepaymentScheduleInstallment> repaymentPeriods, final Set<LoanCharge> loanCharges) {
|
final List<LoanRepaymentScheduleInstallment> repaymentPeriods, final Set<LoanCharge> loanCharges) {
|
||||||
|
|
||||||
|
Money totalInterest = Money.zero(currency);
|
||||||
|
for (final LoanRepaymentScheduleInstallment installment : repaymentPeriods) {
|
||||||
|
totalInterest = totalInterest.plus(installment.getInterestCharged(currency));
|
||||||
|
}
|
||||||
LocalDate startDate = disbursementDate;
|
LocalDate startDate = disbursementDate;
|
||||||
for (final LoanRepaymentScheduleInstallment period : repaymentPeriods) {
|
for (final LoanRepaymentScheduleInstallment period : repaymentPeriods) {
|
||||||
|
|
||||||
final Money feeChargesDueForRepaymentPeriod = cumulativeFeeChargesDueWithin(startDate, period.getDueDate(), loanCharges,
|
final Money feeChargesDueForRepaymentPeriod = cumulativeFeeChargesDueWithin(startDate, period.getDueDate(), loanCharges,
|
||||||
currency,period,repaymentPeriods.size());
|
currency,period,repaymentPeriods.size(), totalInterest);
|
||||||
final Money feeChargesWaivedForRepaymentPeriod = cumulativeFeeChargesWaivedWithin(startDate, period.getDueDate(), loanCharges,
|
final Money feeChargesWaivedForRepaymentPeriod = cumulativeFeeChargesWaivedWithin(startDate, period.getDueDate(), loanCharges,
|
||||||
currency);
|
currency);
|
||||||
final Money feeChargesWrittenOffForRepaymentPeriod = cumulativeFeeChargesWrittenOffWithin(startDate, period.getDueDate(),
|
final Money feeChargesWrittenOffForRepaymentPeriod = cumulativeFeeChargesWrittenOffWithin(startDate, period.getDueDate(),
|
||||||
loanCharges, currency);
|
loanCharges, currency);
|
||||||
|
|
||||||
final Money penaltyChargesDueForRepaymentPeriod = cumulativePenaltyChargesDueWithin(startDate, period.getDueDate(),
|
final Money penaltyChargesDueForRepaymentPeriod = cumulativePenaltyChargesDueWithin(startDate, period.getDueDate(),
|
||||||
loanCharges, currency,period,repaymentPeriods.size());
|
loanCharges, currency,period,repaymentPeriods.size(), totalInterest);
|
||||||
final Money penaltyChargesWaivedForRepaymentPeriod = cumulativePenaltyChargesWaivedWithin(startDate, period.getDueDate(),
|
final Money penaltyChargesWaivedForRepaymentPeriod = cumulativePenaltyChargesWaivedWithin(startDate, period.getDueDate(),
|
||||||
loanCharges, currency);
|
loanCharges, currency);
|
||||||
final Money penaltyChargesWrittenOffForRepaymentPeriod = cumulativePenaltyChargesWrittenOffWithin(startDate,
|
final Money penaltyChargesWrittenOffForRepaymentPeriod = cumulativePenaltyChargesWrittenOffWithin(startDate,
|
||||||
@@ -48,7 +52,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Money cumulativeFeeChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd, final Set<LoanCharge> loanCharges,
|
private Money cumulativeFeeChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd, final Set<LoanCharge> loanCharges,
|
||||||
final MonetaryCurrency monetaryCurrency,LoanRepaymentScheduleInstallment period,int numberOfRepayments) {
|
final MonetaryCurrency monetaryCurrency,LoanRepaymentScheduleInstallment period,int numberOfRepayments,final Money totalInterest) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(monetaryCurrency);
|
Money cumulative = Money.zero(monetaryCurrency);
|
||||||
|
|
||||||
@@ -74,11 +78,11 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
loanCharge.getChargeCalculation().isPercentageBased()) {
|
loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
BigDecimal amount = BigDecimal.ZERO;
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed()).add(period.getLoan().getSummary().getTotalInterestCharged());
|
amount = amount.add(period.getLoan().getPrincpal().getAmount()).add(totalInterest.getAmount());
|
||||||
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
amount = amount.add(period.getLoan().getSummary().getTotalInterestCharged());
|
amount = amount.add(totalInterest.getAmount());
|
||||||
} else {
|
} else {
|
||||||
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed());
|
amount = amount.add(period.getLoan().getPrincpal().getAmount());
|
||||||
}
|
}
|
||||||
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
cumulative = cumulative.plus(loanChargeAmt);
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
@@ -130,7 +134,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Money cumulativePenaltyChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
private Money cumulativePenaltyChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
||||||
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency,LoanRepaymentScheduleInstallment period,int numberOfRepayments) {
|
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency,LoanRepaymentScheduleInstallment period,int numberOfRepayments, Money totalInterest) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(currency);
|
Money cumulative = Money.zero(currency);
|
||||||
|
|
||||||
@@ -156,11 +160,11 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
loanCharge.getChargeCalculation().isPercentageBased()) {
|
loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
BigDecimal amount = BigDecimal.ZERO;
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed()).add(period.getLoan().getSummary().getTotalInterestCharged());
|
amount = amount.add(period.getLoan().getPrincpal().getAmount()).add(totalInterest.getAmount());
|
||||||
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
amount = amount.add(period.getLoan().getSummary().getTotalInterestCharged());
|
amount = amount.add(totalInterest.getAmount());
|
||||||
} else {
|
} else {
|
||||||
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed());
|
amount = amount.add(period.getLoan().getPrincpal().getAmount());
|
||||||
}
|
}
|
||||||
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
cumulative = cumulative.plus(loanChargeAmt);
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
|
|||||||
+1
-1
@@ -91,7 +91,7 @@ public class LoanChargeAssembler {
|
|||||||
final LoanCharge loanCharge = this.loanChargeRepository.findOne(loanChargeId);
|
final LoanCharge loanCharge = this.loanChargeRepository.findOne(loanChargeId);
|
||||||
if (loanCharge == null) { throw new LoanChargeNotFoundException(loanChargeId); }
|
if (loanCharge == null) { throw new LoanChargeNotFoundException(loanChargeId); }
|
||||||
|
|
||||||
loanCharge.update(amount, dueDate, principal, numberOfRepayments, BigDecimal.ZERO);
|
loanCharge.update(amount, dueDate, numberOfRepayments);
|
||||||
|
|
||||||
loanCharges.add(loanCharge);
|
loanCharges.add(loanCharge);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user