Merge branch 'FINERACT-482' into develop
This commit is contained in:
+9
-3
@@ -28,10 +28,12 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||||
import org.apache.fineract.integrationtests.common.CommonConstants;
|
import org.apache.fineract.integrationtests.common.CommonConstants;
|
||||||
import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
|
import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
|
||||||
@@ -2214,13 +2216,17 @@ public class ClientSavingsIntegrationTest {
|
|||||||
Integer holdTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId, String.valueOf(balance - 100),
|
Integer holdTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId, String.valueOf(balance - 100),
|
||||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||||
error = (List) savingsAccountHelperValidationError.withdrawalFromSavingsAccount(savingsId, "300",
|
error = (List) savingsAccountHelperValidationError.withdrawalFromSavingsAccount(savingsId, "300",
|
||||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
|
SavingsAccountHelper.TRANSACTION_DATE_PLUS_ONE, CommonConstants.RESPONSE_ERROR);
|
||||||
assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
|
assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
|
||||||
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||||
|
|
||||||
Integer releaseTransactionId = this.savingsAccountHelper.releaseAmount(savingsId, holdTransactionId);
|
Integer releaseTransactionId = this.savingsAccountHelper.releaseAmount(savingsId, holdTransactionId);
|
||||||
withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "300",
|
Date today = DateUtils.getDateOfTenant();
|
||||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
String todayDate = today.toString();
|
||||||
|
SimpleDateFormat dt1 = new SimpleDateFormat("dd MMM yyyy");
|
||||||
|
todayDate = dt1.format(today).toString();
|
||||||
|
withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "300", todayDate,
|
||||||
|
CommonConstants.RESPONSE_RESOURCE_ID);
|
||||||
withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, withdrawTransactionId);
|
withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, withdrawTransactionId);
|
||||||
balance -= new Float("300");
|
balance -= new Float("300");
|
||||||
assertEquals("Verifying Withdrawal Amount", new Float("300"), withdrawTransaction.get("amount"));
|
assertEquals("Verifying Withdrawal Amount", new Float("300"), withdrawTransaction.get("amount"));
|
||||||
|
|||||||
+1
@@ -69,6 +69,7 @@ public class SavingsAccountHelper {
|
|||||||
public static final String CREATED_DATE_PLUS_ONE = "09 January 2013";
|
public static final String CREATED_DATE_PLUS_ONE = "09 January 2013";
|
||||||
public static final String CREATED_DATE_MINUS_ONE = "07 January 2013";
|
public static final String CREATED_DATE_MINUS_ONE = "07 January 2013";
|
||||||
public static final String TRANSACTION_DATE = "01 March 2013";
|
public static final String TRANSACTION_DATE = "01 March 2013";
|
||||||
|
public static final String TRANSACTION_DATE_PLUS_ONE = "02 March 2013";
|
||||||
public static final String LAST_TRANSACTION_DATE = "01 March 2013";
|
public static final String LAST_TRANSACTION_DATE = "01 March 2013";
|
||||||
public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL";
|
public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL";
|
||||||
|
|
||||||
|
|||||||
+1
@@ -133,6 +133,7 @@ public class SavingsApiConstants {
|
|||||||
public static final String minBalanceForInterestCalculationParamName = "minBalanceForInterestCalculation";
|
public static final String minBalanceForInterestCalculationParamName = "minBalanceForInterestCalculation";
|
||||||
public static final String withdrawBalanceParamName = "withdrawBalance";
|
public static final String withdrawBalanceParamName = "withdrawBalance";
|
||||||
public static final String onHoldFundsParamName = "onHoldFunds";
|
public static final String onHoldFundsParamName = "onHoldFunds";
|
||||||
|
public static final String savingsAmountOnHold = "savingsAmountOnHold";
|
||||||
public static final String withHoldTaxParamName = "withHoldTax";
|
public static final String withHoldTaxParamName = "withHoldTax";
|
||||||
public static final String taxGroupIdParamName = "taxGroupId";
|
public static final String taxGroupIdParamName = "taxGroupId";
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ public class SavingsApiSetConstants extends SavingsApiConstants {
|
|||||||
"interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions",
|
"interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions",
|
||||||
"lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions", "withdrawalFee", "annualFee",
|
"lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions", "withdrawalFee", "annualFee",
|
||||||
onHoldFundsParamName, nominalAnnualInterestRateOverdraftParamName,
|
onHoldFundsParamName, nominalAnnualInterestRateOverdraftParamName,
|
||||||
minOverdraftForInterestCalculationParamName, datatables));
|
minOverdraftForInterestCalculationParamName, datatables, savingsAmountOnHold));
|
||||||
|
|
||||||
protected static final Set<String> SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>(
|
protected static final Set<String> SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>(
|
||||||
Arrays.asList(idParamName, "accountId", accountNoParamName, "currency", "amount", dateParamName,
|
Arrays.asList(idParamName, "accountId", accountNoParamName, "currency", "amount", dateParamName,
|
||||||
|
|||||||
+13
-8
@@ -76,6 +76,7 @@ public class SavingsAccountData {
|
|||||||
private final Integer daysToInactive;
|
private final Integer daysToInactive;
|
||||||
private final Integer daysToDormancy;
|
private final Integer daysToDormancy;
|
||||||
private final Integer daysToEscheat;
|
private final Integer daysToEscheat;
|
||||||
|
private final BigDecimal savingsAmountOnHold;
|
||||||
|
|
||||||
// associations
|
// associations
|
||||||
private final SavingsAccountSummaryData summary;
|
private final SavingsAccountSummaryData summary;
|
||||||
@@ -118,7 +119,7 @@ public class SavingsAccountData {
|
|||||||
final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
|
final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
||||||
final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive, final Integer daysToInactive,
|
final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive, final Integer daysToInactive,
|
||||||
final Integer daysToDormancy, final Integer daysToEscheat) {
|
final Integer daysToDormancy, final Integer daysToEscheat, final BigDecimal savingsAmountOnHold) {
|
||||||
|
|
||||||
final Collection<SavingsProductData> productOptions = null;
|
final Collection<SavingsProductData> productOptions = null;
|
||||||
final Collection<StaffData> fieldOfficerOptions = null;
|
final Collection<StaffData> fieldOfficerOptions = null;
|
||||||
@@ -142,7 +143,7 @@ public class SavingsAccountData {
|
|||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData lookup(final Long accountId, final String accountNo, final EnumOptionData depositType) {
|
public static SavingsAccountData lookup(final Long accountId, final String accountNo, final EnumOptionData depositType) {
|
||||||
@@ -204,6 +205,7 @@ public class SavingsAccountData {
|
|||||||
final Integer daysToInactive = null;
|
final Integer daysToInactive = null;
|
||||||
final Integer daysToDormancy = null;
|
final Integer daysToDormancy = null;
|
||||||
final Integer daysToEscheat = null;
|
final Integer daysToEscheat = null;
|
||||||
|
final BigDecimal savingsAmountOnHold = null;
|
||||||
|
|
||||||
return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
||||||
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, nominalAnnualInterestRate,
|
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, nominalAnnualInterestRate,
|
||||||
@@ -214,7 +216,7 @@ public class SavingsAccountData {
|
|||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData lookupWithProductDetails(final Long accountId, final String accountNo,
|
public static SavingsAccountData lookupWithProductDetails(final Long accountId, final String accountNo,
|
||||||
@@ -274,6 +276,7 @@ public class SavingsAccountData {
|
|||||||
final Integer daysToInactive = null;
|
final Integer daysToInactive = null;
|
||||||
final Integer daysToDormancy = null;
|
final Integer daysToDormancy = null;
|
||||||
final Integer daysToEscheat = null;
|
final Integer daysToEscheat = null;
|
||||||
|
final BigDecimal savingsAmountOnHold = null;
|
||||||
|
|
||||||
return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
||||||
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, nominalAnnualInterestRate,
|
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, nominalAnnualInterestRate,
|
||||||
@@ -284,7 +287,7 @@ public class SavingsAccountData {
|
|||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template,
|
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template,
|
||||||
@@ -320,7 +323,7 @@ public class SavingsAccountData {
|
|||||||
account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
|
account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
|
||||||
account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup,
|
account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup,
|
||||||
account.lastActiveTransactionDate, account.isDormancyTrackingActive, account.daysToInactive,
|
account.lastActiveTransactionDate, account.isDormancyTrackingActive, account.daysToInactive,
|
||||||
account.daysToDormancy, account.daysToEscheat);
|
account.daysToDormancy, account.daysToEscheat, account.savingsAmountOnHold);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||||
@@ -345,7 +348,7 @@ public class SavingsAccountData {
|
|||||||
account.overdraftLimit, account.minRequiredBalance, account.enforceMinRequiredBalance,
|
account.overdraftLimit, account.minRequiredBalance, account.enforceMinRequiredBalance,
|
||||||
account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
|
account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
|
||||||
account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup, account.lastActiveTransactionDate,
|
account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup, account.lastActiveTransactionDate,
|
||||||
account.isDormancyTrackingActive, account.daysToInactive, account.daysToDormancy, account.daysToEscheat);
|
account.isDormancyTrackingActive, account.daysToInactive, account.daysToDormancy, account.daysToEscheat, account.savingsAmountOnHold);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||||
@@ -407,6 +410,7 @@ public class SavingsAccountData {
|
|||||||
final Integer daysToInactive = null;
|
final Integer daysToInactive = null;
|
||||||
final Integer daysToDormancy = null;
|
final Integer daysToDormancy = null;
|
||||||
final Integer daysToEscheat = null;
|
final Integer daysToEscheat = null;
|
||||||
|
final BigDecimal savingsAmountOnHold = null;
|
||||||
|
|
||||||
return new SavingsAccountData(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
return new SavingsAccountData(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
||||||
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, nominalAnnualInterestRate,
|
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, nominalAnnualInterestRate,
|
||||||
@@ -417,7 +421,7 @@ public class SavingsAccountData {
|
|||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SavingsAccountData(final Long id, final String accountNo, final EnumOptionData depositType, final String externalId,
|
private SavingsAccountData(final Long id, final String accountNo, final EnumOptionData depositType, final String externalId,
|
||||||
@@ -441,7 +445,7 @@ public class SavingsAccountData {
|
|||||||
final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
|
final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
||||||
final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive, final Integer daysToInactive,
|
final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive, final Integer daysToInactive,
|
||||||
final Integer daysToDormancy, final Integer daysToEscheat) {
|
final Integer daysToDormancy, final Integer daysToEscheat, final BigDecimal savingsAmountOnHold) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.accountNo = accountNo;
|
this.accountNo = accountNo;
|
||||||
this.depositType = depositType;
|
this.depositType = depositType;
|
||||||
@@ -507,6 +511,7 @@ public class SavingsAccountData {
|
|||||||
this.daysToInactive = daysToInactive;
|
this.daysToInactive = daysToInactive;
|
||||||
this.daysToDormancy = daysToDormancy;
|
this.daysToDormancy = daysToDormancy;
|
||||||
this.daysToEscheat = daysToEscheat;
|
this.daysToEscheat = daysToEscheat;
|
||||||
|
this.savingsAmountOnHold = savingsAmountOnHold;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SavingsAccountChargeData getWithdrawalFee() {
|
private SavingsAccountChargeData getWithdrawalFee() {
|
||||||
|
|||||||
+26
-12
@@ -123,7 +123,7 @@ public class SavingsAccountTransactionDataValidator {
|
|||||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateClosing(final JsonCommand command) {
|
public void validateClosing(final JsonCommand command, final SavingsAccount account) {
|
||||||
final String json = command.json();
|
final String json = command.json();
|
||||||
|
|
||||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||||
@@ -146,6 +146,11 @@ public class SavingsAccountTransactionDataValidator {
|
|||||||
baseDataValidator.reset().parameter(withdrawBalanceParamName).value(withdrawBalance).isOneOfTheseValues(true, false);
|
baseDataValidator.reset().parameter(withdrawBalanceParamName).value(withdrawBalance).isOneOfTheseValues(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (account.getSavingsHoldAmount().compareTo(BigDecimal.ZERO) == 1) {
|
||||||
|
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||||
|
"amount.is.on.hold.release.the.amount.to.continue", account.getId());
|
||||||
|
}
|
||||||
|
|
||||||
validatePaymentTypeDetails(baseDataValidator, element);
|
validatePaymentTypeDetails(baseDataValidator, element);
|
||||||
|
|
||||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
@@ -194,10 +199,9 @@ public class SavingsAccountTransactionDataValidator {
|
|||||||
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
|
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
|
||||||
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
|
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
|
||||||
}
|
}
|
||||||
account.holdFunds(amount);
|
account.holdAmount(amount);
|
||||||
if (account.getWithdrawableBalance().compareTo(BigDecimal.ZERO) == -1) {
|
if (account.getWithdrawableBalance().compareTo(BigDecimal.ZERO)==-1){
|
||||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient balance", account.getId());
|
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient balance", account.getId());
|
||||||
baseDataValidator.failWithCode("validation.msg.savingsaccount.insufficient balance", "Insufficient balance");
|
|
||||||
}
|
}
|
||||||
LocalDate lastTransactionDate = account.retrieveLastTransactionDate();
|
LocalDate lastTransactionDate = account.retrieveLastTransactionDate();
|
||||||
// compare two dates now
|
// compare two dates now
|
||||||
@@ -208,7 +212,8 @@ public class SavingsAccountTransactionDataValidator {
|
|||||||
|
|
||||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
final PaymentDetail paymentDetails = null;
|
final PaymentDetail paymentDetails = null;
|
||||||
Date createdDate = DateUtils.getDateOfTenant();
|
Date createdDate = new Date();
|
||||||
|
|
||||||
SavingsAccountTransaction transaction = SavingsAccountTransaction.holdAmount(account, account.office(), paymentDetails,
|
SavingsAccountTransaction transaction = SavingsAccountTransaction.holdAmount(account, account.office(), paymentDetails,
|
||||||
transactionDate, Money.of(account.getCurrency(), amount), createdDate, createdUser);
|
transactionDate, Money.of(account.getCurrency(), amount), createdDate, createdUser);
|
||||||
return transaction;
|
return transaction;
|
||||||
@@ -219,15 +224,24 @@ public class SavingsAccountTransactionDataValidator {
|
|||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||||
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
|
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||||
|
|
||||||
if (holdTransaction == null) {
|
if (holdTransaction == null) {
|
||||||
baseDataValidator.failWithCode("validation.msg.validation.errors.exist", "Transaction not found");
|
baseDataValidator.failWithCode("validation.msg.validation.errors.exist", "Transaction not found");
|
||||||
} else if (holdTransaction.getReleaseIdOfHoldAmountTransaction() != null) {
|
} else if (holdTransaction.getReleaseIdOfHoldAmountTransaction() != null) {
|
||||||
baseDataValidator.parameter(SavingsApiConstants.amountParamName).value(holdTransaction.getAmount()).failWithCode("validation.msg.amount.is.not.on.hold",
|
baseDataValidator.parameter(SavingsApiConstants.amountParamName).value(holdTransaction.getAmount())
|
||||||
"Transaction amount is not on hold");
|
.failWithCode("validation.msg.amount.is.not.on.hold", "Transaction amount is not on hold");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (holdTransaction != null) {
|
||||||
|
boolean isActive = holdTransaction.getSavingsAccount().isActive();
|
||||||
|
if (!isActive) {
|
||||||
|
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
|
||||||
|
.failWithCodeNoParameterAddedToErrorCode(
|
||||||
|
SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
Date createdDate = DateUtils.getDateOfTenant();
|
Date createdDate = new Date();
|
||||||
LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
||||||
SavingsAccountTransaction transaction = SavingsAccountTransaction.releaseAmount(holdTransaction, transactionDate, createdDate,
|
SavingsAccountTransaction transaction = SavingsAccountTransaction.releaseAmount(holdTransaction, transactionDate, createdDate,
|
||||||
createdUser);
|
createdUser);
|
||||||
|
|||||||
+30
-7
@@ -325,6 +325,8 @@ public class SavingsAccount extends AbstractPersistableCustom<Long> {
|
|||||||
@JoinColumn(name = "tax_group_id")
|
@JoinColumn(name = "tax_group_id")
|
||||||
private TaxGroup taxGroup;
|
private TaxGroup taxGroup;
|
||||||
|
|
||||||
|
@Column(name = "total_savings_amount_on_hold", scale = 6, precision = 19, nullable = true)
|
||||||
|
private BigDecimal savingsOnHoldAmount;
|
||||||
protected SavingsAccount() {
|
protected SavingsAccount() {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
@@ -1051,19 +1053,16 @@ public class SavingsAccount extends AbstractPersistableCustom<Long> {
|
|||||||
Money runningBalance = Money.zero(this.currency);
|
Money runningBalance = Money.zero(this.currency);
|
||||||
Money minRequiredBalance = minRequiredBalanceDerived(getCurrency());
|
Money minRequiredBalance = minRequiredBalanceDerived(getCurrency());
|
||||||
LocalDate lastSavingsDate = null;
|
LocalDate lastSavingsDate = null;
|
||||||
|
final BigDecimal withdrawalFee = null;
|
||||||
for (final SavingsAccountTransaction transaction : transactionsSortedByDate) {
|
for (final SavingsAccountTransaction transaction : transactionsSortedByDate) {
|
||||||
if (transaction.isNotReversed() && transaction.isCredit()) {
|
if (transaction.isNotReversed() && transaction.isCredit()) {
|
||||||
runningBalance = runningBalance.plus(transaction.getAmount(this.currency));
|
runningBalance = runningBalance.plus(transaction.getAmount(this.currency));
|
||||||
} else if (transaction.isNotReversed() && transaction.isDebit()) {
|
} else if (transaction.isNotReversed() && transaction.isDebit()) {
|
||||||
runningBalance = runningBalance.minus(transaction.getAmount(this.currency));
|
runningBalance = runningBalance.minus(transaction.getAmount(this.currency));
|
||||||
} else if(transaction.isAmountOnHold() && transaction.getReleaseIdOfHoldAmountTransaction() == null){
|
|
||||||
runningBalance = runningBalance.minus(transaction.getAmount(this.currency));
|
|
||||||
}else {
|
}else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final BigDecimal withdrawalFee = null;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop through the onHold funds and see if we need to deduct or add
|
* Loop through the onHold funds and see if we need to deduct or add
|
||||||
* to minimum required balance and the point in time the transaction
|
* to minimum required balance and the point in time the transaction
|
||||||
@@ -1093,6 +1092,12 @@ public class SavingsAccount extends AbstractPersistableCustom<Long> {
|
|||||||
lastSavingsDate = transaction.transactionLocalDate();
|
lastSavingsDate = transaction.transactionLocalDate();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (this.getSavingsHoldAmount().compareTo(BigDecimal.ZERO) == 1) {
|
||||||
|
if (runningBalance.minus(this.getSavingsHoldAmount()).isLessThanZero()) {
|
||||||
|
throw new InsufficientAccountBalanceException("transactionAmount", getAccountBalance(), withdrawalFee,
|
||||||
|
transactionAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateAccountBalanceDoesNotBecomeNegative(final String transactionAction,
|
public void validateAccountBalanceDoesNotBecomeNegative(final String transactionAction,
|
||||||
@@ -2753,7 +2758,7 @@ public class SavingsAccount extends AbstractPersistableCustom<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getWithdrawableBalance() {
|
public BigDecimal getWithdrawableBalance() {
|
||||||
return getAccountBalance().subtract(minRequiredBalanceDerived(getCurrency()).getAmount()).subtract(this.getOnHoldFunds());
|
return getAccountBalance().subtract(minRequiredBalanceDerived(getCurrency()).getAmount()).subtract(this.getOnHoldFunds()).subtract(this.getSavingsHoldAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaxGroup getTaxGroup() {
|
public TaxGroup getTaxGroup() {
|
||||||
@@ -3006,9 +3011,27 @@ public class SavingsAccount extends AbstractPersistableCustom<Long> {
|
|||||||
|
|
||||||
public LocalDate retrieveLastTransactionDate() {
|
public LocalDate retrieveLastTransactionDate() {
|
||||||
final List<SavingsAccountTransaction> transactionsSortedByDate = retreiveListOfTransactions();
|
final List<SavingsAccountTransaction> transactionsSortedByDate = retreiveListOfTransactions();
|
||||||
SavingsAccountTransaction lastTransaction = transactionsSortedByDate.get(transactionsSortedByDate.size() - 1);
|
SavingsAccountTransaction lastTransaction = null;
|
||||||
return lastTransaction.transactionLocalDate();
|
if (transactionsSortedByDate.size() > 0) {
|
||||||
|
lastTransaction = transactionsSortedByDate.get(transactionsSortedByDate.size() - 1);
|
||||||
|
}
|
||||||
|
LocalDate lastransactionDate = null;
|
||||||
|
if (lastTransaction != null) {
|
||||||
|
lastransactionDate = lastTransaction.transactionLocalDate();
|
||||||
|
}
|
||||||
|
return lastransactionDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal getSavingsHoldAmount() {
|
||||||
|
return this.savingsOnHoldAmount == null ? BigDecimal.ZERO : this.savingsOnHoldAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void holdAmount(BigDecimal amount) {
|
||||||
|
this.savingsOnHoldAmount = getSavingsHoldAmount().add(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseAmount(BigDecimal amount) {
|
||||||
|
this.savingsOnHoldAmount = getSavingsHoldAmount().subtract(amount);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+4
@@ -787,4 +787,8 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom<L
|
|||||||
public Long getReleaseIdOfHoldAmountTransaction() {
|
public Long getReleaseIdOfHoldAmountTransaction() {
|
||||||
return this.releaseIdOfHoldAmountTransaction;
|
return this.releaseIdOfHoldAmountTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAmountOnHoldNotReleased() {
|
||||||
|
return (isAmountOnHold() && getReleaseIdOfHoldAmountTransaction() == null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+11
-2
@@ -304,6 +304,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
sqlBuilder.append("sa.withhold_tax as withHoldTax, ");
|
sqlBuilder.append("sa.withhold_tax as withHoldTax, ");
|
||||||
sqlBuilder.append("sa.total_withhold_tax_derived as totalWithholdTax, ");
|
sqlBuilder.append("sa.total_withhold_tax_derived as totalWithholdTax, ");
|
||||||
sqlBuilder.append("sa.last_interest_calculation_date as lastInterestCalculationDate, ");
|
sqlBuilder.append("sa.last_interest_calculation_date as lastInterestCalculationDate, ");
|
||||||
|
sqlBuilder.append("sa.total_savings_amount_on_hold as onHoldAmount, ");
|
||||||
sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName, ");
|
sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName, ");
|
||||||
sqlBuilder.append("(select IFNULL(max(sat.transaction_date),sa.activatedon_date) ");
|
sqlBuilder.append("(select IFNULL(max(sat.transaction_date),sa.activatedon_date) ");
|
||||||
sqlBuilder.append("from m_savings_account_transaction as sat ");
|
sqlBuilder.append("from m_savings_account_transaction as sat ");
|
||||||
@@ -511,12 +512,19 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
"minBalanceForInterestCalculation");
|
"minBalanceForInterestCalculation");
|
||||||
final BigDecimal onHoldFunds = rs.getBigDecimal("onHoldFunds");
|
final BigDecimal onHoldFunds = rs.getBigDecimal("onHoldFunds");
|
||||||
|
|
||||||
|
final BigDecimal onHoldAmount = rs.getBigDecimal("onHoldAmount");
|
||||||
|
|
||||||
BigDecimal availableBalance = accountBalance;
|
BigDecimal availableBalance = accountBalance;
|
||||||
if (availableBalance != null && onHoldFunds != null) {
|
if (availableBalance != null && onHoldFunds != null) {
|
||||||
|
|
||||||
availableBalance = availableBalance.subtract(onHoldFunds);
|
availableBalance = availableBalance.subtract(onHoldFunds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (availableBalance != null && onHoldAmount != null) {
|
||||||
|
|
||||||
|
availableBalance = availableBalance.subtract(onHoldAmount);
|
||||||
|
}
|
||||||
|
|
||||||
BigDecimal interestNotPosted = BigDecimal.ZERO;
|
BigDecimal interestNotPosted = BigDecimal.ZERO;
|
||||||
LocalDate lastInterestCalculationDate = null;
|
LocalDate lastInterestCalculationDate = null;
|
||||||
if(totalInterestEarned != null){
|
if(totalInterestEarned != null){
|
||||||
@@ -542,7 +550,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
||||||
summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||||
minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||||
taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, onHoldAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1074,6 +1082,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
// final LocalDate annualFeeNextDueDate = null;
|
// final LocalDate annualFeeNextDueDate = null;
|
||||||
final SavingsAccountSummaryData summary = null;
|
final SavingsAccountSummaryData summary = null;
|
||||||
final BigDecimal onHoldFunds = null;
|
final BigDecimal onHoldFunds = null;
|
||||||
|
final BigDecimal savingsAmountOnHold = null;
|
||||||
|
|
||||||
final SavingsAccountSubStatusEnumData subStatus = null;
|
final SavingsAccountSubStatusEnumData subStatus = null;
|
||||||
final LocalDate lastActiveTransactionDate = null;
|
final LocalDate lastActiveTransactionDate = null;
|
||||||
@@ -1090,7 +1099,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
||||||
summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||||
minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||||
taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -612,8 +612,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
public CommandProcessingResult close(final Long savingsId, final JsonCommand command) {
|
public CommandProcessingResult close(final Long savingsId, final JsonCommand command) {
|
||||||
final AppUser user = this.context.authenticatedUser();
|
final AppUser user = this.context.authenticatedUser();
|
||||||
|
|
||||||
this.savingsAccountTransactionDataValidator.validateClosing(command);
|
|
||||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
this.savingsAccountTransactionDataValidator.validateClosing(command, account);
|
||||||
|
|
||||||
final boolean isLinkedWithAnyActiveLoan = this.accountAssociationsReadPlatformService.isLinkedWithAnyActiveAccount(savingsId);
|
final boolean isLinkedWithAnyActiveLoan = this.accountAssociationsReadPlatformService.isLinkedWithAnyActiveAccount(savingsId);
|
||||||
|
|
||||||
if (isLinkedWithAnyActiveLoan) {
|
if (isLinkedWithAnyActiveLoan) {
|
||||||
@@ -1403,7 +1404,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
.validateReleaseAmountAndAssembleForm(holdTransaction, submittedBy);
|
.validateReleaseAmountAndAssembleForm(holdTransaction, submittedBy);
|
||||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
checkClientOrGroupActive(account);
|
checkClientOrGroupActive(account);
|
||||||
account.releaseFunds(transaction.getAmount());
|
account.releaseAmount(transaction.getAmount());
|
||||||
|
|
||||||
this.savingsAccountTransactionRepository.save(transaction);
|
this.savingsAccountTransactionRepository.save(transaction);
|
||||||
holdTransaction.updateReleaseId(transaction.getId());
|
holdTransaction.updateReleaseId(transaction.getId());
|
||||||
|
|||||||
+4
@@ -40,5 +40,9 @@ INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `c
|
|||||||
|
|
||||||
ALTER TABLE `m_savings_account_transaction` ADD COLUMN `release_id_of_hold_amount` BIGINT(20) NULL DEFAULT NULL;
|
ALTER TABLE `m_savings_account_transaction` ADD COLUMN `release_id_of_hold_amount` BIGINT(20) NULL DEFAULT NULL;
|
||||||
|
|
||||||
|
-- modify `m_savings_account`
|
||||||
|
|
||||||
|
ALTER TABLE `m_savings_account` ADD COLUMN `total_savings_amount_on_hold` DECIMAL(19,6) NULL DEFAULT NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user