Merge pull request #2215 from logoutdhaval/fineract-1553
FINERACT-1553: Lien configured at product level
This commit is contained in:
+2
-2
@@ -401,8 +401,8 @@ public class InteropServiceImpl implements InteropService {
|
||||
PaymentDetail paymentDetail = instance(findPaymentType(), savingsAccount.getExternalId(), null, getRoutingCode(), transferCode,
|
||||
null);
|
||||
SavingsAccountTransaction holdTransaction = SavingsAccountTransaction.holdAmount(savingsAccount, savingsAccount.office(),
|
||||
paymentDetail, transactionDate.toLocalDate(), Money.of(savingsAccount.getCurrency(), total), new Date(),
|
||||
getLoginUser());
|
||||
paymentDetail, transactionDate.toLocalDate(), Money.of(savingsAccount.getCurrency(), total), new Date(), getLoginUser(),
|
||||
false);
|
||||
MonetaryCurrency accountCurrency = savingsAccount.getCurrency().copy();
|
||||
holdTransaction.updateRunningBalance(
|
||||
Money.of(accountCurrency, savingsAccount.getWithdrawableBalance().subtract(holdTransaction.getAmount())));
|
||||
|
||||
+2
@@ -135,6 +135,8 @@ public class SavingsApiConstants {
|
||||
public static final String minOverdraftForInterestCalculationParamName = "minOverdraftForInterestCalculation";
|
||||
public static final String minRequiredBalanceParamName = "minRequiredBalance";
|
||||
public static final String enforceMinRequiredBalanceParamName = "enforceMinRequiredBalance";
|
||||
public static final String maxAllowedLienLimitParamName = "maxAllowedLienLimit";
|
||||
public static final String lienAllowedParamName = "lienAllowed";
|
||||
public static final String minBalanceForInterestCalculationParamName = "minBalanceForInterestCalculation";
|
||||
public static final String withdrawBalanceParamName = "withdrawBalance";
|
||||
public static final String onHoldFundsParamName = "onHoldFunds";
|
||||
|
||||
+8
@@ -18,6 +18,11 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.util.Collection;
|
||||
import javax.ws.rs.Consumes;
|
||||
@@ -130,6 +135,9 @@ public class SavingsAccountTransactionsApiResource {
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = SavingsAccountTransactionsApiResourceSwagger.PostSavingsAccountTransactionsRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SavingsAccountTransactionsApiResourceSwagger.PostSavingsAccountTransactionsResponse.class))) })
|
||||
public String transaction(@PathParam("savingsId") final Long savingsId, @QueryParam("command") final String commandParam,
|
||||
final String apiRequestBodyAsJson) {
|
||||
try {
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
final class SavingsAccountTransactionsApiResourceSwagger {
|
||||
|
||||
private SavingsAccountTransactionsApiResourceSwagger() {}
|
||||
|
||||
@Schema(description = "PostSavingsAccountTransactionsRequest")
|
||||
public static final class PostSavingsAccountTransactionsRequest {
|
||||
|
||||
private PostSavingsAccountTransactionsRequest() {}
|
||||
|
||||
@Schema(example = "27 March 2022")
|
||||
public String transactionDate;
|
||||
@Schema(example = "1000")
|
||||
public Integer transactionAmount;
|
||||
@Schema(example = "en")
|
||||
public String locale;
|
||||
@Schema(example = "dd MMMM yyyy")
|
||||
public String dateFormat;
|
||||
@Schema(example = "true")
|
||||
public String lienAllowed;
|
||||
@Schema(example = "String")
|
||||
public String reasonForBlock;
|
||||
}
|
||||
|
||||
@Schema(description = "PostSavingsAccountTransactionsResponse")
|
||||
public static final class PostSavingsAccountTransactionsResponse {
|
||||
|
||||
private PostSavingsAccountTransactionsResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Integer officeId;
|
||||
@Schema(example = "1")
|
||||
public Integer clientId;
|
||||
@Schema(example = "1")
|
||||
public Integer savingsId;
|
||||
@Schema(example = "1")
|
||||
public Integer resourceId;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -135,7 +135,7 @@ public class SavingsProductsApiResource {
|
||||
@Operation(summary = "Create a Savings Product", description = "Creates a Savings Product\n\n"
|
||||
+ "Mandatory Fields: name, shortName, description, currencyCode, digitsAfterDecimal,inMultiplesOf, nominalAnnualInterestRate, interestCompoundingPeriodType, interestCalculationType, interestCalculationDaysInYearType,accountingRule\n\n"
|
||||
+ "Mandatory Fields for Cash based accounting (accountingRule = 2): savingsReferenceAccountId, savingsControlAccountId, interestOnSavingsAccountId, incomeFromFeeAccountId, transfersInSuspenseAccountId, incomeFromPenaltyAccountId\n\n"
|
||||
+ "Optional Fields: minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, paymentChannelToFundSourceMappings, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, charges, allowOverdraft, overdraftLimit, minBalanceForInterestCalculation,withHoldTax,taxGroupId,accountMapping")
|
||||
+ "Optional Fields: minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, paymentChannelToFundSourceMappings, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, charges, allowOverdraft, overdraftLimit, minBalanceForInterestCalculation,withHoldTax,taxGroupId,accountMapping, lienAllowed, maxAllowedLienLimit")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = SavingsProductsApiResourceSwagger.PostSavingsProductsRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SavingsProductsApiResourceSwagger.PostSavingsProductsResponse.class))) })
|
||||
|
||||
+3
-3
@@ -37,9 +37,9 @@ public class SavingsAccountConstant extends SavingsApiConstants {
|
||||
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||
// withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
|
||||
withdrawalFeeForTransfersParamName, feeAmountParamName, feeOnMonthDayParamName, chargesParamName, allowOverdraftParamName,
|
||||
overdraftLimitParamName, minRequiredBalanceParamName, enforceMinRequiredBalanceParamName,
|
||||
nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName, withHoldTaxParamName, datatables,
|
||||
gsimApplicationId, gsimLastApplication));
|
||||
overdraftLimitParamName, minRequiredBalanceParamName, enforceMinRequiredBalanceParamName, lienAllowedParamName,
|
||||
maxAllowedLienLimitParamName, nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
|
||||
withHoldTaxParamName, datatables, gsimApplicationId, gsimLastApplication));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of {@link SavingsAccountData}. Where possible, we try to
|
||||
|
||||
+45
-30
@@ -80,6 +80,8 @@ public final class SavingsAccountData implements Serializable {
|
||||
private final BigDecimal overdraftLimit;
|
||||
private final BigDecimal minRequiredBalance;
|
||||
private final boolean enforceMinRequiredBalance;
|
||||
private final BigDecimal maxAllowedLienLimit;
|
||||
private final boolean lienAllowed;
|
||||
private final BigDecimal minBalanceForInterestCalculation;
|
||||
private final BigDecimal onHoldFunds;
|
||||
private final boolean withHoldTax;
|
||||
@@ -191,6 +193,8 @@ public final class SavingsAccountData implements Serializable {
|
||||
this.overdraftLimit = overdraftLimit;
|
||||
this.minRequiredBalance = null;
|
||||
this.enforceMinRequiredBalance = false;
|
||||
this.maxAllowedLienLimit = null;
|
||||
this.lienAllowed = false;
|
||||
this.minBalanceForInterestCalculation = null;
|
||||
this.onHoldFunds = null;
|
||||
this.withHoldTax = false;
|
||||
@@ -546,6 +550,8 @@ public final class SavingsAccountData implements Serializable {
|
||||
this.overdraftLimit = overdraftLimit;
|
||||
this.minRequiredBalance = null;
|
||||
this.enforceMinRequiredBalance = false;
|
||||
this.maxAllowedLienLimit = null;
|
||||
this.lienAllowed = false;
|
||||
this.minBalanceForInterestCalculation = null;
|
||||
this.onHoldFunds = null;
|
||||
this.withHoldTax = false;
|
||||
@@ -594,11 +600,11 @@ public final class SavingsAccountData implements Serializable {
|
||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeForTransfers, final SavingsAccountSummaryData summary, final boolean allowOverdraft,
|
||||
final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal onHoldFunds,
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
||||
final boolean withHoldTax, final TaxGroupData taxGroup, final LocalDate lastActiveTransactionDate,
|
||||
final boolean isDormancyTrackingActive, final Integer daysToInactive, final Integer daysToDormancy, final Integer daysToEscheat,
|
||||
final BigDecimal savingsAmountOnHold) {
|
||||
final BigDecimal maxAllowedLienLimit, final boolean lienAllowed, final BigDecimal minBalanceForInterestCalculation,
|
||||
final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
||||
final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive, final Integer daysToInactive,
|
||||
final Integer daysToDormancy, final Integer daysToEscheat, final BigDecimal savingsAmountOnHold) {
|
||||
|
||||
final Collection<SavingsProductData> productOptions = null;
|
||||
final Collection<StaffData> fieldOfficerOptions = null;
|
||||
@@ -620,9 +626,9 @@ public final class SavingsAccountData implements Serializable {
|
||||
transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance,
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax, taxGroup, lastActiveTransactionDate, isDormancyTrackingActive,
|
||||
daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation, onHoldFunds,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup, lastActiveTransactionDate,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
}
|
||||
|
||||
public static SavingsAccountData lookup(final Long accountId, final String accountNo, final EnumOptionData depositType) {
|
||||
@@ -659,6 +665,8 @@ public final class SavingsAccountData implements Serializable {
|
||||
final BigDecimal minOverdraftForInterestCalculation = null;
|
||||
final BigDecimal minRequiredBalance = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final BigDecimal maxAllowedLienLimit = null;
|
||||
final boolean lienAllowed = false;
|
||||
final BigDecimal minBalanceForInterestCalculation = null;
|
||||
final BigDecimal onHoldFunds = null;
|
||||
|
||||
@@ -694,9 +702,9 @@ public final class SavingsAccountData implements Serializable {
|
||||
withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup, lastActiveTransactionDate,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
minRequiredBalance, enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation,
|
||||
onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
}
|
||||
|
||||
public static SavingsAccountData lookupWithProductDetails(final Long accountId, final String accountNo,
|
||||
@@ -731,6 +739,8 @@ public final class SavingsAccountData implements Serializable {
|
||||
final BigDecimal minOverdraftForInterestCalculation = null;
|
||||
final BigDecimal minRequiredBalance = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final BigDecimal maxAllowedLienLimit = null;
|
||||
final boolean lienAllowed = false;
|
||||
final BigDecimal minBalanceForInterestCalculation = null;
|
||||
final BigDecimal onHoldFunds = null;
|
||||
|
||||
@@ -766,9 +776,9 @@ public final class SavingsAccountData implements Serializable {
|
||||
withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup, lastActiveTransactionDate,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
minRequiredBalance, enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation,
|
||||
onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template,
|
||||
@@ -801,10 +811,10 @@ public final class SavingsAccountData implements Serializable {
|
||||
template.interestCalculationTypeOptions, template.interestCalculationDaysInYearTypeOptions,
|
||||
template.lockinPeriodFrequencyTypeOptions, template.withdrawalFeeTypeOptions, charges, template.chargeOptions,
|
||||
account.allowOverdraft, account.overdraftLimit, account.minRequiredBalance, account.enforceMinRequiredBalance,
|
||||
account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
|
||||
account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup, account.lastActiveTransactionDate,
|
||||
account.isDormancyTrackingActive, account.daysToInactive, account.daysToDormancy, account.daysToEscheat,
|
||||
account.savingsAmountOnHold);
|
||||
account.maxAllowedLienLimit, account.lienAllowed, account.minBalanceForInterestCalculation, account.onHoldFunds,
|
||||
account.nominalAnnualInterestRateOverdraft, account.minOverdraftForInterestCalculation, account.withHoldTax,
|
||||
account.taxGroup, account.lastActiveTransactionDate, account.isDormancyTrackingActive, account.daysToInactive,
|
||||
account.daysToDormancy, account.daysToEscheat, account.savingsAmountOnHold);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||
@@ -827,10 +837,11 @@ public final class SavingsAccountData implements Serializable {
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges,
|
||||
chargeOptions, account.allowOverdraft, account.overdraftLimit, account.minRequiredBalance,
|
||||
account.enforceMinRequiredBalance, account.minBalanceForInterestCalculation, account.onHoldFunds,
|
||||
account.nominalAnnualInterestRateOverdraft, account.minOverdraftForInterestCalculation, account.withHoldTax,
|
||||
account.taxGroup, account.lastActiveTransactionDate, account.isDormancyTrackingActive, account.daysToInactive,
|
||||
account.daysToDormancy, account.daysToEscheat, account.savingsAmountOnHold);
|
||||
account.enforceMinRequiredBalance, account.maxAllowedLienLimit, account.lienAllowed,
|
||||
account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
|
||||
account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup, account.lastActiveTransactionDate,
|
||||
account.isDormancyTrackingActive, account.daysToInactive, account.daysToDormancy, account.daysToEscheat,
|
||||
account.savingsAmountOnHold);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||
@@ -867,6 +878,8 @@ public final class SavingsAccountData implements Serializable {
|
||||
final BigDecimal minOverdraftForInterestCalculation = null;
|
||||
final BigDecimal minRequiredBalance = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final BigDecimal maxAllowedLienLimit = null;
|
||||
final boolean lienAllowed = false;
|
||||
final BigDecimal minBalanceForInterestCalculation = null;
|
||||
final BigDecimal onHoldFunds = null;
|
||||
final boolean withHoldTax = false;
|
||||
@@ -902,9 +915,9 @@ public final class SavingsAccountData implements Serializable {
|
||||
withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup, lastActiveTransactionDate,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
minRequiredBalance, enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation,
|
||||
onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
}
|
||||
|
||||
private SavingsAccountData(final Long id, final String accountNo, final EnumOptionData depositType, final String externalId,
|
||||
@@ -924,11 +937,11 @@ public final class SavingsAccountData implements Serializable {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
|
||||
final Collection<SavingsAccountChargeData> charges, final Collection<ChargeData> chargeOptions, final boolean allowOverdraft,
|
||||
final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal onHoldFunds,
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
||||
final boolean withHoldTax, final TaxGroupData taxGroup, final LocalDate lastActiveTransactionDate,
|
||||
final boolean isDormancyTrackingActive, final Integer daysToInactive, final Integer daysToDormancy, final Integer daysToEscheat,
|
||||
final BigDecimal savingsAmountOnHold) {
|
||||
final BigDecimal maxAllowedLienLimit, final boolean lienAllowd, final BigDecimal minBalanceForInterestCalculation,
|
||||
final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
||||
final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive, final Integer daysToInactive,
|
||||
final Integer daysToDormancy, final Integer daysToEscheat, final BigDecimal savingsAmountOnHold) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.depositType = depositType;
|
||||
@@ -986,6 +999,8 @@ public final class SavingsAccountData implements Serializable {
|
||||
this.minOverdraftForInterestCalculation = minOverdraftForInterestCalculation;
|
||||
this.minRequiredBalance = minRequiredBalance;
|
||||
this.enforceMinRequiredBalance = enforceMinRequiredBalance;
|
||||
this.maxAllowedLienLimit = maxAllowedLienLimit;
|
||||
this.lienAllowed = lienAllowd;
|
||||
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
|
||||
this.onHoldFunds = onHoldFunds;
|
||||
this.withHoldTax = withHoldTax;
|
||||
|
||||
+27
-1
@@ -33,8 +33,10 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interest
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.maxAllowedLienLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minOverdraftForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateOverdraftParamName;
|
||||
@@ -60,6 +62,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
@@ -221,7 +224,7 @@ public class SavingsAccountDataValidator {
|
||||
validateSavingsCharges(element, baseDataValidator);
|
||||
|
||||
validateOverdraftParams(baseDataValidator, element);
|
||||
|
||||
validateLienParams(baseDataValidator, element);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -415,6 +418,29 @@ public class SavingsAccountDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLienParams(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
if (this.fromApiJsonHelper.parameterExists(lienAllowedParamName, element)) {
|
||||
final Boolean lienAllowed = this.fromApiJsonHelper.extractBooleanNamed(lienAllowedParamName, element);
|
||||
baseDataValidator.reset().parameter(lienAllowedParamName).value(lienAllowed).ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
if (BooleanUtils.isTrue(this.fromApiJsonHelper.extractBooleanNamed(lienAllowedParamName, element))) {
|
||||
final BigDecimal maxAllowedLienLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxAllowedLienLimitParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(maxAllowedLienLimitParamName).value(maxAllowedLienLimit).ignoreIfNull()
|
||||
.zeroOrPositiveAmount();
|
||||
}
|
||||
if (BooleanUtils.isTrue(this.fromApiJsonHelper.extractBooleanNamed(lienAllowedParamName, element))
|
||||
&& BooleanUtils.isTrue(this.fromApiJsonHelper.extractBooleanNamed(allowOverdraftParamName, element))) {
|
||||
final BigDecimal maxAllowedLienLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxAllowedLienLimitParamName,
|
||||
element);
|
||||
final BigDecimal overdraftLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(overdraftLimitParamName, element);
|
||||
if (overdraftLimit.compareTo(maxAllowedLienLimit) > 0) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("Overdraft.limit.can.not.be.greater.than.lien.limit");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateOverdraftParams(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
if (this.fromApiJsonHelper.parameterExists(allowOverdraftParamName, element)) {
|
||||
final Boolean allowOverdraft = this.fromApiJsonHelper.extractBooleanNamed(allowOverdraftParamName, element);
|
||||
|
||||
+47
-59
@@ -73,6 +73,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
private final boolean isManualTransaction;
|
||||
private final Boolean isReversal;
|
||||
private final Long originalTransactionId;
|
||||
private final Boolean lienTransaction;
|
||||
private final Long releaseTransactionId;
|
||||
private final String reasonForBlock;
|
||||
private Set<SavingsAccountChargesPaidByData> chargesPaidByData = new HashSet<>();
|
||||
@@ -105,29 +106,31 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
String accountNumber, String checkNumber, String routingCode, String receiptNumber, String bankNumber, Long savingsAccountId,
|
||||
SavingsAccountTransactionEnumData transactionType, Integer rowIndex, String locale, String dateFormat) {
|
||||
return new SavingsAccountTransactionData(transactionAmount, transactionDate, paymentTypeId, accountNumber, checkNumber, routingCode,
|
||||
receiptNumber, bankNumber, savingsAccountId, transactionType, rowIndex, locale, dateFormat);
|
||||
receiptNumber, bankNumber, savingsAccountId, transactionType, rowIndex, locale, dateFormat, false);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransactionData interestPosting(final SavingsAccountData savingsAccount, final LocalDate date,
|
||||
final Money amount, final boolean isManualTransaction) {
|
||||
final boolean isReversed = false;
|
||||
final Boolean lienTransaction = false;
|
||||
final SavingsAccountTransactionType savingsAccountTransactionType = SavingsAccountTransactionType.INTEREST_POSTING;
|
||||
SavingsAccountTransactionEnumData savingsAccountTransactionEnumData = new SavingsAccountTransactionEnumData(
|
||||
savingsAccountTransactionType.getValue().longValue(), savingsAccountTransactionType.getCode(),
|
||||
savingsAccountTransactionType.getValue().toString());
|
||||
return new SavingsAccountTransactionData(amount.getAmount(), date, savingsAccount.getId(), savingsAccountTransactionEnumData,
|
||||
isReversed, null, isManualTransaction);
|
||||
isReversed, null, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransactionData overdraftInterest(final SavingsAccountData savingsAccount, final LocalDate date,
|
||||
final Money amount, final boolean isManualTransaction) {
|
||||
final boolean isReversed = false;
|
||||
final Boolean lienTransaction = false;
|
||||
final SavingsAccountTransactionType savingsAccountTransactionType = SavingsAccountTransactionType.OVERDRAFT_INTEREST;
|
||||
SavingsAccountTransactionEnumData savingsAccountTransactionEnumData = new SavingsAccountTransactionEnumData(
|
||||
savingsAccountTransactionType.getValue().longValue(), savingsAccountTransactionType.getCode(),
|
||||
savingsAccountTransactionType.getValue().toString());
|
||||
return new SavingsAccountTransactionData(amount.getAmount(), date, savingsAccount.getId(), savingsAccountTransactionEnumData,
|
||||
isReversed, null, isManualTransaction);
|
||||
isReversed, null, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public List<TaxDetailsData> getTaxDetails() {
|
||||
@@ -311,12 +314,13 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
return new SavingsAccountTransactionData(accountTransaction.getSavingsAccountId(), null, accountTransaction.getPaymentDetailData(),
|
||||
accountTransaction.getTransactionType(), accountTransaction.getTransactionLocalDate(),
|
||||
accountTransaction.getSubmittedOnDate(), accountTransaction.getAmount(), accountTransaction.isReversed(), null,
|
||||
accountTransaction.isManualTransaction());
|
||||
accountTransaction.isManualTransaction(), accountTransaction.lienTransaction);
|
||||
}
|
||||
|
||||
private SavingsAccountTransactionData(final Long savingsId, final Long officeId, final PaymentDetailData paymentDetailData,
|
||||
final SavingsAccountTransactionEnumData savingsAccountTransactionType, final LocalDate transactionDate, final Date createdDate,
|
||||
final BigDecimal amount, final boolean isReversed, final Long userId, final boolean isManualTransaction) {
|
||||
final BigDecimal amount, final boolean isReversed, final Long userId, final boolean isManualTransaction,
|
||||
final Boolean lienTransaction) {
|
||||
this.savingsAccountId = savingsId;
|
||||
this.paymentDetailData = paymentDetailData;
|
||||
this.transactionType = savingsAccountTransactionType;
|
||||
@@ -324,6 +328,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
this.submittedOnDate = createdDate;
|
||||
this.amount = amount;
|
||||
this.isManualTransaction = isManualTransaction;
|
||||
this.lienTransaction = lienTransaction;
|
||||
this.id = null;
|
||||
this.accountId = null;
|
||||
this.accountNo = null;
|
||||
@@ -442,12 +447,13 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
final Money amount, final Map<TaxComponentData, BigDecimal> taxDetails) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final Boolean lienTransaction = false;
|
||||
SavingsAccountTransactionType savingsAccountTransactionType = SavingsAccountTransactionType.WITHHOLD_TAX;
|
||||
SavingsAccountTransactionEnumData transactionType = new SavingsAccountTransactionEnumData(
|
||||
savingsAccountTransactionType.getValue().longValue(), savingsAccountTransactionType.getCode(),
|
||||
savingsAccountTransactionType.getValue().toString());
|
||||
SavingsAccountTransactionData accountTransaction = new SavingsAccountTransactionData(amount.getAmount(), date,
|
||||
savingsAccount.getId(), transactionType, isReversed, null, isManualTransaction);
|
||||
savingsAccount.getId(), transactionType, isReversed, null, isManualTransaction, lienTransaction);
|
||||
updateTaxDetails(taxDetails, accountTransaction);
|
||||
return accountTransaction;
|
||||
}
|
||||
@@ -515,7 +521,8 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
}
|
||||
|
||||
private SavingsAccountTransactionData(BigDecimal transactionAmount, LocalDate transactionDate, Long savingsAccountId,
|
||||
SavingsAccountTransactionEnumData transactionType, boolean isReversed, String locale, boolean isManualTransaction) {
|
||||
SavingsAccountTransactionEnumData transactionType, boolean isReversed, String locale, boolean isManualTransaction,
|
||||
final Boolean lienTransaction) {
|
||||
this.id = null;
|
||||
this.transactionType = transactionType;
|
||||
this.accountId = null;
|
||||
@@ -548,13 +555,15 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
this.isManualTransaction = isManualTransaction;
|
||||
this.isReversal = null;
|
||||
this.originalTransactionId = null;
|
||||
this.lienTransaction = lienTransaction;
|
||||
this.releaseTransactionId = null;
|
||||
this.reasonForBlock = null;
|
||||
}
|
||||
|
||||
private SavingsAccountTransactionData(BigDecimal transactionAmount, LocalDate transactionDate, Long paymentTypeId, String accountNumber,
|
||||
String checkNumber, String routingCode, String receiptNumber, String bankNumber, Long savingsAccountId,
|
||||
SavingsAccountTransactionEnumData transactionType, Integer rowIndex, String locale, String dateFormat) {
|
||||
SavingsAccountTransactionEnumData transactionType, Integer rowIndex, String locale, String dateFormat,
|
||||
final Boolean lienTransaction) {
|
||||
this.id = null;
|
||||
this.transactionType = transactionType;
|
||||
this.accountId = null;
|
||||
@@ -587,6 +596,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
this.isManualTransaction = false;
|
||||
this.isReversal = null;
|
||||
this.originalTransactionId = null;
|
||||
this.lienTransaction = lienTransaction;
|
||||
this.releaseTransactionId = null;
|
||||
this.reasonForBlock = null;
|
||||
}
|
||||
@@ -594,7 +604,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
private SavingsAccountTransactionData(Integer id, BigDecimal transactionAmount, LocalDate transactionDate, Long paymentTypeId,
|
||||
String accountNumber, String checkNumber, String routingCode, String receiptNumber, String bankNumber, Long savingsAccountId,
|
||||
SavingsAccountTransactionEnumData transactionType, Integer rowIndex, String locale, String dateFormat,
|
||||
BigDecimal cumulativeBalance) {
|
||||
BigDecimal cumulativeBalance, final Boolean lienTransaction) {
|
||||
this.id = null;
|
||||
this.transactionType = transactionType;
|
||||
this.accountId = null;
|
||||
@@ -628,6 +638,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
this.isManualTransaction = false;
|
||||
this.isReversal = null;
|
||||
this.originalTransactionId = null;
|
||||
this.lienTransaction = lienTransaction;
|
||||
this.releaseTransactionId = null;
|
||||
this.reasonForBlock = null;
|
||||
}
|
||||
@@ -721,24 +732,27 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
final Collection<PaymentTypeData> paymentTypeOptions = null;
|
||||
return new SavingsAccountTransactionData(id, transactionType, paymentDetailData, savingsId, savingsAccountNo, date, currency,
|
||||
amount, outstandingChargeAmount, runningBalance, reversed, submittedOnDate, paymentTypeOptions, interestedPostedAsOn,
|
||||
cumulativeBalance, balanceEndDate);
|
||||
cumulativeBalance, balanceEndDate, false);
|
||||
}
|
||||
|
||||
private SavingsAccountTransactionData(final Long id, final SavingsAccountTransactionEnumData transactionType,
|
||||
final PaymentDetailData paymentDetailData, final Long savingsId, final String savingsAccountNo, final LocalDate date,
|
||||
final CurrencyData currency, final BigDecimal amount, final BigDecimal outstandingChargeAmount, final BigDecimal runningBalance,
|
||||
final boolean reversed, final LocalDate submittedOnDate, final Collection<PaymentTypeData> paymentTypeOptions,
|
||||
final boolean interestedPostedAsOn, final BigDecimal cumulativeBalance, final LocalDate balanceEndDate) {
|
||||
final boolean interestedPostedAsOn, final BigDecimal cumulativeBalance, final LocalDate balanceEndDate,
|
||||
final Boolean lienTransaction) {
|
||||
|
||||
this(id, transactionType, paymentDetailData, savingsId, savingsAccountNo, date, currency, amount, outstandingChargeAmount,
|
||||
runningBalance, reversed, paymentTypeOptions, submittedOnDate, interestedPostedAsOn, cumulativeBalance, balanceEndDate);
|
||||
runningBalance, reversed, paymentTypeOptions, submittedOnDate, interestedPostedAsOn, cumulativeBalance, balanceEndDate,
|
||||
lienTransaction);
|
||||
}
|
||||
|
||||
private SavingsAccountTransactionData(final Long id, final SavingsAccountTransactionEnumData transactionType,
|
||||
final PaymentDetailData paymentDetailData, final Long savingsId, final String savingsAccountNo, final LocalDate date,
|
||||
final CurrencyData currency, final BigDecimal amount, final BigDecimal outstandingChargeAmount, final BigDecimal runningBalance,
|
||||
final boolean reversed, final Collection<PaymentTypeData> paymentTypeOptions, final LocalDate submittedOnDate,
|
||||
final boolean interestedPostedAsOn, final BigDecimal cumulativeBalance, final LocalDate balanceEndDate) {
|
||||
final boolean interestedPostedAsOn, final BigDecimal cumulativeBalance, final LocalDate balanceEndDate,
|
||||
final Boolean lienTransaction) {
|
||||
this.id = id;
|
||||
this.transactionDate = date;
|
||||
this.transactionType = transactionType;
|
||||
@@ -762,6 +776,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
this.isManualTransaction = false;
|
||||
this.isReversal = null;
|
||||
this.originalTransactionId = null;
|
||||
this.lienTransaction = lienTransaction;
|
||||
this.releaseTransactionId = null;
|
||||
this.reasonForBlock = null;
|
||||
}
|
||||
@@ -774,7 +789,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
final Collection<PaymentTypeData> paymentTypeOptions = null;
|
||||
return new SavingsAccountTransactionData(id, transactionType, paymentDetailData, savingsId, savingsAccountNo, date, currency,
|
||||
amount, outstandingChargeAmount, runningBalance, reversed, transfer, paymentTypeOptions, interestedPostedAsOn,
|
||||
submittedByUsername, note);
|
||||
submittedByUsername, note, false);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransactionData create(final Long id, final SavingsAccountTransactionEnumData transactionType,
|
||||
@@ -782,17 +797,18 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
final CurrencyData currency, final BigDecimal amount, final BigDecimal outstandingChargeAmount, final BigDecimal runningBalance,
|
||||
final boolean reversed, final AccountTransferData transfer, final LocalDate submittedOnDate, final boolean interestedPostedAsOn,
|
||||
final String submittedByUsername, final String note, final Boolean isReversal, final Long originalTransactionId,
|
||||
final Long releaseTransactionId, final String reasonForBlock) {
|
||||
final Boolean lienTransaction, final Long releaseTransactionId, final String reasonForBlock) {
|
||||
final Collection<PaymentTypeData> paymentTypeOptions = null;
|
||||
return new SavingsAccountTransactionData(id, transactionType, paymentDetailData, savingsId, savingsAccountNo, date, currency,
|
||||
amount, outstandingChargeAmount, runningBalance, reversed, transfer, paymentTypeOptions, submittedOnDate,
|
||||
interestedPostedAsOn, submittedByUsername, note, isReversal, originalTransactionId, releaseTransactionId, reasonForBlock);
|
||||
interestedPostedAsOn, submittedByUsername, note, isReversal, originalTransactionId, lienTransaction, releaseTransactionId,
|
||||
reasonForBlock);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransactionData create(final Long id) {
|
||||
final Collection<PaymentTypeData> paymentTypeOptions = null;
|
||||
return new SavingsAccountTransactionData(id, null, null, null, null, null, null, null, null, null, false, null, paymentTypeOptions,
|
||||
null, false, null, null, null, null);
|
||||
null, false, null, null, null, null, false, null, null);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransactionData template(final Long savingsId, final String savingsAccountNo,
|
||||
@@ -808,9 +824,10 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
final boolean interestedPostedAsOn = false;
|
||||
final String submittedByUsername = null;
|
||||
final String note = null;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransactionData(id, transactionType, paymentDetailData, savingsId, savingsAccountNo, defaultLocalDate,
|
||||
currency, amount, outstandingChargeAmount, runningBalance, reversed, null, null, interestedPostedAsOn, submittedByUsername,
|
||||
note);
|
||||
note, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransactionData templateOnTop(final SavingsAccountTransactionData savingsAccountTransactionData,
|
||||
@@ -821,17 +838,19 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
savingsAccountTransactionData.amount, savingsAccountTransactionData.outstandingChargeAmount,
|
||||
savingsAccountTransactionData.runningBalance, savingsAccountTransactionData.reversed,
|
||||
savingsAccountTransactionData.transfer, paymentTypeOptions, savingsAccountTransactionData.interestedPostedAsOn,
|
||||
savingsAccountTransactionData.submittedByUsername, savingsAccountTransactionData.note);
|
||||
savingsAccountTransactionData.submittedByUsername, savingsAccountTransactionData.note,
|
||||
savingsAccountTransactionData.lienTransaction);
|
||||
}
|
||||
|
||||
private SavingsAccountTransactionData(final Long id, final SavingsAccountTransactionEnumData transactionType,
|
||||
final PaymentDetailData paymentDetailData, final Long savingsId, final String savingsAccountNo, final LocalDate date,
|
||||
final CurrencyData currency, final BigDecimal amount, final BigDecimal outstandingChargeAmount, final BigDecimal runningBalance,
|
||||
final boolean reversed, final AccountTransferData transfer, final Collection<PaymentTypeData> paymentTypeOptions,
|
||||
final boolean interestedPostedAsOn, final String submittedByUsername, final String note) {
|
||||
final boolean interestedPostedAsOn, final String submittedByUsername, final String note, final Boolean lienTransaction) {
|
||||
|
||||
this(id, transactionType, paymentDetailData, savingsId, savingsAccountNo, date, currency, amount, outstandingChargeAmount,
|
||||
runningBalance, reversed, transfer, paymentTypeOptions, date, interestedPostedAsOn, submittedByUsername, note, null, null);
|
||||
runningBalance, reversed, transfer, paymentTypeOptions, date, interestedPostedAsOn, submittedByUsername, note, null, null,
|
||||
lienTransaction, null, null);
|
||||
}
|
||||
|
||||
private SavingsAccountTransactionData(final Long id, final SavingsAccountTransactionEnumData transactionType,
|
||||
@@ -839,7 +858,8 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
final CurrencyData currency, final BigDecimal amount, final BigDecimal outstandingChargeAmount, final BigDecimal runningBalance,
|
||||
final boolean reversed, final AccountTransferData transfer, final Collection<PaymentTypeData> paymentTypeOptions,
|
||||
final LocalDate submittedOnDate, final boolean interestedPostedAsOn, final String submittedByUsername, final String note,
|
||||
final Boolean isReversal, final Long originalTransactionId, final Long releaseTransactionId, final String reasonForBlock) {
|
||||
final Boolean isReversal, final Long originalTransactionId, final Boolean lienTransaction, final Long releaseTransactionId,
|
||||
final String reasonForBlock) {
|
||||
this.id = id;
|
||||
this.transactionType = transactionType;
|
||||
this.paymentDetailData = paymentDetailData;
|
||||
@@ -865,6 +885,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
this.isManualTransaction = false;
|
||||
this.isReversal = isReversal;
|
||||
this.originalTransactionId = originalTransactionId;
|
||||
this.lienTransaction = lienTransaction;
|
||||
this.releaseTransactionId = releaseTransactionId;
|
||||
this.reasonForBlock = reasonForBlock;
|
||||
}
|
||||
@@ -873,7 +894,8 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
final PaymentDetailData paymentDetailData, final Long savingsId, final String savingsAccountNo, final LocalDate date,
|
||||
final CurrencyData currency, final BigDecimal amount, final BigDecimal outstandingChargeAmount, final BigDecimal runningBalance,
|
||||
final boolean reversed, final AccountTransferData transfer, final Collection<PaymentTypeData> paymentTypeOptions,
|
||||
final LocalDate submittedOnDate, final boolean interestedPostedAsOn, final BigDecimal cumulativeBalance) {
|
||||
final LocalDate submittedOnDate, final boolean interestedPostedAsOn, final BigDecimal cumulativeBalance,
|
||||
final Boolean lienTransaction) {
|
||||
this.id = id;
|
||||
this.transactionType = transactionType;
|
||||
this.paymentDetailData = paymentDetailData;
|
||||
@@ -900,41 +922,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
this.isManualTransaction = false;
|
||||
this.isReversal = null;
|
||||
this.originalTransactionId = null;
|
||||
this.releaseTransactionId = null;
|
||||
this.reasonForBlock = null;
|
||||
}
|
||||
|
||||
private SavingsAccountTransactionData(final Long id, final SavingsAccountTransactionEnumData transactionType,
|
||||
final PaymentDetailData paymentDetailData, final Long savingsId, final String savingsAccountNo, final LocalDate date,
|
||||
final CurrencyData currency, final BigDecimal amount, final BigDecimal outstandingChargeAmount, final BigDecimal runningBalance,
|
||||
final boolean reversed, final AccountTransferData transfer, final Collection<PaymentTypeData> paymentTypeOptions,
|
||||
final LocalDate submittedOnDate, final boolean interestedPostedAsOn, final String submittedByUsername, final String note,
|
||||
final Boolean isReversal, final Long originalTransactionId) {
|
||||
this.id = id;
|
||||
this.transactionType = transactionType;
|
||||
this.paymentDetailData = paymentDetailData;
|
||||
this.accountId = savingsId;
|
||||
this.accountNo = savingsAccountNo;
|
||||
this.date = date;
|
||||
this.currency = currency;
|
||||
this.amount = amount;
|
||||
this.outstandingChargeAmount = outstandingChargeAmount;
|
||||
this.runningBalance = runningBalance;
|
||||
this.reversed = reversed;
|
||||
this.transfer = transfer;
|
||||
this.paymentTypeOptions = paymentTypeOptions;
|
||||
if (submittedOnDate != null) {
|
||||
this.submittedOnDate = Date.from(submittedOnDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
} else {
|
||||
this.submittedOnDate = null;
|
||||
}
|
||||
|
||||
this.interestedPostedAsOn = interestedPostedAsOn;
|
||||
this.submittedByUsername = submittedByUsername;
|
||||
this.note = note;
|
||||
this.isManualTransaction = false;
|
||||
this.isReversal = isReversal;
|
||||
this.originalTransactionId = originalTransactionId;
|
||||
this.lienTransaction = lienTransaction;
|
||||
this.releaseTransactionId = null;
|
||||
this.reasonForBlock = null;
|
||||
}
|
||||
@@ -953,7 +941,7 @@ public final class SavingsAccountTransactionData implements Serializable {
|
||||
savingsAccountTransactionData.runningBalance, savingsAccountTransactionData.reversed,
|
||||
savingsAccountTransactionData.transfer, savingsAccountTransactionData.paymentTypeOptions,
|
||||
savingsAccountTransactionData.interestedPostedAsOn, savingsAccountTransactionData.submittedByUsername,
|
||||
savingsAccountTransactionData.note);
|
||||
savingsAccountTransactionData.note, savingsAccountTransactionData.lienTransaction);
|
||||
}
|
||||
|
||||
public void setId(final Long id) {
|
||||
|
||||
+36
-24
@@ -23,7 +23,7 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.activate
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.bankNumberParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.checkNumberParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.closedOnDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.paymentTypeIdParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.receiptNumberParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.routingCodeParamName;
|
||||
@@ -44,6 +44,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
@@ -53,8 +54,6 @@ import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
@@ -71,8 +70,7 @@ public class SavingsAccountTransactionDataValidator {
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private static final Set<String> SAVINGS_ACCOUNT_HOLD_AMOUNT_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(transactionDateParamName, SavingsApiConstants.dateFormatParamName, SavingsApiConstants.localeParamName,
|
||||
transactionAmountParamName, lienParamName, SavingsApiConstants.reasonForBlockParamName));
|
||||
|
||||
transactionAmountParamName, lienAllowedParamName, SavingsApiConstants.reasonForBlockParamName));
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final SavingsAccountAssembler savingAccountAssembler;
|
||||
|
||||
@@ -217,7 +215,7 @@ public class SavingsAccountTransactionDataValidator {
|
||||
|
||||
}
|
||||
|
||||
public SavingsAccountTransaction validateHoldAndAssembleForm(final String json, final SavingsAccount account, final AppUser createdUser,
|
||||
public void validateHoldAndAssembleForm(final String json, final SavingsAccount account, final AppUser createdUser,
|
||||
final boolean backdatedTxnsAllowedTill) {
|
||||
|
||||
if (StringUtils.isBlank(json)) {
|
||||
@@ -249,21 +247,43 @@ public class SavingsAccountTransactionDataValidator {
|
||||
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
|
||||
}
|
||||
|
||||
Boolean lien = false;
|
||||
if (this.fromApiJsonHelper.parameterExists(lienParamName, element)) {
|
||||
lien = this.fromApiJsonHelper.extractBooleanNamed(lienParamName, element);
|
||||
}
|
||||
Boolean isEnforceMinRequiredBalanceEnabled = account.getEnforceMinRequiredBalance();
|
||||
Boolean isAccountLienEnabled = account.isLienAllowed();
|
||||
Boolean isOverdraftEnabled = account.isAllowOverdraft();
|
||||
|
||||
if (account.getEnforceMinRequiredBalance()) {
|
||||
if (account.getWithdrawableBalance().compareTo(BigDecimal.ZERO) < 0) {
|
||||
if (!lien) {
|
||||
if (account.getWithdrawableBalanceWithoutMinimumBalance().compareTo(account.getMinRequiredBalance()) < 0) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient balance", account.getId());
|
||||
Boolean lienAllowed = false;
|
||||
if (BooleanUtils.isTrue(fromApiJsonHelper.extractBooleanNamed(lienAllowedParamName, element))) {
|
||||
lienAllowed = this.fromApiJsonHelper.extractBooleanNamed(lienAllowedParamName, element);
|
||||
if (isAccountLienEnabled) {
|
||||
if (isOverdraftEnabled) {
|
||||
if (account.getOverdraftLimit().compareTo(account.getMaxAllowedLienLimit()) > 0) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"Overdraft.limit.can.not.be.greater.than.lien.limit", account.getId());
|
||||
}
|
||||
}
|
||||
if (amount.compareTo(account.getMaxAllowedLienLimit()) > 0) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("lien.limit.exceeded", account.getId());
|
||||
}
|
||||
} else {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("lien.is.not.allowed.in.product.level", account.getId());
|
||||
}
|
||||
} else {
|
||||
if (isOverdraftEnabled) {
|
||||
if (amount.compareTo(account.getWithdrawableBalance()) > 0 && amount.compareTo(account.getOverdraftLimit()) > 0) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient.balance", account.getId());
|
||||
}
|
||||
}
|
||||
if (isEnforceMinRequiredBalanceEnabled) {
|
||||
if (amount.compareTo(account.getWithdrawableBalance()) > 0) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient.balance", account.getId());
|
||||
}
|
||||
}
|
||||
if (!isOverdraftEnabled && !isEnforceMinRequiredBalanceEnabled) {
|
||||
if (amount.compareTo(account.getWithdrawableBalance()) > 0) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient.balance", account.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocalDate lastTransactionDate = null;
|
||||
|
||||
if (!backdatedTxnsAllowedTill) {
|
||||
@@ -279,13 +299,6 @@ public class SavingsAccountTransactionDataValidator {
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
final PaymentDetail paymentDetails = null;
|
||||
Date createdDate = new Date();
|
||||
|
||||
SavingsAccountTransaction transaction = SavingsAccountTransaction.holdAmount(account, account.office(), paymentDetails,
|
||||
transactionDate, Money.of(account.getCurrency(), amount), createdDate, createdUser);
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public SavingsAccountTransaction validateReleaseAmountAndAssembleForm(final SavingsAccountTransaction holdTransaction,
|
||||
@@ -312,7 +325,6 @@ public class SavingsAccountTransactionDataValidator {
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
Date createdDate = new Date();
|
||||
LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
||||
|
||||
SavingsAccountTransaction transaction = SavingsAccountTransaction.releaseAmount(holdTransaction, transactionDate, createdDate,
|
||||
createdUser);
|
||||
return transaction;
|
||||
|
||||
+45
-27
@@ -56,6 +56,8 @@ public final class SavingsProductData implements Serializable {
|
||||
private final BigDecimal overdraftLimit;
|
||||
private final BigDecimal minRequiredBalance;
|
||||
private final boolean enforceMinRequiredBalance;
|
||||
private final BigDecimal maxAllowedLienLimit;
|
||||
private final boolean lienAllowed;
|
||||
private final BigDecimal minBalanceForInterestCalculation;
|
||||
private final BigDecimal nominalAnnualInterestRateOverdraft;
|
||||
private final BigDecimal minOverdraftForInterestCalculation;
|
||||
@@ -124,6 +126,8 @@ public final class SavingsProductData implements Serializable {
|
||||
final BigDecimal overdraftLimit = null;
|
||||
final BigDecimal minRequiredBalance = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final BigDecimal maxAllowedLienLimit = null;
|
||||
final boolean lienAllowed = false;
|
||||
final BigDecimal minBalanceForInterestCalculation = null;
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft = null;
|
||||
final BigDecimal minOverdraftForInterestCalculation = null;
|
||||
@@ -141,9 +145,9 @@ public final class SavingsProductData implements Serializable {
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions,
|
||||
penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit,
|
||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax, taxGroup, taxGroupOptions, isDormancyTrackingActive, daysToInactive,
|
||||
daysToDormancy, daysToEscheat, accountMappingForPayment);
|
||||
minRequiredBalance, enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup, taxGroupOptions,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, accountMappingForPayment);
|
||||
}
|
||||
|
||||
public static SavingsProductData withCharges(final SavingsProductData product, final Collection<ChargeData> charges) {
|
||||
@@ -157,10 +161,11 @@ public final class SavingsProductData implements Serializable {
|
||||
product.lockinPeriodFrequencyTypeOptions, product.withdrawalFeeTypeOptions, product.paymentTypeOptions,
|
||||
product.accountingRuleOptions, product.accountingMappingOptions, charges, product.chargeOptions, product.penaltyOptions,
|
||||
product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings, product.allowOverdraft, product.overdraftLimit,
|
||||
product.minRequiredBalance, product.enforceMinRequiredBalance, product.minBalanceForInterestCalculation,
|
||||
product.nominalAnnualInterestRateOverdraft, product.minOverdraftForInterestCalculation, product.withHoldTax,
|
||||
product.taxGroup, product.taxGroupOptions, product.isDormancyTrackingActive, product.daysToInactive, product.daysToDormancy,
|
||||
product.daysToEscheat, product.accountMappingForPayment);
|
||||
product.minRequiredBalance, product.enforceMinRequiredBalance, product.maxAllowedLienLimit, product.lienAllowed,
|
||||
product.minBalanceForInterestCalculation, product.nominalAnnualInterestRateOverdraft,
|
||||
product.minOverdraftForInterestCalculation, product.withHoldTax, product.taxGroup, product.taxGroupOptions,
|
||||
product.isDormancyTrackingActive, product.daysToInactive, product.daysToDormancy, product.daysToEscheat,
|
||||
product.accountMappingForPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,10 +197,10 @@ public final class SavingsProductData implements Serializable {
|
||||
accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions,
|
||||
existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings, existingProduct.allowOverdraft,
|
||||
existingProduct.overdraftLimit, existingProduct.minRequiredBalance, existingProduct.enforceMinRequiredBalance,
|
||||
existingProduct.minBalanceForInterestCalculation, existingProduct.nominalAnnualInterestRateOverdraft,
|
||||
existingProduct.minOverdraftForInterestCalculation, existingProduct.withHoldTax, existingProduct.taxGroup, taxGroupOptions,
|
||||
existingProduct.isDormancyTrackingActive, existingProduct.daysToInactive, existingProduct.daysToDormancy,
|
||||
existingProduct.daysToEscheat, accountMappingForPayment);
|
||||
existingProduct.maxAllowedLienLimit, existingProduct.lienAllowed, existingProduct.minBalanceForInterestCalculation,
|
||||
existingProduct.nominalAnnualInterestRateOverdraft, existingProduct.minOverdraftForInterestCalculation,
|
||||
existingProduct.withHoldTax, existingProduct.taxGroup, taxGroupOptions, existingProduct.isDormancyTrackingActive,
|
||||
existingProduct.daysToInactive, existingProduct.daysToDormancy, existingProduct.daysToEscheat, accountMappingForPayment);
|
||||
}
|
||||
|
||||
public static SavingsProductData withAccountingDetails(final SavingsProductData existingProduct,
|
||||
@@ -227,11 +232,12 @@ public final class SavingsProductData implements Serializable {
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions,
|
||||
accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions,
|
||||
feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, existingProduct.allowOverdraft, existingProduct.overdraftLimit,
|
||||
existingProduct.minRequiredBalance, existingProduct.enforceMinRequiredBalance,
|
||||
existingProduct.minBalanceForInterestCalculation, existingProduct.nominalAnnualInterestRateOverdraft,
|
||||
existingProduct.minOverdraftForInterestCalculation, existingProduct.withHoldTax, existingProduct.taxGroup,
|
||||
existingProduct.taxGroupOptions, existingProduct.isDormancyTrackingActive, existingProduct.daysToInactive,
|
||||
existingProduct.daysToDormancy, existingProduct.daysToEscheat, existingProduct.accountMappingForPayment);
|
||||
existingProduct.minRequiredBalance, existingProduct.enforceMinRequiredBalance, existingProduct.maxAllowedLienLimit,
|
||||
existingProduct.lienAllowed, existingProduct.minBalanceForInterestCalculation,
|
||||
existingProduct.nominalAnnualInterestRateOverdraft, existingProduct.minOverdraftForInterestCalculation,
|
||||
existingProduct.withHoldTax, existingProduct.taxGroup, existingProduct.taxGroupOptions,
|
||||
existingProduct.isDormancyTrackingActive, existingProduct.daysToInactive, existingProduct.daysToDormancy,
|
||||
existingProduct.daysToEscheat, existingProduct.accountMappingForPayment);
|
||||
}
|
||||
|
||||
public static SavingsProductData instance(final Long id, final String name, final String shortName, final String description,
|
||||
@@ -240,7 +246,8 @@ public final class SavingsProductData implements Serializable {
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
|
||||
final EnumOptionData accountingType, final boolean allowOverdraft, final BigDecimal overdraftLimit,
|
||||
final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance, final BigDecimal minBalanceForInterestCalculation,
|
||||
final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance, final BigDecimal maxAllowedLienLimit,
|
||||
final boolean lienAllowed, final BigDecimal minBalanceForInterestCalculation,
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
||||
final boolean withHoldTax, final TaxGroupData taxGroup, final Boolean isDormancyTrackingActive, final Long daysToInactive,
|
||||
final Long daysToDormancy, final Long daysToEscheat) {
|
||||
@@ -273,9 +280,9 @@ public final class SavingsProductData implements Serializable {
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions,
|
||||
penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit,
|
||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax, taxGroup, taxGroupOptions, isDormancyTrackingActive, daysToInactive,
|
||||
daysToDormancy, daysToEscheat, accountMappingForPayment);
|
||||
minRequiredBalance, enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup, taxGroupOptions,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, accountMappingForPayment);
|
||||
}
|
||||
|
||||
public static SavingsProductData lookup(final Long id, final String name) {
|
||||
@@ -301,6 +308,8 @@ public final class SavingsProductData implements Serializable {
|
||||
final BigDecimal minOverdraftForInterestCalculation = null;
|
||||
final BigDecimal minRequiredBalance = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final BigDecimal maxAllowedLienLimit = null;
|
||||
final boolean lienAllowed = false;
|
||||
final BigDecimal minBalanceForInterestCalculation = null;
|
||||
final boolean withHoldTax = false;
|
||||
final TaxGroupData taxGroup = null;
|
||||
@@ -334,9 +343,9 @@ public final class SavingsProductData implements Serializable {
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions,
|
||||
penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit,
|
||||
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax, taxGroup, taxGroupOptions, isDormancyTrackingActive, daysToInactive,
|
||||
daysToDormancy, daysToEscheat, accountMappingForPayment);
|
||||
minRequiredBalance, enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup, taxGroupOptions,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, accountMappingForPayment);
|
||||
}
|
||||
|
||||
public static SavingsProductData createForInterestPosting(final Long id, final EnumOptionData accountingRule) {
|
||||
@@ -387,6 +396,8 @@ public final class SavingsProductData implements Serializable {
|
||||
this.overdraftLimit = null;
|
||||
this.minRequiredBalance = null;
|
||||
this.enforceMinRequiredBalance = false;
|
||||
this.maxAllowedLienLimit = null;
|
||||
this.lienAllowed = false;
|
||||
this.minBalanceForInterestCalculation = null;
|
||||
this.nominalAnnualInterestRateOverdraft = null;
|
||||
this.minOverdraftForInterestCalculation = null;
|
||||
@@ -418,10 +429,11 @@ public final class SavingsProductData implements Serializable {
|
||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings,
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings, final boolean allowOverdraft,
|
||||
final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
||||
final Collection<TaxGroupData> taxGroupOptions, final Boolean isDormancyTrackingActive, final Long daysToInactive,
|
||||
final Long daysToDormancy, final Long daysToEscheat, final String accountMappingForPayment) {
|
||||
final BigDecimal maxAllowedLienLimit, final boolean lienAllowed, final BigDecimal minBalanceForInterestCalculation,
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
||||
final boolean withHoldTax, final TaxGroupData taxGroup, final Collection<TaxGroupData> taxGroupOptions,
|
||||
final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy, final Long daysToEscheat,
|
||||
final String accountMappingForPayment) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
@@ -468,6 +480,8 @@ public final class SavingsProductData implements Serializable {
|
||||
this.overdraftLimit = overdraftLimit;
|
||||
this.minRequiredBalance = minRequiredBalance;
|
||||
this.enforceMinRequiredBalance = enforceMinRequiredBalance;
|
||||
this.maxAllowedLienLimit = maxAllowedLienLimit;
|
||||
this.lienAllowed = lienAllowed;
|
||||
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
|
||||
this.nominalAnnualInterestRateOverdraft = nominalAnnualInterestRateOverdraft;
|
||||
this.minOverdraftForInterestCalculation = minOverdraftForInterestCalculation;
|
||||
@@ -563,6 +577,10 @@ public final class SavingsProductData implements Serializable {
|
||||
return minRequiredBalance;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxAllowedLienLimit() {
|
||||
return maxAllowedLienLimit;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
+29
-3
@@ -34,8 +34,10 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interest
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.maxAllowedLienLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minOverdraftForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
@@ -62,6 +64,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SavingProductAccountingParams;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
@@ -103,6 +106,7 @@ public class SavingsProductDataValidator {
|
||||
daysToInactiveParamName, daysToEscheatParamName, allowOverdraftParamName, overdraftLimitParamName,
|
||||
nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
|
||||
SavingsApiConstants.minRequiredBalanceParamName, SavingsApiConstants.enforceMinRequiredBalanceParamName,
|
||||
SavingsApiConstants.maxAllowedLienLimitParamName, SavingsApiConstants.lienAllowedParamName,
|
||||
minBalanceForInterestCalculationParamName, withHoldTaxParamName, taxGroupIdParamName));
|
||||
|
||||
@Autowired
|
||||
@@ -340,9 +344,8 @@ public class SavingsProductDataValidator {
|
||||
baseDataValidator.reset().parameter(minBalanceForInterestCalculationParamName).value(minBalanceForInterestCalculation)
|
||||
.ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
validateTaxWithHoldingParams(baseDataValidator, element, true);
|
||||
|
||||
validateLienParams(baseDataValidator, element);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -545,7 +548,7 @@ public class SavingsProductDataValidator {
|
||||
}
|
||||
|
||||
validateTaxWithHoldingParams(baseDataValidator, element, false);
|
||||
|
||||
validateLienParams(baseDataValidator, element);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -650,6 +653,29 @@ public class SavingsProductDataValidator {
|
||||
|
||||
}
|
||||
|
||||
private void validateLienParams(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
if (this.fromApiJsonHelper.parameterExists(lienAllowedParamName, element)) {
|
||||
final Boolean lienAllowed = this.fromApiJsonHelper.extractBooleanNamed(lienAllowedParamName, element);
|
||||
baseDataValidator.reset().parameter(lienAllowedParamName).value(lienAllowed).ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(maxAllowedLienLimitParamName, element)) {
|
||||
final BigDecimal maxAllowedLienLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxAllowedLienLimitParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(maxAllowedLienLimitParamName).value(maxAllowedLienLimit).ignoreIfNull()
|
||||
.zeroOrPositiveAmount();
|
||||
}
|
||||
if (BooleanUtils.isTrue(this.fromApiJsonHelper.extractBooleanNamed(lienAllowedParamName, element))
|
||||
&& BooleanUtils.isTrue(this.fromApiJsonHelper.extractBooleanNamed(allowOverdraftParamName, element))) {
|
||||
final BigDecimal maxAllowedLienLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxAllowedLienLimitParamName,
|
||||
element);
|
||||
final BigDecimal overdraftLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(overdraftLimitParamName, element);
|
||||
if (overdraftLimit.compareTo(maxAllowedLienLimit) > 0) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("Overdraft.limit.can.not.be.greater.than.lien.limit");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateTaxWithHoldingParams(final DataValidatorBuilder baseDataValidator, final JsonElement element,
|
||||
final boolean isCreate) {
|
||||
if (this.fromApiJsonHelper.parameterExists(withHoldTaxParamName, element)) {
|
||||
|
||||
+48
-8
@@ -22,9 +22,11 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enforceMinRequiredBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.localeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.maxAllowedLienLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minOverdraftForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateOverdraftParamName;
|
||||
@@ -293,6 +295,12 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
@Column(name = "min_required_balance", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minRequiredBalance;
|
||||
|
||||
@Column(name = "is_lien_allowed", nullable = false)
|
||||
private boolean lienAllowed;
|
||||
|
||||
@Column(name = "max_allowed_lien_limit", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal maxAllowedLienLimit;
|
||||
|
||||
@Column(name = "on_hold_funds_derived", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal onHoldFunds;
|
||||
|
||||
@@ -337,7 +345,6 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "total_savings_amount_on_hold", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal savingsOnHoldAmount;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "account", orphanRemoval = true, fetch = FetchType.LAZY)
|
||||
protected List<InteropIdentifier> identifiers = new ArrayList<>();
|
||||
|
||||
@@ -354,15 +361,17 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final Set<SavingsAccountCharge> savingsAccountCharges,
|
||||
final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance,
|
||||
final BigDecimal minRequiredBalance, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax) {
|
||||
final BigDecimal minRequiredBalance, final BigDecimal maxAllowedLienLimit, final boolean lienAllowed,
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
||||
final boolean withHoldTax) {
|
||||
|
||||
final SavingsAccountStatusType status = SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL;
|
||||
return new SavingsAccount(client, group, product, fieldOfficer, accountNo, externalId, status, accountType, submittedOnDate,
|
||||
submittedBy, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeApplicableForTransfer, savingsAccountCharges, allowOverdraft, overdraftLimit, enforceMinRequiredBalance,
|
||||
minRequiredBalance, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax);
|
||||
minRequiredBalance, maxAllowedLienLimit, lienAllowed, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax);
|
||||
}
|
||||
|
||||
protected SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff fieldOfficer,
|
||||
@@ -377,8 +386,8 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
this(client, group, product, fieldOfficer, accountNo, externalId, status, accountType, submittedOnDate, submittedBy,
|
||||
nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeApplicableForTransfer, savingsAccountCharges, allowOverdraft, overdraftLimit, false, null, null, null,
|
||||
withHoldTax);
|
||||
withdrawalFeeApplicableForTransfer, savingsAccountCharges, allowOverdraft, overdraftLimit, false, null, null, false, null,
|
||||
null, withHoldTax);
|
||||
}
|
||||
|
||||
protected SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff savingsOfficer,
|
||||
@@ -390,8 +399,8 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final Set<SavingsAccountCharge> savingsAccountCharges,
|
||||
final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance,
|
||||
final BigDecimal minRequiredBalance, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||
final BigDecimal minOverdraftForInterestCalculation, boolean withHoldTax) {
|
||||
final BigDecimal minRequiredBalance, final BigDecimal maxAllowedLienLimit, final boolean lienAllowed,
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation, boolean withHoldTax) {
|
||||
this.client = client;
|
||||
this.group = group;
|
||||
this.product = product;
|
||||
@@ -434,6 +443,8 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
|
||||
this.enforceMinRequiredBalance = enforceMinRequiredBalance;
|
||||
this.minRequiredBalance = minRequiredBalance;
|
||||
this.lienAllowed = lienAllowed;
|
||||
this.maxAllowedLienLimit = maxAllowedLienLimit;
|
||||
this.minBalanceForInterestCalculation = product.minBalanceForInterestCalculation();
|
||||
// this.savingsOfficerHistory = null;
|
||||
this.withHoldTax = withHoldTax;
|
||||
@@ -1751,6 +1762,18 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.minRequiredBalance = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(lienAllowedParamName, this.lienAllowed)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(lienAllowedParamName);
|
||||
actualChanges.put(lienAllowedParamName, newValue);
|
||||
this.lienAllowed = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(maxAllowedLienLimitParamName, this.maxAllowedLienLimit)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(maxAllowedLienLimitParamName);
|
||||
actualChanges.put(maxAllowedLienLimitParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.maxAllowedLienLimit = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(withHoldTaxParamName, this.withHoldTax)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(withHoldTaxParamName);
|
||||
@@ -1950,6 +1973,10 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
return this.enforceMinRequiredBalance;
|
||||
}
|
||||
|
||||
public Boolean getLienAllowed() {
|
||||
return this.lienAllowed;
|
||||
}
|
||||
|
||||
public void unassignSavingsOfficer() {
|
||||
this.savingsOfficer = null;
|
||||
}
|
||||
@@ -3429,6 +3456,11 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
.subtract(this.getSavingsHoldAmount());
|
||||
}
|
||||
|
||||
public BigDecimal getWithdrawableBalanceWithLien() {
|
||||
return getAccountBalance().subtract(minRequiredBalanceDerived(getCurrency()).getAmount()).subtract(this.getOnHoldFunds())
|
||||
.subtract(this.getSavingsHoldAmount());
|
||||
}
|
||||
|
||||
public BigDecimal getWithdrawableBalanceWithoutMinimumBalance() {
|
||||
return getAccountBalance().subtract(this.getOnHoldFunds()).subtract(this.getSavingsHoldAmount());
|
||||
}
|
||||
@@ -3833,6 +3865,14 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
return this.enforceMinRequiredBalance;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxAllowedLienLimit() {
|
||||
return this.maxAllowedLienLimit;
|
||||
}
|
||||
|
||||
public boolean isLienAllowed() {
|
||||
return this.lienAllowed;
|
||||
}
|
||||
|
||||
public BigDecimal getMinBalanceForInterestCalculation() {
|
||||
return this.minBalanceForInterestCalculation;
|
||||
}
|
||||
|
||||
+21
-4
@@ -30,8 +30,10 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interest
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.maxAllowedLienLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minOverdraftForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
@@ -294,6 +296,20 @@ public class SavingsAccountAssembler {
|
||||
minRequiredBalance = product.minRequiredBalance();
|
||||
}
|
||||
|
||||
boolean lienAllowed = false;
|
||||
if (command.parameterExists(lienAllowedParamName)) {
|
||||
lienAllowed = command.booleanPrimitiveValueOfParameterNamed(lienAllowedParamName);
|
||||
} else {
|
||||
lienAllowed = product.isLienAllowed();
|
||||
}
|
||||
|
||||
BigDecimal maxAllowedLienLimit = BigDecimal.ZERO;
|
||||
if (command.parameterExists(maxAllowedLienLimitParamName)) {
|
||||
maxAllowedLienLimit = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(maxAllowedLienLimitParamName);
|
||||
} else {
|
||||
maxAllowedLienLimit = product.maxAllowedLienLimit();
|
||||
}
|
||||
|
||||
boolean withHoldTax = product.withHoldTax();
|
||||
if (command.parameterExists(withHoldTaxParamName)) {
|
||||
withHoldTax = command.booleanPrimitiveValueOfParameterNamed(withHoldTaxParamName);
|
||||
@@ -306,8 +322,8 @@ public class SavingsAccountAssembler {
|
||||
externalId, accountType, submittedOnDate, submittedBy, interestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, charges, allowOverdraft,
|
||||
overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax);
|
||||
overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, maxAllowedLienLimit, lienAllowed,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax);
|
||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
|
||||
|
||||
account.validateNewApplicationState(DateUtils.getLocalDateOfTenant(), SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||
@@ -423,8 +439,9 @@ public class SavingsAccountAssembler {
|
||||
product.interestPostingPeriodType(), product.interestCalculationType(), product.interestCalculationDaysInYearType(),
|
||||
product.minRequiredOpeningBalance(), product.lockinPeriodFrequency(), product.lockinPeriodFrequencyType(),
|
||||
product.isWithdrawalFeeApplicableForTransfer(), charges, product.isAllowOverdraft(), product.overdraftLimit(),
|
||||
product.isMinRequiredBalanceEnforced(), product.minRequiredBalance(), product.nominalAnnualInterestRateOverdraft(),
|
||||
product.minOverdraftForInterestCalculation(), product.withHoldTax());
|
||||
product.isMinRequiredBalanceEnforced(), product.minRequiredBalance(), product.maxAllowedLienLimit(),
|
||||
product.isLienAllowed(), product.nominalAnnualInterestRateOverdraft(), product.minOverdraftForInterestCalculation(),
|
||||
product.withHoldTax());
|
||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
|
||||
|
||||
account.validateNewApplicationState(DateUtils.getLocalDateOfTenant(), SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||
|
||||
+4
@@ -24,6 +24,7 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.portfolio.savings.SavingsTransactionBooleanValues;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
|
||||
public interface SavingsAccountDomainService {
|
||||
|
||||
@@ -43,4 +44,7 @@ public interface SavingsAccountDomainService {
|
||||
|
||||
SavingsAccountTransaction handleReversal(SavingsAccount account, SavingsAccountTransaction savingsAccountTransaction,
|
||||
boolean backdatedTxnsAllowedTill);
|
||||
|
||||
SavingsAccountTransaction handleHold(SavingsAccount account, AppUser createdUser, BigDecimal amount, LocalDate transactionDate,
|
||||
Boolean lienAllowed);
|
||||
}
|
||||
|
||||
+13
@@ -36,6 +36,7 @@ import org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BusinessEntity;
|
||||
import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BusinessEvents;
|
||||
@@ -219,6 +220,18 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
return deposit;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public SavingsAccountTransaction handleHold(final SavingsAccount account, final AppUser createdUser, BigDecimal amount,
|
||||
LocalDate transactionDate, Boolean lienAllowed) {
|
||||
final PaymentDetail paymentDetails = null;
|
||||
Date createdDate = new Date();
|
||||
|
||||
SavingsAccountTransaction transaction = SavingsAccountTransaction.holdAmount(account, account.office(), paymentDetails,
|
||||
transactionDate, Money.of(account.getCurrency(), amount), createdDate, createdUser, lienAllowed);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingsAccountTransaction handleDividendPayout(final SavingsAccount account, final LocalDate transactionDate,
|
||||
final BigDecimal transactionAmount, final boolean backdatedTxnsAllowedTill) {
|
||||
|
||||
+45
-23
@@ -140,6 +140,9 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
@Column(name = "original_transaction_id")
|
||||
private Long originalTxnId;
|
||||
|
||||
@Column(name = "is_lien_transaction")
|
||||
private Boolean lienTransaction;
|
||||
|
||||
SavingsAccountTransaction() {
|
||||
this.dateOf = null;
|
||||
this.typeOf = null;
|
||||
@@ -150,8 +153,9 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
final PaymentDetail paymentDetail, final LocalDate date, final Money amount, Date createdDate, final AppUser appUser) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.DEPOSIT.getValue(), date,
|
||||
createdDate, amount, isReversed, appUser, isManualTransaction);
|
||||
createdDate, amount, isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction deposit(final SavingsAccount savingsAccount, final Office office,
|
||||
@@ -159,54 +163,61 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
final SavingsAccountTransactionType savingsAccountTransactionType) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, savingsAccountTransactionType.getValue(), date,
|
||||
createdDate, amount, isReversed, appUser, isManualTransaction);
|
||||
createdDate, amount, isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction withdrawal(final SavingsAccount savingsAccount, final Office office,
|
||||
final PaymentDetail paymentDetail, final LocalDate date, final Money amount, Date createdDate, final AppUser appUser) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.WITHDRAWAL.getValue(),
|
||||
date, createdDate, amount, isReversed, appUser, isManualTransaction);
|
||||
date, createdDate, amount, isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction interestPosting(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
final Money amount, final boolean isManualTransaction) {
|
||||
final boolean isReversed = false;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.INTEREST_POSTING.getValue(), date,
|
||||
amount, isReversed, null, isManualTransaction);
|
||||
amount, isReversed, null, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction overdraftInterest(final SavingsAccount savingsAccount, final Office office,
|
||||
final LocalDate date, final Money amount, final boolean isManualTransaction) {
|
||||
final boolean isReversed = false;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue(), date,
|
||||
amount, isReversed, null, isManualTransaction);
|
||||
amount, isReversed, null, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction withdrawalFee(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
final Money amount, final AppUser appUser) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue(), date, amount,
|
||||
isReversed, appUser, isManualTransaction);
|
||||
isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction annualFee(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
final Money amount, final AppUser appUser) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.ANNUAL_FEE.getValue(), date, amount,
|
||||
isReversed, appUser, isManualTransaction);
|
||||
isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction charge(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
final Money amount, final AppUser appUser) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.PAY_CHARGE.getValue(), date, amount,
|
||||
isReversed, appUser, isManualTransaction);
|
||||
isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction from(final Integer transactionTypeEnum, final LocalDate transactionDate,
|
||||
@@ -221,8 +232,9 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
final Money amount, final AppUser appUser) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.WAIVE_CHARGES.getValue(), date, amount,
|
||||
isReversed, appUser, isManualTransaction);
|
||||
isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction initiateTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
@@ -230,9 +242,10 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail,
|
||||
SavingsAccountTransactionType.INITIATE_TRANSFER.getValue(), date, new Date(),
|
||||
savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, isManualTransaction);
|
||||
savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction approveTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
@@ -240,9 +253,10 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail,
|
||||
SavingsAccountTransactionType.APPROVE_TRANSFER.getValue(), date, new Date(),
|
||||
savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, isManualTransaction);
|
||||
savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction withdrawTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
@@ -250,17 +264,20 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail,
|
||||
SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue(), date, new Date(),
|
||||
savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, isManualTransaction);
|
||||
savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction withHoldTax(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
final Money amount, final Map<TaxComponent, BigDecimal> taxDetails) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
final Boolean lienTransaction = false;
|
||||
SavingsAccountTransaction accountTransaction = new SavingsAccountTransaction(savingsAccount, office,
|
||||
SavingsAccountTransactionType.WITHHOLD_TAX.getValue(), date, amount, isReversed, null, isManualTransaction);
|
||||
SavingsAccountTransactionType.WITHHOLD_TAX.getValue(), date, amount, isReversed, null, isManualTransaction,
|
||||
lienTransaction);
|
||||
updateTaxDetails(taxDetails, accountTransaction);
|
||||
return accountTransaction;
|
||||
}
|
||||
@@ -269,9 +286,10 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
final boolean accountTransaction) {
|
||||
final boolean isReversed = false;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Boolean lienTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, savingsAccount.office(), paymentDetail,
|
||||
SavingsAccountTransactionType.ESCHEAT.getValue(), date, new Date(), savingsAccount.getSummary().getAccountBalance(),
|
||||
isReversed, appUser, accountTransaction);
|
||||
isReversed, appUser, accountTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static void updateTaxDetails(final Map<TaxComponent, BigDecimal> taxDetails,
|
||||
@@ -287,25 +305,27 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
public static SavingsAccountTransaction copyTransaction(SavingsAccountTransaction accountTransaction) {
|
||||
return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail,
|
||||
accountTransaction.typeOf, accountTransaction.transactionLocalDate(), accountTransaction.createdDate,
|
||||
accountTransaction.amount, accountTransaction.reversed, accountTransaction.appUser, accountTransaction.isManualTransaction);
|
||||
accountTransaction.amount, accountTransaction.reversed, accountTransaction.appUser, accountTransaction.isManualTransaction,
|
||||
accountTransaction.lienTransaction);
|
||||
}
|
||||
|
||||
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final Integer typeOf,
|
||||
final LocalDate transactionLocalDate, final Money amount, final boolean isReversed, final AppUser appUser,
|
||||
final boolean isManualTransaction) {
|
||||
this(savingsAccount, office, null, typeOf, transactionLocalDate, new Date(), amount, isReversed, appUser, isManualTransaction);
|
||||
final boolean isManualTransaction, final Boolean lienTransaction) {
|
||||
this(savingsAccount, office, null, typeOf, transactionLocalDate, new Date(), amount, isReversed, appUser, isManualTransaction,
|
||||
lienTransaction);
|
||||
}
|
||||
|
||||
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail,
|
||||
final Integer typeOf, final LocalDate transactionLocalDate, final Date createdDate, final Money amount,
|
||||
final boolean isReversed, final AppUser appUser, final boolean isManualTransaction) {
|
||||
final boolean isReversed, final AppUser appUser, final boolean isManualTransaction, final Boolean lienTransaction) {
|
||||
this(savingsAccount, office, paymentDetail, typeOf, transactionLocalDate, createdDate, amount.getAmount(), isReversed, appUser,
|
||||
isManualTransaction);
|
||||
isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail,
|
||||
final Integer typeOf, final LocalDate transactionLocalDate, final Date createdDate, final BigDecimal amount,
|
||||
final boolean isReversed, final AppUser appUser, final boolean isManualTransaction) {
|
||||
final boolean isReversed, final AppUser appUser, final boolean isManualTransaction, final Boolean lienTransaction) {
|
||||
this.savingsAccount = savingsAccount;
|
||||
this.office = office;
|
||||
this.typeOf = typeOf;
|
||||
@@ -316,6 +336,7 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
this.createdDate = createdDate;
|
||||
this.appUser = appUser;
|
||||
this.isManualTransaction = isManualTransaction;
|
||||
this.lienTransaction = lienTransaction;
|
||||
}
|
||||
|
||||
private SavingsAccountTransaction(final Integer transactionTypeEnum, final LocalDate transactionDate, final BigDecimal amount,
|
||||
@@ -337,18 +358,19 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction holdAmount(final SavingsAccount savingsAccount, final Office office,
|
||||
final PaymentDetail paymentDetail, final LocalDate date, final Money amount, Date createdDate, final AppUser appUser) {
|
||||
final PaymentDetail paymentDetail, final LocalDate date, final Money amount, Date createdDate, final AppUser appUser,
|
||||
final Boolean lienTransaction) {
|
||||
final boolean isReversed = false;
|
||||
final boolean isManualTransaction = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.AMOUNT_HOLD.getValue(),
|
||||
date, createdDate, amount, isReversed, appUser, isManualTransaction);
|
||||
date, createdDate, amount, isReversed, appUser, isManualTransaction, lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction releaseAmount(SavingsAccountTransaction accountTransaction, LocalDate transactionDate,
|
||||
Date createdDate, final AppUser appUser) {
|
||||
return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail,
|
||||
SavingsAccountTransactionType.AMOUNT_RELEASE.getValue(), transactionDate, createdDate, accountTransaction.amount,
|
||||
accountTransaction.reversed, appUser, accountTransaction.isManualTransaction);
|
||||
accountTransaction.reversed, appUser, accountTransaction.isManualTransaction, accountTransaction.lienTransaction);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction reversal(SavingsAccountTransaction accountTransaction) {
|
||||
|
||||
+43
-12
@@ -35,9 +35,11 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interest
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.localeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.maxAllowedLienLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minOverdraftForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName;
|
||||
@@ -179,6 +181,12 @@ public class SavingsProduct extends AbstractPersistableCustom {
|
||||
@Column(name = "min_required_balance", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minRequiredBalance;
|
||||
|
||||
@Column(name = "is_lien_allowed", nullable = false)
|
||||
private boolean lienAllowed;
|
||||
|
||||
@Column(name = "max_allowed_lien_limit", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal maxAllowedLienLimit;
|
||||
|
||||
@Column(name = "min_balance_for_interest_calculation", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minBalanceForInterestCalculation;
|
||||
|
||||
@@ -209,17 +217,17 @@ public class SavingsProduct extends AbstractPersistableCustom {
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges,
|
||||
final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance,
|
||||
final BigDecimal minRequiredBalance, final BigDecimal minBalanceForInterestCalculation,
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation, boolean withHoldTax,
|
||||
TaxGroup taxGroup, final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy,
|
||||
final Long daysToEscheat) {
|
||||
final BigDecimal minRequiredBalance, final boolean lienAllowed, final BigDecimal maxAllowedLienLimit,
|
||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||
final BigDecimal minOverdraftForInterestCalculation, boolean withHoldTax, TaxGroup taxGroup,
|
||||
final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy, final Long daysToEscheat) {
|
||||
|
||||
return new SavingsProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges,
|
||||
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, minBalanceForInterestCalculation,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup, isDormancyTrackingActive,
|
||||
daysToInactive, daysToDormancy, daysToEscheat);
|
||||
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, lienAllowed, maxAllowedLienLimit,
|
||||
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||
taxGroup, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||
}
|
||||
|
||||
protected SavingsProduct() {
|
||||
@@ -238,7 +246,7 @@ public class SavingsProduct extends AbstractPersistableCustom {
|
||||
this(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit,
|
||||
false, null, minBalanceForInterestCalculation, null, null, withHoldTax, taxGroup, null, null, null, null);
|
||||
false, null, false, null, minBalanceForInterestCalculation, null, null, withHoldTax, taxGroup, null, null, null, null);
|
||||
}
|
||||
|
||||
protected SavingsProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency,
|
||||
@@ -248,10 +256,10 @@ public class SavingsProduct extends AbstractPersistableCustom {
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges,
|
||||
final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance,
|
||||
final BigDecimal minRequiredBalance, BigDecimal minBalanceForInterestCalculation,
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
||||
final boolean withHoldTax, final TaxGroup taxGroup, final Boolean isDormancyTrackingActive, final Long daysToInactive,
|
||||
final Long daysToDormancy, final Long daysToEscheat) {
|
||||
final BigDecimal minRequiredBalance, final boolean lienAllowed, final BigDecimal maxAllowedLienLimit,
|
||||
BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroup taxGroup,
|
||||
final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy, final Long daysToEscheat) {
|
||||
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
@@ -293,6 +301,8 @@ public class SavingsProduct extends AbstractPersistableCustom {
|
||||
|
||||
this.enforceMinRequiredBalance = enforceMinRequiredBalance;
|
||||
this.minRequiredBalance = minRequiredBalance;
|
||||
this.lienAllowed = lienAllowed;
|
||||
this.maxAllowedLienLimit = maxAllowedLienLimit;
|
||||
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
|
||||
this.withHoldTax = withHoldTax;
|
||||
this.taxGroup = taxGroup;
|
||||
@@ -540,6 +550,19 @@ public class SavingsProduct extends AbstractPersistableCustom {
|
||||
this.minRequiredBalance = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(lienAllowedParamName, this.lienAllowed)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(lienAllowedParamName);
|
||||
actualChanges.put(lienAllowedParamName, newValue);
|
||||
this.lienAllowed = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(maxAllowedLienLimitParamName, this.maxAllowedLienLimit)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(maxAllowedLienLimitParamName);
|
||||
actualChanges.put(maxAllowedLienLimitParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.maxAllowedLienLimit = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minBalanceForInterestCalculationParamName,
|
||||
this.minBalanceForInterestCalculation)) {
|
||||
final BigDecimal newValue = command
|
||||
@@ -689,6 +712,14 @@ public class SavingsProduct extends AbstractPersistableCustom {
|
||||
return this.enforceMinRequiredBalance;
|
||||
}
|
||||
|
||||
public BigDecimal maxAllowedLienLimit() {
|
||||
return this.maxAllowedLienLimit;
|
||||
}
|
||||
|
||||
public boolean isLienAllowed() {
|
||||
return this.lienAllowed;
|
||||
}
|
||||
|
||||
public Set<Charge> charges() {
|
||||
return this.charges;
|
||||
}
|
||||
|
||||
+15
-3
@@ -34,8 +34,10 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interest
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.maxAllowedLienLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minOverdraftForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName;
|
||||
@@ -170,6 +172,16 @@ public class SavingsProductAssembler {
|
||||
if (command.parameterExists(minRequiredBalanceParamName)) {
|
||||
minRequiredBalance = command.bigDecimalValueOfParameterNamed(minRequiredBalanceParamName);
|
||||
}
|
||||
|
||||
boolean lienAllowed = false;
|
||||
if (command.parameterExists(lienAllowedParamName)) {
|
||||
lienAllowed = command.booleanPrimitiveValueOfParameterNamed(lienAllowedParamName);
|
||||
}
|
||||
|
||||
BigDecimal maxAllowedLienLimit = BigDecimal.ZERO;
|
||||
if (command.parameterExists(maxAllowedLienLimitParamName)) {
|
||||
maxAllowedLienLimit = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(maxAllowedLienLimitParamName);
|
||||
}
|
||||
final BigDecimal minBalanceForInterestCalculation = command
|
||||
.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minBalanceForInterestCalculationParamName);
|
||||
|
||||
@@ -184,9 +196,9 @@ public class SavingsProductAssembler {
|
||||
return SavingsProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges,
|
||||
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, minBalanceForInterestCalculation,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup, isDormancyTrackingActive,
|
||||
daysToInactive, daysToDormancy, daysToEscheat);
|
||||
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, lienAllowed, maxAllowedLienLimit,
|
||||
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||
taxGroup, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||
}
|
||||
|
||||
public Set<Charge> assembleListOfSavingsProductCharges(final JsonCommand command, final String savingsProductCurrencyCode) {
|
||||
|
||||
+28
-12
@@ -332,6 +332,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sa.min_balance_for_interest_calculation as minBalanceForInterestCalculation,");
|
||||
sqlBuilder.append("sa.min_required_balance as minRequiredBalance, ");
|
||||
sqlBuilder.append("sa.enforce_min_required_balance as enforceMinRequiredBalance, ");
|
||||
sqlBuilder.append("sa.max_allowed_lien_limit as maxAllowedLienLimit, ");
|
||||
sqlBuilder.append("sa.is_lien_allowed as lienAllowed, ");
|
||||
sqlBuilder.append("sa.on_hold_funds_derived as onHoldFunds, ");
|
||||
sqlBuilder.append("sa.withhold_tax as withHoldTax, ");
|
||||
sqlBuilder.append("sa.total_withhold_tax_derived as totalWithholdTax, ");
|
||||
@@ -575,14 +577,17 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
|
||||
final BigDecimal minRequiredBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredBalance");
|
||||
final boolean enforceMinRequiredBalance = rs.getBoolean("enforceMinRequiredBalance");
|
||||
final BigDecimal maxAllowedLienLimit = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "maxAllowedLienLimit");
|
||||
final boolean lienAllowed = rs.getBoolean("lienAllowed");
|
||||
savingsAccountData = SavingsAccountData.instance(id, accountNo, depositType, externalId, null, null, null, null,
|
||||
productId, null, null, null, status, subStatus, null, timeline, currency, nominalAnnualInterestRate,
|
||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeForTransfers, summary, allowOverdraft, overdraftLimit, minRequiredBalance,
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax, taxGroupData, lastActiveTransactionDate,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, onHoldAmount);
|
||||
enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation, onHoldFunds,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroupData,
|
||||
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat,
|
||||
onHoldAmount);
|
||||
|
||||
savingsAccountData.setClientData(clientData);
|
||||
savingsAccountData.setGroupGeneralData(groupGeneralData);
|
||||
@@ -811,6 +816,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sa.min_balance_for_interest_calculation as minBalanceForInterestCalculation,");
|
||||
sqlBuilder.append("sa.min_required_balance as minRequiredBalance, ");
|
||||
sqlBuilder.append("sa.enforce_min_required_balance as enforceMinRequiredBalance, ");
|
||||
sqlBuilder.append("sa.max_allowed_lien_limit as maxAllowedLienLimit, ");
|
||||
sqlBuilder.append("sa.is_lien_allowed as lienAllowed, ");
|
||||
sqlBuilder.append("sa.on_hold_funds_derived as onHoldFunds, ");
|
||||
sqlBuilder.append("sa.withhold_tax as withHoldTax, ");
|
||||
sqlBuilder.append("sa.total_withhold_tax_derived as totalWithholdTax, ");
|
||||
@@ -991,6 +998,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final BigDecimal minRequiredBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredBalance");
|
||||
final boolean enforceMinRequiredBalance = rs.getBoolean("enforceMinRequiredBalance");
|
||||
|
||||
final BigDecimal maxAllowedLienLimit = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "maxAllowedLienLimit");
|
||||
final boolean lienAllowed = rs.getBoolean("lienAllowed");
|
||||
|
||||
/*
|
||||
* final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
*
|
||||
@@ -1057,9 +1067,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeForTransfers, summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||
minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation,
|
||||
withHoldTax, taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
|
||||
daysToEscheat, onHoldAmount);
|
||||
maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax, taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive,
|
||||
daysToInactive, daysToDormancy, daysToEscheat, onHoldAmount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1320,7 +1330,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append(" au.username as submittedByUsername, ");
|
||||
sqlBuilder.append(" nt.note as transactionNote, ");
|
||||
sqlBuilder.append("tr.running_balance_derived as runningBalance, tr.is_reversed as reversed,");
|
||||
sqlBuilder.append("tr.is_reversal as isReversal, tr.original_transaction_id as originalTransactionId,");
|
||||
sqlBuilder.append(
|
||||
"tr.is_reversal as isReversal, tr.original_transaction_id as originalTransactionId, tr.is_lien_transaction as lienTransaction, ");
|
||||
sqlBuilder.append("fromtran.id as fromTransferId, fromtran.is_reversed as fromTransferReversed,");
|
||||
sqlBuilder.append("fromtran.transaction_date as fromTransferDate, fromtran.amount as fromTransferAmount,");
|
||||
sqlBuilder.append("fromtran.description as fromTransferDescription,");
|
||||
@@ -1368,6 +1379,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final boolean reversed = rs.getBoolean("reversed");
|
||||
final boolean isReversal = rs.getBoolean("isReversal");
|
||||
final Long originalTransactionId = rs.getLong("originalTransactionId");
|
||||
final Boolean lienTransaction = rs.getBoolean("lienTransaction");
|
||||
|
||||
final Long savingsId = rs.getLong("savingsId");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
@@ -1422,7 +1434,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final String note = rs.getString("transactionNote");
|
||||
return SavingsAccountTransactionData.create(id, transactionType, paymentDetailData, savingsId, accountNo, date, currency,
|
||||
amount, outstandingChargeAmount, runningBalance, reversed, transfer, submittedOnDate, postInterestAsOn,
|
||||
submittedByUsername, note, isReversal, originalTransactionId, releaseTransactionId, reasonForBlock);
|
||||
submittedByUsername, note, isReversal, originalTransactionId, lienTransaction, releaseTransactionId, reasonForBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1510,7 +1522,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
// ");
|
||||
// sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay ");
|
||||
sqlBuilder.append("sp.min_required_balance as minRequiredBalance, ");
|
||||
sqlBuilder.append("sp.enforce_min_required_balance as enforceMinRequiredBalance ");
|
||||
sqlBuilder.append("sp.enforce_min_required_balance as enforceMinRequiredBalance, ");
|
||||
sqlBuilder.append("sp.max_allowed_lien_limit as maxAllowedLienLimit, ");
|
||||
sqlBuilder.append("sp.is_lien_allowed as lienAllowed ");
|
||||
sqlBuilder.append("from m_savings_product sp ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
||||
sqlBuilder.append("left join m_tax_group tg on tg.id = sp.tax_group_id ");
|
||||
@@ -1580,6 +1594,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
|
||||
final BigDecimal minRequiredBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredBalance");
|
||||
final boolean enforceMinRequiredBalance = rs.getBoolean("enforceMinRequiredBalance");
|
||||
final BigDecimal maxAllowedLienLimit = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "maxAllowedLienLimit");
|
||||
final boolean lienAllowed = rs.getBoolean("lienAllowed");
|
||||
final BigDecimal minBalanceForInterestCalculation = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
|
||||
"minBalanceForInterestCalculation");
|
||||
|
||||
@@ -1639,9 +1655,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeForTransfers, summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||
minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation,
|
||||
withHoldTax, taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
|
||||
daysToEscheat, savingsAmountOnHold);
|
||||
maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax, taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive,
|
||||
daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -23,7 +23,9 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.amountParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.chargeIdParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.transactionAmountParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.transactionDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawBalanceParamName;
|
||||
|
||||
@@ -1811,6 +1813,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
final AppUser submittedBy = this.context.authenticatedUser();
|
||||
final boolean backdatedTxnsAllowedTill = this.savingAccountAssembler.getPivotConfigStatus();
|
||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId, backdatedTxnsAllowedTill);
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed(transactionDateParamName);
|
||||
final boolean lienAllowed = command.booleanObjectValueOfParameterNamed(lienAllowedParamName);
|
||||
|
||||
checkClientOrGroupActive(account);
|
||||
|
||||
@@ -1823,11 +1827,11 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
runningBalance = runningBalance.minus(amount);
|
||||
}
|
||||
|
||||
this.savingsAccountTransactionDataValidator.validateHoldAndAssembleForm(command.json(), account, submittedBy,
|
||||
backdatedTxnsAllowedTill);
|
||||
SavingsAccountTransaction transaction = this.savingsAccountDomainService.handleHold(account, getAppUserIfPresent(), amount,
|
||||
transactionDate, lienAllowed);
|
||||
account.holdAmount(amount);
|
||||
|
||||
SavingsAccountTransaction transaction = this.savingsAccountTransactionDataValidator.validateHoldAndAssembleForm(command.json(),
|
||||
account, submittedBy, backdatedTxnsAllowedTill);
|
||||
|
||||
transaction.updateRunningBalance(runningBalance);
|
||||
|
||||
final String reasonForBlock = command.stringValueOfParameterNamed(SavingsApiConstants.reasonForBlockParamName);
|
||||
|
||||
+7
-3
@@ -129,6 +129,8 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
sqlBuilder.append("sp.min_overdraft_for_interest_calculation as minOverdraftForInterestCalculation, ");
|
||||
sqlBuilder.append("sp.min_required_balance as minRequiredBalance, ");
|
||||
sqlBuilder.append("sp.enforce_min_required_balance as enforceMinRequiredBalance, ");
|
||||
sqlBuilder.append("sp.max_allowed_lien_limit as maxAllowedLienLimit, ");
|
||||
sqlBuilder.append("sp.is_lien_allowed as lienAllowed, ");
|
||||
sqlBuilder.append("sp.min_balance_for_interest_calculation as minBalanceForInterestCalculation,");
|
||||
sqlBuilder.append("sp.accounting_type as accountingType, ");
|
||||
sqlBuilder.append("sp.withhold_tax as withHoldTax,");
|
||||
@@ -203,6 +205,8 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
|
||||
final BigDecimal minRequiredBalance = rs.getBigDecimal("minRequiredBalance");
|
||||
final boolean enforceMinRequiredBalance = rs.getBoolean("enforceMinRequiredBalance");
|
||||
final BigDecimal maxAllowedLienLimit = rs.getBigDecimal("maxAllowedLienLimit");
|
||||
final boolean lienAllowed = rs.getBoolean("lienAllowed");
|
||||
final BigDecimal minBalanceForInterestCalculation = rs.getBigDecimal("minBalanceForInterestCalculation");
|
||||
|
||||
final boolean withHoldTax = rs.getBoolean("withHoldTax");
|
||||
@@ -221,9 +225,9 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
return SavingsProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate,
|
||||
compoundingInterestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
||||
accountingRuleType, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||
taxGroupData, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||
accountingRuleType, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance, maxAllowedLienLimit,
|
||||
lienAllowed, minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation,
|
||||
withHoldTax, taxGroupData, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,4 +29,5 @@
|
||||
<include file="parts/0007_product_loan_higher_than_applied_loan_amount_management.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0008_loan_charge_add_external_id.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0009_hold_reason_savings_account.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0010_lien_allowed_on_savings_account_products.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<changeSet author="fineract" id="1">
|
||||
<addColumn tableName="m_savings_account">
|
||||
<column defaultValueComputed="NULL" name="max_allowed_lien_limit" type="DECIMAL(19, 6)"/>
|
||||
<column defaultValueBoolean="false" name="is_lien_allowed" type="boolean">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<addColumn tableName="m_savings_product">
|
||||
<column defaultValueComputed="NULL" name="max_allowed_lien_limit" type="DECIMAL(19, 6)"/>
|
||||
<column defaultValueBoolean="false" name="is_lien_allowed" type="boolean">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<addColumn tableName="m_savings_account_transaction">
|
||||
<column defaultValueBoolean="false" name="is_lien_transaction" type="boolean">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+304
-19
@@ -2017,6 +2017,68 @@ public class ClientSavingsIntegrationTest {
|
||||
enforceMinRequiredBalance, allowOverdraft, taxGroupId, false);
|
||||
}
|
||||
|
||||
// LienAtProductLevel
|
||||
private Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String minOpenningBalance, String minBalanceForInterestCalculation, final boolean enforceMinRequiredBalance,
|
||||
final boolean allowOverDraft, final boolean lienAllowed) {
|
||||
|
||||
LOG.info("------------------------------CREATING NEW SAVINGS PRODUCT WITH LIEN---------------------------------------");
|
||||
SavingsProductHelper savingsProductHelper = new SavingsProductHelper();
|
||||
if (lienAllowed) {
|
||||
final String maxAllowedLienLimit = "2000.0";
|
||||
savingsProductHelper.withLienAllowed(maxAllowedLienLimit);
|
||||
}
|
||||
if (enforceMinRequiredBalance) {
|
||||
final String minRequiredBalance = "100.0";
|
||||
savingsProductHelper.withMinRequiredBalance(minRequiredBalance);
|
||||
savingsProductHelper.withEnforceMinRequiredBalance("true");
|
||||
}
|
||||
if (allowOverDraft) {
|
||||
final String overDraftLimit = "500.0";
|
||||
savingsProductHelper.withOverDraft(overDraftLimit);
|
||||
}
|
||||
final String savingsProductJSON = savingsProductHelper.withInterestCompoundingPeriodTypeAsDaily()
|
||||
|
||||
.withInterestPostingPeriodTypeAsMonthly()
|
||||
|
||||
.withInterestCalculationPeriodTypeAsDailyBalance()
|
||||
|
||||
.withMinBalanceForInterestCalculation(minBalanceForInterestCalculation)
|
||||
|
||||
.withMinimumOpenningBalance(minOpenningBalance).build();
|
||||
|
||||
return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec);
|
||||
}
|
||||
|
||||
// LienAtProductlevel with Overdraft Limit > Lien Limit
|
||||
private Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String minOpenningBalance, String minBalanceForInterestCalculation, final boolean enforceMinRequiredBalance,
|
||||
final boolean allowOverDraft, final String overDraftLimit, final boolean lienAllowed, final String lienAllowedLimit) {
|
||||
LOG.info("------------------------------CREATING NEW SAVINGS PRODUCT WITH LIEN---------------------------------------");
|
||||
SavingsProductHelper savingsProductHelper = new SavingsProductHelper();
|
||||
if (lienAllowed) {
|
||||
savingsProductHelper.withLienAllowed(lienAllowedLimit);
|
||||
}
|
||||
if (enforceMinRequiredBalance) {
|
||||
final String minRequiredBalance = "100.0";
|
||||
savingsProductHelper.withMinRequiredBalance(minRequiredBalance);
|
||||
savingsProductHelper.withEnforceMinRequiredBalance("true");
|
||||
}
|
||||
if (allowOverDraft) {
|
||||
savingsProductHelper.withOverDraft(overDraftLimit);
|
||||
}
|
||||
final String savingsProductJSON = savingsProductHelper.withInterestCompoundingPeriodTypeAsDaily()
|
||||
|
||||
.withInterestPostingPeriodTypeAsMonthly()
|
||||
|
||||
.withInterestCalculationPeriodTypeAsDailyBalance()
|
||||
|
||||
.withMinBalanceForInterestCalculation(minBalanceForInterestCalculation)
|
||||
|
||||
.withMinimumOpenningBalance(minOpenningBalance).build();
|
||||
return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec);
|
||||
}
|
||||
|
||||
private Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String minOpenningBalance, String minBalanceForInterestCalculation, String minRequiredBalance,
|
||||
String enforceMinRequiredBalance, final boolean allowOverdraft, final String taxGroupId, boolean withDormancy) {
|
||||
@@ -2177,26 +2239,23 @@ public class ClientSavingsIntegrationTest {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testSavingsAccountLienStatus() {
|
||||
|
||||
public void testSavingsAccountLienAllowedAtProductLevelWithEnforceBalance() {
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
|
||||
SavingsAccountHelper savingsAccountHelperValidationError = new SavingsAccountHelper(this.requestSpec,
|
||||
new ResponseSpecBuilder().build());
|
||||
|
||||
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
|
||||
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
|
||||
|
||||
final String minBalanceForInterestCalculation = null;
|
||||
final String minRequiredBalance = null;
|
||||
final String enforceMinRequiredBalance = "true";
|
||||
final boolean enforceMinRequiredBalance = true;
|
||||
final boolean allowOverdraft = false;
|
||||
final boolean lienAllowed = true;
|
||||
|
||||
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE,
|
||||
minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft);
|
||||
minBalanceForInterestCalculation, enforceMinRequiredBalance, allowOverdraft, lienAllowed);
|
||||
Assertions.assertNotNull(savingsProductID);
|
||||
|
||||
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
|
||||
@@ -2211,38 +2270,264 @@ public class ClientSavingsIntegrationTest {
|
||||
savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
|
||||
|
||||
List<HashMap> error = (List) savingsAccountHelperValidationError.holdAmountInSavingsAccount(savingsId, "1500", false,
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR); // lien:false
|
||||
List<HashMap> error = (List) savingsAccountHelperValidationError.holdAmountInSavingsAccount(savingsId, "2000", false,
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
|
||||
assertEquals("validation.msg.savingsaccount.insufficient.balance", error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||
|
||||
assertEquals("validation.msg.savingsaccount.insufficient balance", error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||
|
||||
Integer holdTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId, "1500", true,
|
||||
Integer lienHoldTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId, "2000", true,
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
|
||||
HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId);
|
||||
|
||||
Float balance = Float.parseFloat("-500");
|
||||
Float balance = Float.parseFloat("-1000");
|
||||
|
||||
assertEquals(balance, summary.get("availableBalance"), "Verifying available Balance is -500");
|
||||
|
||||
Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "1000",
|
||||
assertEquals(balance, summary.get("availableBalance"), "Verifying available Balance is -1000");
|
||||
Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "1200",
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
|
||||
Calendar todaysDate = Calendar.getInstance();
|
||||
final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime());
|
||||
|
||||
ArrayList<HashMap> savingsAccountErrorData = (ArrayList<HashMap>) validationErrorHelper.withdrawalFromSavingsAccount(savingsId,
|
||||
"1000", TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
|
||||
"200", TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
|
||||
|
||||
assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
|
||||
savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||
|
||||
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500", TRANSACTION_DATE,
|
||||
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "100", TRANSACTION_DATE,
|
||||
CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
|
||||
Assertions.assertNotNull(withdrawTransactionId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testSavingsAccountLienAllowedAtProductLevelWithOverDraftLimit() {
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
|
||||
SavingsAccountHelper savingsAccountHelperValidationError = new SavingsAccountHelper(this.requestSpec,
|
||||
new ResponseSpecBuilder().build());
|
||||
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
|
||||
|
||||
final String minBalanceForInterestCalculation = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final boolean allowOverdraft = true;
|
||||
final boolean lienAllowed = true;
|
||||
|
||||
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE,
|
||||
minBalanceForInterestCalculation, enforceMinRequiredBalance, allowOverdraft, lienAllowed);
|
||||
Assertions.assertNotNull(savingsProductID);
|
||||
|
||||
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
|
||||
Assertions.assertNotNull(savingsProductID);
|
||||
|
||||
HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap);
|
||||
|
||||
savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
|
||||
|
||||
savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
|
||||
|
||||
List<HashMap> error = (List) savingsAccountHelperValidationError.holdAmountInSavingsAccount(savingsId, "2000", false,
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
|
||||
assertEquals("validation.msg.savingsaccount.insufficient.balance", error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||
|
||||
Integer lienHoldTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId, "2000", true,
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
|
||||
HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId);
|
||||
|
||||
Float balance = Float.parseFloat("-1000");
|
||||
|
||||
assertEquals(balance, summary.get("availableBalance"), "Verifying available Balance is -1000");
|
||||
|
||||
Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "1200",
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
|
||||
Calendar todaysDate = Calendar.getInstance();
|
||||
final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime());
|
||||
|
||||
ArrayList<HashMap> savingsAccountErrorData = (ArrayList<HashMap>) validationErrorHelper.withdrawalFromSavingsAccount(savingsId,
|
||||
"300", TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
|
||||
|
||||
assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
|
||||
savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||
|
||||
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "200", TRANSACTION_DATE,
|
||||
CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
|
||||
Assertions.assertNotNull(withdrawTransactionId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testSavingsAccountLienAllowedAtProductLevelWithNoConfig() {
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
|
||||
SavingsAccountHelper savingsAccountHelperValidationError = new SavingsAccountHelper(this.requestSpec,
|
||||
new ResponseSpecBuilder().build());
|
||||
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
|
||||
|
||||
final String minBalanceForInterestCalculation = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final boolean allowOverdraft = false;
|
||||
final boolean lienAllowed = true;
|
||||
|
||||
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE,
|
||||
minBalanceForInterestCalculation, enforceMinRequiredBalance, allowOverdraft, lienAllowed);
|
||||
Assertions.assertNotNull(savingsProductID);
|
||||
|
||||
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
|
||||
Assertions.assertNotNull(savingsProductID);
|
||||
|
||||
HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap);
|
||||
|
||||
savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
|
||||
|
||||
savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
|
||||
|
||||
List<HashMap> error = (List) savingsAccountHelperValidationError.holdAmountInSavingsAccount(savingsId, "2000", false,
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
|
||||
assertEquals("validation.msg.savingsaccount.insufficient.balance", error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||
|
||||
Integer lienHoldTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId, "2000", true,
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
|
||||
HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId);
|
||||
|
||||
Float balance = Float.parseFloat("-1000");
|
||||
|
||||
assertEquals(balance, summary.get("availableBalance"), "Verifying available Balance is -1000");
|
||||
|
||||
Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "1100",
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
|
||||
Calendar todaysDate = Calendar.getInstance();
|
||||
final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime());
|
||||
|
||||
ArrayList<HashMap> savingsAccountErrorData = (ArrayList<HashMap>) validationErrorHelper.withdrawalFromSavingsAccount(savingsId,
|
||||
"200", TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);// withdrawable amount = 200;
|
||||
|
||||
assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
|
||||
savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||
|
||||
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "100", TRANSACTION_DATE,
|
||||
CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
|
||||
Assertions.assertNotNull(withdrawTransactionId);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testSavingsAccountWithoutLienAllowed() {
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
|
||||
SavingsAccountHelper savingsAccountHelperValidationError = new SavingsAccountHelper(this.requestSpec,
|
||||
new ResponseSpecBuilder().build());
|
||||
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
|
||||
|
||||
final String minBalanceForInterestCalculation = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final boolean allowOverdraft = true;
|
||||
final boolean lienAllowed = false;
|
||||
|
||||
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE,
|
||||
minBalanceForInterestCalculation, enforceMinRequiredBalance, allowOverdraft, lienAllowed);
|
||||
Assertions.assertNotNull(savingsProductID);
|
||||
|
||||
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
|
||||
Assertions.assertNotNull(savingsProductID);
|
||||
|
||||
HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap);
|
||||
|
||||
savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
|
||||
|
||||
savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId);
|
||||
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
|
||||
|
||||
List<HashMap> error = (List) savingsAccountHelperValidationError.holdAmountInSavingsAccount(savingsId, "2000", true,
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
|
||||
assertEquals("validation.msg.savingsaccount.lien.is.not.allowed.in.product.level",
|
||||
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||
|
||||
Integer lienHoldTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId, "1500", false,
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);// as per overdraft limit
|
||||
|
||||
HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId);
|
||||
|
||||
Float balance = Float.parseFloat("-500"); // opening balance
|
||||
|
||||
assertEquals(balance, summary.get("availableBalance"), "Verifying available Balance is -500");
|
||||
|
||||
Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "2000", // available
|
||||
// to
|
||||
// use
|
||||
// 1100
|
||||
// and
|
||||
// another
|
||||
// 1000
|
||||
// on
|
||||
// transactional
|
||||
// hold
|
||||
|
||||
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
|
||||
Calendar todaysDate = Calendar.getInstance();
|
||||
final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime());
|
||||
|
||||
ArrayList<HashMap> savingsAccountErrorData = (ArrayList<HashMap>) validationErrorHelper.withdrawalFromSavingsAccount(savingsId,
|
||||
"1600", TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);// can not withdraw: amount on transactional
|
||||
// hold
|
||||
|
||||
assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
|
||||
savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
|
||||
|
||||
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "1500",
|
||||
TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
|
||||
Assertions.assertNotNull(withdrawTransactionId);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testSavingsAccountLienAllowedAtProductLevelWithOverDraftLimitGreaterThanLienLimit() {
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
|
||||
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
|
||||
|
||||
final String minBalanceForInterestCalculation = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final boolean allowOverdraft = true;
|
||||
final String overDraftLimit = "2000.0";
|
||||
final boolean lienAllowed = true;
|
||||
final String lineAllowedLimit = "1000.0";
|
||||
|
||||
final Integer savingsProductID = createSavingsProduct(this.requestSpec, errorResponse, MINIMUM_OPENING_BALANCE,
|
||||
minBalanceForInterestCalculation, enforceMinRequiredBalance, allowOverdraft, overDraftLimit, lienAllowed, lineAllowedLimit);
|
||||
Assertions.assertNull(savingsProductID);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* incorrect savings account balance when charge transaction is reversed during an overdraft recalculate Daily
|
||||
* Balances
|
||||
|
||||
+5
-4
@@ -377,11 +377,12 @@ public class SavingsAccountHelper {
|
||||
getActivatedSavingsAsJSON(), isBlock);
|
||||
}
|
||||
|
||||
public Object holdAmountInSavingsAccount(final Integer savingsID, final String amount, final Boolean lienStatus, String date,
|
||||
public Object holdAmountInSavingsAccount(final Integer savingsID, final String amount, final Boolean lienAllowed, String date,
|
||||
String jsonAttributeToGetback) {
|
||||
LOG.info("--------------------------------- SAVINGS TRANSACTION HOLD AMOUNT--------------------------------");
|
||||
|
||||
return performSavingActions(createSavingsTransactionURL(HOLD_AMOUNT_SAVINGS_COMMAND, savingsID),
|
||||
getLienSavingsTransactionJSON(amount, date, lienStatus), jsonAttributeToGetback);
|
||||
getLienSavingsTransactionJSON(amount, date, lienAllowed), jsonAttributeToGetback);
|
||||
}
|
||||
|
||||
public Integer releaseAmount(final Integer savingsId, final Integer transactionId) {
|
||||
@@ -459,13 +460,13 @@ public class SavingsAccountHelper {
|
||||
return savingsAccountWithdrawalJson;
|
||||
}
|
||||
|
||||
private String getLienSavingsTransactionJSON(final String amount, final String transactionDate, final Boolean lien) {
|
||||
private String getLienSavingsTransactionJSON(final String amount, final String transactionDate, final Boolean lienAllowed) {
|
||||
final HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("locale", CommonConstants.LOCALE);
|
||||
map.put("dateFormat", CommonConstants.DATE_FORMAT);
|
||||
map.put("transactionDate", transactionDate);
|
||||
map.put("transactionAmount", amount);
|
||||
map.put("lien", lien);
|
||||
map.put("lienAllowed", lienAllowed);
|
||||
map.put("reasonForBlock", "unUsualActivity");
|
||||
String savingsAccountWithdrawalJson = new Gson().toJson(map);
|
||||
LOG.info(savingsAccountWithdrawalJson);
|
||||
|
||||
+13
-3
@@ -86,6 +86,8 @@ public class SavingsProductHelper {
|
||||
private String overdraftLimit = null;
|
||||
private String minRequiredBalance = null;
|
||||
private String enforceMinRequiredBalance = "false";
|
||||
private String lienAllowed = "false";
|
||||
private String maxAllowedLienLimit = null;
|
||||
private Boolean withHoldTax = false;
|
||||
private String taxGroupId = null;
|
||||
private boolean isDormancyTrackingActive = false;
|
||||
@@ -129,6 +131,8 @@ public class SavingsProductHelper {
|
||||
map.put("overdraftLimit", this.overdraftLimit);
|
||||
map.put("minRequiredBalance", this.minRequiredBalance);
|
||||
map.put("enforceMinRequiredBalance", this.enforceMinRequiredBalance);
|
||||
map.put("lienAllowed", this.lienAllowed);
|
||||
map.put("maxAllowedLienLimit", this.maxAllowedLienLimit);
|
||||
map.put("withHoldTax", this.withHoldTax.toString());
|
||||
|
||||
if (withHoldTax) {
|
||||
@@ -216,16 +220,22 @@ public class SavingsProductHelper {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SavingsProductHelper withMinRequiredBalance(String minBalance) {
|
||||
this.minRequiredBalance = minBalance;
|
||||
public SavingsProductHelper withMinRequiredBalance(final String minRequiredBalance) {
|
||||
this.minRequiredBalance = minRequiredBalance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SavingsProductHelper withEnforceMinRequiredBalance(String enforceMinRequiredBalance) {
|
||||
public SavingsProductHelper withEnforceMinRequiredBalance(final String enforceMinRequiredBalance) {
|
||||
this.enforceMinRequiredBalance = enforceMinRequiredBalance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SavingsProductHelper withLienAllowed(final String maxAllowedLienLimit) {
|
||||
this.lienAllowed = "true";
|
||||
this.maxAllowedLienLimit = maxAllowedLienLimit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SavingsProductHelper withOverDraft(final String overdraftLimit) {
|
||||
this.allowOverdraft = "true";
|
||||
this.overdraftLimit = overdraftLimit;
|
||||
|
||||
Reference in New Issue
Block a user