FINERACT-1734: Loan status can and only be set using the State Machine
This commit is contained in:
committed by
Arnold Gálovics
parent
d003326e48
commit
d06c3655af
+16
-7
@@ -27,16 +27,26 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi
|
|||||||
private final List<LoanStatus> allowedLoanStatuses;
|
private final List<LoanStatus> allowedLoanStatuses;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanStatus transition(final LoanEvent loanEvent, final LoanStatus from) {
|
public LoanStatus dryTransition(final LoanEvent loanEvent, final Loan loan) {
|
||||||
|
return getNextState(loanEvent, loan);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transition(final LoanEvent loanEvent, final Loan loan) {
|
||||||
|
LoanStatus newState = getNextState(loanEvent, loan);
|
||||||
|
loan.setLoanStatus(newState.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoanStatus getNextState(LoanEvent loanEvent, Loan loan) {
|
||||||
|
Integer plainFrom = loan.getPlainStatus();
|
||||||
|
if (loanEvent.equals(LoanEvent.LOAN_CREATED) && plainFrom == null) {
|
||||||
|
return submittedTransition();
|
||||||
|
}
|
||||||
|
|
||||||
|
LoanStatus from = loan.status();
|
||||||
LoanStatus newState = from;
|
LoanStatus newState = from;
|
||||||
|
|
||||||
switch (loanEvent) {
|
switch (loanEvent) {
|
||||||
case LOAN_CREATED:
|
|
||||||
if (from == null) {
|
|
||||||
newState = submittedTransition();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LOAN_REJECTED:
|
case LOAN_REJECTED:
|
||||||
if (from.hasStateOf(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL)) {
|
if (from.hasStateOf(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL)) {
|
||||||
newState = rejectedTransition();
|
newState = rejectedTransition();
|
||||||
@@ -126,7 +136,6 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+38
-64
@@ -700,9 +700,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
chargesPayment.getAmount(getCurrency()).getAmount(), installmentNumber);
|
chargesPayment.getAmount(getCurrency()).getAmount(), installmentNumber);
|
||||||
chargesPayment.getLoanChargesPaid().add(loanChargePaidBy);
|
chargesPayment.getLoanChargesPaid().add(loanChargePaidBy);
|
||||||
addLoanTransaction(chargesPayment);
|
addLoanTransaction(chargesPayment);
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_CHARGE_PAYMENT,
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_CHARGE_PAYMENT, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
this.loanStatus = statusEnum.getValue();
|
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||||
.determineProcessor(this.transactionProcessingStrategy);
|
.determineProcessor(this.transactionProcessingStrategy);
|
||||||
@@ -2025,13 +2023,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
updateLoanSchedule(loanSchedule);
|
updateLoanSchedule(loanSchedule);
|
||||||
|
|
||||||
LoanStatus from = null;
|
lifecycleStateMachine.transition(LoanEvent.LOAN_CREATED, this);
|
||||||
if (this.loanStatus != null) {
|
|
||||||
from = LoanStatus.fromInt(this.loanStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
final LoanStatus statusEnum = lifecycleStateMachine.transition(LoanEvent.LOAN_CREATED, from);
|
|
||||||
this.loanStatus = statusEnum.getValue();
|
|
||||||
|
|
||||||
this.externalId = externalId;
|
this.externalId = externalId;
|
||||||
this.termFrequency = loanApplicationTerms.getLoanTermFrequency();
|
this.termFrequency = loanApplicationTerms.getLoanTermFrequency();
|
||||||
@@ -2114,9 +2106,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
||||||
|
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECTED, LoanStatus.fromInt(this.loanStatus));
|
final LoanStatus statusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_REJECTED, this);
|
||||||
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
||||||
this.loanStatus = statusEnum.getValue();
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECTED, this);
|
||||||
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
|
|
||||||
final LocalDate rejectedOn = command.localDateValueOfParameterNamed("rejectedOnDate");
|
final LocalDate rejectedOn = command.localDateValueOfParameterNamed("rejectedOnDate");
|
||||||
@@ -2160,9 +2152,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
||||||
|
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAWN, LoanStatus.fromInt(this.loanStatus));
|
final LoanStatus statusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_WITHDRAWN, this);
|
||||||
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
||||||
this.loanStatus = statusEnum.getValue();
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAWN, this);
|
||||||
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
|
|
||||||
LocalDate withdrawnOn = command.localDateValueOfParameterNamed("withdrawnOnDate");
|
LocalDate withdrawnOn = command.localDateValueOfParameterNamed("withdrawnOnDate");
|
||||||
@@ -2215,7 +2207,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
* statusEnum is holding the possible new status derived from loanLifecycleStateMachine.transition.
|
* statusEnum is holding the possible new status derived from loanLifecycleStateMachine.transition.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
final LoanStatus newStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVED, LoanStatus.fromInt(this.loanStatus));
|
final LoanStatus newStatusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_APPROVED, this);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: There is no need to check below condition, if loanLifecycleStateMachine.transition is doing it's
|
* FIXME: There is no need to check below condition, if loanLifecycleStateMachine.transition is doing it's
|
||||||
@@ -2225,7 +2217,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (!newStatusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
if (!newStatusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
||||||
this.loanStatus = newStatusEnum.getValue();
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVED, this);
|
||||||
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
|
|
||||||
// only do below if status has changed in the 'approval' case
|
// only do below if status has changed in the 'approval' case
|
||||||
@@ -2363,9 +2355,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
||||||
|
|
||||||
final LoanStatus currentStatus = LoanStatus.fromInt(this.loanStatus);
|
final LoanStatus currentStatus = LoanStatus.fromInt(this.loanStatus);
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVAL_UNDO, currentStatus);
|
final LoanStatus statusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_APPROVAL_UNDO, this);
|
||||||
if (!statusEnum.hasStateOf(currentStatus)) {
|
if (!statusEnum.hasStateOf(currentStatus)) {
|
||||||
this.loanStatus = statusEnum.getValue();
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVAL_UNDO, this);
|
||||||
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
|
|
||||||
this.approvedOnDate = null;
|
this.approvedOnDate = null;
|
||||||
@@ -2414,12 +2406,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
public ChangedTransactionDetail disburse(final AppUser currentUser, final JsonCommand command, final Map<String, Object> actualChanges,
|
public ChangedTransactionDetail disburse(final AppUser currentUser, final JsonCommand command, final Map<String, Object> actualChanges,
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final PaymentDetail paymentDetail) {
|
final ScheduleGeneratorDTO scheduleGeneratorDTO, final PaymentDetail paymentDetail) {
|
||||||
|
|
||||||
final LoanStatus statusEnum = this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED,
|
this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
|
|
||||||
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
||||||
|
|
||||||
this.loanStatus = statusEnum.getValue();
|
|
||||||
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
|
|
||||||
this.disbursedBy = currentUser;
|
this.disbursedBy = currentUser;
|
||||||
@@ -2526,8 +2516,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
public boolean canDisburse(final LocalDate actualDisbursementDate) {
|
public boolean canDisburse(final LocalDate actualDisbursementDate) {
|
||||||
LocalDate lastDisburseDate = this.actualDisbursementDate;
|
LocalDate lastDisburseDate = this.actualDisbursementDate;
|
||||||
final LoanStatus statusEnum = this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED,
|
final LoanStatus statusEnum = this.loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_DISBURSED, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
|
|
||||||
boolean isMultiTrancheDisburse = false;
|
boolean isMultiTrancheDisburse = false;
|
||||||
LoanStatus actualLoanStatus = LoanStatus.fromInt(this.loanStatus);
|
LoanStatus actualLoanStatus = LoanStatus.fromInt(this.loanStatus);
|
||||||
@@ -2921,12 +2910,12 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
||||||
final LoanStatus currentStatus = LoanStatus.fromInt(this.loanStatus);
|
final LoanStatus currentStatus = LoanStatus.fromInt(this.loanStatus);
|
||||||
final LoanStatus statusEnum = this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, currentStatus);
|
final LoanStatus statusEnum = this.loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_DISBURSAL_UNDO, this);
|
||||||
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_DISBURSAL_UNDO, getDisbursementDate());
|
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_DISBURSAL_UNDO, getDisbursementDate());
|
||||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||||
if (!statusEnum.hasStateOf(currentStatus)) {
|
if (!statusEnum.hasStateOf(currentStatus)) {
|
||||||
this.loanStatus = statusEnum.getValue();
|
this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, this);
|
||||||
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
|
|
||||||
final LocalDate actualDisbursementDate = getDisbursementDate();
|
final LocalDate actualDisbursementDate = getDisbursementDate();
|
||||||
@@ -3162,9 +3151,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (loanTransaction.isRecoveryRepayment()) {
|
if (loanTransaction.isRecoveryRepayment()) {
|
||||||
statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RECOVERY_PAYMENT, LoanStatus.fromInt(this.loanStatus));
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_RECOVERY_PAYMENT, this);
|
||||||
} else {
|
} else {
|
||||||
statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, LoanStatus.fromInt(this.loanStatus));
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loanTransaction.isRecoveryRepayment()
|
if (loanTransaction.isRecoveryRepayment()
|
||||||
@@ -3173,8 +3162,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
throw new InvalidLoanStateTransitionException("transaction", "cannot.be.greater.than.total.written.off", errorMessage);
|
throw new InvalidLoanStateTransitionException("transaction", "cannot.be.greater.than.total.written.off", errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loanStatus = statusEnum.getValue();
|
|
||||||
|
|
||||||
loanTransaction.updateLoan(this);
|
loanTransaction.updateLoan(this);
|
||||||
|
|
||||||
final boolean isTransactionChronologicallyLatest = isChronologicallyLatestRepaymentOrWaiver(loanTransaction, getLoanTransactions());
|
final boolean isTransactionChronologicallyLatest = isChronologicallyLatestRepaymentOrWaiver(loanTransaction, getLoanTransactions());
|
||||||
@@ -3392,16 +3379,12 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isAllChargesPaid) {
|
if (isAllChargesPaid) {
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL,
|
loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
this.loanStatus = statusEnum.getValue();
|
|
||||||
|
|
||||||
this.closedOnDate = transactionDate;
|
this.closedOnDate = transactionDate;
|
||||||
this.actualMaturityDate = transactionDate;
|
this.actualMaturityDate = transactionDate;
|
||||||
} else if (LoanStatus.fromInt(this.loanStatus).isOverpaid()) {
|
} else if (LoanStatus.fromInt(this.loanStatus).isOverpaid()) {
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
this.loanStatus = statusEnum.getValue();
|
|
||||||
}
|
}
|
||||||
processIncomeAccrualTransactionOnLoanClosure();
|
processIncomeAccrualTransactionOnLoanClosure();
|
||||||
}
|
}
|
||||||
@@ -3473,8 +3456,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
private void handleLoanOverpayment(final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
private void handleLoanOverpayment(final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||||
|
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_OVERPAYMENT, LoanStatus.fromInt(this.loanStatus));
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_OVERPAYMENT, this);
|
||||||
this.loanStatus = statusEnum.getValue();
|
|
||||||
|
|
||||||
this.closedOnDate = null;
|
this.closedOnDate = null;
|
||||||
this.actualMaturityDate = null;
|
this.actualMaturityDate = null;
|
||||||
@@ -3635,9 +3617,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isClosedObligationsMet() || isClosedWrittenOff() || isClosedWithOutsandingAmountMarkedForReschedule()) {
|
if (isClosedObligationsMet() || isClosedWrittenOff() || isClosedWithOutsandingAmountMarkedForReschedule()) {
|
||||||
LoanStatus loanStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_ADJUST_TRANSACTION,
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_ADJUST_TRANSACTION, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
this.loanStatus = loanStatusEnum.getValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newTransactionDetail.isRepaymentType() || newTransactionDetail.isInterestWaiver()) {
|
if (newTransactionDetail.isRepaymentType() || newTransactionDetail.isInterestWaiver()) {
|
||||||
@@ -3657,9 +3637,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||||
final LoanTransaction writeOffTransaction = findWriteOffTransaction();
|
final LoanTransaction writeOffTransaction = findWriteOffTransaction();
|
||||||
writeOffTransaction.reverse();
|
writeOffTransaction.reverse();
|
||||||
LoanStatus loanStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO,
|
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
this.loanStatus = loanStatusEnum.getValue();
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||||
.determineProcessor(this.transactionProcessingStrategy);
|
.determineProcessor(this.transactionProcessingStrategy);
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
@@ -3740,12 +3718,11 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING);
|
validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING);
|
||||||
|
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING,
|
final LoanStatus statusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.WRITE_OFF_OUTSTANDING, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
|
|
||||||
LoanTransaction loanTransaction = null;
|
LoanTransaction loanTransaction = null;
|
||||||
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
||||||
this.loanStatus = statusEnum.getValue();
|
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING, this);
|
||||||
changes.put("status", LoanEnumerations.status(this.loanStatus));
|
changes.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
|
|
||||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||||
@@ -3866,10 +3843,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
final Money totalOutstanding = this.summary.getTotalOutstanding(loanCurrency());
|
final Money totalOutstanding = this.summary.getTotalOutstanding(loanCurrency());
|
||||||
if (totalOutstanding.isGreaterThanZero() && getInArrearsTolerance().isGreaterThanOrEqualTo(totalOutstanding)) {
|
if (totalOutstanding.isGreaterThanZero() && getInArrearsTolerance().isGreaterThanOrEqualTo(totalOutstanding)) {
|
||||||
|
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL,
|
final LoanStatus statusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.REPAID_IN_FULL, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
||||||
this.loanStatus = statusEnum.getValue();
|
loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, this);
|
||||||
changes.put("status", LoanEnumerations.status(this.loanStatus));
|
changes.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
}
|
}
|
||||||
this.closedOnDate = closureDate;
|
this.closedOnDate = closureDate;
|
||||||
@@ -3899,10 +3875,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
// TODO - KW - technically should set somewhere that this loan
|
// TODO - KW - technically should set somewhere that this loan
|
||||||
// has
|
// has
|
||||||
// 'overpaid' amount
|
// 'overpaid' amount
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL,
|
final LoanStatus statusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.REPAID_IN_FULL, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
||||||
this.loanStatus = statusEnum.getValue();
|
loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, this);
|
||||||
changes.put("status", LoanEnumerations.status(this.loanStatus));
|
changes.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
}
|
}
|
||||||
this.closedOnDate = closureDate;
|
this.closedOnDate = closureDate;
|
||||||
@@ -3928,9 +3903,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
final LocalDate rescheduledOn = command.localDateValueOfParameterNamed("transactionDate");
|
final LocalDate rescheduledOn = command.localDateValueOfParameterNamed("transactionDate");
|
||||||
|
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RESCHEDULE, LoanStatus.fromInt(this.loanStatus));
|
final LoanStatus statusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_RESCHEDULE, this);
|
||||||
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
|
||||||
this.loanStatus = statusEnum.getValue();
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_RESCHEDULE, this);
|
||||||
changes.put("status", LoanEnumerations.status(this.loanStatus));
|
changes.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3961,6 +3936,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
return LoanStatus.fromInt(this.loanStatus);
|
return LoanStatus.fromInt(this.loanStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getPlainStatus() {
|
||||||
|
return this.loanStatus;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSubmittedAndPendingApproval() {
|
public boolean isSubmittedAndPendingApproval() {
|
||||||
return status().isSubmittedAndPendingApproval();
|
return status().isSubmittedAndPendingApproval();
|
||||||
}
|
}
|
||||||
@@ -4793,7 +4772,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
this.loanTransactions.remove(loanTransaction);
|
this.loanTransactions.remove(loanTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLoanStatus(final Integer loanStatus) {
|
// Intentionally kept as package-private. Nobody should set the status directly but use the
|
||||||
|
// DefaultLoanLifecycleStateMachine to transition
|
||||||
|
void setLoanStatus(final Integer loanStatus) {
|
||||||
this.loanStatus = loanStatus;
|
this.loanStatus = loanStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6073,9 +6054,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
updateLoanSummaryDerivedFields();
|
updateLoanSummaryDerivedFields();
|
||||||
|
|
||||||
if (this.totalOverpaid == null || BigDecimal.ZERO.compareTo(this.totalOverpaid) == 0) {
|
if (this.totalOverpaid == null || BigDecimal.ZERO.compareTo(this.totalOverpaid) == 0) {
|
||||||
LoanStatus statusEnum = defaultLoanLifecycleStateMachine.transition(LoanEvent.LOAN_CREDIT_BALANCE_REFUND,
|
defaultLoanLifecycleStateMachine.transition(LoanEvent.LOAN_CREDIT_BALANCE_REFUND, this);
|
||||||
LoanStatus.fromInt(this.loanStatus));
|
|
||||||
this.loanStatus = statusEnum.getValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6116,15 +6095,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = null;
|
ChangedTransactionDetail changedTransactionDetail = null;
|
||||||
|
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REFUND, LoanStatus.fromInt(this.loanStatus));
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REFUND, this);
|
||||||
this.loanStatus = statusEnum.getValue();
|
|
||||||
|
|
||||||
loanTransaction.updateLoan(this);
|
loanTransaction.updateLoan(this);
|
||||||
|
|
||||||
// final boolean isTransactionChronologicallyLatest =
|
|
||||||
// isChronologicallyLatestRefund(loanTransaction,
|
|
||||||
// this.loanTransactions);
|
|
||||||
|
|
||||||
if (status().isOverpaid() || status().isClosed()) {
|
if (status().isOverpaid() || status().isClosed()) {
|
||||||
|
|
||||||
final String errorMessage = "This refund option is only for active loans ";
|
final String errorMessage = "This refund option is only for active loans ";
|
||||||
|
|||||||
+3
-1
@@ -20,5 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.domain;
|
|||||||
|
|
||||||
public interface LoanLifecycleStateMachine {
|
public interface LoanLifecycleStateMachine {
|
||||||
|
|
||||||
LoanStatus transition(LoanEvent loanEvent, LoanStatus from);
|
LoanStatus dryTransition(LoanEvent loanEvent, Loan loan);
|
||||||
|
|
||||||
|
void transition(LoanEvent loanEvent, Loan loan);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-10
@@ -2261,8 +2261,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final LoanTransaction newTransferTransaction = LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate);
|
final LoanTransaction newTransferTransaction = LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate);
|
||||||
loan.addLoanTransaction(newTransferTransaction);
|
loan.addLoanTransaction(newTransferTransaction);
|
||||||
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine();
|
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine();
|
||||||
LoanStatus loanStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_INITIATE_TRANSFER, loan.status());
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_INITIATE_TRANSFER, loan);
|
||||||
loan.setLoanStatus(loanStatusEnum.getValue());
|
|
||||||
|
|
||||||
this.loanTransactionRepository.saveAndFlush(newTransferTransaction);
|
this.loanTransactionRepository.saveAndFlush(newTransferTransaction);
|
||||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
@@ -2284,13 +2283,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate);
|
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate);
|
||||||
loan.addLoanTransaction(newTransferAcceptanceTransaction);
|
loan.addLoanTransaction(newTransferAcceptanceTransaction);
|
||||||
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine();
|
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine();
|
||||||
LoanStatus loanStatusEnum;
|
|
||||||
if (loan.getTotalOverpaid() != null) {
|
if (loan.getTotalOverpaid() != null) {
|
||||||
loanStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_OVERPAYMENT, loan.status());
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_OVERPAYMENT, loan);
|
||||||
} else {
|
} else {
|
||||||
loanStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, loan.status());
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, loan);
|
||||||
}
|
}
|
||||||
loan.setLoanStatus(loanStatusEnum.getValue());
|
|
||||||
if (loanOfficer != null) {
|
if (loanOfficer != null) {
|
||||||
loan.reassignLoanOfficer(loanOfficer, transferDate);
|
loan.reassignLoanOfficer(loanOfficer, transferDate);
|
||||||
}
|
}
|
||||||
@@ -2316,8 +2313,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate);
|
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate);
|
||||||
loan.addLoanTransaction(newTransferAcceptanceTransaction);
|
loan.addLoanTransaction(newTransferAcceptanceTransaction);
|
||||||
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine();
|
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine();
|
||||||
LoanStatus loanStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAW_TRANSFER, loan.status());
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAW_TRANSFER, loan);
|
||||||
loan.setLoanStatus(loanStatusEnum.getValue());
|
|
||||||
|
|
||||||
this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction);
|
this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction);
|
||||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
@@ -2334,8 +2330,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
this.loanAssembler.setHelpers(loan);
|
this.loanAssembler.setHelpers(loan);
|
||||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanRejectTransferBusinessEvent(loan));
|
businessEventNotifierService.notifyPreBusinessEvent(new LoanRejectTransferBusinessEvent(loan));
|
||||||
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine();
|
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine();
|
||||||
LoanStatus loanStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECT_TRANSFER, loan.status());
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECT_TRANSFER, loan);
|
||||||
loan.setLoanStatus(loanStatusEnum.getValue());
|
|
||||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanRejectTransferBusinessEvent(loan));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanRejectTransferBusinessEvent(loan));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user