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) {
|
||||
if (loanCharge.isWaivedOrPartiallyWaived(loanCurrency())) {
|
||||
if (loanCharge.isWaived()) {
|
||||
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());
|
||||
}
|
||||
@@ -1793,7 +1793,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
return !isSubmittedAndPendingApproval();
|
||||
}
|
||||
|
||||
private LoanStatus status() {
|
||||
public LoanStatus status() {
|
||||
return LoanStatus.fromInt(this.loanStatus);
|
||||
}
|
||||
|
||||
|
||||
+15
-11
@@ -82,6 +82,9 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
@Column(name = "is_paid_derived", nullable = 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) {
|
||||
|
||||
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
|
||||
@@ -101,8 +104,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
// ChargeCalculationType.fromInt(chargeCalculationType);
|
||||
// }
|
||||
|
||||
return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation,
|
||||
dueDate);
|
||||
return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation, dueDate);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -132,8 +134,8 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
|
||||
if (dueDate == null) {
|
||||
final String defaultUserMessage = "Loan charge is missing due date.";
|
||||
throw new LoanChargeWithoutMandatoryFieldException("loanCharge", "dueDate", defaultUserMessage,
|
||||
chargeDefinition.getId(), chargeDefinition.getName());
|
||||
throw new LoanChargeWithoutMandatoryFieldException("loanCharge", "dueDate", defaultUserMessage, chargeDefinition.getId(),
|
||||
chargeDefinition.getName());
|
||||
}
|
||||
|
||||
this.dueDate = dueDate.toDate();
|
||||
@@ -218,6 +220,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
this.amountWrittenOff = BigDecimal.ZERO;
|
||||
this.amountOutstanding = calculateAmountOutstanding(currency);
|
||||
this.paid = false;
|
||||
this.waived = false;
|
||||
}
|
||||
|
||||
public void resetPaidAmount(final MonetaryCurrency currency) {
|
||||
@@ -227,9 +230,10 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public Money waive(final MonetaryCurrency currency) {
|
||||
this.amountWaived = this.amount;
|
||||
this.amountOutstanding = calculateAmountOutstanding(currency);
|
||||
this.paid = determineIfFullyPaid();
|
||||
this.amountWaived = this.amountOutstanding;
|
||||
this.amountOutstanding = BigDecimal.ZERO;
|
||||
this.paid = false;
|
||||
this.waived = true;
|
||||
return getAmountWaived(currency);
|
||||
}
|
||||
|
||||
@@ -452,16 +456,16 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
return this.paid;
|
||||
}
|
||||
|
||||
public boolean isWaived() {
|
||||
return this.waived;
|
||||
}
|
||||
|
||||
public boolean isPaidOrPartiallyPaid(final MonetaryCurrency currency) {
|
||||
|
||||
final Money amountWaivedOrWrittenOff = getAmountWaived(currency).plus(getAmountWrittenOff(currency));
|
||||
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) {
|
||||
return Money.of(currency, this.amount);
|
||||
}
|
||||
|
||||
+28
-7
@@ -24,6 +24,10 @@ import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyReposit
|
||||
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||
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.loanaccount.command.LoanUpdateCommand;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
|
||||
@@ -143,7 +147,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
context.authenticatedUser();
|
||||
|
||||
final Loan loan = retrieveLoanBy(loanId);
|
||||
final BigDecimal totalInterestCharged = loan.getSummary().getTotalInterestCharged();
|
||||
final BigDecimal totalInterestCharged = loan.getSummary().getTotalInterestCharged();
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||
@@ -164,7 +168,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
// accountingBridgedate, this would not work if interest
|
||||
// recalculation in introduced
|
||||
accountingBridgeData.put("calculatedInterest", totalInterestCharged);
|
||||
|
||||
|
||||
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
|
||||
@@ -310,7 +314,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final Note note = Note.loanTransactionNote(loan, waiveTransaction, noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -535,16 +539,28 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final Loan loan = retrieveLoanBy(loanId);
|
||||
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 List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||
|
||||
final LoanTransaction waiveTransaction = loan.waiveLoanCharge(loanCharge, defaultLoanLifecycleStateMachine(), changes,
|
||||
existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
this.loanTransactionRepository.save(waiveTransaction);
|
||||
this.loanRepository.save(loan);
|
||||
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -558,7 +574,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
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 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);
|
||||
this.loanRepository.save(loan);
|
||||
|
||||
@@ -688,7 +709,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.withLoanId(loanId) //
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param loan
|
||||
* @param existingTransactionIds
|
||||
|
||||
Reference in New Issue
Block a user