+12
@@ -56,6 +56,14 @@ public enum ChargeCalculationType {
|
|||||||
return this.value.equals(ChargeCalculationType.PERCENT_OF_AMOUNT.getValue());
|
return this.value.equals(ChargeCalculationType.PERCENT_OF_AMOUNT.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPercentageOfAmountAndInterest() {
|
||||||
|
return this.value.equals(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPercentageOfInterest() {
|
||||||
|
return this.value.equals(ChargeCalculationType.PERCENT_OF_INTEREST.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isFlat() {
|
public boolean isFlat() {
|
||||||
return this.value.equals(ChargeCalculationType.FLAT.getValue());
|
return this.value.equals(ChargeCalculationType.FLAT.getValue());
|
||||||
}
|
}
|
||||||
@@ -63,4 +71,8 @@ public enum ChargeCalculationType {
|
|||||||
public boolean isAllowedSavingsChargeCalculationType() {
|
public boolean isAllowedSavingsChargeCalculationType() {
|
||||||
return isFlat() || isPercentageOfAmount();
|
return isFlat() || isPercentageOfAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPercentageBased(){
|
||||||
|
return isPercentageOfAmount() || isPercentageOfAmountAndInterest() || isPercentageOfInterest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+38
-29
@@ -16,7 +16,8 @@ public enum ChargeTimeType {
|
|||||||
SAVINGS_CLOSURE(4, "chargeTimeType.savingsClosure"), // only for savings
|
SAVINGS_CLOSURE(4, "chargeTimeType.savingsClosure"), // only for savings
|
||||||
WITHDRAWAL_FEE(5, "chargeTimeType.withdrawalFee"), // only for savings
|
WITHDRAWAL_FEE(5, "chargeTimeType.withdrawalFee"), // only for savings
|
||||||
ANNUAL_FEE(6, "chargeTimeType.annualFee"), // only for savings
|
ANNUAL_FEE(6, "chargeTimeType.annualFee"), // only for savings
|
||||||
MONTHLY_FEE(7, "chargeTimeType.monthlyFee"); // only for savings
|
MONTHLY_FEE(7, "chargeTimeType.monthlyFee"), // only for savings
|
||||||
|
INSTALMENT_FEE(8,"chargeTimeType.instalmentFee");//only for loan charges
|
||||||
|
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
private final String code;
|
private final String code;
|
||||||
@@ -47,34 +48,37 @@ public enum ChargeTimeType {
|
|||||||
public static ChargeTimeType fromInt(final Integer chargeTime) {
|
public static ChargeTimeType fromInt(final Integer chargeTime) {
|
||||||
ChargeTimeType chargeTimeType = ChargeTimeType.INVALID;
|
ChargeTimeType chargeTimeType = ChargeTimeType.INVALID;
|
||||||
if (chargeTime != null) {
|
if (chargeTime != null) {
|
||||||
switch (chargeTime) {
|
switch (chargeTime) {
|
||||||
case 1:
|
case 1:
|
||||||
chargeTimeType = DISBURSEMENT;
|
chargeTimeType = DISBURSEMENT;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
chargeTimeType = SPECIFIED_DUE_DATE;
|
chargeTimeType = SPECIFIED_DUE_DATE;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
chargeTimeType = SAVINGS_ACTIVATION;
|
chargeTimeType = SAVINGS_ACTIVATION;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
chargeTimeType = SAVINGS_CLOSURE;
|
chargeTimeType = SAVINGS_CLOSURE;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
chargeTimeType = WITHDRAWAL_FEE;
|
chargeTimeType = WITHDRAWAL_FEE;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
chargeTimeType = ANNUAL_FEE;
|
chargeTimeType = ANNUAL_FEE;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
chargeTimeType = MONTHLY_FEE;
|
chargeTimeType = MONTHLY_FEE;
|
||||||
break;
|
break;
|
||||||
default:
|
case 8:
|
||||||
chargeTimeType = INVALID;
|
chargeTimeType = INSTALMENT_FEE;
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
|
chargeTimeType = INVALID;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return chargeTimeType;
|
}
|
||||||
|
return chargeTimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTimeOfDisbursement() {
|
public boolean isTimeOfDisbursement() {
|
||||||
@@ -105,8 +109,13 @@ public enum ChargeTimeType {
|
|||||||
return this.value.equals(ChargeTimeType.MONTHLY_FEE.getValue());
|
return this.value.equals(ChargeTimeType.MONTHLY_FEE.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isInstalmentFee() {
|
||||||
|
return this.value.equals(ChargeTimeType.INSTALMENT_FEE.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isAllowedLoanChargeTime() {
|
public boolean isAllowedLoanChargeTime() {
|
||||||
return isTimeOfDisbursement() || isOnSpecifiedDueDate();
|
return isTimeOfDisbursement() || isOnSpecifiedDueDate() || isInstalmentFee();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAllowedSavingsChargeTime() {
|
public boolean isAllowedSavingsChargeTime() {
|
||||||
|
|||||||
+11
-3
@@ -11,7 +11,7 @@ public class LoanChargeCannotBePayedException extends AbstractPlatformDomainRule
|
|||||||
|
|
||||||
/*** enum of reasons of why Loan Charge cannot be waived **/
|
/*** enum of reasons of why Loan Charge cannot be waived **/
|
||||||
public static enum LOAN_CHARGE_CANNOT_BE_PAYED_REASON {
|
public static enum LOAN_CHARGE_CANNOT_BE_PAYED_REASON {
|
||||||
ALREADY_PAID, ALREADY_WAIVED, LOAN_INACTIVE, CHARGE_NOT_ACCOUNT_TRANSFER;
|
ALREADY_PAID, ALREADY_WAIVED, LOAN_INACTIVE, CHARGE_NOT_ACCOUNT_TRANSFER,CHARGE_NOT_PAYABLE;
|
||||||
|
|
||||||
public String errorMessage() {
|
public String errorMessage() {
|
||||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||||
@@ -20,7 +20,11 @@ public class LoanChargeCannotBePayedException extends AbstractPlatformDomainRule
|
|||||||
return "This loan charge has already been waived";
|
return "This loan charge has already been waived";
|
||||||
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||||
return "This loan charge can be payed as the loan associated with it is currently inactive";
|
return "This loan charge can be payed as the loan associated with it is currently inactive";
|
||||||
} else if (name().toString().equalsIgnoreCase("CHARGE_NOT_ACCOUNT_TRANSFER")) { return "This loan charge can be payed as the charge payment mode is not account transfer"; }
|
} else if (name().toString().equalsIgnoreCase("CHARGE_NOT_ACCOUNT_TRANSFER")) {
|
||||||
|
return "This loan charge can be payed as the charge payment mode is not account transfer";
|
||||||
|
}else if (name().toString().equalsIgnoreCase("CHARGE_NOT_PAYABLE")) {
|
||||||
|
return "This loan charge is not Payable through account transfer";
|
||||||
|
}
|
||||||
|
|
||||||
return name().toString();
|
return name().toString();
|
||||||
}
|
}
|
||||||
@@ -32,7 +36,11 @@ public class LoanChargeCannotBePayedException extends AbstractPlatformDomainRule
|
|||||||
return "error.msg.loan.charge.already.waived";
|
return "error.msg.loan.charge.already.waived";
|
||||||
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||||
return "error.msg.loan.charge.associated.loan.inactive";
|
return "error.msg.loan.charge.associated.loan.inactive";
|
||||||
} else if (name().toString().equalsIgnoreCase("CHARGE_NOT_ACCOUNT_TRANSFER")) { return "error.msg.loan.charge.payment.mode.not.account.transfer"; }
|
} else if (name().toString().equalsIgnoreCase("CHARGE_NOT_ACCOUNT_TRANSFER")) {
|
||||||
|
return "error.msg.loan.charge.payment.mode.not.account.transfer";
|
||||||
|
}else if (name().toString().equalsIgnoreCase("CHARGE_NOT_PAYABLE")) {
|
||||||
|
return "error.msg.loan.charge.payment.not.allowed.account.transfer";
|
||||||
|
}
|
||||||
return name().toString();
|
return name().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -11,14 +11,19 @@ public class LoanChargeCannotBeWaivedException extends AbstractPlatformDomainRul
|
|||||||
|
|
||||||
/*** enum of reasons of why Loan Charge cannot be waived **/
|
/*** enum of reasons of why Loan Charge cannot be waived **/
|
||||||
public static enum LOAN_CHARGE_CANNOT_BE_WAIVED_REASON {
|
public static enum LOAN_CHARGE_CANNOT_BE_WAIVED_REASON {
|
||||||
ALREADY_PAID, ALREADY_WAIVED, LOAN_INACTIVE;
|
ALREADY_PAID, ALREADY_WAIVED, LOAN_INACTIVE, WAIVE_NOT_ALLOWED_FOR_CHARGE;
|
||||||
|
|
||||||
public String errorMessage() {
|
public String errorMessage() {
|
||||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||||
return "This loan charge has been completely paid";
|
return "This loan charge has been completely paid";
|
||||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||||
return "This loan charge has already been waived";
|
return "This loan charge has already been waived";
|
||||||
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) { return "This loan charge can be waived as the loan associated with it is currently inactive"; }
|
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||||
|
return "This loan charge can be waived as the loan associated with it is currently inactive";
|
||||||
|
} else if(name().toString().equalsIgnoreCase("WAIVE_NOT_ALLOWED_FOR_CHARGE")){
|
||||||
|
return "This loan charge can be waived";
|
||||||
|
}
|
||||||
|
|
||||||
return name().toString();
|
return name().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +32,11 @@ public class LoanChargeCannotBeWaivedException extends AbstractPlatformDomainRul
|
|||||||
return "error.msg.loan.charge.already.paid";
|
return "error.msg.loan.charge.already.paid";
|
||||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||||
return "error.msg.loan.charge.already.waived";
|
return "error.msg.loan.charge.already.waived";
|
||||||
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) { return "error.msg.loan.charge.associated.loan.inactive"; }
|
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||||
|
return "error.msg.loan.charge.associated.loan.inactive";
|
||||||
|
} else if(name().toString().equalsIgnoreCase("WAIVE_NOT_ALLOWED_FOR_CHARGE")) {
|
||||||
|
return "error.msg.loan.charge.waive.not.allowed";
|
||||||
|
}
|
||||||
return name().toString();
|
return name().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -27,9 +27,9 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead
|
|||||||
public List<EnumOptionData> retrieveCalculationTypes() {
|
public List<EnumOptionData> retrieveCalculationTypes() {
|
||||||
|
|
||||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
|
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
|
||||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT)
|
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT),
|
||||||
// chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST),
|
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST),
|
||||||
// chargeCalculationType(ChargeCalculationType.PERCENT_OF_INTEREST)
|
chargeCalculationType(ChargeCalculationType.PERCENT_OF_INTEREST)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,12 +64,12 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EnumOptionData> retrieveLoanCalculationTypes() {
|
public List<EnumOptionData> retrieveLoanCalculationTypes() {
|
||||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT), chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT));
|
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT), chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT), chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST), chargeCalculationType(ChargeCalculationType.PERCENT_OF_INTEREST));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EnumOptionData> retrieveLoanCollectionTimeTypes() {
|
public List<EnumOptionData> retrieveLoanCollectionTimeTypes() {
|
||||||
return Arrays.asList(chargeTimeType(ChargeTimeType.DISBURSEMENT), chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE));
|
return Arrays.asList(chargeTimeType(ChargeTimeType.DISBURSEMENT), chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE),chargeTimeType(ChargeTimeType.INSTALMENT_FEE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+3
@@ -43,6 +43,9 @@ public class ChargeEnumerations {
|
|||||||
case MONTHLY_FEE:
|
case MONTHLY_FEE:
|
||||||
optionData = new EnumOptionData(ChargeTimeType.MONTHLY_FEE.getValue().longValue(), ChargeTimeType.MONTHLY_FEE.getCode(), "Monthly Fee");
|
optionData = new EnumOptionData(ChargeTimeType.MONTHLY_FEE.getValue().longValue(), ChargeTimeType.MONTHLY_FEE.getCode(), "Monthly Fee");
|
||||||
break;
|
break;
|
||||||
|
case INSTALMENT_FEE:
|
||||||
|
optionData = new EnumOptionData(ChargeTimeType.INSTALMENT_FEE.getValue().longValue(), ChargeTimeType.INSTALMENT_FEE.getCode(), "Instalment Fee");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid");
|
optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid");
|
||||||
break;
|
break;
|
||||||
|
|||||||
+76
-6
@@ -427,9 +427,6 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
||||||
|
|
||||||
loanCharge.update(this);
|
|
||||||
setOfLoanCharges().add(loanCharge);
|
|
||||||
|
|
||||||
this.summary = updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
this.summary = updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||||
@@ -452,6 +449,19 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateLoanSummaryDerivedFields();
|
updateLoanSummaryDerivedFields();
|
||||||
|
loanCharge.update(this);
|
||||||
|
BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge);
|
||||||
|
BigDecimal chargeAmt = BigDecimal.ZERO;
|
||||||
|
if(loanCharge.getChargeCalculation().isPercentageBased()){
|
||||||
|
chargeAmt = loanCharge.getPercentage();
|
||||||
|
}else{
|
||||||
|
chargeAmt = loanCharge.amount();
|
||||||
|
if(loanCharge.isInstalmentFee()){
|
||||||
|
chargeAmt = chargeAmt.divide(BigDecimal.valueOf(this.repaymentScheduleDetail().getNumberOfRepayments()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount, this.repaymentScheduleDetail().getNumberOfRepayments());
|
||||||
|
setOfLoanCharges().add(loanCharge);
|
||||||
return changedTransactionDetail;
|
return changedTransactionDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,9 +634,9 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(3);
|
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(3);
|
||||||
|
|
||||||
validateLoanIsNotClosed(loanCharge);
|
validateLoanIsNotClosed(loanCharge);
|
||||||
|
|
||||||
if (setOfLoanCharges().contains(loanCharge)) {
|
if (setOfLoanCharges().contains(loanCharge)) {
|
||||||
final Map<String, Object> loanChargeChanges = loanCharge.update(command, getPrincpal().getAmount());
|
BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge);
|
||||||
|
final Map<String, Object> loanChargeChanges = loanCharge.update(command, amount);
|
||||||
actualChanges.putAll(loanChargeChanges);
|
actualChanges.putAll(loanChargeChanges);
|
||||||
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
||||||
}
|
}
|
||||||
@@ -656,6 +666,30 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return actualChanges;
|
return actualChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param loanCharge
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private BigDecimal calculateAmountPercentageAppliedTo(final LoanCharge loanCharge) {
|
||||||
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
|
switch (loanCharge.getChargeCalculation()) {
|
||||||
|
case PERCENT_OF_AMOUNT:
|
||||||
|
amount = getPrincpal().getAmount();
|
||||||
|
break;
|
||||||
|
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||||
|
final BigDecimal totalInterestCharged = this.loanSummaryWrapper.calculateTotalInterestCharged(
|
||||||
|
repaymentScheduleInstallments, getCurrency()).getAmount();
|
||||||
|
amount = getPrincpal().getAmount().add(totalInterestCharged);
|
||||||
|
break;
|
||||||
|
case PERCENT_OF_INTEREST:
|
||||||
|
amount = getSummary().getTotalInterestCharged();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
public LoanTransaction waiveLoanCharge(final LoanCharge loanCharge, final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
public LoanTransaction waiveLoanCharge(final LoanCharge loanCharge, final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
||||||
final Map<String, Object> changes, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
final Map<String, Object> changes, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||||
|
|
||||||
@@ -765,7 +799,21 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
public void updateLoanCharges(final Set<LoanCharge> loanCharges) {
|
public void updateLoanCharges(final Set<LoanCharge> loanCharges) {
|
||||||
setOfLoanCharges().clear();
|
setOfLoanCharges().clear();
|
||||||
setOfLoanCharges().addAll(associateChargesWithThisLoan(loanCharges));
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
|
loanCharge.update(this);
|
||||||
|
BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge);
|
||||||
|
BigDecimal chargeAmt = BigDecimal.ZERO;
|
||||||
|
if(loanCharge.getChargeCalculation().isPercentageBased()){
|
||||||
|
chargeAmt = loanCharge.getPercentage();
|
||||||
|
}else{
|
||||||
|
chargeAmt = loanCharge.amount();
|
||||||
|
if(loanCharge.isInstalmentFee()){
|
||||||
|
chargeAmt = chargeAmt.divide(BigDecimal.valueOf(this.repaymentScheduleDetail().getNumberOfRepayments()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount, this.repaymentScheduleDetail().getNumberOfRepayments());
|
||||||
|
}
|
||||||
|
setOfLoanCharges().addAll(loanCharges);
|
||||||
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1012,6 +1060,17 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
actualChanges.put("recalculateLoanSchedule", true);
|
actualChanges.put("recalculateLoanSchedule", true);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : possiblyModifedLoanCharges) {
|
for (final LoanCharge loanCharge : possiblyModifedLoanCharges) {
|
||||||
|
BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge);
|
||||||
|
BigDecimal chargeAmt = BigDecimal.ZERO;
|
||||||
|
if(loanCharge.getChargeCalculation().isPercentageBased()){
|
||||||
|
chargeAmt = loanCharge.getPercentage();
|
||||||
|
}else{
|
||||||
|
chargeAmt = loanCharge.amount();
|
||||||
|
if(loanCharge.isInstalmentFee()){
|
||||||
|
chargeAmt = chargeAmt.divide(BigDecimal.valueOf(this.repaymentScheduleDetail().getNumberOfRepayments()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount, this.repaymentScheduleDetail().getNumberOfRepayments());
|
||||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1143,6 +1202,17 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
// charges are optional
|
// charges are optional
|
||||||
for (final LoanCharge loanCharge : setOfLoanCharges()) {
|
for (final LoanCharge loanCharge : setOfLoanCharges()) {
|
||||||
|
BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge);
|
||||||
|
BigDecimal chargeAmt = BigDecimal.ZERO;
|
||||||
|
if(loanCharge.getChargeCalculation().isPercentageBased()){
|
||||||
|
chargeAmt = loanCharge.getPercentage();
|
||||||
|
}else{
|
||||||
|
chargeAmt = loanCharge.amount();
|
||||||
|
if(loanCharge.isInstalmentFee()){
|
||||||
|
chargeAmt = chargeAmt.divide(BigDecimal.valueOf(this.repaymentScheduleDetail().getNumberOfRepayments()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount, this.repaymentScheduleDetail().getNumberOfRepayments());
|
||||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+80
-60
@@ -103,9 +103,23 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
final ChargeTimeType chargeTime = null;
|
final ChargeTimeType chargeTime = null;
|
||||||
final ChargeCalculationType chargeCalculation = null;
|
final ChargeCalculationType chargeCalculation = null;
|
||||||
final ChargePaymentMode chargePaymentMode = null;
|
final ChargePaymentMode chargePaymentMode = null;
|
||||||
|
BigDecimal amountPercentageAppliedTo = BigDecimal.ZERO;
|
||||||
|
switch (ChargeCalculationType.fromInt(chargeDefinition.getChargeCalculation())) {
|
||||||
|
case PERCENT_OF_AMOUNT:
|
||||||
|
amountPercentageAppliedTo = loan.getPrincpal().getAmount();
|
||||||
|
break;
|
||||||
|
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||||
|
amountPercentageAppliedTo = loan.getPrincpal().getAmount().add(loan.getSummary().getTotalInterestCharged());
|
||||||
|
break;
|
||||||
|
case PERCENT_OF_INTEREST:
|
||||||
|
amountPercentageAppliedTo = loan.getSummary().getTotalInterestCharged();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation, dueDate,
|
return new LoanCharge(loan, chargeDefinition, amountPercentageAppliedTo, amount, chargeTime, chargeCalculation, dueDate,
|
||||||
chargePaymentMode);
|
chargePaymentMode, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -113,8 +127,8 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
*/
|
*/
|
||||||
public static LoanCharge createNewWithoutLoan(final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount,
|
public static LoanCharge createNewWithoutLoan(final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount,
|
||||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate,
|
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate,
|
||||||
final ChargePaymentMode chargePaymentMode) {
|
final ChargePaymentMode chargePaymentMode,final Integer numberOfRepayments) {
|
||||||
return new LoanCharge(null, chargeDefinition, loanPrincipal, amount, chargeTime, chargeCalculation, dueDate, chargePaymentMode);
|
return new LoanCharge(null, chargeDefinition, loanPrincipal, amount, chargeTime, chargeCalculation, dueDate, chargePaymentMode, numberOfRepayments);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected LoanCharge() {
|
protected LoanCharge() {
|
||||||
@@ -123,7 +137,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
public LoanCharge(final Loan loan, final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount,
|
public LoanCharge(final Loan loan, final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount,
|
||||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate,
|
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate,
|
||||||
final ChargePaymentMode chargePaymentMode) {
|
final ChargePaymentMode chargePaymentMode, Integer numberOfRepayments) {
|
||||||
this.loan = loan;
|
this.loan = loan;
|
||||||
this.charge = chargeDefinition;
|
this.charge = chargeDefinition;
|
||||||
this.penaltyCharge = chargeDefinition.isPenalty();
|
this.penaltyCharge = chargeDefinition.isPenalty();
|
||||||
@@ -162,12 +176,11 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
if (chargePaymentMode != null) {
|
if (chargePaymentMode != null) {
|
||||||
this.chargePaymentMode = chargePaymentMode.getValue();
|
this.chargePaymentMode = chargePaymentMode.getValue();
|
||||||
}
|
}
|
||||||
|
populateDerivedFields(loanPrincipal, chargeAmount,numberOfRepayments);
|
||||||
populateDerivedFields(loanPrincipal,chargeAmount);
|
|
||||||
this.paid = determineIfFullyPaid();
|
this.paid = determineIfFullyPaid();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateDerivedFields(final BigDecimal loanPrincipal, final BigDecimal chargeAmount) {
|
private void populateDerivedFields(final BigDecimal amountPercentageAppliedTo, final BigDecimal chargeAmount,Integer numberOfRepayments) {
|
||||||
|
|
||||||
switch (ChargeCalculationType.fromInt(this.chargeCalculation)) {
|
switch (ChargeCalculationType.fromInt(this.chargeCalculation)) {
|
||||||
case INVALID:
|
case INVALID:
|
||||||
@@ -181,40 +194,31 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
break;
|
break;
|
||||||
case FLAT:
|
case FLAT:
|
||||||
this.percentage = null;
|
this.percentage = null;
|
||||||
this.amount = chargeAmount;
|
|
||||||
this.amountPercentageAppliedTo = null;
|
this.amountPercentageAppliedTo = null;
|
||||||
this.amountPaid = null;
|
this.amountPaid = null;
|
||||||
this.amountOutstanding = chargeAmount;
|
if(this.isInstalmentFee()){
|
||||||
|
if(numberOfRepayments == null){
|
||||||
|
numberOfRepayments = this.loan.repaymentScheduleDetail().getNumberOfRepayments();
|
||||||
|
}
|
||||||
|
this.amount = chargeAmount.multiply(BigDecimal.valueOf(numberOfRepayments));
|
||||||
|
}else{
|
||||||
|
this.amount = chargeAmount;
|
||||||
|
}
|
||||||
|
this.amountOutstanding = this.amount;
|
||||||
this.amountWaived = null;
|
this.amountWaived = null;
|
||||||
this.amountWrittenOff = null;
|
this.amountWrittenOff = null;
|
||||||
break;
|
break;
|
||||||
case PERCENT_OF_AMOUNT:
|
case PERCENT_OF_AMOUNT:
|
||||||
|
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||||
|
case PERCENT_OF_INTEREST:
|
||||||
this.percentage = chargeAmount;
|
this.percentage = chargeAmount;
|
||||||
this.amountPercentageAppliedTo = loanPrincipal;
|
this.amountPercentageAppliedTo = amountPercentageAppliedTo;
|
||||||
this.amount = minimumAndMaximumCap(percentageOf(this.amountPercentageAppliedTo, this.percentage));
|
this.amount = minimumAndMaximumCap(percentageOf(this.amountPercentageAppliedTo, this.percentage));
|
||||||
this.amountPaid = null;
|
this.amountPaid = null;
|
||||||
this.amountOutstanding = calculateOutstanding();
|
this.amountOutstanding = calculateOutstanding();
|
||||||
this.amountWaived = null;
|
this.amountWaived = null;
|
||||||
this.amountWrittenOff = null;
|
this.amountWrittenOff = null;
|
||||||
break;
|
break;
|
||||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
|
||||||
this.percentage = null;
|
|
||||||
this.amount = null;
|
|
||||||
this.amountPercentageAppliedTo = null;
|
|
||||||
this.amountPaid = null;
|
|
||||||
this.amountOutstanding = BigDecimal.ZERO;
|
|
||||||
this.amountWaived = null;
|
|
||||||
this.amountWrittenOff = null;
|
|
||||||
break;
|
|
||||||
case PERCENT_OF_INTEREST:
|
|
||||||
this.percentage = null;
|
|
||||||
this.amount = null;
|
|
||||||
this.amountPercentageAppliedTo = null;
|
|
||||||
this.amountPaid = null;
|
|
||||||
this.amountOutstanding = BigDecimal.ZERO;
|
|
||||||
this.amountWaived = null;
|
|
||||||
this.amountWrittenOff = null;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +259,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
this.loan = loan;
|
this.loan = loan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(final BigDecimal amount, final LocalDate dueDate, final BigDecimal loanPrincipal) {
|
public void update(final BigDecimal amount, final LocalDate dueDate, final BigDecimal loanPrincipal, Integer numberOfRepayments) {
|
||||||
if (dueDate != null) {
|
if (dueDate != null) {
|
||||||
this.dueDate = dueDate.toDate();
|
this.dueDate = dueDate.toDate();
|
||||||
}
|
}
|
||||||
@@ -265,31 +269,28 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
case INVALID:
|
case INVALID:
|
||||||
break;
|
break;
|
||||||
case FLAT:
|
case FLAT:
|
||||||
this.amount = amount;
|
if(this.isInstalmentFee()){
|
||||||
|
if(numberOfRepayments == null){
|
||||||
|
numberOfRepayments = this.loan.repaymentScheduleDetail().getNumberOfRepayments();
|
||||||
|
}
|
||||||
|
this.amount = amount.multiply(BigDecimal.valueOf(numberOfRepayments));
|
||||||
|
}else{
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PERCENT_OF_AMOUNT:
|
case PERCENT_OF_AMOUNT:
|
||||||
|
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||||
|
case PERCENT_OF_INTEREST:
|
||||||
this.percentage = amount;
|
this.percentage = amount;
|
||||||
this.amountPercentageAppliedTo = loanPrincipal;
|
this.amountPercentageAppliedTo = loanPrincipal;
|
||||||
this.amount = minimumAndMaximumCap(percentageOf(this.amountPercentageAppliedTo, this.percentage));
|
this.amount = minimumAndMaximumCap(percentageOf(this.amountPercentageAppliedTo, this.percentage));
|
||||||
this.amountOutstanding = calculateOutstanding();
|
this.amountOutstanding = calculateOutstanding();
|
||||||
break;
|
break;
|
||||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
|
||||||
this.percentage = amount;
|
|
||||||
this.amount = null;
|
|
||||||
this.amountPercentageAppliedTo = null;
|
|
||||||
this.amountOutstanding = null;
|
|
||||||
break;
|
|
||||||
case PERCENT_OF_INTEREST:
|
|
||||||
this.percentage = amount;
|
|
||||||
this.amount = null;
|
|
||||||
this.amountPercentageAppliedTo = null;
|
|
||||||
this.amountOutstanding = null;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> update(final JsonCommand command, final BigDecimal loanPrincipal) {
|
public Map<String, Object> update(final JsonCommand command, final BigDecimal amount) {
|
||||||
|
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(7);
|
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(7);
|
||||||
|
|
||||||
@@ -316,25 +317,19 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
case INVALID:
|
case INVALID:
|
||||||
break;
|
break;
|
||||||
case FLAT:
|
case FLAT:
|
||||||
this.amount = newValue;
|
if(this.isInstalmentFee()){
|
||||||
|
this.amount = newValue.multiply(BigDecimal.valueOf(this.loan.repaymentScheduleDetail().getNumberOfRepayments()));
|
||||||
|
}else{
|
||||||
|
this.amount = newValue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PERCENT_OF_AMOUNT:
|
case PERCENT_OF_AMOUNT:
|
||||||
this.percentage = newValue;
|
|
||||||
this.amountPercentageAppliedTo = loanPrincipal;
|
|
||||||
this.amount = minimumAndMaximumCap(percentageOf(this.amountPercentageAppliedTo, this.percentage));
|
|
||||||
this.amountOutstanding = calculateOutstanding();
|
|
||||||
break;
|
|
||||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||||
this.percentage = newValue;
|
|
||||||
this.amount = null;
|
|
||||||
this.amountPercentageAppliedTo = null;
|
|
||||||
this.amountOutstanding = null;
|
|
||||||
break;
|
|
||||||
case PERCENT_OF_INTEREST:
|
case PERCENT_OF_INTEREST:
|
||||||
this.percentage = newValue;
|
this.percentage = newValue;
|
||||||
this.amount = null;
|
this.amountPercentageAppliedTo = amount;
|
||||||
this.amountPercentageAppliedTo = null;
|
this.amount = minimumAndMaximumCap(percentageOf(this.amountPercentageAppliedTo, this.percentage));
|
||||||
this.amountOutstanding = null;
|
this.amountOutstanding = calculateOutstanding();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,6 +345,10 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
return ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.SPECIFIED_DUE_DATE);
|
return ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.SPECIFIED_DUE_DATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInstalmentFee() {
|
||||||
|
return ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.INSTALMENT_FEE);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isGreaterThanZero(final BigDecimal value) {
|
private boolean isGreaterThanZero(final BigDecimal value) {
|
||||||
return value.compareTo(BigDecimal.ZERO) == 1;
|
return value.compareTo(BigDecimal.ZERO) == 1;
|
||||||
}
|
}
|
||||||
@@ -367,11 +366,16 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean determineIfFullyPaid() {
|
private boolean determineIfFullyPaid() {
|
||||||
|
if(this.amount == null){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return BigDecimal.ZERO.compareTo(calculateOutstanding()) == 0;
|
return BigDecimal.ZERO.compareTo(calculateOutstanding()) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal calculateOutstanding() {
|
private BigDecimal calculateOutstanding() {
|
||||||
|
if(this.amount == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
BigDecimal amountPaidLocal = BigDecimal.ZERO;
|
BigDecimal amountPaidLocal = BigDecimal.ZERO;
|
||||||
if (this.amountPaid != null) {
|
if (this.amountPaid != null) {
|
||||||
amountPaidLocal = this.amountPaid;
|
amountPaidLocal = this.amountPaid;
|
||||||
@@ -573,4 +577,20 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
public ChargePaymentMode getChargePaymentMode() {
|
public ChargePaymentMode getChargePaymentMode() {
|
||||||
return ChargePaymentMode.fromInt(this.chargePaymentMode);
|
return ChargePaymentMode.fromInt(this.chargePaymentMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ChargeCalculationType getChargeCalculation() {
|
||||||
|
return ChargeCalculationType.fromInt(this.chargeCalculation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BigDecimal getPercentage() {
|
||||||
|
return this.percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void updateAmount(BigDecimal amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
calculateOutstanding();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+67
-8
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.loanaccount.domain;
|
package org.mifosplatform.portfolio.loanaccount.domain;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -25,14 +26,14 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
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);
|
currency,period,repaymentPeriods.size());
|
||||||
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);
|
loanCharges, currency,period,repaymentPeriods.size());
|
||||||
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,
|
||||||
@@ -47,13 +48,42 @@ 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) {
|
final MonetaryCurrency monetaryCurrency,LoanRepaymentScheduleInstallment period,int numberOfRepayments) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(monetaryCurrency);
|
Money cumulative = Money.zero(monetaryCurrency);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd) && loanCharge.isFeeCharge()) {
|
if (loanCharge.isFeeCharge()) {
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
if (loanCharge.isInstalmentFee()) {
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
|
amount = amount.add(period.getPrincipal(monetaryCurrency).getAmount()).add(
|
||||||
|
period.getInterestCharged(monetaryCurrency).getAmount());
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
|
amount = amount.add(period.getInterestCharged(monetaryCurrency).getAmount());
|
||||||
|
} else {
|
||||||
|
amount = amount.add(period.getPrincipal(monetaryCurrency).getAmount());
|
||||||
|
}
|
||||||
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
|
} else {
|
||||||
|
cumulative = cumulative.plus(loanCharge.amount().divide(BigDecimal.valueOf(numberOfRepayments)));
|
||||||
|
}
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
|
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed()).add(period.getLoan().getSummary().getTotalInterestCharged());
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
|
amount = amount.add(period.getLoan().getSummary().getTotalInterestCharged());
|
||||||
|
} else {
|
||||||
|
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed());
|
||||||
|
}
|
||||||
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
|
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
||||||
|
cumulative = cumulative.plus(loanCharge.amount());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,13 +119,42 @@ 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) {
|
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency,LoanRepaymentScheduleInstallment period,int numberOfRepayments) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(currency);
|
Money cumulative = Money.zero(currency);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd) && loanCharge.isPenaltyCharge()) {
|
if (loanCharge.isPenaltyCharge()) {
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
if (loanCharge.isInstalmentFee()) {
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
|
amount = amount.add(period.getPrincipal(currency).getAmount())
|
||||||
|
.add(period.getInterestCharged(currency).getAmount());
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
|
amount = amount.add(period.getInterestCharged(currency).getAmount());
|
||||||
|
} else {
|
||||||
|
amount = amount.add(period.getPrincipal(currency).getAmount());
|
||||||
|
}
|
||||||
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
|
} else {
|
||||||
|
cumulative = cumulative.plus(loanCharge.amount().divide(BigDecimal.valueOf(numberOfRepayments)));
|
||||||
|
}
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
|
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed()).add(period.getLoan().getSummary().getTotalInterestCharged());
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
|
amount = amount.add(period.getLoan().getSummary().getTotalInterestCharged());
|
||||||
|
} else {
|
||||||
|
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed());
|
||||||
|
}
|
||||||
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
|
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
||||||
|
cumulative = cumulative.plus(loanCharge.amount());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
@@ -274,4 +274,9 @@ public final class LoanSummary {
|
|||||||
.plus(this.totalFeeChargesOutstanding).plus(this.totalPenaltyChargesOutstanding);
|
.plus(this.totalFeeChargesOutstanding).plus(this.totalPenaltyChargesOutstanding);
|
||||||
this.totalOutstanding = totalOutstanding.getAmount();
|
this.totalOutstanding = totalOutstanding.getAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BigDecimal getTotalPrincipalDisbursed() {
|
||||||
|
return this.totalPrincipalDisbursed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+9
-2
@@ -257,14 +257,21 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
|
|
||||||
private LoanCharge findEarliestUnpaidChargeFromUnOrderedSet(final Set<LoanCharge> charges) {
|
private LoanCharge findEarliestUnpaidChargeFromUnOrderedSet(final Set<LoanCharge> charges) {
|
||||||
LoanCharge earliestUnpaidCharge = null;
|
LoanCharge earliestUnpaidCharge = null;
|
||||||
|
LoanCharge installemntCharge = null;
|
||||||
for (final LoanCharge loanCharge : charges) {
|
for (final LoanCharge loanCharge : charges) {
|
||||||
if (loanCharge.isNotFullyPaid() && !loanCharge.isDueAtDisbursement()) {
|
if (loanCharge.isNotFullyPaid() && !loanCharge.isDueAtDisbursement()) {
|
||||||
if (earliestUnpaidCharge == null || loanCharge.getDueLocalDate().isBefore(earliestUnpaidCharge.getDueLocalDate())) {
|
if(loanCharge.isInstalmentFee()){
|
||||||
|
if(installemntCharge == null){
|
||||||
|
installemntCharge = loanCharge;
|
||||||
|
}
|
||||||
|
}else if (earliestUnpaidCharge == null || loanCharge.getDueLocalDate().isBefore(earliestUnpaidCharge.getDueLocalDate())) {
|
||||||
earliestUnpaidCharge = loanCharge;
|
earliestUnpaidCharge = loanCharge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(earliestUnpaidCharge == null || earliestUnpaidCharge.getDueLocalDate().isAfter(new LocalDate())){
|
||||||
|
earliestUnpaidCharge = installemntCharge;
|
||||||
|
}
|
||||||
|
|
||||||
return earliestUnpaidCharge;
|
return earliestUnpaidCharge;
|
||||||
}
|
}
|
||||||
|
|||||||
+70
-8
@@ -108,9 +108,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
outstandingBalance = outstandingBalance.minus(principalInterestForThisPeriod.principal());
|
outstandingBalance = outstandingBalance.minus(principalInterestForThisPeriod.principal());
|
||||||
|
|
||||||
// 7. determine fees and penalties
|
// 7. determine fees and penalties
|
||||||
final Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges, currency);
|
final Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges, currency,
|
||||||
|
principalInterestForThisPeriod, principalDisbursed, totalInterestChargedForFullLoanTerm, numberOfRepayments);
|
||||||
final Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges,
|
final Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges,
|
||||||
currency);
|
currency, principalInterestForThisPeriod, principalDisbursed, totalInterestChargedForFullLoanTerm, numberOfRepayments);
|
||||||
|
|
||||||
// 8. sum up real totalInstallmentDue from components
|
// 8. sum up real totalInstallmentDue from components
|
||||||
final Money totalInstallmentDue = principalInterestForThisPeriod.principal() //
|
final Money totalInstallmentDue = principalInterestForThisPeriod.principal() //
|
||||||
@@ -174,13 +175,43 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
final MonetaryCurrency monetaryCurrency, final PrincipalInterest principalInterestForThisPeriod,
|
||||||
|
final Money principalDisbursed, final Money totalInterestChargedForFullLoanTerm, int numberOfRepayments) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(monetaryCurrency);
|
Money cumulative = Money.zero(monetaryCurrency);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd) && loanCharge.isFeeCharge()) {
|
if (loanCharge.isFeeCharge()) {
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
if (loanCharge.isInstalmentFee()) {
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
|
amount = amount.add(principalInterestForThisPeriod.principal().getAmount()).add(
|
||||||
|
principalInterestForThisPeriod.interest().getAmount());
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
|
amount = amount.add(principalInterestForThisPeriod.interest().getAmount());
|
||||||
|
} else {
|
||||||
|
amount = amount.add(principalInterestForThisPeriod.principal().getAmount());
|
||||||
|
}
|
||||||
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
|
} else {
|
||||||
|
cumulative = cumulative.plus(loanCharge.amount().divide(BigDecimal.valueOf(numberOfRepayments)));
|
||||||
|
}
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
|
amount = amount.add(principalDisbursed.getAmount()).add(totalInterestChargedForFullLoanTerm.getAmount());
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
|
amount = amount.add(totalInterestChargedForFullLoanTerm.getAmount());
|
||||||
|
} else {
|
||||||
|
amount = amount.add(principalDisbursed.getAmount());
|
||||||
|
}
|
||||||
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
|
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
||||||
|
cumulative = cumulative.plus(loanCharge.amount());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,13 +219,44 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Money cumulativePenaltyChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
private Money cumulativePenaltyChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
||||||
final Set<LoanCharge> loanCharges, final MonetaryCurrency monetaryCurrency) {
|
final Set<LoanCharge> loanCharges, final MonetaryCurrency monetaryCurrency,
|
||||||
|
final PrincipalInterest principalInterestForThisPeriod, final Money principalDisbursed,
|
||||||
|
final Money totalInterestChargedForFullLoanTerm, int numberOfRepayments) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(monetaryCurrency);
|
Money cumulative = Money.zero(monetaryCurrency);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd) && loanCharge.isPenaltyCharge()) {
|
if (loanCharge.isPenaltyCharge()) {
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
if (loanCharge.isInstalmentFee()) {
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
|
amount = amount.add(principalInterestForThisPeriod.principal().getAmount()).add(
|
||||||
|
principalInterestForThisPeriod.interest().getAmount());
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
|
amount = amount.add(principalInterestForThisPeriod.interest().getAmount());
|
||||||
|
} else {
|
||||||
|
amount = amount.add(principalInterestForThisPeriod.principal().getAmount());
|
||||||
|
}
|
||||||
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
|
} else {
|
||||||
|
cumulative = cumulative.plus(loanCharge.amount().divide(BigDecimal.valueOf(numberOfRepayments)));
|
||||||
|
}
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
|
amount = amount.add(principalDisbursed.getAmount()).add(totalInterestChargedForFullLoanTerm.getAmount());
|
||||||
|
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||||
|
amount = amount.add(totalInterestChargedForFullLoanTerm.getAmount());
|
||||||
|
} else {
|
||||||
|
amount = amount.add(principalDisbursed.getAmount());
|
||||||
|
}
|
||||||
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
|
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
||||||
|
cumulative = cumulative.plus(loanCharge.amount());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -325,12 +325,6 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
existingLoanApplication.updateTransactionProcessingStrategy(strategy);
|
existingLoanApplication.updateTransactionProcessingStrategy(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String chargesParamName = "charges";
|
|
||||||
if (changes.containsKey(chargesParamName)) {
|
|
||||||
final Set<LoanCharge> loanCharges = this.loanChargeAssembler.fromParsedJson(command.parsedJson());
|
|
||||||
existingLoanApplication.updateLoanCharges(loanCharges);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String collateralParamName = "collateral";
|
final String collateralParamName = "collateral";
|
||||||
if (changes.containsKey(collateralParamName)) {
|
if (changes.containsKey(collateralParamName)) {
|
||||||
final Set<LoanCollateral> loanCollateral = this.loanCollateralAssembler.fromParsedJson(command.parsedJson());
|
final Set<LoanCollateral> loanCollateral = this.loanCollateralAssembler.fromParsedJson(command.parsedJson());
|
||||||
@@ -347,6 +341,12 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
existingLoanApplication.updateLoanSchedule(loanSchedule);
|
existingLoanApplication.updateLoanSchedule(loanSchedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final String chargesParamName = "charges";
|
||||||
|
if (changes.containsKey(chargesParamName)) {
|
||||||
|
final Set<LoanCharge> loanCharges = this.loanChargeAssembler.fromParsedJson(command.parsedJson());
|
||||||
|
existingLoanApplication.updateLoanCharges(loanCharges);
|
||||||
|
}
|
||||||
|
|
||||||
this.loanRepository.saveAndFlush(existingLoanApplication);
|
this.loanRepository.saveAndFlush(existingLoanApplication);
|
||||||
|
|
||||||
final String submittedOnNote = command.stringValueOfParameterNamed("submittedOnNote");
|
final String submittedOnNote = command.stringValueOfParameterNamed("submittedOnNote");
|
||||||
|
|||||||
+3
-2
@@ -47,6 +47,7 @@ public class LoanChargeAssembler {
|
|||||||
final Set<LoanCharge> loanCharges = new HashSet<LoanCharge>();
|
final Set<LoanCharge> loanCharges = new HashSet<LoanCharge>();
|
||||||
|
|
||||||
final BigDecimal principal = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element);
|
final BigDecimal principal = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element);
|
||||||
|
final Integer numberOfRepayments = this.fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
|
||||||
|
|
||||||
if (element.isJsonObject()) {
|
if (element.isJsonObject()) {
|
||||||
final JsonObject topLevelJsonElement = element.getAsJsonObject();
|
final JsonObject topLevelJsonElement = element.getAsJsonObject();
|
||||||
@@ -83,14 +84,14 @@ public class LoanChargeAssembler {
|
|||||||
chargePaymentModeEnum = ChargePaymentMode.fromInt(chargePaymentMode);
|
chargePaymentModeEnum = ChargePaymentMode.fromInt(chargePaymentMode);
|
||||||
}
|
}
|
||||||
final LoanCharge loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, principal, amount, chargeTime,
|
final LoanCharge loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, principal, amount, chargeTime,
|
||||||
chargeCalculation, dueDate, chargePaymentModeEnum);
|
chargeCalculation, dueDate, chargePaymentModeEnum,numberOfRepayments);
|
||||||
loanCharges.add(loanCharge);
|
loanCharges.add(loanCharge);
|
||||||
} else {
|
} else {
|
||||||
final Long loanChargeId = id;
|
final Long loanChargeId = id;
|
||||||
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);
|
loanCharge.update(amount, dueDate, principal, numberOfRepayments);
|
||||||
|
|
||||||
loanCharges.add(loanCharge);
|
loanCharges.add(loanCharge);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-2
@@ -925,7 +925,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
if (loanCharge.isWaived()) {
|
if (loanCharge.isWaived()) {
|
||||||
throw new LoanChargeCannotBeWaivedException(LOAN_CHARGE_CANNOT_BE_WAIVED_REASON.ALREADY_WAIVED, loanCharge.getId());
|
throw new LoanChargeCannotBeWaivedException(LOAN_CHARGE_CANNOT_BE_WAIVED_REASON.ALREADY_WAIVED, loanCharge.getId());
|
||||||
} else if (loanCharge.isPaid()) { throw new LoanChargeCannotBeWaivedException(LOAN_CHARGE_CANNOT_BE_WAIVED_REASON.ALREADY_PAID,
|
} else if (loanCharge.isPaid()) { throw new LoanChargeCannotBeWaivedException(LOAN_CHARGE_CANNOT_BE_WAIVED_REASON.ALREADY_PAID,
|
||||||
loanCharge.getId()); }
|
loanCharge.getId());
|
||||||
|
} else if (loanCharge.isInstalmentFee()){
|
||||||
|
throw new LoanChargeCannotBeWaivedException(LOAN_CHARGE_CANNOT_BE_WAIVED_REASON.WAIVE_NOT_ALLOWED_FOR_CHARGE,
|
||||||
|
loanCharge.getId());
|
||||||
|
}
|
||||||
|
|
||||||
final Map<String, Object> changes = new LinkedHashMap<String, Object>(3);
|
final Map<String, Object> changes = new LinkedHashMap<String, Object>(3);
|
||||||
|
|
||||||
@@ -1001,7 +1005,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
if (loanCharge.isWaived()) {
|
if (loanCharge.isWaived()) {
|
||||||
throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.ALREADY_WAIVED, loanCharge.getId());
|
throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.ALREADY_WAIVED, loanCharge.getId());
|
||||||
} else if (loanCharge.isPaid()) { throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.ALREADY_PAID,
|
} else if (loanCharge.isPaid()) { throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.ALREADY_PAID,
|
||||||
loanCharge.getId()); }
|
loanCharge.getId());
|
||||||
|
}else if (loanCharge.isInstalmentFee()){
|
||||||
|
throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.CHARGE_NOT_PAYABLE,
|
||||||
|
loanCharge.getId());
|
||||||
|
}
|
||||||
|
|
||||||
if (!loanCharge.getChargePaymentMode().isPaymentModeAccountTransfer()) { throw new LoanChargeCannotBePayedException(
|
if (!loanCharge.getChargePaymentMode().isPaymentModeAccountTransfer()) { throw new LoanChargeCannotBePayedException(
|
||||||
LOAN_CHARGE_CANNOT_BE_PAYED_REASON.CHARGE_NOT_ACCOUNT_TRANSFER, loanCharge.getId()); }
|
LOAN_CHARGE_CANNOT_BE_PAYED_REASON.CHARGE_NOT_ACCOUNT_TRANSFER, loanCharge.getId()); }
|
||||||
|
|||||||
Reference in New Issue
Block a user