added some validations around transfers of savings accounts
This commit is contained in:
+16
@@ -113,6 +113,22 @@ public enum SavingsAccountTransactionType {
|
|||||||
return this.value.equals(SavingsAccountTransactionType.WAIVE_CHARGES.getValue());
|
return this.value.equals(SavingsAccountTransactionType.WAIVE_CHARGES.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTransferInitiation() {
|
||||||
|
return this.value.equals(SavingsAccountTransactionType.INITIATE_TRANSFER.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTransferApproval() {
|
||||||
|
return this.value.equals(SavingsAccountTransactionType.APPROVE_TRANSFER.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTransferRejection() {
|
||||||
|
return this.value.equals(SavingsAccountTransactionType.REJECT_TRANSFER.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTransferWithdrawal() {
|
||||||
|
return this.value.equals(SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isDebit() {
|
public boolean isDebit() {
|
||||||
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isCharge();
|
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isCharge();
|
||||||
}
|
}
|
||||||
|
|||||||
+27
@@ -79,6 +79,8 @@ import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
|||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDTO;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDTO;
|
||||||
import org.mifosplatform.portfolio.savings.domain.interest.PostingPeriod;
|
import org.mifosplatform.portfolio.savings.domain.interest.PostingPeriod;
|
||||||
import org.mifosplatform.portfolio.savings.exception.InsufficientAccountBalanceException;
|
import org.mifosplatform.portfolio.savings.exception.InsufficientAccountBalanceException;
|
||||||
|
import org.mifosplatform.portfolio.savings.exception.SavingsActivityPriorToClientTransferException;
|
||||||
|
import org.mifosplatform.portfolio.savings.exception.SavingsTransferTransactionsCannotBeUndoneException;
|
||||||
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
|
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
|
||||||
import org.mifosplatform.useradministration.domain.AppUser;
|
import org.mifosplatform.useradministration.domain.AppUser;
|
||||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
@@ -605,6 +607,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_DEPOSIT, transactionDTO.getTransactionDate());
|
||||||
|
|
||||||
transactionDTO.getExistingTransactionIds().addAll(findExistingTransactionIds());
|
transactionDTO.getExistingTransactionIds().addAll(findExistingTransactionIds());
|
||||||
transactionDTO.getExistingReversedTransactionIds().addAll(findExistingReversedTransactionIds());
|
transactionDTO.getExistingReversedTransactionIds().addAll(findExistingReversedTransactionIds());
|
||||||
@@ -679,6 +682,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_WITHDRAWAL, transactionDTO.getTransactionDate());
|
||||||
|
|
||||||
transactionDTO.getExistingTransactionIds().addAll(findExistingTransactionIds());
|
transactionDTO.getExistingTransactionIds().addAll(findExistingTransactionIds());
|
||||||
transactionDTO.getExistingReversedTransactionIds().addAll(findExistingReversedTransactionIds());
|
transactionDTO.getExistingReversedTransactionIds().addAll(findExistingReversedTransactionIds());
|
||||||
@@ -823,6 +827,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_PAY_FEE, annualFeeTransactionDate);
|
||||||
|
|
||||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||||
@@ -1416,6 +1421,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_APPLICATION_APPROVED, approvedOn);
|
||||||
|
|
||||||
// FIXME - kw - support field officer history for savings accounts
|
// FIXME - kw - support field officer history for savings accounts
|
||||||
// if (this.fieldOfficer != null) {
|
// if (this.fieldOfficer != null) {
|
||||||
@@ -1476,6 +1482,9 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
// throw non found exception
|
// throw non found exception
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
validateAttemptToUndoTransferRelatedTransactions(transactionToUndo);
|
||||||
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION,
|
||||||
|
transactionToUndo.transactionLocalDate());
|
||||||
transactionToUndo.reverse();
|
transactionToUndo.reverse();
|
||||||
reversedTransactionIds.add(transactionId);
|
reversedTransactionIds.add(transactionId);
|
||||||
|
|
||||||
@@ -1558,6 +1567,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
actualChanges.put(SavingsApiConstants.closedOnDateParamName, rejectedOnAsString);
|
actualChanges.put(SavingsApiConstants.closedOnDateParamName, rejectedOnAsString);
|
||||||
|
|
||||||
final LocalDate submittalDate = getSubmittedOnLocalDate();
|
final LocalDate submittalDate = getSubmittedOnLocalDate();
|
||||||
|
|
||||||
if (rejectedOn.isBefore(submittalDate)) {
|
if (rejectedOn.isBefore(submittalDate)) {
|
||||||
|
|
||||||
final DateTimeFormatter formatter = DateTimeFormat.forPattern(command.dateFormat()).withLocale(command.extractLocale());
|
final DateTimeFormatter formatter = DateTimeFormat.forPattern(command.dateFormat()).withLocale(command.extractLocale());
|
||||||
@@ -1576,6 +1586,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_APPLICATION_REJECTED, rejectedOn);
|
||||||
|
|
||||||
return actualChanges;
|
return actualChanges;
|
||||||
}
|
}
|
||||||
@@ -1634,6 +1645,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_APPLICATION_WITHDRAWAL_BY_CUSTOMER, withdrawnOn);
|
||||||
|
|
||||||
return actualChanges;
|
return actualChanges;
|
||||||
}
|
}
|
||||||
@@ -1715,6 +1727,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_ACTIVATE, activationDate);
|
||||||
|
|
||||||
// auto enter deposit for minimum required opening balance when
|
// auto enter deposit for minimum required opening balance when
|
||||||
// activating account.
|
// activating account.
|
||||||
@@ -1778,6 +1791,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("results.in.balance.not.zero");
|
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("results.in.balance.not.zero");
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_CLOSE_ACCOUNT, closedDate);
|
||||||
this.status = SavingsAccountStatusType.CLOSED.getValue();
|
this.status = SavingsAccountStatusType.CLOSED.getValue();
|
||||||
actualChanges.put(SavingsApiConstants.statusParamName, SavingsEnumerations.status(this.status));
|
actualChanges.put(SavingsApiConstants.statusParamName, SavingsEnumerations.status(this.status));
|
||||||
actualChanges.put(SavingsApiConstants.localeParamName, command.locale());
|
actualChanges.put(SavingsApiConstants.localeParamName, command.locale());
|
||||||
@@ -1794,6 +1808,19 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
return actualChanges;
|
return actualChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent event, LocalDate activityDate) {
|
||||||
|
if (this.client != null && this.client.getOfficeJoiningLocalDate() != null) {
|
||||||
|
LocalDate clientOfficeJoiningDate = client.getOfficeJoiningLocalDate();
|
||||||
|
if (activityDate.isBefore(clientOfficeJoiningDate)) { throw new SavingsActivityPriorToClientTransferException(event.toString(),
|
||||||
|
clientOfficeJoiningDate); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateAttemptToUndoTransferRelatedTransactions(SavingsAccountTransaction savingsAccountTransaction) {
|
||||||
|
if (savingsAccountTransaction.isTransferRelatedTransaction()) { throw new SavingsTransferTransactionsCannotBeUndoneException(
|
||||||
|
savingsAccountTransaction.getId()); }
|
||||||
|
}
|
||||||
|
|
||||||
private Date calculateDateAccountIsLockedUntil(final LocalDate activationLocalDate) {
|
private Date calculateDateAccountIsLockedUntil(final LocalDate activationLocalDate) {
|
||||||
|
|
||||||
Date lockedInUntilLocalDate = null;
|
Date lockedInUntilLocalDate = null;
|
||||||
|
|||||||
+20
@@ -232,6 +232,26 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
|||||||
return this.reversed;
|
return this.reversed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTransferInitiation() {
|
||||||
|
return SavingsAccountTransactionType.fromInt(this.typeOf).isTransferInitiation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTransferApproval() {
|
||||||
|
return SavingsAccountTransactionType.fromInt(this.typeOf).isTransferApproval();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTransferRejection() {
|
||||||
|
return SavingsAccountTransactionType.fromInt(this.typeOf).isTransferRejection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTransferWithdrawal() {
|
||||||
|
return SavingsAccountTransactionType.fromInt(this.typeOf).isTransferWithdrawal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTransferRelatedTransaction() {
|
||||||
|
return isTransferInitiation() || isTransferApproval() || isTransferRejection() || isTransferWithdrawal();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean occursOn(final LocalDate occursOnDate) {
|
public boolean occursOn(final LocalDate occursOnDate) {
|
||||||
return getTransactionLocalDate().isEqual(occursOnDate);
|
return getTransactionLocalDate().isEqual(occursOnDate);
|
||||||
}
|
}
|
||||||
|
|||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.savings.domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum SavingsEvent {
|
||||||
|
|
||||||
|
SAVINGS_APPLICATION_REJECTED("application.rejected"), //
|
||||||
|
SAVINGS_APPLICATION_WITHDRAWAL_BY_CUSTOMER("application.withdrawal"), //
|
||||||
|
SAVINGS_APPLICATION_APPROVED("application.approval"), //
|
||||||
|
SAVINGS_APPLICATION_APPROVAL_UNDO("application.approval.undo"), //
|
||||||
|
SAVINGS_ACTIVATE("activate"), //
|
||||||
|
SAVINGS_DEPOSIT("deposit"), //
|
||||||
|
SAVINGS_WITHDRAWAL("withdraw"), //
|
||||||
|
SAVINGS_POST_INTEREST("interest.post"), //
|
||||||
|
SAVINGS_UNDO_TRANSACTION("transaction.undo"), //
|
||||||
|
SAVINGS_ADJUST_TRANSACTION("transaction.adjust"), //
|
||||||
|
SAVINGS_APPLY_FEE("fee.apply"), //
|
||||||
|
SAVINGS_PAY_FEE("fee.pay"), //
|
||||||
|
SAVINGS_CLOSE_ACCOUNT("account.close");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private SavingsEvent(final String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* 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.savings.exception;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link AbstractPlatformDomainRuleException} thrown an action to transition a
|
||||||
|
* loan from one state to another violates a domain rule.
|
||||||
|
*/
|
||||||
|
public class SavingsActivityPriorToClientTransferException extends AbstractPlatformDomainRuleException {
|
||||||
|
|
||||||
|
public SavingsActivityPriorToClientTransferException(final String action, Object... defaultUserMessageArgs) {
|
||||||
|
super("error.msg.savings." + action + "." + "not.permitted.before.client.transfer.date",
|
||||||
|
"Transactions on savings account prior to the customer joining date are not permitted", defaultUserMessageArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* 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.savings.exception;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link AbstractPlatformDomainRuleException} thrown an action to transition a
|
||||||
|
* loan from one state to another violates a domain rule.
|
||||||
|
*/
|
||||||
|
public class SavingsTransferTransactionsCannotBeUndoneException extends AbstractPlatformDomainRuleException {
|
||||||
|
|
||||||
|
public SavingsTransferTransactionsCannotBeUndoneException(Long transactionId) {
|
||||||
|
super("error.msg.savings.transfer.transactions.cannot.be.undone",
|
||||||
|
"Transactions related to savings account transfers cannot be undone", transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user