added validation around Loan life cycle events like, repayment, disbursement etc..

This commit is contained in:
ashok-conflux
2013-12-16 17:08:19 +05:30
committed by Vishwas Babu A J
parent 49a2f30e2c
commit a354b3e664
3 changed files with 140 additions and 4 deletions
@@ -89,6 +89,12 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi
newState = stateOf(LoanStatus.OVERPAID, this.allowedLoanStatuses);
}
break;
case LOAN_CLOSED:
break;
case WRITE_OFF_OUTSTANDING_UNDO:
break;
default:
break;
}
return newState;
@@ -44,6 +44,8 @@ import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.security.service.RandomPasswordGenerator;
import org.mifosplatform.organisation.holiday.domain.Holiday;
@@ -1314,7 +1316,9 @@ public class Loan extends AbstractPersistable<Long> {
public Map<String, Object> loanApplicationRejection(final AppUser currentUser, final JsonCommand command,
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
validateAccountStatus(LoanEvent.LOAN_REJECTED);
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>();
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECTED, LoanStatus.fromInt(this.loanStatus));
@@ -1410,6 +1414,8 @@ public class Loan extends AbstractPersistable<Long> {
public Map<String, Object> loanApplicationApproval(final AppUser currentUser, final JsonCommand command,
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
validateAccountStatus(LoanEvent.LOAN_APPROVED);
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>();
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVED, LoanStatus.fromInt(this.loanStatus));
@@ -1458,6 +1464,7 @@ public class Loan extends AbstractPersistable<Long> {
public Map<String, Object> undoApproval(final LoanLifecycleStateMachine loanLifecycleStateMachine) {
validateAccountStatus(LoanEvent.LOAN_APPROVAL_UNDO);
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>();
final LoanStatus currentStatus = LoanStatus.fromInt(this.loanStatus);
@@ -1506,6 +1513,7 @@ public class Loan extends AbstractPersistable<Long> {
final LocalDate calculatedRepaymentsStartingFromDate, final boolean isHolidayEnabled, final List<Holiday> holidays,
final WorkingDays workingDays, final boolean allowTransactionsOnHoliday, final boolean allowTransactionsOnNonWorkingDay) {
validateAccountStatus(LoanEvent.LOAN_DISBURSED);
updateLoanToPreDisbursalState();
final LoanStatus statusEnum = this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED,
@@ -1674,8 +1682,9 @@ public class Loan extends AbstractPersistable<Long> {
final List<Long> existingReversedTransactionIds, final LocalDate calculatedRepaymentsStartingFromDate,
final boolean isHolidayEnabled, final List<Holiday> holidays, final WorkingDays workingDays) {
validateAccountStatus(LoanEvent.LOAN_DISBURSAL_UNDO);
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>();
final LoanStatus currentStatus = LoanStatus.fromInt(this.loanStatus);
final LoanStatus statusEnum = this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, currentStatus);
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_DISBURSAL_UNDO, getDisbursementDate());
@@ -1736,6 +1745,8 @@ public class Loan extends AbstractPersistable<Long> {
public ChangedTransactionDetail waiveInterest(final LoanTransaction waiveInterestTransaction,
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
final List<Long> existingReversedTransactionIds) {
validateAccountStatus(LoanEvent.LOAN_REPAYMENT_OR_WAIVER);
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
waiveInterestTransaction.getTransactionDate());
@@ -1754,6 +1765,7 @@ public class Loan extends AbstractPersistable<Long> {
final List<Long> existingReversedTransactionIds, final boolean allowTransactionsOnHoliday, final List<Holiday> holidays,
final WorkingDays workingDays, final boolean allowTransactionsOnNonWorkingDay) {
validateAccountStatus(LoanEvent.LOAN_REPAYMENT_OR_WAIVER);
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, repaymentTransaction.getTransactionDate());
validateRepaymentDateIsOnHoliday(repaymentTransaction.getTransactionDate(), allowTransactionsOnHoliday, holidays);
@@ -1773,6 +1785,7 @@ public class Loan extends AbstractPersistable<Long> {
final boolean allowTransactionsOnHoliday, final List<Holiday> holidays, final WorkingDays workingDays,
final boolean allowTransactionsOnNonWorkingDay, final LoanTransaction paymentTransaction, final Integer installmentNumber) {
validateAccountStatus(LoanEvent.LOAN_CHARGE_PAYMENT);
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_CHARGE_PAYMENT, paymentTransaction.getTransactionDate());
validateRepaymentDateIsOnHoliday(paymentTransaction.getTransactionDate(), allowTransactionsOnHoliday, holidays);
validateRepaymentDateIsOnNonWorkingDay(paymentTransaction.getTransactionDate(), workingDays, allowTransactionsOnNonWorkingDay);
@@ -2113,6 +2126,9 @@ public class Loan extends AbstractPersistable<Long> {
}
public ChangedTransactionDetail undoWrittenOff(final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds){
validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO);
existingTransactionIds.addAll(findExistingTransactionIds());
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
final LoanTransaction writeOffTransaction = findWriteOffTransaction();
@@ -2179,6 +2195,8 @@ public class Loan extends AbstractPersistable<Long> {
final Map<String, Object> changes, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
final AppUser currentUser) {
validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING);
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING,
LoanStatus.fromInt(this.loanStatus));
@@ -2235,7 +2253,9 @@ public class Loan extends AbstractPersistable<Long> {
public LoanTransaction close(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine,
final Map<String, Object> changes, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
validateAccountStatus(LoanEvent.LOAN_CLOSED);
existingTransactionIds.addAll(findExistingTransactionIds());
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
@@ -2363,6 +2383,10 @@ public class Loan extends AbstractPersistable<Long> {
return status().isSubmittedAndPendingApproval();
}
private boolean isApproved() {
return status().isApproved();
}
private boolean isNotDisbursed() {
return !isDisbursed();
}
@@ -3043,4 +3067,108 @@ public class Loan extends AbstractPersistable<Long> {
return loanChargePerInstallments;
}
private void validateAccountStatus(final LoanEvent event) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
switch (event) {
case LOAN_CREATED:
break;
case LOAN_APPROVED:
if (!isSubmittedAndPendingApproval()) {
final String defaultUserMessage = "Loan Account Approval is not allowed. Loan Account is not in submitted and pending approval state.";
final ApiParameterError error = ApiParameterError.generalError(
"error.msg.loan.approve.account.is.not.submitted.and.pending.state", defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case LOAN_APPROVAL_UNDO:
if (!isApproved()) {
final String defaultUserMessage = "Loan Account Undo Approval is not allowed. Loan Account is not in approved state.";
final ApiParameterError error = ApiParameterError.generalError("error.msg.loan.undo.approval.account.is.not.approved",
defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case LOAN_DISBURSED:
if (!(isApproved() && isNotDisbursed())) {
final String defaultUserMessage = "Loan Disbursal is not allowed. Loan Account is not in approved and not disbursed state.";
final ApiParameterError error = ApiParameterError.generalError(
"error.msg.loan.disbursal.account.is.not.approve.not.disbursed.state", defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case LOAN_DISBURSAL_UNDO:
if (!isOpen()) {
final String defaultUserMessage = "Loan Undo disbursal is not allowed. Loan Account is not active.";
final ApiParameterError error = ApiParameterError.generalError("error.msg.loan.undo.disbursal.account.is.not.active",
defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case LOAN_REPAYMENT_OR_WAIVER:
if (!isOpen()) {
final String defaultUserMessage = "Loan Repayment or Waiver is not allowed. Loan Account is not active.";
final ApiParameterError error = ApiParameterError.generalError(
"error.msg.loan.repayment.or.waiver.account.is.not.active", defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case LOAN_REJECTED:
if (!isClosedWrittenOff()) {
final String defaultUserMessage = "Loan application cannot be rejected. Loan Account is not in Submitted and Pending approval state.";
final ApiParameterError error = ApiParameterError.generalError(
"error.msg.loan.reject.account.is.not.submitted.pending.approval.state", defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case LOAN_WITHDRAWN:
if (!isSubmittedAndPendingApproval()) {
final String defaultUserMessage = "Loan application cannot be withdrawn. Loan Account is not in Submitted and Pending approval state.";
final ApiParameterError error = ApiParameterError.generalError(
"error.msg.loan.withdrawn.account.is.not.submitted.pending.approval.state", defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case WRITE_OFF_OUTSTANDING:
if (!isOpen()) {
final String defaultUserMessage = "Loan Written off is not allowed. Loan Account is not active.";
final ApiParameterError error = ApiParameterError.generalError("error.msg.loan.writtenoff.account.is.not.active",
defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case WRITE_OFF_OUTSTANDING_UNDO:
if (!isClosedWrittenOff()) {
final String defaultUserMessage = "Loan Undo Written off is not allowed. Loan Account is not Written off.";
final ApiParameterError error = ApiParameterError.generalError(
"error.msg.loan.undo.writtenoff.account.is.not.written.off", defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case REPAID_IN_FULL:
break;
case LOAN_CHARGE_PAYMENT:
if (!isClosedWrittenOff()) {
final String defaultUserMessage = "Charge payment is not allowed. Loan Account is not Active.";
final ApiParameterError error = ApiParameterError.generalError("error.msg.loan.charge.payment.account.is.not.active",
defaultUserMessage);
dataValidationErrors.add(error);
}
break;
case LOAN_CLOSED:
if (!isClosedWrittenOff()) {
final String defaultUserMessage = "Closing Loan Account is not allowed. Loan Account is not Active.";
final ApiParameterError error = ApiParameterError.generalError("error.msg.loan.close.account.is.not.active",
defaultUserMessage);
dataValidationErrors.add(error);
}
break;
default:
break;
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
}
@@ -20,7 +20,9 @@ public enum LoanEvent {
LOAN_REPAYMENT_OR_WAIVER, //
REPAID_IN_FULL, //
WRITE_OFF_OUTSTANDING, //
WRITE_OFF_OUTSTANDING_UNDO, //
LOAN_RESCHEDULE, //
INTERST_REBATE_OWED, //
LOAN_OVERPAYMENT, LOAN_CHARGE_PAYMENT;
LOAN_OVERPAYMENT, LOAN_CHARGE_PAYMENT,
LOAN_CLOSED;
}