You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by pt...@apache.org on 2021/11/19 22:18:39 UTC

[fineract] branch develop updated: FINERACT-1390:WithdrawChargesPerPaymentType

This is an automated email from the ASF dual-hosted git repository.

ptuomola pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 2513ee4  FINERACT-1390:WithdrawChargesPerPaymentType
2513ee4 is described below

commit 2513ee48379fec73c4ef4497efc8729fe15217a7
Author: rrpawar96 <rr...@gmail.com>
AuthorDate: Sat Jan 1 02:10:21 2022 +0530

    FINERACT-1390:WithdrawChargesPerPaymentType
---
 .../fineract/portfolio/charge/data/ChargeData.java | 85 ++++++++++++----------
 .../fineract/portfolio/charge/domain/Charge.java   | 69 ++++++++++++++++--
 ...geDefinitionCommandFromApiJsonDeserializer.java | 26 ++++++-
 .../service/ChargeReadPlatformServiceImpl.java     | 19 ++++-
 ...hargeWritePlatformServiceJpaRepositoryImpl.java | 28 ++++++-
 .../portfolio/paymenttype/domain/PaymentType.java  |  4 +
 .../portfolio/savings/domain/SavingsAccount.java   | 17 ++++-
 .../savings/domain/SavingsAccountCharge.java       |  4 +
 .../V271_2__withdrawal_charges_paymenttype.sql     | 27 +++++++
 .../ClientSavingsIntegrationTest.java              | 83 +++++++++++++++++++++
 .../common/charges/ChargesHelper.java              | 21 ++++++
 .../common/savings/SavingsAccountHelper.java       | 19 +++++
 12 files changed, 349 insertions(+), 53 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
index d070c3a..1b4c47a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
@@ -48,6 +48,8 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
     private final Integer freeWithdrawalChargeFrequency;
     private final Integer restartFrequency;
     private final Integer restartFrequencyEnum;
+    private final boolean isPaymentType;
+    private final PaymentTypeData paymentTypeOptions;
     private final CurrencyData currency;
     private final BigDecimal amount;
     private final EnumOptionData chargeTimeType;
@@ -99,34 +101,36 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
         final GLAccountData account = null;
         final TaxGroupData taxGroupData = null;
 
-        return new ChargeData(null, null, null, null, null, null, null, null, false, false, false, null, null, null, taxGroupData,
-                currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions,
-                loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
-                savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, null, null, null, null, null,
-                feeFrequencyOptions, account, incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions,
-                shareChargeTimeTypeOptions, accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions);
+        return new ChargeData(null, null, null, null, null, null, null, null, false, false, false, null, null, null, false, null,
+                taxGroupData, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions,
+                chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
+                savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
+                clientChargeTimeTypeOptions, null, null, null, null, null, feeFrequencyOptions, account, incomeOrLiabilityAccountOptions,
+                taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig,
+                expenseAccountOptions, assetAccountOptions);
     }
 
     public static ChargeData withTemplate(final ChargeData charge, final ChargeData template) {
         return new ChargeData(charge.id, charge.name, charge.amount, charge.currency, charge.chargeTimeType, charge.chargeAppliesTo,
                 charge.chargeCalculationType, charge.chargePaymentMode, charge.penalty, charge.active, charge.freeWithdrawal,
-                charge.freeWithdrawalChargeFrequency, charge.restartFrequency, charge.restartFrequencyEnum, charge.taxGroup,
-                template.currencyOptions, template.chargeCalculationTypeOptions, template.chargeAppliesToOptions,
-                template.chargeTimeTypeOptions, template.chargePaymetModeOptions, template.loanChargeCalculationTypeOptions,
-                template.loanChargeTimeTypeOptions, template.savingsChargeCalculationTypeOptions, template.savingsChargeTimeTypeOptions,
-                template.clientChargeCalculationTypeOptions, template.clientChargeTimeTypeOptions, charge.feeOnMonthDay, charge.feeInterval,
-                charge.minCap, charge.maxCap, charge.feeFrequency, template.feeFrequencyOptions, charge.incomeOrLiabilityAccount,
-                template.incomeOrLiabilityAccountOptions, template.taxGroupOptions, template.shareChargeCalculationTypeOptions,
-                template.shareChargeTimeTypeOptions, template.accountMappingForChargeConfig, template.expenseAccountOptions,
-                template.assetAccountOptions);
+                charge.freeWithdrawalChargeFrequency, charge.restartFrequency, charge.restartFrequencyEnum, charge.isPaymentType,
+                charge.paymentTypeOptions, charge.taxGroup, template.currencyOptions, template.chargeCalculationTypeOptions,
+                template.chargeAppliesToOptions, template.chargeTimeTypeOptions, template.chargePaymetModeOptions,
+                template.loanChargeCalculationTypeOptions, template.loanChargeTimeTypeOptions, template.savingsChargeCalculationTypeOptions,
+                template.savingsChargeTimeTypeOptions, template.clientChargeCalculationTypeOptions, template.clientChargeTimeTypeOptions,
+                charge.feeOnMonthDay, charge.feeInterval, charge.minCap, charge.maxCap, charge.feeFrequency, template.feeFrequencyOptions,
+                charge.incomeOrLiabilityAccount, template.incomeOrLiabilityAccountOptions, template.taxGroupOptions,
+                template.shareChargeCalculationTypeOptions, template.shareChargeTimeTypeOptions, template.accountMappingForChargeConfig,
+                template.expenseAccountOptions, template.assetAccountOptions);
     }
 
     public static ChargeData instance(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
             final EnumOptionData chargeTimeType, final EnumOptionData chargeAppliesTo, final EnumOptionData chargeCalculationType,
             final EnumOptionData chargePaymentMode, final MonthDay feeOnMonthDay, final Integer feeInterval, final boolean penalty,
             final boolean active, final boolean freeWithdrawal, final Integer freeWithdrawalChargeFrequency, final Integer restartFrequency,
-            final Integer restartFrequencyEnum, final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency,
-            final GLAccountData accountData, TaxGroupData taxGroupData) {
+            final Integer restartFrequencyEnum, final boolean isPaymentType, final PaymentTypeData paymentTypeOptions,
+            final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency, final GLAccountData accountData,
+            TaxGroupData taxGroupData) {
 
         final Collection<CurrencyData> currencyOptions = null;
         final List<EnumOptionData> chargeCalculationTypeOptions = null;
@@ -148,13 +152,13 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
         final List<GLAccountData> expenseAccountOptions = null;
         final List<GLAccountData> assetAccountOptions = null;
         return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
-                penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, taxGroupData,
-                currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions,
-                loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
-                savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval,
-                minCap, maxCap, feeFrequency, feeFrequencyOptions, accountData, incomeOrLiabilityAccountOptions, taxGroupOptions,
-                shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig, expenseAccountOptions,
-                assetAccountOptions);
+                penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, isPaymentType,
+                paymentTypeOptions, taxGroupData, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions,
+                chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
+                savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
+                clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, accountData,
+                incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions,
+                accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions);
     }
 
     public static ChargeData lookup(final Long id, final String name, final boolean isPenalty) {
@@ -200,27 +204,28 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
         final List<GLAccountData> assetAccountOptions = null;
 
         return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
-                penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, taxGroupData,
-                currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions,
-                loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
-                savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval,
-                minCap, maxCap, feeFrequency, feeFrequencyOptions, account, incomeOrLiabilityAccountOptions, taxGroupOptions,
-                shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig, expenseAccountOptions,
-                assetAccountOptions);
+                penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, isPaymentType,
+                paymentTypeOptions, taxGroupData, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions,
+                chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
+                savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
+                clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, account,
+                incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions,
+                accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions);
     }
 
     private ChargeData(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
             final EnumOptionData chargeTimeType, final EnumOptionData chargeAppliesTo, final EnumOptionData chargeCalculationType,
             final EnumOptionData chargePaymentMode, final boolean penalty, final boolean active, final boolean freeWithdrawal,
             final Integer freeWithdrawalChargeFrequency, final Integer restartFrequency, final Integer restartFrequencyEnum,
-            final TaxGroupData taxGroupData, final Collection<CurrencyData> currencyOptions,
-            final List<EnumOptionData> chargeCalculationTypeOptions, final List<EnumOptionData> chargeAppliesToOptions,
-            final List<EnumOptionData> chargeTimeTypeOptions, final List<EnumOptionData> chargePaymentModeOptions,
-            final List<EnumOptionData> loansChargeCalculationTypeOptions, final List<EnumOptionData> loansChargeTimeTypeOptions,
-            final List<EnumOptionData> savingsChargeCalculationTypeOptions, final List<EnumOptionData> savingsChargeTimeTypeOptions,
-            final List<EnumOptionData> clientChargeCalculationTypeOptions, final List<EnumOptionData> clientChargeTimeTypeOptions,
-            final MonthDay feeOnMonthDay, final Integer feeInterval, final BigDecimal minCap, final BigDecimal maxCap,
-            final EnumOptionData feeFrequency, final List<EnumOptionData> feeFrequencyOptions, final GLAccountData account,
+            final boolean isPaymentType, final PaymentTypeData paymentTypeOptions, final TaxGroupData taxGroupData,
+            final Collection<CurrencyData> currencyOptions, final List<EnumOptionData> chargeCalculationTypeOptions,
+            final List<EnumOptionData> chargeAppliesToOptions, final List<EnumOptionData> chargeTimeTypeOptions,
+            final List<EnumOptionData> chargePaymentModeOptions, final List<EnumOptionData> loansChargeCalculationTypeOptions,
+            final List<EnumOptionData> loansChargeTimeTypeOptions, final List<EnumOptionData> savingsChargeCalculationTypeOptions,
+            final List<EnumOptionData> savingsChargeTimeTypeOptions, final List<EnumOptionData> clientChargeCalculationTypeOptions,
+            final List<EnumOptionData> clientChargeTimeTypeOptions, final MonthDay feeOnMonthDay, final Integer feeInterval,
+            final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency,
+            final List<EnumOptionData> feeFrequencyOptions, final GLAccountData account,
             final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions, final Collection<TaxGroupData> taxGroupOptions,
             final List<EnumOptionData> shareChargeCalculationTypeOptions, final List<EnumOptionData> shareChargeTimeTypeOptions,
             final String accountMappingForChargeConfig, final List<GLAccountData> expenseAccountOptions,
@@ -241,6 +246,8 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
         this.freeWithdrawalChargeFrequency = freeWithdrawalChargeFrequency;
         this.restartFrequency = restartFrequency;
         this.restartFrequencyEnum = restartFrequencyEnum;
+        this.isPaymentType = isPaymentType;
+        this.paymentTypeOptions = paymentTypeOptions;
         this.minCap = minCap;
         this.maxCap = maxCap;
         this.currencyOptions = currencyOptions;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
index 670db81..ea1eda4 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
@@ -49,6 +49,8 @@ import org.apache.fineract.portfolio.charge.exception.ChargeMustBePenaltyExcepti
 import org.apache.fineract.portfolio.charge.exception.ChargeParameterUpdateNotSupportedException;
 import org.apache.fineract.portfolio.charge.service.ChargeEnumerations;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
+import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
+import org.apache.fineract.portfolio.paymenttype.domain.PaymentType;
 import org.apache.fineract.portfolio.tax.data.TaxGroupData;
 import org.apache.fineract.portfolio.tax.domain.TaxGroup;
 
@@ -116,6 +118,13 @@ public class Charge extends AbstractPersistableCustom {
     @Column(name = "restart_frequency_enum", nullable = true)
     private Integer restartFrequencyEnum;
 
+    @Column(name = "is_payment_type", nullable = false)
+    private boolean enablePaymentType;
+
+    @ManyToOne
+    @JoinColumn(name = "payment_type_id", nullable = false)
+    private PaymentType paymentType;
+
     @ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "income_or_liability_account_id")
     private GLAccount account;
@@ -124,7 +133,8 @@ public class Charge extends AbstractPersistableCustom {
     @JoinColumn(name = "tax_group_id")
     private TaxGroup taxGroup;
 
-    public static Charge fromJson(final JsonCommand command, final GLAccount account, final TaxGroup taxGroup) {
+    public static Charge fromJson(final JsonCommand command, final GLAccount account, final TaxGroup taxGroup,
+            final PaymentType paymentType) {
 
         final String name = command.stringValueOfParameterNamed("name");
         final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
@@ -149,6 +159,9 @@ public class Charge extends AbstractPersistableCustom {
         boolean enableFreeWithdrawalCharge = false;
         enableFreeWithdrawalCharge = command.booleanPrimitiveValueOfParameterNamed("enableFreeWithdrawalCharge");
 
+        boolean enablePaymentType = false;
+        enablePaymentType = command.booleanPrimitiveValueOfParameterNamed("enablePaymentType");
+
         Integer freeWithdrawalFrequency = null;
         Integer restartCountFrequency = null;
         PeriodFrequencyType countFrequencyType = null;
@@ -162,7 +175,7 @@ public class Charge extends AbstractPersistableCustom {
 
         return new Charge(name, amount, currencyCode, chargeAppliesTo, chargeTimeType, chargeCalculationType, penalty, active, paymentMode,
                 feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, enableFreeWithdrawalCharge, freeWithdrawalFrequency,
-                restartCountFrequency, countFrequencyType, account, taxGroup);
+                restartCountFrequency, countFrequencyType, account, taxGroup, enablePaymentType, paymentType);
     }
 
     protected Charge() {}
@@ -172,7 +185,7 @@ public class Charge extends AbstractPersistableCustom {
             final ChargePaymentMode paymentMode, final MonthDay feeOnMonthDay, final Integer feeInterval, final BigDecimal minCap,
             final BigDecimal maxCap, final Integer feeFrequency, final boolean enableFreeWithdrawalCharge,
             final Integer freeWithdrawalFrequency, final Integer restartFrequency, final PeriodFrequencyType restartFrequencyEnum,
-            final GLAccount account, final TaxGroup taxGroup) {
+            final GLAccount account, final TaxGroup taxGroup, final boolean enablePaymentType, final PaymentType paymentType) {
         this.name = name;
         this.amount = amount;
         this.currencyCode = currencyCode;
@@ -224,6 +237,14 @@ public class Charge extends AbstractPersistableCustom {
                 this.restartFrequencyEnum = restartFrequencyEnum.getValue();
             }
 
+            if (enablePaymentType) {
+                if (paymentType != null) {
+
+                    this.enablePaymentType = enablePaymentType;
+                    this.paymentType = paymentType;
+                }
+            }
+
         } else if (isLoanCharge()) {
 
             if (penalty && (chargeTime.isTimeOfDisbursement() || chargeTime.isTrancheDisbursement())) {
@@ -334,6 +355,10 @@ public class Charge extends AbstractPersistableCustom {
         return this.enableFreeWithdrawal;
     }
 
+    public boolean isEnablePaymentType() {
+        return this.enablePaymentType;
+    }
+
     public Integer getFrequencyFreeWithdrawalCharge() {
         return this.freeWithdrawalFrequency;
     }
@@ -346,6 +371,22 @@ public class Charge extends AbstractPersistableCustom {
         return this.restartFrequencyEnum;
     }
 
+    public PaymentType getPaymentType() {
+        return this.paymentType;
+    }
+
+    public void setPaymentType(PaymentType paymentType) {
+        this.paymentType = paymentType;
+    }
+
+    private Long getPaymentTypeId() {
+        Long paymentTypeId = null;
+        if (this.paymentType != null) {
+            paymentTypeId = this.paymentType.getId();
+        }
+        return paymentTypeId;
+    }
+
     public Map<String, Object> update(final JsonCommand command) {
         final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
 
@@ -439,6 +480,19 @@ public class Charge extends AbstractPersistableCustom {
 
         }
 
+        final String enablePaymentTypeParamName = "enablePaymentType";
+        if (command.isChangeInBooleanParameterNamed(enablePaymentTypeParamName, this.enablePaymentType)) {
+            final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(enablePaymentTypeParamName);
+            actualChanges.put(enablePaymentTypeParamName, newValue);
+            this.enablePaymentType = newValue;
+        }
+
+        final String paymentTypeParamName = "paymentTypeId";
+        if (command.isChangeInLongParameterNamed(paymentTypeParamName, getPaymentTypeId())) {
+            final Long newValue = command.longValueOfParameterNamed(paymentTypeParamName);
+            actualChanges.put(paymentTypeParamName, newValue);
+        }
+
         final String chargeAppliesToParamName = "chargeAppliesTo";
         if (command.isChangeInIntegerParameterNamed(chargeAppliesToParamName, this.chargeAppliesTo)) {
             /*
@@ -613,11 +667,16 @@ public class Charge extends AbstractPersistableCustom {
             taxGroupData = TaxGroupData.lookup(taxGroup.getId(), taxGroup.getName());
         }
 
+        PaymentTypeData paymentTypeData = null;
+        if (this.paymentType != null) {
+            paymentTypeData = PaymentTypeData.instance(paymentType.getId(), paymentType.getPaymentName());
+        }
+
         final CurrencyData currency = new CurrencyData(this.currencyCode, null, 0, 0, null, null);
         return ChargeData.instance(getId(), this.name, this.amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType,
                 chargePaymentmode, getFeeOnMonthDay(), this.feeInterval, this.penalty, this.active, this.enableFreeWithdrawal,
-                this.freeWithdrawalFrequency, this.restartFrequency, this.restartFrequencyEnum, this.minCap, this.maxCap, feeFrequencyType,
-                accountData, taxGroupData);
+                this.freeWithdrawalFrequency, this.restartFrequency, this.restartFrequencyEnum, this.enablePaymentType, paymentTypeData,
+                this.minCap, this.maxCap, feeFrequencyType, accountData, taxGroupData);
     }
 
     public Integer getChargePaymentMode() {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java
index e5d35e8..eee9ff9 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java
@@ -54,8 +54,8 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
     private final Set<String> supportedParameters = new HashSet<>(Arrays.asList("name", "amount", "locale", "currencyCode",
             "currencyOptions", "chargeAppliesTo", "chargeTimeType", "chargeCalculationType", "chargeCalculationTypeOptions", "penalty",
             "active", "chargePaymentMode", "feeOnMonthDay", "feeInterval", "monthDayFormat", "minCap", "maxCap", "feeFrequency",
-            "enableFreeWithdrawalCharge", "freeWithdrawalFrequency", "restartCountFrequency", "countFrequencyType",
-            ChargesApiConstants.glAccountIdParamName, ChargesApiConstants.taxGroupIdParamName));
+            "enableFreeWithdrawalCharge", "freeWithdrawalFrequency", "restartCountFrequency", "countFrequencyType", "paymentTypeId",
+            "enablePaymentType", ChargesApiConstants.glAccountIdParamName, ChargesApiConstants.taxGroupIdParamName));
 
     private final FromJsonHelper fromApiJsonHelper;
 
@@ -114,6 +114,17 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
             }
         }
 
+        if (this.fromApiJsonHelper.parameterExists("enablePaymentType", element)) {
+
+            final boolean enablePaymentType = this.fromApiJsonHelper.extractBooleanNamed("enablePaymentType", element);
+            baseDataValidator.reset().parameter("enablePaymentType").value(enablePaymentType).notNull();
+
+            if (enablePaymentType) {
+                final Integer paymentTypeId = this.fromApiJsonHelper.extractIntegerNamed("paymentTypeId", element, Locale.getDefault());
+                baseDataValidator.reset().parameter("paymentTypeId").value(paymentTypeId).integerGreaterThanZero();
+            }
+        }
+
         if (feeFrequency != null) {
             baseDataValidator.reset().parameter("feeInterval").value(feeInterval).notNull();
         }
@@ -320,6 +331,17 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
                         Locale.getDefault());
                 baseDataValidator.reset().parameter("countFrequencyType").value(countFrequencyType);
             }
+
+            Boolean enablePaymentType = false;
+            if (this.fromApiJsonHelper.parameterExists("enablePaymentType", element)) {
+                enablePaymentType = this.fromApiJsonHelper.extractBooleanNamed("enablePaymentType", element);
+                baseDataValidator.reset().parameter("enablePaymentType").value(enablePaymentType).notNull();
+
+                if (enablePaymentType) {
+                    final Integer paymentTypeId = this.fromApiJsonHelper.extractIntegerNamed("paymentTypeId", element, Locale.getDefault());
+                    baseDataValidator.reset().parameter("paymentTypeId").value(paymentTypeId).integerGreaterThanZero();
+                }
+            }
         }
 
         if (this.fromApiJsonHelper.parameterExists("chargeAppliesTo", element)) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java
index 26f46ea..cf9ab4e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java
@@ -43,6 +43,7 @@ import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
 import org.apache.fineract.portfolio.charge.exception.ChargeNotFoundException;
 import org.apache.fineract.portfolio.common.service.CommonEnumerations;
 import org.apache.fineract.portfolio.common.service.DropdownReadPlatformService;
+import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
 import org.apache.fineract.portfolio.tax.data.TaxGroupData;
 import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -293,10 +294,10 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
                     + "oc.internationalized_name_code as currencyNameCode, c.fee_on_day as feeOnDay, c.fee_on_month as feeOnMonth, "
                     + "c.fee_interval as feeInterval, c.fee_frequency as feeFrequency,c.min_cap as minCap,c.max_cap as maxCap, "
                     + "c.income_or_liability_account_id as glAccountId , acc.name as glAccountName, acc.gl_code as glCode, "
-                    + "tg.id as taxGroupId, tg.name as taxGroupName " + "from m_charge c "
-                    + "join m_organisation_currency oc on c.currency_code = oc.code "
+                    + "tg.id as taxGroupId, c.is_payment_type as isPaymentType, pt.id as paymentTypeId, pt.value as paymentTypeName, tg.name as taxGroupName "
+                    + "from m_charge c " + "join m_organisation_currency oc on c.currency_code = oc.code "
                     + " LEFT JOIN acc_gl_account acc on acc.id = c.income_or_liability_account_id "
-                    + " LEFT JOIN m_tax_group tg on tg.id = c.tax_group_id ";
+                    + " LEFT JOIN m_tax_group tg on tg.id = c.tax_group_id " + " LEFT JOIN m_payment_type pt on pt.id = c.payment_type_id ";
         }
 
         public String loanProductChargeSchema() {
@@ -378,9 +379,19 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
             final int restartFrequency = rs.getInt("restartFrequency");
             final int restartFrequencyEnum = rs.getInt("restartFrequencyEnum");
 
+            final boolean isPaymentType = rs.getBoolean("isPaymentType");
+            final Long paymentTypeId = JdbcSupport.getLong(rs, "paymentTypeId");
+
+            final String paymentTypeName = rs.getString("paymentTypeName");
+            PaymentTypeData paymentTypeData = null;
+            if (paymentTypeId != null) {
+                paymentTypeData = PaymentTypeData.instance(paymentTypeId, paymentTypeName);
+            }
+
             return ChargeData.instance(id, name, amount, currency, chargeTimeType, chargeAppliesToType, chargeCalculationType,
                     chargePaymentMode, feeOnMonthDay, feeInterval, penalty, active, isFreeWithdrawal, freeWithdrawalChargeFrequency,
-                    restartFrequency, restartFrequencyEnum, minCap, maxCap, feeFrequencyType, glAccountData, taxGroupData);
+                    restartFrequency, restartFrequencyEnum, isPaymentType, paymentTypeData, minCap, maxCap, feeFrequencyType, glAccountData,
+                    taxGroupData);
         }
     }
 
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java
index 22959c0..e11d44a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java
@@ -42,6 +42,8 @@ import org.apache.fineract.portfolio.charge.exception.ChargeNotFoundException;
 import org.apache.fineract.portfolio.charge.serialization.ChargeDefinitionCommandFromApiJsonDeserializer;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
+import org.apache.fineract.portfolio.paymentdetail.PaymentDetailConstants;
+import org.apache.fineract.portfolio.paymenttype.domain.PaymentType;
 import org.apache.fineract.portfolio.paymenttype.domain.PaymentTypeRepositoryWrapper;
 import org.apache.fineract.portfolio.tax.domain.TaxGroup;
 import org.apache.fineract.portfolio.tax.domain.TaxGroupRepositoryWrapper;
@@ -110,7 +112,16 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWriteP
                 taxGroup = this.taxGroupRepository.findOneWithNotFoundDetection(taxGroupId);
             }
 
-            final Charge charge = Charge.fromJson(command, glAccount, taxGroup);
+            final boolean enablePaymentType = command.booleanPrimitiveValueOfParameterNamed("enablePaymentType");
+            PaymentType paymentType = null;
+            if (enablePaymentType) {
+                final Long paymentTypeId = command.longValueOfParameterNamed(PaymentDetailConstants.paymentTypeParamName);
+                if (paymentTypeId != null) {
+                    paymentType = this.paymentTyperepositoryWrapper.findOneWithNotFoundDetection(paymentTypeId);
+                }
+            }
+
+            final Charge charge = Charge.fromJson(command, glAccount, taxGroup, paymentType);
             this.chargeRepository.save(charge);
 
             // check if the office specific products are enabled. If yes, then
@@ -179,6 +190,21 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWriteP
                 chargeForUpdate.setAccount(newIncomeAccount);
             }
 
+            final String paymentTypeIdParamName = "paymentTypeId";
+            if (changes.containsKey(paymentTypeIdParamName)) {
+
+                final Integer paymentTypeIdNewValue = command.integerValueOfParameterNamed(paymentTypeIdParamName);
+
+                PaymentType paymentType = null;
+                if (paymentTypeIdNewValue != null) {
+                    final Long paymentTypeId = paymentTypeIdNewValue.longValue();
+
+                    paymentType = this.paymentTyperepositoryWrapper.findOneWithNotFoundDetection(paymentTypeId);
+                    chargeForUpdate.setPaymentType(paymentType);
+                }
+
+            }
+
             if (changes.containsKey(ChargesApiConstants.taxGroupIdParamName)) {
                 final Long newValue = command.longValueOfParameterNamed(ChargesApiConstants.taxGroupIdParamName);
                 TaxGroup taxGroup = null;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymenttype/domain/PaymentType.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymenttype/domain/PaymentType.java
index aaac576..1207eba 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymenttype/domain/PaymentType.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymenttype/domain/PaymentType.java
@@ -97,4 +97,8 @@ public class PaymentType extends AbstractPersistableCustom {
         return isCashPayment;
     }
 
+    public String getPaymentName() {
+        return name;
+    }
+
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
index b882955..a33c8e3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
@@ -1076,14 +1076,27 @@ public class SavingsAccount extends AbstractPersistableCustom {
         for (SavingsAccountCharge charge : this.charges()) {
 
             if (charge.isWithdrawalFee() && charge.isActive()) {
+
                 if (charge.getFreeWithdrawalCount() == null) {
                     charge.setFreeWithdrawalCount(0);
                 }
 
-                if (charge.isEnableFreeWithdrawal()) {
+                if (charge.isEnablePaymentType() && charge.isEnableFreeWithdrawal()) { // discount transaction to
+                                                                                       // specific paymentType
+                    if (paymentDetail.getPaymentType().getPaymentName().equals(charge.getCharge().getPaymentType().getPaymentName())) {
+                        resetFreeChargeDaysCount(charge, transactionAmount, transactionDate, user);
+                    }
+                } else if (charge.isEnablePaymentType()) { // normal charge-transaction to specific paymentType
+                    if (paymentDetail.getPaymentType().getPaymentName().equals(charge.getCharge().getPaymentType().getPaymentName())) {
+                        charge.updateWithdralFeeAmount(transactionAmount);
+                        this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, user);
+                    }
+                } else if (!charge.isEnablePaymentType() && charge.isEnableFreeWithdrawal()) { // discount transaction
+                                                                                               // irrespective of
+                                                                                               // PaymentTypes.
                     resetFreeChargeDaysCount(charge, transactionAmount, transactionDate, user);
 
-                } else {
+                } else { // normal-withdraw
                     charge.updateWithdralFeeAmount(transactionAmount);
                     this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, user);
                 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountCharge.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountCharge.java
index f0e8401..4e35d0b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountCharge.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountCharge.java
@@ -677,6 +677,10 @@ public class SavingsAccountCharge extends AbstractPersistableCustom {
         return charge.isEnableFreeWithdrawal();
     }
 
+    public boolean isEnablePaymentType() {
+        return charge.isEnablePaymentType();
+    }
+
     public Integer getFrequencyFreeWithdrawalCharge() { // number of times free withdrawal allowed
         return charge.getFrequencyFreeWithdrawalCharge();
     }
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V271_2__withdrawal_charges_paymenttype.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V271_2__withdrawal_charges_paymenttype.sql
new file mode 100644
index 0000000..8a77ba4
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V271_2__withdrawal_charges_paymenttype.sql
@@ -0,0 +1,27 @@
+--
+-- 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.
+--
+
+ALTER TABLE `m_charge`
+    ADD COLUMN `is_payment_type` INT NULL DEFAULT '0' AFTER `restart_frequency_enum`;
+
+ALTER TABLE `m_charge`
+    ADD COLUMN `payment_type_id` INT(11) NULL DEFAULT NULL AFTER `is_payment_type`;
+
+ALTER TABLE `m_charge`
+ADD CONSTRAINT `FK_m_payment_detail_m_payment_types` FOREIGN KEY (`payment_type_id`) REFERENCES `m_payment_type` (`id`);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
index e3acbaa..cb843e4 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
@@ -42,6 +42,7 @@ import java.util.Locale;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.CommonConstants;
+import org.apache.fineract.integrationtests.common.PaymentTypeHelper;
 import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
 import org.apache.fineract.integrationtests.common.TaxComponentHelper;
 import org.apache.fineract.integrationtests.common.TaxGroupHelper;
@@ -2127,4 +2128,86 @@ public class ClientSavingsIntegrationTest {
         assertEquals(balance, summary.get("accountBalance"), "Verifying opening Balance is -300");
 
     }
+
+    @Test
+    public void testSavingsAccountWithdrawalChargesOnPaymentTypes() {
+
+        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 = "false";
+        final boolean allowOverdraft = false;
+        final String MINIMUM_OPENING_BALANCE = "10000";
+        final String withdrawalAmountOne = "1000";
+        final String withdrawalAmountTwo = "2000";
+        final Integer withdrawalChargeOne = 10;
+        final Integer withdrawalChargeTwo = 20;
+
+        final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE,
+                minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft);
+        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);
+
+        String name = PaymentTypeHelper.randomNameGenerator("P_T", 5);
+        String description = PaymentTypeHelper.randomNameGenerator("PT_Desc", 15);
+        Boolean isCashPayment = false;
+        Integer position = 1;
+
+        Integer paymentTypeIdOne = PaymentTypeHelper.createPaymentType(requestSpec, responseSpec, name, description, isCashPayment,
+                position);
+        Assertions.assertNotNull(paymentTypeIdOne);
+
+        final Integer chargeIdOne = ChargesHelper.createCharges(this.requestSpec, this.responseSpec,
+                ChargesHelper.paymentTypeCharge(withdrawalChargeOne, true, paymentTypeIdOne));
+        Assertions.assertNotNull(chargeIdOne);
+
+        this.savingsAccountHelper.addChargesForSavings(savingsId, chargeIdOne, false, BigDecimal.valueOf(withdrawalChargeOne));
+
+        Integer withdrawTransactionIdOne = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccountWithPaymentType(savingsId,
+                withdrawalAmountOne, SavingsAccountHelper.TRANSACTION_DATE, paymentTypeIdOne.toString(),
+                CommonConstants.RESPONSE_RESOURCE_ID);
+
+        Float balance = Float.parseFloat("8990");
+        // Withdraw charge from paymentType 1 is 10 So balance should be 10,000(deposit)-1000(wd)-"10(charge)" = 8990
+
+        HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId);
+        assertEquals(balance, summary.get("accountBalance"), "Verifying Balance after withdrawal charge ");
+
+        String paymentTypeNameTwo = PaymentTypeHelper.randomNameGenerator("P_T", 5);
+
+        Integer paymentTypeIdTwo = PaymentTypeHelper.createPaymentType(requestSpec, responseSpec, paymentTypeNameTwo, description,
+                isCashPayment, position);
+        Assertions.assertNotNull(paymentTypeIdTwo);
+
+        final Integer chargeIdTwo = ChargesHelper.createCharges(this.requestSpec, this.responseSpec,
+                ChargesHelper.paymentTypeCharge(withdrawalChargeTwo, true, paymentTypeIdTwo));
+        Assertions.assertNotNull(chargeIdTwo);
+
+        this.savingsAccountHelper.addChargesForSavings(savingsId, chargeIdTwo, false, BigDecimal.valueOf(withdrawalChargeTwo));
+
+        Integer withdrawTransactionIdTwo = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccountWithPaymentType(savingsId,
+                withdrawalAmountTwo, SavingsAccountHelper.TRANSACTION_DATE, paymentTypeIdTwo.toString(),
+                CommonConstants.RESPONSE_RESOURCE_ID);
+
+        Float balanceAfterChargeTwo = Float.parseFloat("6970");
+        // Withdraw charge from paymentType 2 is 20 So balance should be 8990(balance)-2000(wd)-"20(charge)" = 6970
+
+        HashMap summaryTwo = this.savingsAccountHelper.getSavingsSummary(savingsId);
+        assertEquals(balanceAfterChargeTwo, summaryTwo.get("accountBalance"), "Verifying Balance after withdrawal charge two ");
+    }
 }
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java
index 32ce65b..b2401d2 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java
@@ -188,6 +188,27 @@ public final class ChargesHelper {
         return chargesCreateJson;
     }
 
+    public static String paymentTypeCharge(Integer amount, final boolean enablePaymentType, final Integer paymentTypeId) {
+        return paymentTypeChargeJSON(amount, enablePaymentType, paymentTypeId);
+    }
+
+    public static String paymentTypeChargeJSON(Integer amount, final boolean enablePaymentType, final Integer paymentTypeId) {
+        final HashMap<String, Object> map = new HashMap<>();
+        map.put("active", ChargesHelper.ACTIVE);
+        map.put("amount", amount);
+        map.put("chargeAppliesTo", ChargesHelper.CHARGE_APPLIES_TO_SAVINGS);
+        map.put("chargeCalculationType", ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT);
+        map.put("currencyCode", ChargesHelper.CURRENCY_CODE);
+        map.put("locale", CommonConstants.LOCALE);
+        map.put("monthDayFormat", ChargesHelper.MONTH_DAY_FORMAT);
+        map.put("name", Utils.randomNameGenerator("Charge_Savings_", 6));
+        map.put("chargeTimeType", CHARGE_WITHDRAWAL_FEE);
+        map.put("enablePaymentType", enablePaymentType);
+        map.put("paymentTypeId", paymentTypeId);
+        String paymentTypeJson = new Gson().toJson(map);
+        return paymentTypeJson;
+    }
+
     public static String getLoanSpecifiedDueDateJSON() {
         return getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, ChargesHelper.AMOUNT, ChargesHelper.PENALTY);
     }
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java
index 0507f3e..f076950 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java
@@ -253,6 +253,13 @@ public class SavingsAccountHelper {
                 getSavingsTransactionJSON(amount, date), jsonAttributeToGetback);
     }
 
+    public Object withdrawalFromSavingsAccountWithPaymentType(final Integer savingsId, final String amount, String date, String paymentType,
+            String jsonAttributeToGetback) {
+        LOG.info("\n--------------------------------- SAVINGS TRANSACTION WITHDRAWAL WITH PAYMENT TYPE--------------------------------");
+        return performSavingActions(createSavingsTransactionURL(WITHDRAW_SAVINGS_COMMAND, savingsId),
+                getSavingsTransactionPaymentTypeJSON(amount, date, paymentType), jsonAttributeToGetback);
+    }
+
     public Integer updateSavingsAccountTransaction(final Integer savingsId, final Integer transactionId, final String amount) {
         LOG.info("\n--------------------------------- MODIFY SAVINGS TRANSACTION  --------------------------------");
         return (Integer) performSavingActions(createAdjustTransactionURL(MODIFY_TRASACTION_COMMAND, savingsId, transactionId),
@@ -432,6 +439,18 @@ public class SavingsAccountHelper {
         return savingsAccountWithdrawalJson;
     }
 
+    private String getSavingsTransactionPaymentTypeJSON(final String amount, final String transactionDate, final String paymentTypeId) {
+        final HashMap<String, String> map = new HashMap<>();
+        map.put("locale", CommonConstants.LOCALE);
+        map.put("dateFormat", CommonConstants.DATE_FORMAT);
+        map.put("transactionDate", transactionDate);
+        map.put("transactionAmount", amount);
+        map.put("paymentTypeId", paymentTypeId);
+        String savingsAccountWithdrawalJson = new Gson().toJson(map);
+        LOG.info(savingsAccountWithdrawalJson);
+        return savingsAccountWithdrawalJson;
+    }
+
     private String getCalculatedInterestForSavingsApplicationAsJSON() {
         final HashMap<String, String> map = new HashMap<>();
         String savingsAccountCalculatedInterestJson = new Gson().toJson(map);