wip:minor changes to charges
This commit is contained in:
Executable
+2
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE `m_loan_charge`
|
||||||
|
ADD COLUMN `waived` TINYINT(1) NOT NULL DEFAULT '0' AFTER `is_paid_derived`;
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* 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.charge.exception;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||||
|
|
||||||
|
public class LoanChargeCannotBeDeletedException extends AbstractPlatformDomainRuleException {
|
||||||
|
|
||||||
|
/*** enum of reasons of why Loan Charge cannot be waived **/
|
||||||
|
public static enum LOAN_CHARGE_CANNOT_BE_DELETED_REASON {
|
||||||
|
ALREADY_PAID, ALREADY_WAIVED, LOAN_APPROVED;
|
||||||
|
|
||||||
|
public String errorMessage() {
|
||||||
|
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||||
|
return "This loan charge has been partially/completely paid";
|
||||||
|
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||||
|
return "This loan charge has already been waived";
|
||||||
|
} else if (name().toString().equalsIgnoreCase("LOAN_APPROVED")) { return "This charge cannot be deleted as the loan it is associated with has already been approved"; }
|
||||||
|
return name().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String errorCode() {
|
||||||
|
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||||
|
return "error.msg.loan.charge.already.paid";
|
||||||
|
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||||
|
return "error.msg.loan.charge.already.waived";
|
||||||
|
} else if (name().toString().equalsIgnoreCase("LOAN_APPROVED")) { return "error.msg.loan.charge.associated.loan.already.approved"; }
|
||||||
|
return name().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoanChargeCannotBeDeletedException(final LOAN_CHARGE_CANNOT_BE_DELETED_REASON reason, final Long loanChargeId) {
|
||||||
|
super(reason.errorCode(), reason.errorMessage(), loanChargeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* 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.charge.exception;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||||
|
|
||||||
|
public class LoanChargeCannotBeWaivedException extends AbstractPlatformDomainRuleException {
|
||||||
|
|
||||||
|
/*** enum of reasons of why Loan Charge cannot be waived **/
|
||||||
|
public static enum LOAN_CHARGE_CANNOT_BE_WAIVED_REASON {
|
||||||
|
ALREADY_PAID, ALREADY_WAIVED, LOAN_INACTIVE;
|
||||||
|
|
||||||
|
public String errorMessage() {
|
||||||
|
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||||
|
return "This loan charge has been completely paid";
|
||||||
|
} else if (name().toString().equalsIgnoreCase("ALREADY_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"; }
|
||||||
|
return name().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String errorCode() {
|
||||||
|
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||||
|
return "error.msg.loan.charge.already.paid";
|
||||||
|
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||||
|
return "error.msg.loan.charge.already.waived";
|
||||||
|
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) { return "error.msg.loan.charge.associated.loan.inactive"; }
|
||||||
|
return name().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoanChargeCannotBeWaivedException(final LOAN_CHARGE_CANNOT_BE_WAIVED_REASON reason, final Long loanChargeId) {
|
||||||
|
super(reason.errorCode(), reason.errorMessage(), loanChargeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -430,7 +430,7 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateLoanChargeIsNotWaived(final LoanCharge loanCharge) {
|
private void validateLoanChargeIsNotWaived(final LoanCharge loanCharge) {
|
||||||
if (loanCharge.isWaivedOrPartiallyWaived(loanCurrency())) {
|
if (loanCharge.isWaived()) {
|
||||||
final String defaultUserMessage = "This loan charge cannot be removed as the charge as already been waived.";
|
final String defaultUserMessage = "This loan charge cannot be removed as the charge as already been waived.";
|
||||||
throw new LoanChargeCannotBeAddedException("loanCharge", "loanCharge.is.waived", defaultUserMessage, getId(), loanCharge.name());
|
throw new LoanChargeCannotBeAddedException("loanCharge", "loanCharge.is.waived", defaultUserMessage, getId(), loanCharge.name());
|
||||||
}
|
}
|
||||||
@@ -1793,7 +1793,7 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return !isSubmittedAndPendingApproval();
|
return !isSubmittedAndPendingApproval();
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoanStatus status() {
|
public LoanStatus status() {
|
||||||
return LoanStatus.fromInt(this.loanStatus);
|
return LoanStatus.fromInt(this.loanStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-11
@@ -82,6 +82,9 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
@Column(name = "is_paid_derived", nullable = false)
|
@Column(name = "is_paid_derived", nullable = false)
|
||||||
private boolean paid = false;
|
private boolean paid = false;
|
||||||
|
|
||||||
|
@Column(name = "waived", nullable = false)
|
||||||
|
private boolean waived = false;
|
||||||
|
|
||||||
public static LoanCharge createNewFromJson(final Loan loan, final Charge chargeDefinition, final JsonCommand command) {
|
public static LoanCharge createNewFromJson(final Loan loan, final Charge chargeDefinition, final JsonCommand command) {
|
||||||
|
|
||||||
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
|
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
|
||||||
@@ -101,8 +104,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
// ChargeCalculationType.fromInt(chargeCalculationType);
|
// ChargeCalculationType.fromInt(chargeCalculationType);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation,
|
return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation, dueDate);
|
||||||
dueDate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -132,8 +134,8 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
if (dueDate == null) {
|
if (dueDate == null) {
|
||||||
final String defaultUserMessage = "Loan charge is missing due date.";
|
final String defaultUserMessage = "Loan charge is missing due date.";
|
||||||
throw new LoanChargeWithoutMandatoryFieldException("loanCharge", "dueDate", defaultUserMessage,
|
throw new LoanChargeWithoutMandatoryFieldException("loanCharge", "dueDate", defaultUserMessage, chargeDefinition.getId(),
|
||||||
chargeDefinition.getId(), chargeDefinition.getName());
|
chargeDefinition.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dueDate = dueDate.toDate();
|
this.dueDate = dueDate.toDate();
|
||||||
@@ -218,6 +220,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
this.amountWrittenOff = BigDecimal.ZERO;
|
this.amountWrittenOff = BigDecimal.ZERO;
|
||||||
this.amountOutstanding = calculateAmountOutstanding(currency);
|
this.amountOutstanding = calculateAmountOutstanding(currency);
|
||||||
this.paid = false;
|
this.paid = false;
|
||||||
|
this.waived = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetPaidAmount(final MonetaryCurrency currency) {
|
public void resetPaidAmount(final MonetaryCurrency currency) {
|
||||||
@@ -227,9 +230,10 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Money waive(final MonetaryCurrency currency) {
|
public Money waive(final MonetaryCurrency currency) {
|
||||||
this.amountWaived = this.amount;
|
this.amountWaived = this.amountOutstanding;
|
||||||
this.amountOutstanding = calculateAmountOutstanding(currency);
|
this.amountOutstanding = BigDecimal.ZERO;
|
||||||
this.paid = determineIfFullyPaid();
|
this.paid = false;
|
||||||
|
this.waived = true;
|
||||||
return getAmountWaived(currency);
|
return getAmountWaived(currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,16 +456,16 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
return this.paid;
|
return this.paid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWaived() {
|
||||||
|
return this.waived;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPaidOrPartiallyPaid(final MonetaryCurrency currency) {
|
public boolean isPaidOrPartiallyPaid(final MonetaryCurrency currency) {
|
||||||
|
|
||||||
final Money amountWaivedOrWrittenOff = getAmountWaived(currency).plus(getAmountWrittenOff(currency));
|
final Money amountWaivedOrWrittenOff = getAmountWaived(currency).plus(getAmountWrittenOff(currency));
|
||||||
return Money.of(currency, this.amountPaid).plus(amountWaivedOrWrittenOff).isGreaterThanZero();
|
return Money.of(currency, this.amountPaid).plus(amountWaivedOrWrittenOff).isGreaterThanZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWaivedOrPartiallyWaived(final MonetaryCurrency currency) {
|
|
||||||
return getAmountWaived(currency).isGreaterThanZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Money getAmount(final MonetaryCurrency currency) {
|
private Money getAmount(final MonetaryCurrency currency) {
|
||||||
return Money.of(currency, this.amount);
|
return Money.of(currency, this.amount);
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-1
@@ -24,6 +24,10 @@ import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyReposit
|
|||||||
import org.mifosplatform.organisation.staff.domain.Staff;
|
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||||
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
|
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||||
|
import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeDeletedException;
|
||||||
|
import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeDeletedException.LOAN_CHARGE_CANNOT_BE_DELETED_REASON;
|
||||||
|
import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException;
|
||||||
|
import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException.LOAN_CHARGE_CANNOT_BE_WAIVED_REASON;
|
||||||
import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException;
|
import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException;
|
||||||
import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand;
|
import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
|
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
|
||||||
@@ -535,10 +539,22 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final Loan loan = retrieveLoanBy(loanId);
|
final Loan loan = retrieveLoanBy(loanId);
|
||||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||||
|
|
||||||
|
// Charges may be waived only when the loan associated with them are
|
||||||
|
// active
|
||||||
|
if (!loan.status().isActive()) { throw new LoanChargeCannotBeWaivedException(LOAN_CHARGE_CANNOT_BE_WAIVED_REASON.LOAN_INACTIVE,
|
||||||
|
loanCharge.getId()); }
|
||||||
|
|
||||||
|
// validate loan charge is not already paid or waived
|
||||||
|
if (loanCharge.isWaived()) {
|
||||||
|
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,
|
||||||
|
loanCharge.getId()); }
|
||||||
|
|
||||||
final Map<String, Object> changes = new LinkedHashMap<String, Object>(3);
|
final Map<String, Object> changes = new LinkedHashMap<String, Object>(3);
|
||||||
|
|
||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
|
|
||||||
final LoanTransaction waiveTransaction = loan.waiveLoanCharge(loanCharge, defaultLoanLifecycleStateMachine(), changes,
|
final LoanTransaction waiveTransaction = loan.waiveLoanCharge(loanCharge, defaultLoanLifecycleStateMachine(), changes,
|
||||||
existingTransactionIds, existingReversedTransactionIds);
|
existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
|
||||||
@@ -558,7 +574,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult deleteLoanCharge(final Long loanId, final Long loanChargeId, final JsonCommand command) {
|
public CommandProcessingResult deleteLoanCharge(final Long loanId, final Long loanChargeId, final JsonCommand command) {
|
||||||
@@ -568,6 +583,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final Loan loan = retrieveLoanBy(loanId);
|
final Loan loan = retrieveLoanBy(loanId);
|
||||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||||
|
|
||||||
|
// validate loan charge is not partly paid or waived
|
||||||
|
if (loanCharge.isWaived()) {
|
||||||
|
throw new LoanChargeCannotBeDeletedException(LOAN_CHARGE_CANNOT_BE_DELETED_REASON.ALREADY_WAIVED, loanCharge.getId());
|
||||||
|
} else if (loanCharge.isPaidOrPartiallyPaid(loan.getCurrency())) { throw new LoanChargeCannotBeDeletedException(
|
||||||
|
LOAN_CHARGE_CANNOT_BE_DELETED_REASON.ALREADY_PAID, loanCharge.getId()); }
|
||||||
|
|
||||||
loan.removeLoanCharge(loanCharge);
|
loan.removeLoanCharge(loanCharge);
|
||||||
this.loanRepository.save(loan);
|
this.loanRepository.save(loan);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user